一、网络抓包工具
本文使用Wireshark抓取网络报文
二、协议数据单元分析
1. 以太帧结构
- 第1-6字节(a4 b1 c1 98 fa e4)
目的MAC地址 - 第7-12字节(00 00 5e 00 01 65)
源MAC地址 - 第13-14字节(08 00)
类型,这里是IPv4 - 最后6字节(00 00 00 00 00 00)
padding
以太帧基于CSMA/CD技术(载波监听多点接入/碰撞检测),并且IEEE规定了这个碰撞域最小直径为64字节。所以在网路中传输时,以太网帧字节数小于64帧,将由padding段填充。抓包中看到接收包为60字节,是因为抓取时以太网帧已经被网卡填充到了64字节,而Wireshark抓包不显示最后4字节的校验字段FCS,因此最终显示60字节。
如果是发送包,由于抓包是在发送前,网卡还未填充padding,因此没有padding。
2. IPv4数据结构
- 第1字节(45)
包含版本和首部长度。化为二进制为0100 0101,其中0100为IP版本号,这里为4;0101为首部长度,需要乘以5得到20,为20字节 - 第2字节(00)
服务类型 - 第3-4字节(00 28)
IP头与数据包中数据的长度,这里是40字节 - 第5-6字节(73 45)
标识符,识别一个数据包或被分片数据包的次序,一个唯一的标识数字 - 第7-8字节(40 00)
三位标志和13位偏移量。对应二进制为010 000000000,其中010分别表示无保留位(Reserved bit: Not set)、IP不分片(Don’t fragment: Set)、其余分段没有设置(More fragments: Not set)
000000000为偏移量,该数据包是个分片,数据包按分片偏移值顺序重组 - 第9字节(40)
生存时间TTL,这里是64,每经过一个路由器,TTL减1,为0时数据包被丢弃 - 第10字节(06)
协议号,这里表示报文采用TCP数据协议 - 第11-12字节(00 00)
首部校验和,确认IP头的内容没有被损坏或者篡改。此处为无法确认,这是因为Wireshark总是常常抓取正在运行自己的PC的网络帧,通常的结果是校验和溢出帧不正确,因为它们被Wireshark记录后又被网卡仅仅对传播计算。为避免频繁的提示校验值出错,默认验证禁止。 - 第13-16字节(0a cb e8 bb)
源IP地址,这里是10.203.232.187 - 第17-20字节(d4 40 3f d7)
目标IP地址,这里是212.64.63.215 - 之后
传递的实际数据,这里是TCP报文
3. IPv6数据结构
- 第1-4字节(60 02 87 2f)
化为二进制为0110 00000000 00101000011100101111
1-4bit:版本号,值为6对应IPv6
5-12bit:流类别,等同于IPv4的服务类型
13-32bit:流标签,IPv6中的新增字段,用于区分实时流量,不同的流标签+源地址可以唯一确定一条数据流,中间网络设备可以根据这些信息更加高效率的区分数据流。 - 第5-6字节(00 14)
有效载荷长度,这里为20字节 - 第7字节(06)
下一报头。定义紧跟在IPv6报头后面的第一个扩展报头(如果存在)的类型,或者上层协议数据单元中的协议类型。这里指TCP - 第8字节(80)
跳数限制,类似IPv4中TTL - 第9-24字节(20 01 0d a8 10 02 60 04 00 00 00 00 00 01 dc 2b)
源地址:2001:da8:1002:6004::1:dc2b - 第25-40字节(24 0e 00 f7 4f 01 00 02 00 03 00 00 00 00 03 f0)
目标地址240e:f7:4f01:2:3::3f0 - 之后
这里没有扩展报头,之后是传递的实际数据,这里是TCP报文
三、协议功能分析
1. ICMP协议的回送请求和回答分析
- 请求报文
- 第1字节(08)
类型:占一个字节:用来表示ICMP的消息类型。这里为8,表示回送请求 - 第2字节(00)
代码:占一个字节:用来对类型的进一步说明。类型8,代码0,表示Echo request——回显请求(Ping请求) - 第3-4字节(4d 5a)
校验和,判断数据是否有误 - 第5-8字节(00 01 00 01)
前两字节为标识符,后两字节为序列号。在接收回答时根据标识符和序列号找到发送请求的进程。Windows和Linux生成标识符和序列号的方式不同,windows为LE:little-endian byte order,Linux为BE:big-endian,因此Wireshark同时显示了这两种解读方式 - 第9-42字节
ICMP报文数据,此次请求发送的数据
- 回答报文
- 第1字节(00)
类型:占一个字节:用来表示ICMP的消息类型。这里为0,表示应答 - 第2字节(00)
代码:占一个字节:用来对类型的进一步说明。类型0,代码0,表示Echo Reply——回显应答(Ping应答) - 第3-4字节(55 5a)
校验和,判断数据是否有误 - 第5-8字节(00 01 00 01)
前两字节为标识符,后两字节为序列号。在接收回答时根据标识符和序列号找到发送请求的进程。Windows和Linux生成标识符和序列号的方式不同,windows为LE:little-endian byte order,Linux为BE:big-endian,因此Wireshark同时显示了这两种解读方式 - 第9-42字节
ICMP报文数据,此次接收的数据,用于和之前发送的数据比对
2. TCP的三次握手过程分析
- 第一次握手
客户端向服务器发送连接请求包,标志位SYN(同步序号)置为1,序号为X=0
- 第二次握手
服务器收到客户端发过来报文,由SYN=1知道客户端要求建立联机。向客户端发送一个SYN和ACK都置为1的TCP报文,设置初始序号Y=0,将确认序号(Acknowledgement Number)设置为客户的序列号加1,即X+1 = 0+1=1
- 第三次握手
客户端收到服务器发来的包后检查确认序号(Acknowledgement Number)是否正确,即第一次发送的序号加1(X+1=1)。以及标志位ACK是否为1。若正确,客户端再次发送确认包,ACK标志位为1,SYN标志位为0。确认序号(Acknowledgement Number)=Y+1=0+1=1,发送序号为X+1=1。服务器收到后确认序号值与ACK=1则连接建立成功,可以传送数据了。
3. ARP机制分析
- 询问
- 以太帧内容
目标地址为ff:ff:ff:ff:ff:ff,即广播;源地址为本电脑;类型为ARP。即广播本电脑发出的ARP询问请求 - ARP内容
Opcode为1,即询问;目标IP为10.203.200.74;由于此时目标MAC地址未知,所以为全0
- 应答
- 以太帧内容
目标地址为本机;源地址为00:00:5e:00:01:65,即目标IP所在设备的MAC;类型为ARP。即目标设备应答ARP询问 - ARP内容
Opcode为2,即应答;并且获取了发送方IP与MAC,据此新增IP地址与MAC地址的映射关系
四、协议机制分析
这里分析浏览器的常用协议,包括DNS、HTTP、WebSocket、TLS(以HTTPS为例),网址来源于马萨诸塞大学Wireshark labs
1. DNS
浏览器第一次访问网页, 使用Wireshark得到如下两个数据包
这两条数据均通过UDP协议传输,我们首先分析UDP,再分析DNS
- DNS请求
- 第1-2字节(30 25)
事务ID,DNS服务器应答时会带上相同的事务ID,通过它可以区分 DNS 应答报文是对哪个请求进行响应的 - 第3-4字节(01 00)
标志字段,携带本次请求的相关信息,这里表示标准查询 - 第5-6字节(00 01)
问题计数, DNS 查询请求的数目,这里表示有1个问题 - 第7-8字段(00 00)
回答资源记录数,DNS 响应的数目,这里为0 - 第9-10字段(00 00)
权威名称服务器计数,权威名称服务器的数目。 - 第11-12字段(00 00)
附加资源记录数,额外的记录数目(权威名称服务器对应 IP 地址的数目)。 - 之后
查询问题区域,显示 DNS 查询请求的问题,包含:
查询名。一般为要查询的域名,有时也会是 IP 地址,用于反向查询
查询类型。DNS 查询请求的资源类型。通常查询类型为 A 类型,表示由域名获取对应的 IP 地址
查询类。地址类型,通常为互联网地址,值为 1
- DNS应答
与DNS请求基本相同,不同之处在于:
- 标志字段(81 80)
这里表示标准应答且没有错误 - 资源记录部分
可能包含回答问题区域字段、权威名称服务器区域字段、附加信息区域字段。这里只有回答问题区域字段。包括:
域名字段。这里为 gaia.cs.umass.edu
类型字段。这里为A类型,即域名对应IP
类字段。这里为互联网地址
生存时间
数据长度
资源数据。这里为IP地址,获取了域名的对应IP
2. HTTP
打开网页,使用Wireshark得到以下两条数据,分别代表请求和响应
- HTTP请求
HTTP数据以文本形式传输,由状态行、请求头部、空行、响应包体4个部分组成,格式较为自由。本次报文包括以下信息
- 请求方式:GET
- 请求uri:统一资源标识符,表示资源的相对路径
- 请求版本:这里是HTTP 1.1协议
- 域名:这里是gaia.cs.umass.edu
- 连接状态:keep-alive,可以使TCP连接复用,避免建立过多的TCP连接
- 缓存机制:表示缓存时间,在缓存时间内再次获取时不会发起请求,而是使用本地缓存。max-age=0表示任何时候都会去服务器重新获取数据
- 此外还有其它一些字段,携带本次请求相关信息,后端根据这些信息,判断是否拒绝请求、返回什么数据等
- 本次请求是简单GET请求,未携带query,因此响应包体为空
- HTTP响应
与请求的数据结构类似,不过没有请求头,取而代之的是服务器返回的响应头,包含响应的相关信息,浏览器根据响应头的信息执行相关操作
注意到响应包体依然为空,这是因为响应状态码为304 Not Modified。注意之前发送请求时,请求头中有If-Modified-Since和If-None-Match字段,后端根据这两个字段判断,发现客户端缓存资源已经是最新的了(因为我之前访问过该网址,浏览器中有缓存),因此返回304 Not Modified告诉客户端可以直接使用缓存的数据,因而本次响应的响应包体为空。浏览器根据此次响应数据直接调取缓存展示
- 补充
3. WebSocket (WS)
http具有无连接性,数据传输完成后立刻断开连接。但某些情景下需要前后端时刻通信,例如在线聊天室,此时就需要利用ws协议,使用这个网站,用于构建ws连接,Wireshark抓包结构如下
其中前三条数据是TCP的三次握手,这里不再分析
第四条条记录是websocket的开始,即握手请求
请求详情中有如下的Header
- Connection: Upgrade 连接升级
- Upgrade: websocket 升级的协议
- Sec-WebSocket-Version:13 websocket的版本
- Sec-WebSocket-Key: vKABUOhStlkywDf7HOg/Hg== 一个随机值用来验证服务器是否支持websocket
- Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits 开启压缩;第二个参数是服务器支持的最大客户端窗口
如果一个服务器支持websocket,当服务器接受到了上面的请求,就会利用Sec-WebSocket-Key加上一个固定值并生产一个 Sec-WebSocket-Accept,并以http 响应的形式发送给客户端,也就是第五条记录。
之后可以通过ws协议进行交互
其中数据可以采用自定义协议,也可以用文本形式
4. TLS
访问网站,发现浏览器显示协议为https,说明数据使用了TLS协议加密。 TLS协议在传输层上封装了应用层的数据,因此可以在不需要修改应用层协议的前提下给不安全的应用层协议提供一定的安全保障。例如HTTP数据以明文形式在网路中传输,有可能被截取破译,而HTTPS协议的数据以加密形式传输,更加安全。类似的TLS还可用于WS协议,也就是WSS协议。
下面一步步分析TLS建立过程
- Client Hello
- Random Bytes:客户端产生的28字节随机数,用于生成最终密钥,后面的过程还会传递两个随机数,三个随机数做为EC Diffie-Hellman算法的相关参数,运算出会话密钥。先把这个随机数称为random_c.
- Session ID:会话标识符:如果是一个新的连接,这个值为0
- Cipher Suites:加密套件(客户端共支持17个加密套件),服务器会从中选择一个服务器也支持的加密套件
- Compression Methods:客户端支持的压缩方法
- Extension: ALPN:客户端支持的应用层协议
- Extension: signature_algorithms: 客户端支持的签名算法
- Server Hello
- Random Bytes:服务器生成的随机数random_s
- Cipher Suites:服务器选择的加密套件:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- Compression Methods:服务器选择的压缩算法为NULL压缩算法。(不支持任何压缩算法),压缩基本由应用层来完成。
- Certificate, Certificate Status, Server Key Exchange, Server Hello Done
Certificate: 服务器返回了三个证书: 第一个是CA签发的证书,对应http://www.cics.umass.edu,之后是CA链的证书。
客户端收到这个证书后,可以根据证书链来验证证书的真伪,进而判断服务器是真是假。 服务器证书中存放一个公钥,用于加密后面生成的Premaster secret
EC Diffie-Hellman: 服务器和浏览器是通过Diffie-Hellman算法来生成最终的密钥
Pubkey: 服务器向客户端发送了Pubkey这个随机数。
此时客户端已经拥有了三个随机数(自身生成的random_c, 服务器发送的random_s以及此处的pubkey),有了这三个参数,就可以运行Diffie-Hellman算法生成Premaster secret(最终的会话密钥)
最后告知客户端服务器这边握手相关的消息发送完毕。
- Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
Pubkey: 浏览器收到服务器发来的Certificate包来之后,运行Diffie-Hellman算法生成一个pubkey,然后发送给服务器。
通过这一步和上面Certificate两个步骤,服务器和浏览器分别交换了pubkey,这样他们就可以分别生成了一个一样的sessionkey。
变更密码规范协议,它非常简单,就是一条通知消息,告知对方以后的通信都是加密的
客户端使用生成的对话密钥,加密之前所有收发握手消息的Hash和MAC值,发送给服务器,服务器将相同的会话密钥(使用相同方法生成)解密此消息,校验其中的Hash和MAC值。
之后的http请求都是采用加密方式,也就是https;对于其它TLS加密的协议,如wss,流程也大致相同