Nginx 全局 IP 屏蔽应使用 http 块中的 geo 指令定义黑名单,支持 IPv4/IPv6 和 CIDR,配合 map 或 if 返回 403;可通过独立文件集中管理,并结合 real_ip 模块还原代理后的真实 IP,确保 set_real_ip_from 仅含可信网段。

在 Nginx 中实现全局 IP 屏蔽,核心是利用 ngx_http_geo_module(内置模块)配合 ngx_http_map_module 或直接使用 deny 指令,将屏蔽逻辑统一定义在顶层上下文(如 http 块),避免在每个 server 或 location 中重复配置。
使用 geo 指令定义屏蔽名单(推荐)
geo 指令天然支持 IP 匹配,且在 http 块中定义后可被所有 server 复用。它比多次写 deny 更高效、更易维护。
- 在
http块中添加:
geo $blocked_ip {
default 0;
192.168.1.100 1;
203.0.113.42 1;
2001:db8::1 1; # 支持 IPv6
192.168.5.0/24 1; # 支持 CIDR
}- 再配合
map或直接在server中使用:
server {
if ($blocked_ip) {
return 403;
}
# 其他配置...
}注意:if 在 server 级别可用,但不建议在 location 内频繁使用;更稳妥的方式是结合 map 转为变量后用 deny:
map $blocked_ip $should_deny {
1 "1";
0 "";
}
server {
deny $should_deny;
# 或者:if ($blocked_ip) { return 403; }
}集中管理黑名单文件(适合大量 IP)
把 IP 列表抽离到独立文件(如 /etc/nginx/conf.d/blacklist.conf),便于脚本自动更新:
- 创建黑名单文件:
# /etc/nginx/conf.d/blacklist.conf
geo $blocked_ip {
default 0;
include /etc/nginx/ip-blacklist.txt;
}- 在
/etc/nginx/ip-blacklist.txt中按行写入:
192.168.10.5 203.0.113.0/24 2001:db8::/32
- 确保该文件被
http块包含(Nginx 配置中已有include conf.d/*.conf;即可) - 每次更新后执行
nginx -t && nginx -s reload
配合 real_ip 模块处理代理后的真实 IP
如果流量经过 CDN 或反向代理(如 Cloudflare、SLB),客户端真实 IP 在 X-Forwarded-For 或 X-Real-IP 头中,需先还原再屏蔽:
- 启用
real_ip模块(通常已编译):
set_real_ip_from 10.0.0.0/8; # 你的可信代理网段 set_real_ip_from 172.16.0.0/12; set_real_ip_from 192.168.0.0/16; real_ip_header X-Forwarded-For; real_ip_recursive on;
- 然后基于
$remote_addr(此时已是真实 IP)做 geo 判断 - 务必确认
set_real_ip_from只包含可信代理,否则可被伪造绕过
验证与调试技巧
屏蔽规则生效前务必验证,避免误杀:
- 用
nginx -t检查语法,特别注意 CIDR 格式和缩进 - 临时加一条测试规则:
geo $test_ip { default 0; 127.0.0.1 1; },再用本地 curl 测试返回 403 - 查看错误日志:
tail -f /var/log/nginx/error.log,留意 geo 匹配警告 - 用
curl -H "X-Forwarded-For: 192.168.1.100" http://your-site/模拟代理请求


















