核心模組
- ngx_http_limit_req_module:限制**請求速率** (漏桶算法),超限返回 503
- ngx_http_limit_conn_module:限制**並發連接數**,超限返回 503
場景一:限制請求頻率 (limit_req)
配置示例
http {
# 定義共享內存區域,鍵為客戶端二進制 IP,10MB 可存 ~16 萬狀態
# 速率:平均每秒 20 請求 (突發允許 5 個額外突發)
limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;
server {
location / {
# 套用限制:zone=one,突發桶大小 5,nodelay=立即處理突發而不延遲
limit_req zone=one burst=5 nodelay;
# 自定義超限返回碼 (默認 503)
limit_req_status 429;
}
# 登錄/註冊接口更嚴格
location /api/login {
limit_req zone=one burst=2 nodelay;
}
}
}
關鍵參數解析
| 指令 | 說明 |
| limit_req_zone | 定義區域:key zone=name:size rate=rate。rate 單位 r/s (每秒) 或 r/m (每分鐘),必須為整數 |
| limit_req | 套用區域:zone=name [burst=number] [nodelay] |
| burst | 漏桶容量。允許突發流量超過 rate,超出部分排隊 (無 nodelay) 或直接拒絕 (有 nodelay) |
| nodelay | 啟用後,突發請求不排隊直接處理,桶滿則拒絕。關閉時,突發請求按 rate 速率排隊延遲處理 |
| limit_req_status | 自定義超限狀態碼 (默認 503),建議 429 Too Many Requests |
速率單位換算
30r/m = 每分鐘 30 請求 = 平均 0.5 r/s (適合極嚴格限制)
100r/s = 每秒 100 請求 (適合靜態資源/API 閘道)
場景二:限制並發連接數 (limit_conn)
配置示例
http {
# 定義並發限制區域
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location / {
# 每個 IP 最大 20 個並發連接
limit_conn conn_limit 20;
# 限制單連接傳輸速度 500KB/s (配合並發限制防盜鏈/下載工具)
limit_rate 500k;
limit_conn_status 429;
}
}
}
參數說明
| 指令 | 說明 |
| limit_conn_zone | 僅能在 http 上下文定義 |
| limit_conn | 可在 http/server/location 使用。zone number |
| limit_rate | 限制**單連接**傳輸速率 (bytes/s)。單 IP 總速率 ≈ limit_rate × limit_conn |
| limit_conn_status | 超限狀態碼 |
白名單機制:放行搜索引擎爬蟲與內部 IP
步驟 1:geo 指令定義白名單變量
http {
geo $limited {
default 1; # 默認限制
# Googlebot IP 段
64.233.160.0/19 0;
66.102.0.0/20 0;
66.249.64.0/19 0;
72.14.192.0/18 0;
74.125.0.0/16 0;
209.85.128.0/17 0;
216.239.32.0/19 0;
# Bingbot
157.55.0.0/16 0;
157.56.0.0/14 0;
207.46.0.0/16 0;
# 內部測試 IP
127.0.0.1/32 0;
10.0.0.0/8 0;
192.168.0.0/16 0;
}
}
步驟 2:map 指令映射限制鍵
http {
# 白名單 IP 映射為空字符串,不會寫入 limit_req_zone 共享內存
map $limited $limit_key {
1 $binary_remote_addr; # 普通 IP 正常限制
0 ""; # 白名單 IP 不限制
}
}
步驟 3:套用映射後的鍵
http {
limit_req_zone $limit_key zone=api_limit:10m rate=100r/s;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
}
}
}
完整防 CC 攻擊配置模板
http {
# 1. 白名單定義
geo $is_limited {
default 1;
127.0.0.1/32 0;
10.0.0.0/8 0;
# 添加已知爬蟲 IP 段...
}
map $is_limited $limit_key {
1 $binary_remote_addr;
0 "";
}
# 2. 請求頻率限制區域
limit_req_zone $limit_key zone=req_zone:20m rate=50r/s;
# 3. 並發連接限制區域
limit_conn_zone $limit_key zone=conn_zone:10m;
server {
listen 80;
server_name example.com;
# 4. 全局套用
limit_req zone=req_zone burst=10 nodelay;
limit_req_status 429;
limit_conn conn_zone 30;
limit_conn_status 429;
limit_rate 1m; # 單連接 1MB/s
# 5. 敏感接口加強
location /api/login {
limit_req zone=req_zone burst=3 nodelay;
}
location /api/register {
limit_req zone=req_zone burst=2 nodelay;
}
# 6. 靜態資源放寬
location ~* \.(jpg|jpeg|png|gif|css|js|ico|woff2?)$ {
limit_req zone=req_zone burst=50 nodelay;
limit_conn conn_zone 50;
expires 30d;
}
}
}
驗證與調試
nginx -t 測試配置語法
systemctl reload nginx 熱加載
- 使用
ab -n 100 -c 10 https://example.com/ 壓測,觀察 429 響應
- 查看錯誤日誌:
grep "limiting requests" /var/log/nginx/error.log
進階建議
- 雙層防護:Nginx 限流 + 應用層 (PHP/Redis) 限流,針對不同業務邏輯精細控制
- 動態調整:結合 OpenResty + Lua 共享字典,根據實時流量動態修改 rate/burst
- 日誌分析:將 429 日誌接入 ELK/Grafana,設置告警觸發自動封禁 (fail2ban/iptables)
- HTTPS 場景:確保
$binary_remote_addr 獲取真實客戶端 IP (配置 real_ip_header + set_real_ip_from)