本文介绍的是HTTP协议基础知识, HTML协议即网络通信过程中使用的一种交互协议,需要有一定的网络基础知识才会理解起来更容易,本文也尽力让内容更容易理解。

再了解了TCP/IP协议族分层结构后,我们可以学习HTTP协议了。

HTTP协议属于应用层的协议,协议定义的是客户端服务端之间通信的数据报文格式,接下来一步一步的学习具体的报文格式及其作用。

成就非凡的侠客,不能只看图练招式,还有内功心法

HTTP协议格式就是踏入江湖的第一段内功心法。没有它你就很难立足于Web江湖谨记:耐心!

HTTP协议格式

要学习HTTP协议格式,需要分别从下面两个部分了解HTTP协议格式:

  1. 请求报文-Request : 客户端/浏览器 发送给 服务端 的报文
  2. 应答报文-Response: 服务端 返回给 客户端/浏览器 的报文

我们来通过下面HTTP交互过程来了解报文格式发送过程:

HTTP交互报文格式

从图中可以看到两种报文发送流程很简单:

  • 第一步:客户端/浏览器 发送给 服务端 一条Request请求报文,告诉服务器,我要浏览页面"www.example.com/index.html"
  • 第二步:服务器 返回给 客户端/浏览器 一条Response应答报文,告诉客户端,好的!接收吧,这是你要的数据。

就这样,一次愉快的请求和应答完成了。


愉快归愉快,可是浏览器向服务器发送了哪些数据呢?

如果连这点都不清楚,那就没办法成为一名合格的虫师啦。

所谓知己知彼,连这个知己都还没搞清楚,何以闯荡江湖

好啦! 耐心的将两种格式(心法)记住,达到倒背如流的程度吧!

Request请求报文格式

Request请求报文就是我们的浏览器发送给服务器的数据格式

Request请求报文格式如下:

格式其实很简单,主要分成三部分:

  • 请求行(RequestLine) : 包含请求方法、请求资源位置和协议版本信息。
  • 头部(Headers): 可能多行,以读到一个空行(一行内容为"\r\n")为结束标识。
  • 实体正文(Body):这里就是实际的请求参数信息或者传输数据,如果不传数据可以没有实体部分。

HTTP协议版本-Version

版本号字段虽然对一名虫师来说不常用,但是对于历史的变迁与未来的方向都可以在版本中映射出他们在江湖中的故事。

  • HTTP/0.9: 1991年,第一个版本,已过时。
  • HTTP/1.0: 1996年,第二个版本,替代0.9版本,仍在使用中,仅支持GETHEADPOST三种方法。
  • HTTP/1.1: 1997年,第三个版本,目前使用最为广泛,新增OPTIONSPUTDELETETRACECONNECT五种方法,默认支持长连接(keep-alive),支持分块传输编码。
  • HTTP/2.0: 2015年5月14日发布RFC7540文档,第四个版本,几乎所有的Web浏览器和主要的Web服务器都通过使用应用程序层协议协商(ALPN)扩展的传输层安全性(TLS)来支持,其中需要TLS 1.2或更高版本(强制性加密支持)。值得一提的是这个协议参考了Google的SPDY协议。增加了对头部基于霍夫曼编码压缩的支持,支持TCP连接的多路复用,极大的降低网络延迟和传输数据量。 维基百科 HTTP/2.0
  • HTTP/3.0: 2018年被提出,第五个版本,2019年9月Google的Chrome浏览器(79)稳定版本中可以启用。在HTTP/3中,将传输层的TCP协议改为使用基于UDP协议的QUIC(快速UDP网络连接)协议实现。而这种改动设计最初也来自Google维基百科 HTTP/3.0

虽然版本在提升,但是协议的格式并没有发生改变,改变的仅仅是压缩算法和传输协议。这对于我们来学习分析格式是没有任何影响的。

HTTP协议请求方法-Method

HTTP协议请求Web地址-URL

我们常说的网页地址,通常就是指URL地址,而URL地址格式其实是统一资源标识符URI的一种特定形式,例如 “http://www.example.com/index.html" 表示 访问主机"www.example.com"上的index.html文件。

看似简单的URL其实包含了一种标准格式URI的规范:

