對伺服器上出現大量的SYN_RECV狀態的TCP連線的問題分析
首先我們需要弄清楚SYN_RCVD狀態是怎樣產生的,通過TCP狀態轉換圖(如下圖)我們可以清楚的看到,SYN_RCVD是TCP三次握手的中間狀態,是服務埠(監聽埠,如應用伺服器的80埠)收到SYN包併發送[SYN,ACK]包後所處的狀態。這時如果再收到ACK的包,就完成了三次握手,建立起TCP連線。
如果伺服器上出現大量的SYN_RCVD狀態的TCP連線說明這些連線一直沒有收到ACK包,這主要有兩種可能,一種是對方(請求方或客戶端)沒有收到伺服器傳送的[SYN,ACK]包,另一種可能是對方收到了[SYN,ACK]包卻沒有ACK。
對於第一種情況一般是由於網路結構或安全規則限制導致(SYN,ACK)包無法傳送到對方,這種情況比較容易判斷:只要在伺服器上能夠ping通網際網路的任意主機,基本可以排除這種情況。
對於第二種情況要稍微複雜一些,這種情況還有兩種可能:一種是對方根本就不打算ACK,一般在對方程式有意為之才會出現,如SYN Flood型別的DOS/DDOS攻擊;另一種可能是對方收到的[SYN,ACK]包不合法,常見的是SYN包的目的地址(服務地址)和應答[SYN,ACK]包的源地址不同。這種情況在只配置了DNAT而不進行SNAT的服務網路環境下容易出現,主要是由於inbound(SYN包)和outbound([SYN,ACK]包)的包穿越了不同的閘道器/防火牆/負載均衡器,從而導致[SYN,ACK]路由到網際網路的源地址(一般是防火牆的出口地址)與SYN包的目的地址(服務的虛擬IP)不同,這時客戶機無法將SYN包和[SYN,ACK]包關聯在一起,從而會認為已發出的SYN包還沒有被應答,於是繼續等待應答包。這樣伺服器端的連線一直保持在SYN_RCVD狀態(半開連線)直到超時。