服務器上出現大量的SYN_RECV或者SYN_SENT狀態的TCP連接的問題分析


 

情況:服務器程序在某一時刻,程序端口正常在運行,telnet程序的端口無法打開,但是客戶端請求能正常連接;
針對出現這一系列的故障,百思不得其解,然后查日志,數據抓包,然后在處理過程中針對SYN_RECV的相關問題,分享給大家,僅供參考;
等靈異的問題處理完成,再把結果和處理的過程分享給大家;

[stock@localhost ~]$ netstat -an | grep SYN_RECV 如下是顯示的一部分
tcp 0 0 222.186.14.x:8080 117.136.1.144:29326 SYN_RECV
tcp 0 0 222.186.14.x:8080 117.136.31.149:31339 SYN_RECV
tcp 0 0 222.186.14.x:8080 117.136.31.149:31403 SYN_RECV
tcp 0 0 222.186.14.x:8080 211.137.119.5:29882 SYN_RECV
tcp 0 0 222.186.14.x:8080 123.151.172.2:16151 SYN_RECV
tcp 0 0 222.186.14.x:8080 1.197.233.48:36075 SYN_RECV
tcp 0 0 222.186.14.x:8080 117.136.8.83:23834 SYN_RECV
tcp 0 0 222.186.14.x:8080 117.136.20.6:48201 SYN_RECV
tcp 0 0 222.186.14.x:8080 117.136.35.16:22842 SYN_RECV


[stock@localhost ~]$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

ESTABLISHED 500 當前建立的連接是500個
SYN_RECV 307 SYN_RECV同步空閑字符接收到的狀態,主要是為了等待第三次握手
[stock@localhost ~]$
根據以上的問題,首先我們來判斷SYN_RECV是怎么產生的尼?
    SYN_RCVD是TCP三次握手的中間狀態,是服務端口如應用服務器端口,收到SYN包並發送[SYN,ACK]包后所處的狀態。這時如果再收到ACK的包,就完成了三次握手,建立起TCP連接。
    SYN_RCVD包產生的原因主要有兩種可能:
第一種可能:客戶端或者請求端沒有收到服務器的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狀態(半開連接)直到超時。
附:TCP的三次握手,四次端口
在TCP/IP協議中,TCP協議提供可靠的連接服務,采用三次握手建立一個連接。
第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器 進入SYN_RECV狀態; 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入 ESTABLISHED狀態,完成三次握手。 完成三次握手,客戶端與服務器開始傳送數據.
TCP的四次斷開:
(1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送(報文段4)。
(2)服務器B收到這個FIN,它發回一個ACK,確認序號為收到的序號加1(報文段5)。和SYN一樣,一個FIN將占用一個序號。
(3)服務器B關閉與客戶端A的連接,發送一個FIN給客戶端A(報文段6)。
(4)客戶端A發回ACK報文確認,並將確認序號設置為收到序號加1(報文段7)。

原文鏈接:http://www.rsyslog.net/archives/164

 

正常情況下,出現SYN_SENT的state應該很少,並且短暫

如果一個連接長時間處在SYN_SENT,有可能是沒連上,比如端口沒有打開

 

如果發現有很多SYN_SENT出現,那一般有這么幾種情況

一是你要訪問的網站不存在或線路不好

二是用掃描軟件掃描一個網段的機器,也會出出現很多SYN_SENT,另外就是可能中了病毒了,例如中了"沖擊波",病毒發作時會掃描其它機器,這樣會有很多SYN_SENT出現。

https://blog.csdn.net/icebergliu1234/article/details/104737407

 

如何制造一個長時間處於SYN_SENT狀態的socket?長時間的定義是超過3秒吧, 至少有時間能開個終端,用netstat看一下

比如A發送SYN_SENT給B,假如B是一台電腦,那么在B的防火牆里把TCP相關的端口deny掉。A進入SYN_SENT狀態后得不到應答,就會進入RTO狀態,在該狀態指數退避的后期重傳周期可能長達十數秒,應該足夠你觀測了。

iptables -D INPUT --protocol tcp --sport 22 --tcp-flags ALL SYN,ACK -j DROP

telnet 127.0.0.1 22

通過這樣的方式,就可以制造出SYN_SENT狀態的socket了。

 

tcp十一種狀態及問題處理方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM