1 前言 - 网络知识的重要性
近几年在排查解决应用系统在客户现场遇到的复杂问题时,越来越觉得除了扎实的LINUX操作系统知识,对TCP/IP网络知识的深入理解也是至关重要的。
有鉴于此,后续笔者会陆续分享一些网络基础知识和故障排查案例,有兴趣的可以深入交流下。
本文介绍下 IP packet 的 TTL 与TCP segment 的 MSL,两者都跟数据包在网络上的生存时间有关。
2 IP packet 的 TTL
IP 数据报头部中有个 TTL 字段,TTL 是 time to live 的缩写,即生存时间,不过其单位不是秒或分钟等具体时间,而是代表一个 IP数据报可以经过的最大路由数,IP数据报每经过一个路由器,它的值就减1,当此值为0时该数据报就会被丢弃,同时发送ICMP报文通知源主机。 TTL的初始值是由发送该数据报的源主机设置的,不同操作系统 TTL 的初始值可能不同,比如 Windows 的TTL的初始值是128,而Linux的TTL初始值大多是64。
有没有办法查看 TTL 呢?可以通过tcpdump或wireshark等抓包工具查看某个具体数据报的TTL:
事实上有经验的同学,可以根据数据包的TTL,推测这批数据包的捕获点是客户端服务端还是中间端。(后续有机会再总结下)。
3 TCP segment 的 MSL
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。
4 TCP 四次挥手的状态转移与 MSL
下面我们来看几张TCP四次挥手释放连接的图示:
从上图可以看到,在TCP连接释放的过程中,从 TIME_WAIT状态到CLOSED 状态有一个超时设置,这个超时设置是2MSL(RFC793定义MSL为2分钟)。
那么为什么在 TIME_WAIT 后必须等待2MSL时间呢?主要原因有两点:
- 为了保证客户端(我们记为A端)发送的最后一个ACK报文段能够到达服务器端:这个ACK报文段在网络传输过程中有可能丢失,从而使处在LASK—ACK状态的服务端(我们记为B端)收不到对已发送的FIN报文段的回包,此时B会超时重传这个FIN报文段,而A就能在2MSL时间内收到这个重传的FIN报文段,接着A重传一次确认,重新启动2MSL计时器。最后,A和B都正常进入到CLOSED状态。如果A在TIME_WAIT状态不等待一段时间,而是在发送完ACK确认后立即释放连接,那么就无法收到B重传的FIN报文段,因而也不会再发送一次确认报文段,这样,B就无法正常进入CLOSED状态。
- 假如A发送的第一个请求连接报文段丢失而未收到确认,A就会重传一次连接请求,后来B收到了确认,建立了连接,数据传输完毕后,就释放了连接。这种情况下A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。假如现在A发送的第一个连接请求报文段没有丢失,而是在某些网络节点长时间滞留了,以至于延误到连接释放后的某个时间才到达B,这本来是已失效的报文段,但B并不知道,就会又建立一次连接。而等待的这2MSL就是为了解决这个问题的,A在发送完最后一个确认报后再经过时间2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
由于从 TIME_WAIT状态到 CLOSED 状态有一个2MSL的超时等待时间,该时间内如果有其它新建的连接尝试使用同样的端口,就会报端口不可用的错误,比如笔者在折腾 apache kyuubi时就遇到了如下错误:
5 网络相关资料推荐
为了深入了解网络知识并掌握网络故障的排查,笔者阅读了大量资料,一些比较推荐的资料如下:
- 《TCP_IP 详解卷1:协议》,经典无需多言,笔者收藏了英文第二版的原版,时不时翻出来阅读下;
- 《TCP_IP 详解卷2:实现》,经典无需多言,推荐英文原版;
- 《图解TCP IP(第5版)》,(日)竹下隆史老师所著,也很不错;
- 《Wireshark网络分析的艺术》,林沛满老师的书籍,以现实故障案例讲知识,诙谐易懂;
- 《Wireshark网络分析就这么简单》,林沛满老师的书籍,以现实故障案例讲知识,诙谐易懂;
- 《Network Analysis using Wireshark2 CookBook》,讲解网鲨工具的使用,推荐;
- 历年 SharkFest 的精彩分享,可以在油管上看,笔者重点看了近三年的视频。