tcpdump 命令用法
-
需要获取
root
权限才可以使用该指令 -
先用
ifconfig
查看自己的网口有哪些
我的主要是ens33
-
eg:
tcpdump -i ens33 tcp and host 202.182.102.233 -nn
-i ens33
表示抓取ens33
网口的数据包icmp
表示抓取icmp
协议的数据包host
表示主机过滤,抓取对应IP的数据包-nn
表示不解析IP地址和端口号的名称输出格式为
时间戳 协议 源地址:源端口 > 目的地址.目的端口 网络包详细信息
-
-w ping.pcap
表示保存为名为ping.pcap
的文件
使用wireshark打开观察
可以看出wireshark采用分层形式展现包的情况,从这个例子也可以看出网络各层都是有着自己负责的范围。
上层协议完成相关工作就会交接给下一层,最终形成一个完整的数据包。- ICMP协议:ICMP头 + Data
- IP层:IP头 | ICMP头 + Data
- 数据链路层:以太帧头 | IP头 | ICMP头 + Data
wireshark 用法
Ubuntu下需要获取root
权限才能使用,用sudo wireshark
打开软件。
TCP 三次握手和四次挥手
实验前提 测试的是我blog部署的主机202.182.102.233
在本地Ubuntu下设置两个终端分别执行下面命令:
-
客户端执行tcpdump抓包
tcpdump -i any tcp and host 202.182.102.233 and port 80 -w http.pcap
-
客户端执行curl
curl http://202.182.102.233
最开始三个包是TCP三次握手建立连接的包
中间是HTTP请求和响应的包
最后的四个包是TCP断开连接的挥手包
wireshark 点击Statistics(统计)
,选择Flow Graph(流量图)
,在下方的流量类型选择TCP Flows
,得到下图。
这里的seq
是相对值,不是绝对值。
右键菜单,选择Protocol Preferences
,取消勾选Relative sequence numbers
,再次重复上面步骤得下图。
实验
TCP第一次握手SYN丢包
先断开自己的VPN
一个终端使用tcpdump
抓包
一个终端尝试与YouTube网站建立连接
抓包结果 SYN包重传了4次,其实应该重传6次,我的Ubuntu里内核超时重传参数值为6。
$ cat /proc/sys/net/ipv4/tcp_syn_retries
6
现在将其值设为2
$ echo 2 > /proc/sys/net/ipv4/tcp_syn_retries
2
重新做上面抓包步骤,得下图结果。
实验结论:当客户端发起连接,第一次握手SYN包在超时时间RTO内没收到服务端的ACK回应,就会再一次重传,每次超时重传的RTO是翻倍上涨的,直到传SYN包的次数到了系统的tcp_syn_retries
值后,客户端就会停止发送请求连接SYN包。
TCP 第二次握手 SYN、ACK 丢包
实验失败,虚拟机问题,无语,太折腾,详情阅读学习指导
客户端 SYN 包超时重传的最大次数,是由 tcp_syn_retries
决定的,默认值是 6 次;服务端 SYN、ACK 包时重传的最大次数,是由 tcp_synack_retries
决定的,默认值是 5 次。--------这里的次数建议查看自己Linux系统的情况 ,貌似每个系统之间设置的参数数值不相同。
TCP 第三次握手 ACK 丢包
TCP 建立连接后的数据包传输,最大超时重传次数是由 tcp_retries2
指定,默认值是 15 次
$ cat /proc/sys/net/ipv4/tcp_retries2
15
TCP保活机制
这个机制定义一个时间段,这个时间段内,如果没有任何连接相关的活动,TCP保活机制就会开始起作用,每隔一个时间间隔,发送一个探测报文
,这个报文所包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的TCP连接已经死亡,系统内核将错误信息通知给上层应用程序。
Linux内核有对象参数设置保活时间,保活探测的次数,保活探测的时间间隔
net.ipv4.tcp_keepalive_time=7200
# 表示保活时间是 7200 秒(2小时),也就 2 小时内如果没有任何连接相关的活动,则会启动保活机制
net.ipv4.tcp_keepalive_intvl=75
# 表示每次检测间隔 75 秒
net.ipv4.tcp_keepalive_probes=9
# 表示检测 9 次无响应,认为对方是不可达的,从而中断本次的连接。
即在Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。
tcp_keepalive_time + (tcp_keepalive_intvl * tcp_keepalive_probes)
7200 + (75 * 9) = 7895 秒 (2小时11分15秒)
抓包时间足够长,说不定能抓到探测报文
在建立 TCP 连接时,如果第三次握手的 ACK,服务端无法收到,则服务端就会短暂处于 SYN_RECV
状态,而客户端会处于 ESTABLISHED
状态。
由于服务端一直收不到 TCP 第三次握手的 ACK,则会一直重传 SYN、ACK 包,直到重传次数超过 tcp_synack_retries
值(默认值 5 次)后,服务端就会断开 TCP 连接。
而客户端则会有两种情况:
- 如果客户端没发送数据包,一直处于
ESTABLISHED
状态,然后经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接,于是客户端连接就会断开连接。 - 如果客户端发送了数据包,一直没有收到服务端对该数据包的确认报文,则会一直重传该数据包,直到重传次数超过
tcp_retries2
值(默认值 15 次)后,客户端就会断开 TCP 连接。
TCP快速建立连接
Linux下修改net.ipv4.tcp_fastopen
内核参数开启Fast open
功能
让服务端能够在第一次与客户端连接后,产生一个Cookie
值通过SYN,ACK包一起发送给客户端,客户端缓存这个Cookie
,在第二次请求时,能够这个值随SYN请求包一同发给服务端,服务端就可以跳过三次握手的过程,这个整个时延为一个RTT。
$ sysctl -w net.ipv4.tcp_fastopen=3
- 0 关闭
- 1 作为客户端使用 Fast Open 功能
- 2 作为服务端使用 Fast Open 功能
- 3 无论作为客户端还是服务器,都可以使用 Fast Open 功能