美文网首页
【tcp】为什么处于 TIME_WAIT 状态的 TCP 连接,

【tcp】为什么处于 TIME_WAIT 状态的 TCP 连接,

作者: Bogon | 来源:发表于2022-04-23 00:03 被阅读0次

    一、背景

    有人反馈,他抓到一个抓包图,客户端和服务端四次挥手后,客户端在 17 秒内又复用了与上一次连接相同的端口,向服务端发起了 SYN 报文, 并成功建立了连接。

    他觉得服务端应该还是处于 TIME_WAIT 状态(因为 Linux 操作系统中,2MSL 的时间是 60 秒,也就是 TIME_WAIT 状态的持续时间),为什么收到客户端的  SYN 报文后可以正常建立连接?

    抓包图手机端不好看,为了方便大家看,我画了一个图:

    二、问题分析排查

    为什么处于 TIME_WAIT 状态的 TCP 连接,收到相同四元组的 SYN 报文后,可以正常建立连接?

    之前写过一篇:处于 TIME_WAIT 状态的连接,收到相同四元组的 SYN 后会发生什么?

    当时文章给出的结论是:

    如果 SYN 报文的「序列号+时间戳」都是合法的话,就会重新建立连接;

    如果 SYN 报文的「序列号+时间戳」其中一个不合法的话,就会回 RST。

    这位读者也看了这篇文章的,他觉得他抓包图中客户端的 SYN 报文的序列号是不合法的,所以应该是回 RST 才对,但是现象却是是可以正常建立连接。

    我开始慌了,难道,我之前的文章写错了?难道处于 TIME_WAIT 状态的连接,只要收到 SYN 报文,不管合不合法,都会重新建立连接?

    如果报文是 SYN 包,时间戳+序列号都是合法的,那么就会允许在 TIME_WAIT 状态下重新建立连接。

    抓包图中的客户端是在 17 秒后重用端口发起 SYN 报文的,所以时间戳肯定相比于历史连接是递增的,所以时间戳是合法的。

    但是,抓包图中 SYN 报文的序列号是不合法的,所以根本就没有进入到 TIME_WAIT 状态重建连接的逻辑。

    经过上面的分析,如果服务端还是处于 TIME_WAIT 状态的话,那么收到不合法的 SYN 报文,肯定是回 RST 的,这一点不用怀疑。

    我开始考虑是不是因为服务端开启了某些 TCP 内核参数,导致 TIME_WAIT 状态的连接被快速回收了,从而使得客户端后面发起的 SYN 报文,可以正常建立连接。

    这里先跟大家说下,有哪些 TCP 内核参数会导致 TIME_WAIT 状态被快速回收:

    参数一:net.ipv4.tcp_tw_reuse,如果开启该选项的话,客户端(连接发起方) 在调用 connect() 函数时,内核会随机找一个 TIME_WAIT 状态超过 1 秒的连接给新的连接复用,所以该选项只适用于连接发起方。

    参数二:net.ipv4.tcp_tw_recycle,如果开启该选项的话,允许处于 TIME_WAIT 状态的连接被快速回收。

    从抓包图可以看出,服务端主动发起的 FIN 报文,所以是服务端处于 TIME_WAIT 状态,所以 tcp_tw_reuse 这个参数不会是导致 TIME_WAIT 状态被快速回收的原因,因为这个参数是用于连接发起方,也就是客户端处于 TIME_WAIT 状态,在发起连接的时候,可以复用 TIME_WAIT 状态。

    所以,排除参数一的可能性。

    我当时就怀疑是因为服务端开启了 tcp_tw_recycle 参数,导致服务端的 TIME_WAIT 状态被快速回收了,并没有经过完整的 2MSL (60秒)时长的 TIME_WAIT 状态。 所以, 我就让读者去确认下,服务端是否开启了 tcp_tw_recycle 参数。

    好家伙,经过读者的确认后,发现服务端真的开启了 tcp_tw_recycle 参数。

    那么抓包图的现象就可以很好解释了,就是因为服务端开启了 tcp_tw_recycle 这个参数,导致服务端的 TIME_WAIT 状态被快速回收了,可能经过不到几秒,服务端就进入到 CLOSED 状态了。然后,17 秒后客户端发起的相同四元组的 SYN 报文,就正常建立连接了,因为服务端并没有处于 TIME_WAIT 状态

    最后总结下,我的分析思路:

    通过抓包图的序列号信息,确认客户端发起的  SYN 报文的序列号是不合法的,所以如果服务端还是处于 TIME_WAIT 状态的话, 收到这个不合法的 SYN 报文,应该是回 RST 的,而抓包图的现象却是正常建立了连接。所以从这个分析中,我确认了服务端的 TIME_WAIT 状态可能是被快速回收了。

    然后,想到了 Linux 两个快速回收  TIME_WAIT 状态的参数 tcp_tw_reuse 和 tcp_tw_recycle,其中 tcp_tw_reuse 参数是用于连接放起方,而本次的案例 TIME_WAIT 状态是在服务端,而不是客户端,所以可以排除这个参数的可能性。

    于是,就让读者确认是否开启了 tcp_tw_recycle 参数,因为开启了这个参数后,不管是服务端还是客户端,处于 TIME_WAIT 状态的连接,都会被快速回收,然后 TCP 连接就会进入到 CLOSE 状态。

    最终,经过读者确认后,发现服务端确实开启 tcp_tw_recycle 参数。

    不过,tcp_tw_recycle 状态还是不建议大家开启的,因为在 NAT 的网络下是不安全的,在 Linux 4.12 版本后,直接取消了这一参数。

    虽然 TIME_WAIT 状态持续的时间是有一点长,显得很不友好,但是它被设计来就是用来避免发生乱七八糟的事情。

    《UNIX网络编程》一书中却说道:TIME_WAIT 是我们的朋友,它是有助于我们的,不要试图避免这个状态,而是应该弄清楚它

    三、参考

    为什么处于 TIME_WAIT 状态的 TCP 连接,收到相同四元组的 SYN 报文后,可以正常建立连接?

    https://mp.weixin.qq.com/s/ITWfYNLzzUGofrp9wNl2lg

    大量的TIME_WAIT 状态 TCP连接对业务有什么影响怎么处理?

    https://baijiahao.baidu.com/s?id=1685497690614598021&wfr=spider&for=pc

    在 TCP 正常挥手过程中,处于 TIME_WAIT 状态的连接,收到相同四元组的 SYN 后会发生什么?

    https://mp.weixin.qq.com/s/CDrMVLHRICIgOwik__ufKg

    如果 TIME_WAIT 状态持续时间过短或者没有,会有什么问题?

    https://mp.weixin.qq.com/s/AjPFIgmeWh-iSGfjQkv_bw

    TIME-WAIT Assassination Hazards in TCP

    https://datatracker.ietf.org/doc/html/rfc1337

    相关文章

      网友评论

          本文标题:【tcp】为什么处于 TIME_WAIT 状态的 TCP 连接,

          本文链接:https://www.haomeiwen.com/subject/rdjoertx.html