在高流量或遭受爬蟲攻擊時,Web Server(如 Apache / Nginx)可能會因為大量連線而消耗過多 PHP-FPM 或系統資源。
Linux iptables 的 hashlimit 模組可以有效限制「每個 IP 的連線速率」,是一種輕量且高效的防護方式。
本文說明:
- hashlimit 的用途
- 基本設定方法
- 測試方式
- 如何安全取消規則(回滾)
一、什麼是 hashlimit?
hashlimit 是 iptables 的一個 match module。
它的特色是:
✅ 針對「每個來源 IP」獨立計算流量
✅ 不會把所有訪客視為同一個來源
✅ 適合防止單一 IP 短時間內大量請求
與 -m limit 不同,limit 是全局限制,容易誤傷正常使用者。
二、基本 HTTP 限制範例
以下規則限制:
- 每個 IP 每秒最多 20 個請求
- 瞬間最多 40 個 burst
- 超過後丟棄(DROP)
bash
iptables -A INPUT -p tcp --dport 80 \
-m hashlimit \
--hashlimit 30/sec \
--hashlimit-burst 80 \
--hashlimit-mode srcip \
--hashlimit-name http_limit \
-j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP
參數說明
| 參數 | 說明 |
|---|---|
| –hashlimit 30/sec | 每秒最多 30 個封包 |
| –hashlimit-burst 80 | 瞬間可達 80 個 |
| –hashlimit-mode srcip | 以來源 IP 為單位計算 |
| –hashlimit-name | 此限制規則的名稱 |
三、如何確認規則是否生效?
使用:
bash
iptables -L INPUT -n -v
可以看到每條規則的封包計數。
如需查看行號(刪除時會用到):
bash
iptables -L INPUT -n --line-numbers
四、如何安全取消規則?
✅ 方法一(推薦):使用行號刪除
先查看規則:
bash
iptables -L INPUT -n --line-numbers
假設顯示:
basic
num target
1 ACCEPT tcp dpt:80 hashlimit ...
2 DROP tcp dpt:80
刪除方式:
bash
iptables -D INPUT 1
iptables -D INPUT 1
⚠ 注意:刪除第一條後,下面規則會往上移動。
✅ 方法二:使用完整規則刪除
bash
iptables -D INPUT -p tcp --dport 80 \
-m hashlimit \
--hashlimit 30/sec \
--hashlimit-burst 80 \
--hashlimit-mode srcip \
--hashlimit-name http_limit \
-j ACCEPT
iptables -D INPUT -p tcp --dport 80 -j DROP
⚠ 必須與建立規則時完全一致。
五、如果使用 iptables-persistent
若系統有安裝:
iptables-persistent
或使用:
netfilter-persistent
刪除規則後,請記得重新儲存:
bash
iptables-save > /etc/iptables/rules.v4
否則重開機後規則會恢復。
六、安全測試建議(避免誤封)
⚠ 在 Production 環境請勿直接啟用 DROP 規則。
建議測試流程:
1️⃣ 先只加入 hashlimit ACCEPT 規則
2️⃣ 觀察流量與錯誤日誌
3️⃣ 確認正常後再加入 DROP
或先於測試機驗證。
七、適用場景
- WordPress 遭受爬蟲過度抓取
- WooCommerce 頁面被大量請求
- 想降低 PHP-FPM 壓力
- 防止單一 IP 造成資源耗盡
八、注意事項
- 若使用 Cloudflare,來源 IP 可能會變成 CDN IP
- iptables 屬於 L3/L4 防火牆,無法判斷 URL
- 規則順序非常重要
結語
hashlimit 是一種:
- 高效
- 核心層級
- 不依賴應用程式
的流量控制方式。
但部署前務必測試,並確保有回滾方案,以避免影響正常使用者。