建連接時SYN超時問題
如果 server 端因為某種情況沒有收到 client 回來的 ACK,那么,這個連接處還處于一個未建立的狀態。于是,server端如果在一定時間內沒有收到,則 server 端的 TCP 會重發 SYN_ACK。
在Linux下,默認重試次數為5次,重試的間隔時間從1s開始每次都翻倍,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發出后還要等32s都知道第5次也超時了。如果第五次重傳之后,還未收到客戶端的 ACK,server 端的 TCP 才會把斷開這個連接。
關于SYN Flood攻擊
攻擊者短時間偽造不同 IP 地址的 SYN 報文,服務端每接收到一個 SYN 報文,就進入SYN_RCVD 狀態,但服務端發送出去的 ACK + SYN 報文,無法得到未知 IP 主機的 ACK 應答,久而久之就會占滿服務端的 SYN 接收隊列(未連接隊列),使得服務器不能為正常用戶服務。
避免方式
設置 tcp_syncookies = 1。當 SYN 隊列滿了后,TCP 會通過源地址端口、目標地址端口和時間戳打造出一個特別的 Sequence Number 發回去(又叫cookie)。
如果是攻擊者則不會有響應,如果是正常連接,則會把這個 SYN Cookie 發回來,然后服務端可以通過 cookie 建連接。
設置 netdev_max_backlog 的值,確定鏈接隊列的大小。當網卡接收數據包的速度大于內核處理的速度時,會有一個隊列保存這些數據包。
通過設置 netdev_max_backlog 的值,確定 SYN_RCVD 狀態連接的最大個數。
通過設置 tcp_abort_on_overflow 的值。當超出處理能時,對新的 SYN 直接回報 RST,丟棄連接。
斷開連接中的異常
從上面的描述可以知道,TIME_WAIT 是個很重要的狀態,但是如果在大并發的短鏈接下,TIME_WAIT 就會太多。TIME_WAIT過多會占用大量的內存資源和端口資源。
優化法一:tcp_tw_reuse
設置tcp_tw_reuse = 1,則可以復用處于 TIME_WAIT 的 socket 為新的連接所用。
有一點需要注意的是,tcp_tw_reuse 功能只能用客戶端(連接發起方),因為開啟了該功能,在調用 connect() 函數時,內核會隨機找一個 time_wait 狀態超過 1 秒的連接給新的連接復用。
使用 tcp_timestamps = 1 選項,還有一個前提,需要打開對 TCP 時間戳的支持,即這個時間戳的字段是在 TCP 頭部的「選項」里,用于記錄 TCP 發送方的當前時間戳和從對端接收到的最新時間戳。
由于引入了時間戳,我們在前面提到的 2MSL 問題就不復存在了,因為重復的數據包會因為時間戳過期被自然丟棄。
優化法二:tcp_max_tw_buckets
這個值默認為 18000,當系統中處于 TIME_WAIT 的連接一旦超過這個值時,系統就會將后面的 TIME_WAIT 連接狀態重置。
這個方法過于暴力,而且治標不治本,帶來的問題遠比解決的問題多,不推薦使用。
-
網絡
+關注
關注
14文章
7517瀏覽量
88627 -
TCP
+關注
關注
8文章
1350瀏覽量
78986 -
連接
+關注
關注
2文章
95瀏覽量
20950 -
服務端
+關注
關注
0文章
66瀏覽量
6987
發布評論請先 登錄
相關推薦
評論