摘自:
滑動視窗的概念大家可以自行搜尋,這裡就不贅述了,大致的概念是傳送和接受雙方都各有乙個傳送視窗和乙個接受視窗,其主要目的就是為了流量控制,使雙方的傳送、接收速度盡可能匹配。
當傳送方的傳送速度大於接收方的處理速度,接收方的緩衝塞滿後,就會告訴傳送方當前視窗size=0,請停止傳送,傳送方此時停止傳送資料。
零視窗出現後,如何繼續資料的傳輸呢。我們假設:接收方視窗更新為非0後,傳送ack給傳送方,更新window的size,是一種可行的方式。但是如果這個ack丟掉了(tcp不會給ack回覆ack),那麼傳送方和接收方就會處於一種尷尬的局面,乙個等著發,乙個等著收,直到超時。
此時引入了堅持定時器的概念,由傳送方主動建立,持續不斷地詢問接收方視窗是否更新,這個詢問被稱為視窗探測(window probes)。
終於到了問題的關鍵,這個定時器沒有時間限制,意味著這個tcp連線會永遠保持下去。
google了很久,沒有查到各大作業系統對於堅持定時器的時間設定,提到零視窗攻擊的資訊也很少,擷取其中乙個明確提到零視窗攻擊的頁面,來自乙個硬體負載均衡的廠商的產品介紹,貌似硬體防火牆或者負載均衡裝置應該有相關的防護設定:
原鏈結
public class client
system.out.print(line);
}......
}
修改tomcat原始碼,將socket物件暴露給業務**,業務**將所有socket和已經傳送的位元組數快取起來(每次傳送資料後即更新對應的位元組數),每隔一段時間掃瞄一遍,將超過閾值時間後傳送位元組仍然沒有變化的socket,強制呼叫socket.close()將其關閉。
socket.setsolinger(true, 0); // socket是阻塞io,資料不傳送完預設是關不掉的,需要設定solinger
socket.close();
寫這篇文章時,試了一下nio的connector會如何,測試結果也不盡人意,堅持定時器仍然生效,過一會兒連線狀態遷移為fin_wait1(抓包裡沒看到發fin,奇怪),連線控制代碼仍然被占用。
恐怖的是,./shutdown.sh關了tomcat,控制代碼仍不能釋放,堅持定時器仍然在持續不斷地探測…客戶端已經利用tcp的機制,綁架了服務端作業系統層面的控制代碼資源?參考
[1]:
TCP滑動視窗
目前建立在tcp協議上的網路協議特別多,有telnet,ssh,有ftp,有http等等。這些協議又可以根據資料吞吐量來大致分成兩大類 1 互動資料型別,例如telet,ssh,這種型別的協議在大多數情況下只是做小流量的資料交換,比如說按一下鍵盤,回顯一些文字等等。2 資料成塊型別,例如ftp,這種...
TCP 視窗機制
tcp協議在能夠傳送資料之前就建立起了 連線 要實現這個連線,啟動tcp連線的那一方首先將傳送乙個syn資料報。這只是乙個不包含資料的資料報,然後,開啟syn標記。如果另一方同時在它收到syn標記的埠通話,它將發回乙個syn ack syn和ack標誌位都被開啟,並將ack 確認 編 號字段設定為剛...
TCP滑動視窗
假設a和b之間新建立了一條tcp連線。裝置a需要傳送一長串資料流,但裝置b無法一次全部接收,所以它限制裝置a每次傳送分段指定數量的位元組數,直到分段中已傳送的位元組數得到確認。之後,裝置a可以繼續傳送更多位元組。每乙個裝置都對傳送,接收及確認資料進行追蹤。tcpbuffer中資料可以分為以下四類 1...