使用 iptables 限制每個 IP 位址的最大連線數和每秒新連線數

使用 iptables 限制每個 IP 位址的最大連線數和每秒新連線數

我們有一個 Ubuntu 12.04 伺服器,連接埠 80 上有 httpd,我們想要限制:

  • 每個 IP 位址到 httpd 的最大連線數為 10
  • 每秒到 httpd 的最大新連線數為 150

我們如何使用 iptables 做到這一點?

答案1

iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 15 --connlimit-mask 32 -j REJECT --reject-with tcp-reset  

這將拒絕來自一個來源 IP 的超過 15 個連線。

iptables -A INPUT -m state --state RELATED,ESTABLISHED -m limit --limit 150/second --limit-burst 160 -j ACCEPT  

在應用每秒 150 個新連線(資料包)的限制之前,允許 160 個新連線(實際上是資料包)。

答案2

您希望 iptables 中的以下規則能夠滿足您問題中的兩個要求:

iptables -t filter -I INPUT -p tcp --dport 80 -j ACCEPT

iptables -t filter -I INPUT -p tcp --dport 80 -m state \
  --state RELATED,ESTABLISHED -j ACCEPT

# Adjust "--connlimit-above NN" to limit the maximum connections per IP
#   that you need.
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
  --connlimit-above 10 --connlimit-mask 32 -j DROP

# Adjust "--connlimit-above NNN" to the maximum total connections you
#   want your web server to support
iptables -t filter -I INPUT -p tcp --syn --dport 80 -m connlimit \
  --connlimit-above 150 -j DROP

因為我們使用 -I (根據 OP 請求),所以我們必須以相反的順序執行它們,以便從下往上「讀取」它們。

我還建議考慮將 --connlimit-mask NN 從 32 更改為 24。您也可以使用任何其他無類別號碼,例如 22 或 30,具體取決於您認為服務的使用方式。

另外,根據您希望客戶的行為方式,您可能想要在上面的兩個規則中使用“-j REJECT --reject-with tcp-reset”而不是“-j DROP”,甚至只在 150 個連接最大規則中使用。

如果您拒絕連接,使用連接埠 80 的瀏覽器或軟體將立即顯示「不可用」狀態,但 DROP 選項將導致用戶端在報告網站不可用之前等待並重試幾次。我自己傾向於使用 DROP,因為它的行為更像是連接不良而不是離線伺服器。

此外,如果在重試期間連線限制回落到 150(或 10)以下,那麼它將最終到達您的伺服器。

然而,REJECT 選項將導致您網站的流量減少一小部分,因為 DROP 會導致它在重試時發送額外的資料包。可能並不是那麼相關。

另一方面,如果您的連接埠 80 流量是叢集的一部分,那麼 REJECT 將告訴叢集控制器它已關閉,並在重試逾時期間停止向其發送流量。

RELATED,ESTABLISHED 規則是在假設您的預設規則是阻止所有流量(iptables -t filter -P INPUT DROP)的情況下存在的。這僅接受屬於已接受連線的更多資料包。

另外 --syn 也告訴它注意(或計算)建立 TCP 連線的封包。

答案3

您需要使用connlimit允許您限制每個客戶端 IP 位址(或位址區塊)到伺服器的平行 TCP 連線數量的模組。

/sbin/iptables -I INPUT -p tcp --syn --dport 80 -m connlimit \
      --connlimit-above 10 -j DROP

相關內容