
我們有一個 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