聊聊 IP packet 的 TTL 与 tcp segment 的 MSL
近几年在排查解决应用系统在客户现场遇到的复杂问题时,越来越觉得除了扎实的LINUX操作系统知识,对TCP/IP网络知识的深入理解也是至关重要的。
有鉴于此,后续笔者会陆续分享一些网络基础知识和故障排查案例,有兴趣的可以深入交流下。
本文介绍下 IP packet 的 TTL 与TCP segment 的 MSL,两者都跟数据包在网络上的生存时间有关。
IP 数据报头部中有个 TTL 字段,TTL 是 time to live 的缩写,即生存时间,不过其单位不是秒或分钟等具体时间,而是代表一个 IP数据报可以经过的最大路由数,IP数据报每经过一个路由器,它的值就减1,当此值为0时该数据报就会被丢弃,同时发送ICMP报文通知源主机。TTL的初始值是由发送该数据报的源主机设置的,不同操作系统 TTL 的初始值可能不同,比如 Windows 的TTL的初始值是128,而Linux的TTL初始值大多是64。
有没有办法查看 TTL 呢?可以通过tcpdump或wireshark等抓包工具查看某个具体数据报的TTL:事实上有经验的同学,可以根据数据包的TTL,推测这批数据包的捕获点是客户端服务端还是中间端。(后续有机会再总结下)。
MSL 是 Maximum Segment Lifetime 的英文缩写,可译为“报文最大生存时间/最长报文段寿命”,它是任何 TCP segment在网络上存在的最长时间,超过这个时间该报文就会被丢弃,也就是说任何 TCP Segment在网络上的存活时间都不会超过MSL.
RFC793定义了MSL为2分钟,但这完全是从工程上来考虑,对于现在的网络,MSL=2 分钟可能太长了一些,因此不同的TCP实现可以根据具体情况配置使用更小的MSL。
那么如何查看MSL的值呢?在LINUX中事实上并没有直接配置 MSL而是配置了 tcp_fin_timeout,由于 tcp_fin_timeout=2MSL,所以我们可以查看tcp_fin_timeout并据此推断MSL:
### 查看 tcp_fin_timeout
sysctl net.ipv4.tcp_fin_timeout
cat /proc/sys/net/ipv4/tcp_keepalive_time
### 修改 tcp_fin_timeout
sysctl -w net.ipv4.tcp_fin_timeout=30
或编辑 /etc/sysctl.conf
如上图可见,LINUX中默认 net.ipv4.tcp_fin_timeout 的值是60s,所以MSL默认是30s.
事实上,通过命令 ss -no state time-wait 就能看到处于 time-wait状态的tcp连接,并能看到其剩余的超时时间:
所以概括起来,IP 的 TTL 与 TCP 的 MSL,两者都跟数据包在网络上的传输与生存时间有关,两者不能直接在数值上对比大小,但在效果上MSL要大于TTL。
下面我们来看几张TCP四次挥手释放连接的图示:
从上图可以看到,在TCP连接释放的过程中,从 TIME_WAIT状态到CLOSED 状态有一个超时设置,这个超时设置是2MSL(RFC793定义MSL为2分钟)。
那么为什么在 TIME_WAIT 后必须等待2MSL时间呢?主要原因有两点:
由于从 TIME_WAIT状态到 CLOSED 状态有一个2MSL的超时等待时间,该时间内如果有其它新建的连接尝试使用同样的端口,就会报端口不可用的错误,比如笔者在折腾 apache kyuubi时就遇到了如下错误:
为了深入了解网络知识并掌握网络故障的排查,笔者阅读了大量资料,一些比较推荐的资料如下:
微信扫一扫
关注该公众号