如下內容純屬虛構,切勿輕易相信!php
syn/ack/fin
三個標誌位報文決定,可是這三個標誌位報文,並非說在構建鏈接的時候只發送一次的,由於協議不知道網絡情況. 故而就存在瞭如下參數,能夠調節發送次數syn+ack
標誌位報文的重試次數,何時發送syn+ack
標誌位呢?三次握手中,響應端爲了應答請求端的syn
標誌位報文,同時請求構建的時候,默認是5次,和上面同樣,網絡環境好,就來個2.syn+ack
報文的攻擊,也就是說,若是有瘋子一直大量發送syn標誌位,可是服務器須要發送syn+ack
來響應,可是那個瘋子卻不回覆ack
標誌位,致使服務器須要一直重試到次數結束.syn
等待隊列是有上限的,由於大量瘋子的syn
報文佔用了,那麼服務器就接收不到正常的syn報文請求了.這裏還有一個響應端syn
等待隊列的參數SYN_RCVD
狀態隊列,默認是1024,根據服務器性能和負載狀況,能夠調高此數值,好比8192syn
等待隊列也溢出了,該怎麼搞?能夠啓用net.ipv4.tcp_syncookies
SYN_RCVD
的狀態仍是128或者512(內核小於2.6.20),其緣由以下:
listen
函數會在調用的時候讀取內核參數net.core.somaxconn
的值,它的默認值是128,來肯定backlog
的大小listen
函數有一個固定值TCP_SYNQ_HSIZE
這個單向鏈表數組,它的默認值是512,你能夠修改這個值,確保這個值*16 <= net.ipv4.tcp_max_syn_backlog,這個鏈表的位置在$KERNEL/include/net/tcp.h
listen
的顯性參數backlog
,那麼服務依然會限制listen 80 default backlog = 8192
listen.backlog = 8192
tcp_max_syn_backlog
是針對syn
半開鏈接的話,這個參數就是針對一個總體的,意思就是說當內核處理不過來的時候,多餘的就先扔到隊列中syn
等待隊列溢出的時候,就給請求端發送syncookies
,直接繞過三次握手,構建鏈接.但這違反了tcp/ip
協議,可能會影響其餘服務,因此若是不肯定是攻擊,而是正常負載,則不要開啓OK,假設咱們內核是大於2.6.20的,那麼咱們若是想要實現如下場景:nginx
- 一個服務器,加載的是nginx服務,他正在接收請求,請求愈來愈多,他處理不過來了,因此將多餘的請求扔到了一個隊列中(隊列上限8192);
- net.core.netdev_max_backlog = 8192
- 可是這時候又來了一大批奇怪的請求,服務器怎麼迴應,這些請求源都不響應,且這些請求量也很大,故而服務器將其扔到了另外一個隊列(隊列上限8192);
- net.core.somaxconn = 8192
- net.ipv4.tcp_max_syn_backlog = 8192
- listen 80 default backlog = 8192
- 爲了防止這些垃圾請求過於佔用資源,服務器規定迴應報文(ack+syn)的次數爲2
- net.ipv4.tcp_synack_retries = 2
到目前爲止,三次握手已經走了一半,繼續路程~數組