Wireshark & Packetdrill | TCP 基础之三次握手

admin 2024年4月24日07:53:33评论8 views字数 5766阅读19分13秒阅读模式

对某个问题是否乐于去解决,取决于该问题是否单调乏味。

前言

Packetdrill ,初识的时候简直了,奉为神器,但受限于懒癌,一直也没怎么好好研究。现在趁着一波热情上来,赶紧结合 Wireshark 好好做下内核协议栈的相关实验,加深理解数据包分析。

Packetdrill 相关的资料并不是很多,所以测试当中也是带着很多疑问,限于能力,有些结论也并不一定准确,纯瞎研究性质。 

实验目的

通过 packetdrill 测试 TCP 基础之三次握手。

实验脚本

# cat tcp_3hs_000.pkt // TCP 基础之三次握手0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0+0  bind(3, ..., ...) = 0+0  listen(3, 1) = 0+0  < S 0:0(0) win 10000 <mss 1460>+0  > S. 0:0(0) ack 1 <...>+0.01 < . 1:1(0) ack 1 win 10000+0 accept(3, ..., ...) = 4

脚本说明

0  socket(..., SOCK_STREAM, IPPROTO_TCP) = 3// 0 是 创建 socket 的绝对时间。// 创建 socket ,socket(int domain, int type, int protocol)// domain,默认值... ,即 AF_INET 。// type,SOCK_STREAM ,指定这个套接字为面向连接的流式套接字(TCP)。// protocol,IPPROTO_TCP,指定TCP协议。// 3,因为 stdin(0),stdout(1),stderr(2) 默认被定义,内核将会给此 socket 指定文件描述符 FD 为 3。+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0// +0 本行代码执行时间相对于上一行代码的偏移时间。// setsockopt() 设置套接字选项的系统调用。// 3,设置的套接字描述符。// SOL_SOCKET,表示要设置的选项位于socket层面。// SO_REUSEADDR,要设置的选项,表示重用本地地址,譬如快速重启服务程序。// [1],表示选项值,1表示启用。// 4,表示选项值的长度,4字节。// 0,设置成功返回0。+0  bind(3, ..., ...) = 0// +0 本行代码执行时间相对于上一行代码的偏移时间。// bind(),用来绑定套接字到本地地址的系统调用。// 3,绑定的套接字描述符。// ... ,省略的bind()的参数,包含绑定的本地IP地址和端口。// 0,设置成功返回0。+0  listen(3, 1) = 0// +0 本行代码执行时间相对于上一行代码的偏移时间。// listen(),用于启动对指定套接字的监听的系统调用。// 3,监听的套接字描述符。// 1,backlog参数,指定排队的全连接队列最大数(最多允许1个待处理的全连接)。
+0  < S 0:0(0) win 10000 <mss 1460>// +0 本行代码执行时间相对于上一行代码的偏移时间。// < ,表示输入或注入的数据包。// S ,表示是 SYN 数据包。// 0:0(0) ,表示开始序号:结束序号(数据包长度)。// win 10000,表示接收窗口10000字节。// <> 表示 TCP options,mss 1460,表示设置mss 1460字节大小。+0  > S. 0:0(0) ack 1 <...>// +0 本行代码执行时间相对于上一行代码的偏移时间。// > ,表示预期协议栈会响应的数据包。 // S. ,表示是 SYN/ACK 数据包。// 0:0(0) ,表示开始序号0:结束序号0(数据包长度0)。// ack 1,表示确认号1,确认了客户端的SYN(seq + 1),因为SYN占1个字节。// <> 表示 TCP options,... 表示默认值。+0.01 < . 1:1(0) ack 1 win 10000// +.1 本行代码执行时间相对于上一行代码的偏移时间,0.01s = 10ms。// < ,表示输入或注入的数据包。// . ,表示是 ACK 数据包。// 1:1(0) ,表示开始序号1:结束序号1(数据包长度0),因为SYN占1个字节。// ack 1 ,表示确认号1,确认了服务端的SYN(seq + 1),因为SYN占1个字节。// win 10000,表示接收窗口10000字节。+0 accept(3, ..., ...) = 4// +0 本行代码执行时间相对于上一行代码的偏移时间。// accept(),表示用来接收连接的系统调用。// 3,监听的套接字描述符。// ... ,省略的两个参数,分别为接收客户端地址和地址长度。// 4,返回新连接的套接字描述符4。   

