如果你的程序写得有毛病,打开了很多TCP连接,但一直没有关闭,即常见的连接泄露场景,你可能想要在排查问题的过程中,先临时kill一波泄露的连接。 又比如你要验证程序在遇到网
如果你的程序写得有毛病,打开了很多TCP连接,但一直没有关闭,即常见的连接泄露场景,你可能想要在排查问题的过程中,先临时kill一波泄露的连接。 又比如你要验证程序在遇到网络错误时的自愈能力,想手动kill掉一些正常TCP连接,看程序是否能自动重连并恢复运行。 这些场景,都需要手动kill一部分TCP连接,那在Linux下有哪些kill连接的方法呢? kill活跃的TCP连接使用ngrep或tcpkill命令可以杀死活跃状态的TCP连接,用法如下:
如上所示,可以发现在杀死连接时,ngrep和tcpkill都向连接方发送了RST包。 实现原理学过《计算机网络》的同学都知道,TCP协议是通过FIN包与ACK包来做四次挥手,从而断开TCP连接的,这是正常的TCP断连过程,但TCP协议中还有RST包,这种包用于异常情况下断开连接,Linux在收到RST包后,会直接关闭本端的Socket连接,而不需要经历四次挥手过程。 而上面的ngrep与tcpkill命令,正是通过给对方发送RST包,从而实现杀死TCP连接的。但要发送一个正确的RST包,需要知道TCP连接交互时所使用的序列号(seq),因为乱序的包会被TCP直接丢弃,所以ngrep和tcpkill还会监听网卡上交互的包,以找到指定连接所使用的序列号seq。 所以,ngrep与tcpkill只能kill有流量的活跃TCP连接,对于空闲连接就无法处理了。 kill空闲的TCP连接对于空闲状态的TCP连接,可以用ss或hping3命令来处理,如下: 使用ss杀死连接通过ss命令的-K选项可以用来kill连接,如下:
注意,使用这个功能需要你的内核版本>=4.9,且打开了CONFIG_INET_DIAG_DESTROY选项,因此某些情况下可能无法使用。 使用hping3杀死连接如果无法使用ss命令,则可以考虑使用hping3命令来kill连接,hping3命令可以发任何类型的TCP包,因此只要模拟tcpkill的原理即可,如下:
上面提到了,TCP协议会直接丢弃乱序的数据包,但是对于SYN包却区别对待了,如果你随便发一个SYN包给已连接状态的Socket,它会回复一个ACK,并携带有正确的seq序列号,如下:
可以在输出中找到,ack=1833836153即是对方回复的序列号,我们用在后面的发RST包中。
整个过程如下: 可以发现前面我们用lsof查到的连接,在发送RST包后就查不到了,说明连接已经被kill了。整个操作看起来有点麻烦,可以自己写个脚本封装一下。 |
2022-04-23
2022-10-16
2022-08-26
2020-04-20
2021-01-20