最近在測試環境部署服務的時候老是會有端口被占用情況用netstat/ss 檢視後發現端口一直被占用
同另外一個ip 建立了tcp 連接配接,類似于這樣:
當然這個問題也不是最近才遇到,之前也遇到過,不過之前都是很快這個連接配接就自動消失,我就可以歡快
的使用我自己喜歡的12345 端口,無奈這次一直連續好幾天這個連接配接一直存在導緻我一直無法使用這個端口。
google 果然告訴我答案,有個叫tcpkill 的工具(可以自行搜尋一下),看到之後立即将源碼下下來
編譯了一把,按照提示将幾個确實的包安裝後編譯成功,然後按照tcpkill 的幫助文檔進行操作
執行上述指令後發現tcpkill 感覺像是處于hang 住狀态,運作了半天也沒見把這個連接配接幹掉,為什麼這個連接配接沒幹掉? 于是用 nc 測試了下,發現如下情況
對于上述現象好奇的看了下tcpkill 的源碼
不難看出是每抓到一個符合條件的包回調一次tcp_kill_cb 函數,也就是說tcpkill 隻有在這條
連接配接上還有資料傳輸才有可能被tcpkill 感覺并幹掉。
至此為什麼我想幹掉的那條tcp 連接配接沒被幹掉原因已經比較明朗了。不外乎以下兩個原因:
按照以上分析tcpkill 是可以幹掉一調活躍連接配接,那麼對于一條非活躍連接配接或者半連接配接要如何幹掉?
看了tcpkill 的代碼,大緻原理是捕捉到tcp 封包之後就知道了這條連接配接資訊,然後
利用libnet 構造一條rst封包發回去直接rst 掉連接配接。于是在tcpkill 代碼之上根據netstat/ss
看到的tcp 四元組資訊構造了一條tst發送出去。
運作之後用tcpdump 抓包可以看到構造的rst 封包被順利的發送出去,但是連接配接并沒有
消失,也就是說tcp 可能根本就沒響應此封包。對比tcpkill reset 部分代碼後發現
還需要設定正确的系列号,突然明白為啥tcpkill 隻能幹掉活躍連接配接了,原來是需要
捕獲流動的封包才能擷取正确的系列号,利用此序列号構造出rst包才能reset掉tcp 連接配接。
那麼如何才能擷取一條非活躍連接配接的序列号呢?
主動發送一條syn包,擷取應答後計算出正确的序列号。為啥要發送一個syn 包呢,因為syn包是一調
tcp 連接配接的開始,此時序列号還未産生,是以可以随機選取一個,當tcp 的一端收到這條syn 包後
會以ack封包進行應答,應答封包中會攜帶正确的序列号,是以我們隻需要根據此序列号發送rst 包
就可以将此連接配接reset 掉。
我們可以結合nc抓包看看:
前三個封包是正常建立tcp 連接配接的封包,至此nc 已經和伺服器建立了一條連接配接,此時連接配接
上是沒有任何資料的。
第四條封包是我們構造出來并主動發送的syn封包
第五條封包是針對第四條封包給出的應答
第六條封包是tcpkill 擷取第五條應答封包後計算出正确的序列号發送的rst封包。
至此問題解決。
注:按照上述原理修改了tcpkill 源碼,使其能夠主動kill 掉非活躍連接配接及半連接配接
<a href="http://site-img-data.oss-cn-shanghai.aliyuncs.com/tcpkill/tcpkill_v2.tar.gz">http://site-img-data.oss-cn-shanghai.aliyuncs.com/tcpkill/tcpkill_v2.tar.gz</a>