乐趣区

关于网络:如何kill一条TCP连接

原创:扣钉日记(微信公众号 ID:codelogs),欢送分享,转载请保留出处。

简介

如果你的程序写得有故障,关上了很多 TCP 连贯,但始终没有敞开,即常见的连贯泄露场景,你可能想要在排查问题的过程中,先长期 kill 一波泄露的连贯。
又比方你要验证程序在遇到网络谬误时的自愈能力,想手动 kill 掉一些失常 TCP 连贯,看程序是否能主动重连并复原运行。

这些场景,都须要手动 kill 一部分 TCP 连贯,那在 Linux 下有哪些 kill 连贯的办法呢?

kill 沉闷的 TCP 连贯

应用 ngrep 或 tcpkill 命令能够杀死沉闷状态的 TCP 连贯,用法如下:

# ngrep 杀死连贯
$ sudo ngrep -d any -K3 '''port 54690'

# 装置 tcpkill,及应用其杀死连贯
$ sudo apt install dsniff  
$ sudo tcpkill -i any 'port 45308'

如上所示,能够发现在杀死连贯时,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 连贯,如下:

# 装置 ss 命令
$ sudo apt install iproute2

# 应用 ss 杀死指标端口为 65987 的连贯
$ sudo ss -K dport = 65987

留神,应用这个性能须要你的内核版本 >=4.9,且关上了 CONFIG_INET_DIAG_DESTROY 选项,因而某些状况下可能无奈应用。

应用 hping3 杀死连贯

如果无奈应用 ss 命令,则能够思考应用 hping3 命令来 kill 连贯,hping3 命令能够发任何类型的 TCP 包,因而只有模仿 tcpkill 的原理即可,如下:

  1. 通过发送 SYN 包来获取 seq

下面提到了,TCP 协定会间接抛弃乱序的数据包,然而对于 SYN 包却区别对待了,如果你轻易发一个 SYN 包给已连贯状态的 Socket,它会回复一个 ACK,并携带有正确的 seq 序列号,如下:

# 第一个参数,示意发送包的指标 ip 地址
# -a:设置包的源 ip 地址
# -s:设置包的源端口
# -p:设置包的指标端口
# --syn:示意发 SYN 包
# -V:verbose output,使 hping3 输入序列号 seq
# -c:设置发包数量
$ sudo hping3 172.26.79.103 -a 192.168.18.230 -s 8080 -p 45316 --syn -V -c 1
using eth0, addr: 172.26.79.103, MTU: 1500
HPING 172.26.79.103 (eth0 172.26.79.103): S set, 40 headers + 0 data bytes
len=40 ip=172.26.79.103 ttl=64 DF id=16518 tos=0 iplen=40
sport=45316 flags=A seq=0 win=502 rtt=13.4 ms
seq=1179666991 ack=1833836153 sum=2acf urp=0

能够在输入中找到,ack=1833836153即是对方回复的序列号,咱们用在前面的发 RST 包中。

  1. 应用 seq 发 RST 包
# --rst:示意发 RST 包
# --win:设置 TCP 窗口大小
# --setseq:设置包的 seq 序列包
$ sudo hping3 172.26.79.103 -a 192.168.18.230 -s 8080 -p 45316 --rst --win 0 --setseq 1833836153 -c 1
HPING 172.26.79.103 (eth0 172.26.79.103): R set, 40 headers + 0 data bytes

--- 172.26.79.103 hping statistic ---
1 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

整个过程如下:

能够发现后面咱们用 lsof 查到的连贯,在发送 RST 包后就查不到了,阐明连贯曾经被 kill 了。整个操作看起来有点麻烦,能够本人写个脚本封装一下。

退出移动版