说在前面
1. 前一篇文章金牛座已经分享过一个 tcpkill 工具,但是实战过程中并不理想,推荐使用本文的 killcx 工具。
2. 由于工具极具实用性,为了达到预期的效果,务必跟着文章的步骤来搞。
问题背景
我们经常会遇到这样的情况:
服务端进程启动监听一个端口比如:8888,然后客户端成功建立连接,【注意不要去关闭客户端连接】,然后 CTRL + C 或 kill -9 干掉服务进程,此时你若重启服务会发现程序报错:socket_bind(): unable to bind address [98]: Address already in use。
问题原因
一般经验丰富的码农立刻都会意识到是有其他进程占用了8888端口,一定是如此吗?我们 ps aux 查看了一下, 咦,进程已经退出了啊,怎么回事?! 继续 netstat 查看,你会发现TCP连接并未释放,而多数是处于TIME_WAIT、FIN_WAIT1、FIN_WAIT2等状态,这是因为客户端死死缠着连接不释放造成的,虽然客户端连接看上去已经断开,但是连接资源并未被内核及时释放,而且 netstat 也解释了为什么系统会报告Address already in use。
解决方案
使用 killcx 工具来关闭TCP连接
killcx是什么
killcx是一个在linux下可以关闭TCP连接的 Perl 脚本,厉害之处在于:无论该TCP连接处于什么状态,都可以有效关闭TCP连接。
killcx官网
安装killcx
(1)官方文档明确指出 killcx 依赖三个模块:
You need the following modules to run killcx :
* Net::RawIP : needed to create spoofed packets.
* Net::Pcap : needed to capture TCP packets.
* NetPacket::Ethernet : needed to decode TCP/IP packets.
(2)所以我们利用CPAN安装这几个模块:
# perl -MCPAN -e shell
cpan> install Net::RawIP
cpan> install Net::Pcap
cpan> install NetPacket::Ethernet
(3)下载 killcx 安装包并解压,直接得到 killcx 脚本
(4)来个全局软链方便使用: ln -s /path/to/killcx /usr/local/bin/killcx
(5)运行 killcx 将会看到如下回显:
实战DEMO
(1) 模拟干掉 ESTABLISHED 连接
(2)模拟干掉 TIME_WAIT 连接