在Nginx中實(shí)現(xiàn)動(dòng)態(tài)封禁IP的三種主流方案
引言
在運(yùn)維和安全實(shí)踐中,經(jīng)常需要根據(jù)實(shí)時(shí)情況封禁某些惡意 IP。但傳統(tǒng)的Nginx 配置是靜態(tài)的——一旦寫死 deny 1.2.3.4;,就必須重啟或重載服務(wù)才能生效。那么,有沒有辦法在不中斷服務(wù)的前提下,實(shí)現(xiàn)動(dòng)態(tài)、實(shí)時(shí)、可編程的 IP 封禁呢?
一、方案對(duì)比
| 方案 | 是否需 reload | 實(shí)時(shí)性 | 技術(shù)棧 | 適用場(chǎng)景 |
|---|---|---|---|---|
| geo + map + 文件 | 是(nginx -s reload) | 秒~分鐘級(jí) | 原生 Nginx | 手動(dòng)或定時(shí)腳本封禁 |
| OpenResty + Lua | 否 | 毫秒級(jí) | OpenResty(Nginx + Lua) | 自動(dòng)化、高并發(fā)、API 化管理 |
| fail2ban + 日志分析 | 否(系統(tǒng)級(jí)封禁) | 秒級(jí) | fail2ban + iptables | 安全防護(hù)、日志驅(qū)動(dòng)型封禁 |
二、方案一:原生 Nginx + 外部文件(簡(jiǎn)單可靠)
適用于不需要極高實(shí)時(shí)性的場(chǎng)景,比如每天批量封禁一批掃描 IP。
1. 創(chuàng)建封禁 IP 列表文件
# /etc/nginx/conf.d/blockips.conf 192.168.1.100 1; 203.0.113.5 1;
格式為:IP 值;,值通常設(shè)為 1 表示“命中”。
2. 在 nginx.conf 中配置
http {
# 從外部文件加載黑名單
geo $block_ip {
default 0;
include /etc/nginx/conf.d/blockips.conf;
}
map $block_ip $deny_ip {
1 "denied";
0 "";
}
server {
listen 80;
if ($deny_ip = "denied") {
return 403;
}
location / {
# 正常業(yè)務(wù)
}
}
}
3. 動(dòng)態(tài)更新方式
- 修改
blockips.conf - 執(zhí)行平滑重載:
nginx -s reload
? 優(yōu)點(diǎn):無需額外依賴,配置簡(jiǎn)單。
?? 缺點(diǎn):每次更新需 reload,不適合高頻操作。
三、方案二:OpenResty + Lua(推薦用于自動(dòng)化)
如果你需要通過 API 實(shí)時(shí)封禁 IP(例如 WAF、風(fēng)控系統(tǒng)調(diào)用),OpenResty 是最佳選擇。它基于 Nginx,嵌入 Lua 腳本引擎,支持共享內(nèi)存,無需 reload 即可生效。
1. 安裝 OpenResty
# Ubuntu 示例 wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add - echo "deb http://openresty.org/package/debian $(lsb_release -sc) openresty" | sudo tee /etc/apt/sources.list.d/openresty.list sudo apt update && sudo apt install openresty
2. 配置 nginx.conf
http {
lua_shared_dict ip_blacklist 10m; # 共享內(nèi)存存儲(chǔ)黑名單
server {
listen 80;
# 【核心】訪問前檢查 IP
access_by_lua_block {
local ip = ngx.var.remote_addr
if ngx.shared.ip_blacklist:get(ip) then
ngx.log(ngx.WARN, "Blocked IP: ", ip)
ngx.exit(403)
end
}
# 動(dòng)態(tài)封禁接口(建議加 IP 白名單保護(hù))
location = /ban {
content_by_lua_block {
local args = ngx.req.get_uri_args()
local ip = args.ip
local seconds = tonumber(args.seconds) or 3600
if not ip or not ip:match("^%d+%.%d+%.%d+%.%d+$") then
ngx.status = 400
ngx.say("Invalid or missing 'ip'")
return
end
ngx.shared.ip_blacklist:set(ip, true, seconds)
ngx.say("Banned ", ip, " for ", seconds, "s")
}
}
# 解封 & 查詢接口
location / { echo "Hello! Your IP: $remote_addr"; }
}
}
3. 使用示例
# 封禁 IP 5 分鐘 curl "http://your-server/ban?ip=1.2.3.4&seconds=300" # 測(cè)試是否被封 curl http://your-server/ # 返回 403
? 優(yōu)點(diǎn):毫秒級(jí)生效、支持 TTL 自動(dòng)過期、可集成到自動(dòng)化系統(tǒng)。
?? 安全提示:務(wù)必限制 /ban 接口的訪問來源!
四、方案三:fail2ban + Nginx 日志(自動(dòng)防御)
適用于防御暴力 破解、高頻 404 掃描等行為。fail2ban 會(huì)監(jiān)控日志,自動(dòng)封禁異常 IP。
1. 確保 Nginx 記錄詳細(xì)日志
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status ...'; access_log /var/log/nginx/access.log main;
2. 創(chuàng)建過濾器 /etc/fail2ban/filter.d/nginx-bad-request.conf
[Definition] failregex = ^<HOST> -.*"(GET|POST).*" 404 .* ignoreregex =
3. 配置 jail(/etc/fail2ban/jail.local)
[nginx-bad-request] enabled = true port = http,https filter = nginx-bad-request logpath = /var/log/nginx/access.log maxretry = 10 # 10 次失敗 findtime = 600 # 在 10 分鐘內(nèi) bantime = 3600 # 封 1 小時(shí) action = iptables-multiport[name=nginx, port="http,https"]
4. 啟動(dòng)并查看狀態(tài)
sudo systemctl start fail2ban sudo fail2ban-client status nginx-bad-request
? 優(yōu)點(diǎn):全自動(dòng)、成熟穩(wěn)定、社區(qū)支持好。
?? 注意:默認(rèn)使用 iptables 封禁,影響整個(gè)服務(wù)器,非僅 Nginx。
五、如何選擇?
- 只想偶爾手動(dòng)封幾個(gè) IP? → 用 方案一(原生 Nginx)。
- 需要程序自動(dòng)封禁、支持 API 調(diào)用? → 用 方案二(OpenResty)。
- 想自動(dòng)防御掃描、爆破? → 用 方案三(fail2ban)。
進(jìn)階技巧:可讓 fail2ban 調(diào)用 OpenResty 的 /ban 接口,實(shí)現(xiàn)“僅封 Nginx + 自動(dòng)過期”的完美組合。
以上就是在Nginx中實(shí)現(xiàn)動(dòng)態(tài)封禁IP的三種主流方案的詳細(xì)內(nèi)容,更多關(guān)于Nginx動(dòng)態(tài)封禁IP的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
nginx+rsync+inotify實(shí)現(xiàn)負(fù)載均衡配置方法
這篇文章主要介紹了nginx+rsync+inotify實(shí)現(xiàn)負(fù)載均衡配置方法,需要的朋友可以參考下2014-11-11
Debian系統(tǒng)下為PHP程序配置Nginx服務(wù)器的基本教程
這篇文章主要介紹了Debian系統(tǒng)下為PHP程序配置Nginx服務(wù)器的基本教程,這里使用到了FastCGI和php-fpm,需要的朋友可以參考下2015-12-12
uwsgi+nginx代理Django無法訪問靜態(tài)資源的解決
這篇文章主要介紹了uwsgi+nginx代理Django無法訪問靜態(tài)資源,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
Nginx配置Https安全認(rèn)證的實(shí)現(xiàn)
為了保障應(yīng)用的安全性,我們?cè)诩軜?gòu)網(wǎng)絡(luò)層的時(shí)候需要采用HTTPS協(xié)議。本文介紹了Nginx配置Https安全認(rèn)證的實(shí)現(xiàn),分享給大家,感興趣的可以了解一下2021-05-05
Nginx靜態(tài)文件響應(yīng)POST請(qǐng)求 提示405錯(cuò)誤的解決方法
Apache、IIS、nginx等絕大多數(shù)web服務(wù)器,都不允許靜態(tài)文件響應(yīng)POST請(qǐng)求,否則會(huì)返回“HTTP/1.1 405 Method not allowed”錯(cuò)誤2013-04-04
使用Nginx和Lua進(jìn)行JWT校驗(yàn)介紹
大家好,本篇文章主要講的是使用Nginx和Lua進(jìn)行JWT校驗(yàn)介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下2021-12-12

