Linux

儘管 SYN_RECV 連接數量較少,但日誌中出現“可能的 SYN 氾濫”

  • October 11, 2012

最近我們有一個 apache 伺服器,由於 SYN 氾濫,它響應非常緩慢。解決方法是啟用 tcp_syncookies ( net.ipv4.tcp_syncookies=1 in /etc/sysctl.conf)。

如果您想了解更多背景資訊,我在這裡發布了一個關於此的問題。

啟用 syncookies 後,我們開始在 /var/log/messages 中大約每 60 秒看到以下消息:

[84440.731929] possible SYN flooding on port 80. Sending cookies.

Vinko Vrsalovic 告訴我這意味著 syn backlog 已滿,因此我將 tcp_max_syn_backlog 提高到 4096。在某些時候,我還通過發出sysctl -w net.ipv4.tcp_synack_retries=3. 這樣做之後,頻率似乎下降了,消息的間隔大約在 60 到 180 秒之間變化。

接下來我發出了sysctl -w net.ipv4.tcp_max_syn_backlog=65536,但我仍然在日誌中收到消息。

在所有這一切中,我一直在觀察處於 SYN_RECV 狀態的連接數(通過執行watch --interval=5 'netstat -tuna |grep "SYN_RECV"|wc -l'),它從未超過 240 左右,遠低於積壓的大小。然而,我有一個 Red Hat 伺服器,它徘徊在 512 左右(此伺服器的限制是預設值 1024)。

是否有任何其他 tcp 設置會限制積壓的大小,或者我是在叫錯樹嗎?SYN_RECV 連接的數量是否應該與netstat -tuna積壓的大小相關?


更新

盡我所能告訴我,我在這里處理的是合法連接,netstat -tuna|wc -l徘徊在 5000 左右。我今天一直在研究這個,發現了 last.fm 員工的這篇文章,這很有用。

我還發現啟用 syncookies 時 tcp_max_syn_backlog 無效(根據此連結

因此,下一步我在 sysctl.conf 中設置以下內容:

net.ipv4.tcp_syn_retries = 3
       # default=5
net.ipv4.tcp_synack_retries = 3
       # default=5
net.ipv4.tcp_max_syn_backlog = 65536
       # default=1024
net.core.wmem_max = 8388608
       # default=124928
net.core.rmem_max = 8388608
       # default=131071
net.core.somaxconn = 512
       # default = 128
net.core.optmem_max = 81920
       # default = 20480

然後我設置了我的響應時間測試,執行sysctl -p並禁用了 syncookies sysctl -w net.ipv4.tcp_syncookies=0

完成此操作後,SYN_RECV 狀態的連接數仍保持在 220-250 左右,但連接再次開始延遲。一旦我注意到這些延遲,我重新啟用了 syncookies 並且延遲停止了。

我相信我所看到的仍然比初始狀態有所改進,但是一些請求仍然被延遲,這比啟用 syncookies 要糟糕得多。所以看起來我一直堅持啟用它們,直到我們可以讓更多的伺服器線上來應對負載。即使那樣,我也不確定我是否有理由再次禁用它們,因為它們僅在伺服器的緩衝區已滿時(顯然)才被發送。

但是,SYN_RECV 狀態下只有約 250 個連接,syn backlog 似乎並沒有滿!SYN 氾濫消息是否有可能是一條紅鯡魚,它不是正在填滿的 syn_backlog 之外的東西?

如果有人有我還沒有嘗試過的任何其他調整選項,我會非常樂意嘗試它們,但我開始懷疑 syn_backlog 設置是否由於某種原因沒有被正確應用。

所以,這是一個巧妙的問題。

最初,我很驚訝您看到任何處於 SYN_RECV 狀態且啟用了 SYN cookie 的連接。SYN cookie 的美妙之處在於,您可以使用加密技術作為伺服器無狀態地參與 TCP 3 次握手,所以我希望伺服器根本不代表半開連接,因為那將是與’沒有被保留。

事實上,快速瀏覽一下原始碼 (tcp_ipv4.c) 會顯示有關核心如何實現 SYN cookie 的有趣資訊。從本質上講,儘管打開了它們,核心仍會正常執行,直到其掛起的連接隊列已滿。這解釋了您現有的處於 SYN_RECV 狀態的連接列表。

只有當掛起的連接隊列已滿,並且收到另一個 SYN 數據包(連接嘗試),並且距離上次警告消息已經超過一分鐘時,核心才會發送您看到的警告消息(“發送 cookie” )。即使沒有警告消息,也會發送 SYN cookie;警告消息只是為了提醒您問題尚未消失。

換句話說,如果你關閉 SYN cookie,消息就會消失。如果您不再被 SYN 淹沒,那隻會對您有用。

要解決您所做的其他一些事情:

  • net.ipv4.tcp_synack_retries:

    • 增加此值不會對那些被欺騙的傳入連接產生任何積極影響,也不會對任何接收 SYN cookie 而不是伺服器端狀態的連接產生任何積極影響(也不會重試它們)。
    • 對於傳入的欺騙連接,增加這會增加您發送到虛假地址的數據包數量,並且可能會增加該欺騙地址在您的連接表中停留的時間(這可能是一個顯著的負面影響)。
    • 在正常負載/傳入連接數下,此值越高,您越有可能通過丟棄數據包的連結快速/成功完成連接。增加這一點的回報會遞減。
  • net.ipv4.tcp_syn_retries:更改此設置不會對入站連接產生任何影響(它只會影響出站連接)

你提到的其他變數我沒有研究過,但我懷疑你的問題的答案就在這裡。

如果您沒有被 SYN 淹沒並且機器對非 HTTP 連接(例如 SSH)有響應,我認為可能存在網路問題,您應該讓網路工程師幫助您查看它。如果機器通常沒有響應,即使您沒有被 SYN 淹沒,如果它影響 TCP 連接的創建,這聽起來像是一個嚴重的負載問題(相當低級別和資源非密集型)

引用自:https://serverfault.com/questions/294209