URI = scheme:[//authority]path[?query][#fragment]

authority = [userinfo@]host[:port]

uri

  • schema: 标识协议类型,例如 http/https/ftp/mailto/jdbc
  • authority : 认证访问信息,以”//“开头,包括主机地址host,可选端口,可选的用户信息userinfo(用户密码认证信息)
  • path : 访问资源路径,以”/“开始表示绝对路径,每层目录都使用”/“分割。
  • query: 查询条件参数设置,前面以”?“开头,每个条件参数格式为"key=value”,相邻参数以"&“符号分割开,例如”/get_proxy?check_count=100&type=http"
  • fragment: 分片ID, 以"#“开头,通常在web页面中用来同一页面的目录导航快速定位章节位置。

下面的示例都是URL地址:

http://www.example.com:8080/admin/login.html
http://www.example.com/query/?q=spider
ftp://ftpuser:ftppass@www.example.com:21

注: 以后了解了数据访问知识后,你会发现URI格式不仅仅用于访问Web页面(http),访问数据库(odbc,jdbc)、FTP(ftp)以及邮箱(mailto)都是可以使用的。

HTTP协议 的请求首部-Headers

HTTP协议请求报文示例

Wireshark是抓包、分析消息的利器,作为虫师必备,下图即一条访问http://localhost:5030/get/?check_count=100请求示例。

wireshark-http-response

在这条HTTP请求报文中,客户端向服务器发送了这些信息:

  • Method方法: GET
  • URL请求路径: /get/?check_count=100 ,实际请求需要结合Host字段为完整的URI地址。
  • HTTP版本信息HTTP/1.1
  • Host请求服务器主机(如果有端口会附带端口): localhost:5030
  • User-Agent客户端程序标识: curl/7.65.2,因为这是我使用curl命令发出的请求。
  • Accept接收媒体格式: */*支持服务端返回任意格式数据.

当这条请求发给服务器后,服务器就会知道 一个来自curl/7.65.2客户端请求/get/位置数据,请求参数为check_count=100,并且客户端支持接收任意格式的数据内容。


Response应答报文格式

学习应答报文协议格式后我们可以了解服务器给我们回答的报文数据格式以及包含了哪些字段信息,以及这些字段都表达了服务器的什么含义,这样我们对返回结果可以理解的更加透彻。方便我们在遇到问题时来分析原因。

Response 应答报文格式

应答返回状态码-Status Code

常见的状态码有:

  • 200-请求成功。
  • 302-服务请求临时重定向到新URL地址。
  • 404-请求地址无法找到或请求错误都会返回404.
  • 503-服务暂时不可用,可能服务器应答超时或者出了其他内部问题。

应答返回的头部信息-Headers

HTTP协议应答报文示例

这段消息是上面请求报文的应答报文,都是来自Wireshark抓包结果。

wireshark-http-response

从这条HTTP报文可以了解到:

  • HTTP协议版本(Response Version): HTTP/1.1
  • 状态码(Status Code): 200
  • 服务器软件(Server): gunicorn/19.9.0
  • 响应时间(Date): “Thu, 06 Aug 2020 12:01:58 GMT”
  • TCP链接状态(Connection): 关闭状态(不是长连接)
  • 返回的内容类型(Content-Type): “text/plain; charset=utf-8” 文本类型,并且使用utf-8编码规则
  • 返回的内容长度(Content-Length): 221字节
  • 文本内容(空行”\r\n"后面的内容): “{proxy:….}”

注意: 这里看到的一些信息是Wireshark软件的辅助解释信息,比如 Request in frame:74 这并不是此报文包含的信息,而是Wireshark根据TCP请求序号关联的一次消息交互结果,这个关联结果意思是此应答报文对应抓包文件中的第74帧的请求,双击后我们就可以跳到请求帧查看客户端发出的请求内容。如下图所示:

http_wireshark_stream

总结

看到这里,表明你已经了解了HTTP协议的两种报文格式。

可以自我练习一下,使用Wireshark工具监听本机的浏览器访问某个网站过程中的交互过程。

你会发现,HTTP协议网站交互内容一览无余,而使用HTTPS协议的网站交互内容是无法查看,这就是加密的作用。

HTTPS协议-安全的HTTP协议

HTTP基础上加了TLS传输安全层,这个层通过浏览器和服务器的协商掌握一个只有两人知道的对称加密秘钥key,使用key对明文的HTTP内容加密传输。

对于秘钥协商的过程简单来说就是:

  1. 服务端先发送公钥给浏览器
  2. 浏览器使用公钥加密自己的key,并传回服务端
  3. 服务端使用私钥解密,获得浏览器的key
  4. 二者开心的使用key加密数据实现安全交互。

这里服务端的公钥私钥是一对非对称加密类型秘钥,谁都可以知道公钥并使用它加密数据,但是私钥只有服务端自己保存。

使用公钥解密的数据只能被对应的私钥解密,而不能被公钥解密。这样就保证了网络数据的安全。

但是非对称加密方式加密长文本数据相对与对称加密算法较慢,这又是它的劣势,因此HTTPS同时使用了这两种算法。

  1. 使用非对称加密算法传递对称加密算法的秘钥。
  2. 使用共享后的对称加密算法秘钥进行数据加密、解密。

下面图片是Wireshark分析的一段HTTPS握手协商交换秘钥的过程:

wireshark-https-flow

具体过程就不细说了,接下来我们说一下如何使用Wireshark查看解密后的HTTPS协议的报文内容。

Wireshark抓包解析HTTPS消息方法

下面方法是记录对称加密算法中的两个随机数,生成对称加密算法的关键参数,知道了这两个参数就可以生成对称秘钥并解密HTTPS协议报文。

  1. 环境变量设置: export SSLKEYLOGFILE="~/.sslkeylogfile.txt"
  2. 命令行执行chrome或者其他浏览器都可以。随便访问一个HTTPS协议网站就会保存sslkey到文件中
  3. 使用SSLKEYLOGFILE变量指定文件到Wireshark中设置一下,设置方法为: 菜单栏Edit ==> Preferences ==> Protocols ==> TLS,找到(Pre)-Master-Secretlog filename中选择刚才设置的~/.sslkeylogfile.txt文件,点击确定。

此时再看看监听获取的HTTPS消息是不是已经被解密了呢?


~END~