nginx中ip黑白名单通过allow/deny指令配合geo/map模块实现热更新,结合real_ip处理代理ip,并可联动外部服务增强动态防护能力。

IP 黑白名单在 Nginx 中不是靠“开关式”配置实现的,而是通过 allow / deny 指令配合作用域(如 location、server 或 http)动态生效。应对网络环境变化的关键,在于让黑白名单可快速更新、不重启服务,并能区分可信来源与攻击流量。
用 geo 模块实现高效、热更新的 IP 分组管理
直接在 server 块里写大量 allow/deny 容易出错且无法热重载。推荐用 geo 模块预定义 IP 状态,再结合 map 转为变量控制访问:
- 在
http块中定义 geo 变量,例如:geo $is_blocked {<br> default 0;<br> 192.168.1.100 1;<br> 203.0.113.0/24 1;<br> include /etc/nginx/conf.d/blocked_ips.conf;<br>} - 用
map将 geo 结果映射为更明确的标记:map $is_blocked $access_granted {<br> 0 "ok";<br> 1 "denied";<br>} - 在 location 中使用:
if ($access_granted = "denied") { return 403; }(注意:仅限简单判断,避免嵌套逻辑)
黑白名单文件分离 + include 实现免 reload 更新
把 IP 列表单独存为文件(如 /etc/nginx/conf.d/whitelist.conf),便于脚本或运维工具自动维护:
- 白名单示例(只允许指定 IP 访问某接口):
location /admin {<br> allow 2001:db8::1;<br> allow 10.10.0.5;<br> deny all;<br>} - 黑名单示例(全局拦截):
http {<br> include /etc/nginx/conf.d/blacklist.conf;<br> server { ... }<br>},其中blacklist.conf内容为多行deny 198.51.100.23; - 更新后执行
nginx -t && nginx -s reload即可生效,无需停服
结合 real_ip 和 X-Forwarded-For 处理代理后的真实客户端 IP
若 Nginx 前有 CDN、负载均衡或反向代理,$remote_addr 是代理地址而非真实用户 IP。需正确配置才能让黑白名单生效:
- 启用
real_ip模块(通常已编译):set_real_ip_from 10.0.0.0/8;<br>set_real_ip_from 172.16.0.0/12;<br>set_real_ip_from 192.168.0.0/16;<br>real_ip_header X-Forwarded-For;<br>real_ip_recursive on;
- 确认日志中
$remote_addr已变为真实客户端 IP,再用于 geo 或 allow/deny 判断 - 避免将不可信的
X-Forwarded-For直接信任——务必限定set_real_ip_from为已知可信代理网段
用第三方模块或外部服务增强动态响应能力
纯静态配置难以应对秒级爆发的扫描或撞库行为。可引入轻量级联动机制:
- 使用
ngx_http_auth_request_module将鉴权请求转发至内部 API(如 Python/Go 编写的黑白名单服务),支持实时查 Redis 或数据库 - 搭配 fail2ban:监听 Nginx 错误日志,自动提取高频恶意 IP,写入黑名单文件并触发 reload
- 对高频请求路径(如
/login)启用limit_req作为第一道防线,减轻黑白名单匹配压力











