在 Linux 內核中診斷網絡問題

n6xb 9年前發布 | 16K 次閱讀 Linux

在 Linux 內核中診斷網絡問題

幾周前,我們開始注意位于華盛頓的追蹤API的服務器網絡流量有很大的變化。從一個相當穩定的日常模式下,我們開始看到300-400 Mbps尖峰流量,但我們的合法的流量(事件和人為更新)是不變的。

在 Linux 內核中診斷網絡問題

突然,我們的網絡流量開始飆升像瘋了似的。

找到虛假的流量來源是當務之急,因為這些尖峰流量正觸發我們的上游路由器啟動DDOS減災模式來阻止流量。

有一些很好的內置的Linux工具幫助診斷網絡問題。

  • ifconfig 會顯示你的網絡接口和多少數據包通過他們

  • ethtool -S 會顯示你的數據包流的一些更詳細的信息,象在NIC級丟棄的數據包的數量。

  • iptables -L -v -n 將顯示你的各種防火墻規則處理數據包數。

  • netstat -s 會告訴由內核網絡協議棧維護的一大堆的計數器值,例如ACK的數量,重發的數量等。

  • sysctl -a | grep net.ip 將顯示你所有kernel中網絡相關的設置。

  • tcpdump 將顯示進出包的內容。

解決問題的線索是使用netstat -s命令的輸出。 不幸的是,當你檢查這個命令的輸出的時候,還很難告訴這些數字意味著什么,應該是什么,以及它們是如何改變的。為了檢查他們是如何變化的,我們創建了一個小程序來顯示連續運行命令的輸出,這讓我們了解各種計數器變化的快慢。一個輸出線看起來特別令人擔憂。

此計數器的通常速率在未受影響的服務器上一般是 30-40 /秒,所以我們知道肯定是哪里出問題了。計數器表明我們正拒絕大量的包,因為這些包含有無效的 TCP 時間戳。臨時的快速解決方案是用下面的命令關閉 TCP 時間戳:

sysctl -w net.ipv4.tcp_timestamps=0

這立即導致了包風暴停止。但是這不是一個永久性的解決方案,因為 TCP 時間戳是用于測量往返時間和分配數據包流中的延遲包到正確位置。在高速連接的時候這將成為一個問題,TCP 序列號可能在數秒間隔內纏繞。關于 TCP 的時間戳和性能的詳細信息,請看 RFC 1323


在 Mixpanel,每當我們看到異常流量模式的時候,我們一般也運行 tcpdump,這樣我們能夠分析流量,然后試圖確定根本原因。我們發現大量的 TCP ACK 數據包在我們的 API 服務器和一個特定的 IP 地址之間來回發送。結果我們的服務器陷入到向另一臺服務器來來回回發送 TCP ACK 包的無限循環里面。一個主機持續地發出 TCP 時間戳,但是另一主機卻不能識別這是有效的時間戳。

這時,我們意識到我們正在處理一個只能在 Linux 內核的 TCP 協議棧才能解決問題。所以我們的 CTO求助于 linux-netdev 看看是否能找到一個解決方案。值得慶幸的是我們發現這個問題已經遇到過的,并且有一個解決方案。原來,這種類型的包風暴可以由一些硬件故障或第三方改變 TCP SEQ,ACK,或連接中的主機認為對方發送過期的數據包所觸發。避免讓這種情況變成一個包風暴的方法是限制速度,設置 Linux 發送重復的 ACK 數據包速度為每秒一個或兩個。這里有一個非常好的解釋。

我們將接受這個補丁而且將之移植到當前正在使用的Ubuntu(Trusty)內核當中。感謝Ubuntu讓這一切變得非常簡單,重新編譯修補過的內核僅僅只需要運行下面的命令,安裝生成的.deb包并重啟系統。

# Get the kernel source and build dependencies
apt-get build-dep linux-image-3.13.0-45-generic
apt-get source linux-image-3.13.0-45-generic
 
# Apply the patch file.
cd linux-lts-trusty-3.13.0/
patch -p1 < Mitigate-TCP-ACK-Loops.patch
 
# Build the kernel
fakeroot ./debian/rules clean
fakeroot ./debian/rules binary-headers binary-generic
 本文由用戶 n6xb 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!