TCP三次握手調優

TCP(Transmission Control Protocol)傳輸控制協議是一種面向鏈接的、可靠的、基於字節流的傳輸層協議。從TCP的定義中能夠看出,TCP是面向鏈接的可靠的通訊方式,鏈接雙方都須要肯定各自的鏈接通道都是OK的。三次握手的目的就是爲了肯定各自的通道是OK的,同時通知對方本身的起始SEQ。當客戶端調用connect函數時便發送了SYN報文同時通知對方本身的起始SEQ,從而發起第一次握手,客戶端進入SYN_SENT狀態;服務端收到SYN報文後,返回SYN+ACK報文到客戶端同時通知對方本身的起始SEQ,從而發起了第二次握手,服務端進入SYN_RCV狀態;客戶端收到服務端的SYN+ACK後,回覆ACK報文,從而發起第三次握手,客戶端進入ESTABLISHED狀態;服務端收到ACK報文後服務端進入ESTABLISHED狀態。自此三次握手就完成了,其流程圖以下:html

TCP的三次握手

過程以下:
image.png服務器

客戶端調優

一、當客戶端發起第一次握手的時候,若是遲遲收不到對方的應答,那麼客戶端會重試,重試的次數由/proc/sys/net/ipv4/tcp_syn_retries控制,默認值是5,重試間隔是1,2,4,8,16,32,總共須要花費63s。能夠根據客戶端與服務端的網絡情況以及服務端的負載,適當下降重試次數調小,如2次,從而出現異常的時候,客戶端能夠儘快感知到異常。cookie

服務端調優

一、當服務端發起第二次握手的時候,若是遲遲收不到對方的應答,那麼服務端也會重試,重試的次數由/proc/sys/net/ipv4/tcp_synack_retries控制,默認值是5,重試間隔是1,2,4,8,16,32,總共須要花費63s。一樣的,若是客戶端與服務器的網絡情況挺好的,能夠把重試次數調小。
二、當服務端發起第二次握手後,會把鏈接放入到半鏈接隊列,隊列的大小由/proc/sys/net/ipv4/tcp_max_syn_backlog控制,默認大小是2048。當這個隊列滿時,服務器將沒法創建鏈接。那麼咱們怎麼知道這個隊列是否有溢出呢?能夠經過以下的命令看到網絡

netstat -s | grep 'SYNs to LISTEN'
75571 SYNs to LISTEN sockets ignored

這個是個累計值,若是發現這個值不斷的變大,能夠把這個隊列調大。同時還能夠設置/proc/sys/net/ipv4/tcp_syncookies=1,打開tcp_syncookies功能。tcp_syncookies能夠取以下的值:
A. tcp_syncookies=0時,關閉syncookies功能,當半鏈接隊列滿時,服務端將沒法創建鏈接;
B. tcp_syncookies=1時,當半鏈接隊列滿時,服務端將啓用syncookies功能;
C. tcp_syncookies=2時,服務端將一直啓用syncookies功能。
tcp_syncookies的主要工做流程以下:
服務端接收到SYN報文並返回TSYN+ACK報文時,不插入半鏈接隊列,而是根據這個SYN報文計算出一個cookie值。這個cookie做爲將要返回的SYN ACK報文的初始序列號。當客戶端返回一個ACK報文時,根據報文頭信息計算cookie,與返回的確認序列號(初始序列號+1)進行對比,若是相同,則是一個正常鏈接,而後將鏈接放入accept隊列。
若是經過netstat -lap發現SYN_RCV狀態的鏈接不斷的增加,那麼就須要經過抓包工具分析是否是發生了syn泛洪攻擊,若是發生了泛洪攻擊,須要經過防火牆阻止這種鏈接。
所謂的SYN泛洪攻擊利用的是TCP的三次握手機制,攻擊端利用僞造的IP地址向被攻擊端發出請求,而被攻擊端發出的響應報文將永遠發送不到目的地,那麼被攻擊端在等待關閉這個鏈接的過程當中消耗了資源,若是有大量的這種鏈接,主機資源將被耗盡,從而達到攻擊的目的。
三、當服務端收到第三次握手的ACK應答報文後,服務端會把鏈接放入accept隊列,accept隊列由listen()函數傳入的參數(參數的值能夠經過ss -lnt命令的輸出「Send-Q」列查看)與/proc/sys/net/core/somaxconn共同控制,取2者的小值。能夠經過以下的命令查看是否由溢出:socket

netstat -s | grep overflow
75571 times the listen queue of a socket overflowed

若是這個值不斷的變大,說明應用程序沒有及時的調用accept函數接收鏈接,能夠先調高上文提升的2個參數。
accept隊列滿後是否丟棄鏈接,是由參數/proc/sys/net/ipv4/tcp_abort_on_overflow控制,默認是0。若是設置爲1而且溢出,則發送RST報文關閉鏈接。通常建議設置爲0,由於丟棄後,客戶端若是發送了數據+ACK,因爲等不到應答,那麼就會重複發送數據+ACK,當服務端接收到ACK後,若是accept隊列不滿了,那麼鏈接就創建了。可見tcp_abort_on_overflow=0,能夠提升TCP鏈接創建成功的機率。只有accept隊列長期溢出的時候,才設置tcp_abort_on_overflow=1。
四、另外還能夠打開TFO功能,提升TCP鏈接創建的效率,TFO詳見文檔:
https://tools.ietf.org/html/r...
https://www.cnblogs.com/passz...tcp

相關文章
相關標籤/搜索