实验测试

1.执行脚本# packetdrill tcp_3hs_000.pkt # 执行完成后退出。2.捕获数据包# tcpdump -i any -nn port 8080tcpdump: data link type LINUX_SLL2tcpdump: verbose output suppressed, use -v[v]... for full protocol decodelistening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes22:57:46.180400 ?     In  IP 192.0.2.1.37353 > 192.168.19.227.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 022:57:46.180424 ?     Out IP 192.168.19.227.8080 > 192.0.2.1.37353: Flags [S.], seq 4169589518, ack 1, win 65535, options [mss 1460], length 022:57:46.190540 ?     In  IP 192.0.2.1.37353 > 192.168.19.227.8080: Flags [.], ack 1, win 10000, length 022:57:46.190624 ?     Out IP 192.168.19.227.8080 > 192.0.2.1.37353: Flags [F.], seq 1, ack 1, win 65535, length 022:57:46.190635 ?     In  IP 192.0.2.1.37353 > 192.168.19.227.8080: Flags [R.], seq 1, ack 1, win 10000, length 0^C5 packets captured7 packets received by filter0 packets dropped by kernel# 

数据包说明

1. TCP三次握手 - SYN22:57:46.180400 ?     In  IP 192.0.2.1.37353 > 192.168.19.227.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0// 对应于脚本 +0  < S 0:0(0) win 10000 <mss 1460> ,因为 < 表示输入数据包,所以 packetdrill 根据此行脚本各字段值构造的 SYN 数据包,注入到内核协议栈。2. TCP三次握手 - SYN/ACK22:57:46.180424 ?     Out IP 192.168.19.227.8080 > 192.0.2.1.37353: Flags [S.], seq 4169589518, ack 1, win 65535, options [mss 1460], length 0// 对应于脚本 +0  > S. 0:0(0) ack 1 <...> ,因为 > 表示预期内核协议栈会响应的数据包,所以如果内核协议栈响应的实际数据包与脚本所预期的数据包一致,则脚本正常执行,如果不一致,则脚本会报错停止运行,并指出相关错误。3. TCP三次握手 - ACK22:57:46.190540 ?     In  IP 192.0.2.1.37353 > 192.168.19.227.8080: Flags [.], ack 1, win 10000, length 0// 对应于脚本 +0.01 < . 1:1(0) ack 1 win 10000,与上一行间隔10ms后 < 输入数据包,所以 packetdrill 根据此行脚本各字段值构造的 ACK 数据包,注入到内核协议栈。4. FIN/ACK 和 RST/ACK22:57:46.190624 ?     Out IP 192.168.19.227.8080 > 192.0.2.1.37353: Flags [F.], seq 1, ack 1, win 65535, length 022:57:46.190635 ?     In  IP 192.0.2.1.37353 > 192.168.19.227.8080: Flags [R.], seq 1, ack 1, win 10000, length 0// packetdrill 脚本之外产生的数据包,或者说预期之外的数据包。// 因为未具体研究 packetdrill 代码,仅根据个人判断,在 packetdrill 脚本执行完毕后,socket 被强行关闭,如果有accept()的情况下,内核会发送 FIN/ACK 结束连接,没有accept()的情况下,则不会发送 FIN/ACK.// 而最后一个客户端所发送的 RST/ACK 结束连接,也像是 packetdrill 脚本默认构造,用于快速重置连接使用的。// 因此这两个数据包一般与 packetdrill 构建的测试脚本无关,分析时可省略。

扩展测试

# cat tcp_3hs_001.pkt ...+0 `sleep 1000000`脚本最后增加 sleep 语句,使得脚本执行完不要退出。测试结果# packetdrill tcp_3hs_001.pkt 脚本执行完后未退出,可见光标闪烁。# ss -anto | grep 8080LISTEN 0      1      192.168.68.247:8080          0.0.0.0:*                       ESTAB  0      0      192.168.68.247:8080        192.0.2.1:44569                   # 通过 ss 查询 TCP 连接建立状态。# ip a396: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 500    link/none     inet 192.168.68.247/16 scope global tun0       valid_lft forever preferred_lft forever    inet6 fe80::b034:651:cd73:73f2/64 scope link stable-privacy        valid_lft forever preferred_lft forever# ip a 查询可见多了一个虚拟的网卡tun0,这也是packetdrill实现的基本原理,可自行查询相关介绍文章。抓包结果# tcpdump -i any -nn port 8080tcpdump: data link type LINUX_SLL2tcpdump: verbose output suppressed, use -v[v]... for full protocol decodelistening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes22:05:59.240395 tun0  In  IP 192.0.2.1.44569 > 192.168.68.247.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 022:05:59.240416 tun0  Out IP 192.168.68.247.8080 > 192.0.2.1.44569: Flags [S.], seq 1898366152, ack 1, win 65535, options [mss 1460], length 022:05:59.250513 tun0  In  IP 192.0.2.1.44569 > 192.168.68.247.8080: Flags [.], ack 1, win 10000, length 0
Sleep 有无的情况下,数据包方面稍微的区别:在无 sleep 语句的情况下,脚本执行完成后就正常退出,通过抓包结果,除了 TCP 三次握手数据包,最后会默认出现服务器发的一个 FIN/ACK 和客户端发的一个 RST/ACK 。在有 sleep 语句的情况下,脚本执行完成后并不退出,因此抓包结果仅有 TCP 三次握手数据包。而在有 sleep 语句的脚本执行后,通过 CTRL+C 可终止脚本运行,如下:# packetdrill tcp_3hs_001.pkt ^Ctcp_3hs_001.pkt:12: error executing `sleep 1000000` command: got signal 2 (Interrupt)# 此时 ip a 查询,已无 tun0 网卡,通过 ss 查询 TCP 连接状态已经变成 FIN-WAIT-1。# ss -anto | grep 8080FIN-WAIT-1 0      1      192.168.68.247:8080        192.0.2.1:44569 timer:(on,540ms,7)       # 抓包结果如下,仅出现一个服务器发送的 FIN 数据包,与上面的 TCP 连接 FIN-WAIT-1 对应。22:27:27.263963 ?     Out IP 192.168.68.247.8080 > 192.0.2.1.44569: Flags [F.], seq 1, ack 1, win 65535, length 0
Wireshark & Packetdrill | TCP 基础之三次握手

往期推荐

1. Wireshark 提示和技巧 | 捕获点之 TCP 三次握手
2. Wireshark 提示和技巧 | a == ${a} 显示过滤宏
3. Wireshark TS | 防火墙空闲会话超时问题
4. Wireshark TS | HTTP 传输文件慢问题
5. 网络设备 MTU MSS Jumboframe 全解

后台回复「TT」获取 Wireshark 提示和技巧系列 合集
后台回复「TS」获取 Wireshark Troubleshooting 系列 合集
如需交流,可后台直接留言,我会在第一时间回复,谢谢!
Wireshark & Packetdrill | TCP 基础之三次握手

原文始发于微信公众号(Echo Reply):Wireshark & Packetdrill | TCP 基础之三次握手

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月24日07:53:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Wireshark & Packetdrill | TCP 基础之三次握手https://cn-sec.com/archives/2081693.html

发表评论

匿名网友 填写信息