必须在location块中按序配置allow指令并以deny all结尾,代理环境需通过set_real_ip_from和real_ip_header还原真实ip,推荐用geo+include提升可维护性。

要让 Nginx 只允许内网特定网段访问运维管理后台(比如 /admin 或 /manage),核心是用好 allow 和 deny all 指令,严格控制位置、顺序和真实 IP 获取方式。
必须在 location 块里写规则
管理后台路径有明确前缀,比如 /admin、/manage/,所有访问控制必须落在对应 location 块内部,不能写在 http 或 server 顶层。否则可能误锁其他路径,或被外层规则覆盖。
- 推荐用
location ^~ /admin/,匹配以/admin/开头的请求,优先级高、不走正则,更稳定 - 避免写成
location /admin(末尾无斜杠),它会意外匹配/administer等无关路径 - 示例正确写法:
location ^~ /admin/ {
allow 10.20.0.0/16;
allow 172.16.100.0/24;
deny all;
proxy_pass http://backend;
}
allow 必须在 deny all 之前,且顺序不能错
Nginx 的 allow/deny 是按行从上到下匹配,命中即停。一旦先写 deny all,后面所有 allow 都不会执行。
- 错误写法:
deny all; allow 10.20.0.0/16;→ 所有请求直接 403 - 正确写法:所有
allow行在前,deny all;必须且只能写在最后 - 每个网段单独一行,不要合并;支持 IPv4 和 IPv6,如
allow 2001:db8::/32;
代理环境下必须拿到真实客户端 IP
如果 Nginx 前面有 SLB、CDN、Traefik 或云 WAF,$remote_addr 是代理地址,直接 allow 就会失效。
- 确认前端透传了
X-Forwarded-For头,并确保该头可信(已在代理层清洗) - 在
http或server块开头加两行:
set_real_ip_from 10.100.0.0/16; # 替换为你的可信代理网段
real_ip_header X-Forwarded-For;
- 再配合
geo模块预判更稳妥(尤其多网段时):
geo $real_ip_allowed {
default 0;
10.20.0.0/16 1;
172.16.100.0/24 1;
}
location ^~ /admin/ {
if ($real_ip_allowed = 0) { return 403; }
proxy_pass http://backend;
}
验证和避坑要点
- 网段掩码必须合法准确:比如
10.20.0.0/16覆盖到10.20.255.255,写成/24就漏掉大部分运维出口 - 非法掩码如
/33不报错但整条规则静默失效,每次改完必须运行nginx -t - 测试不能只用本地
127.0.0.1,要用真实不同网段机器 curl,覆盖边界 IP(如10.20.255.255和10.21.0.1) - 被拒请求默认返回 403,如需隐藏路径存在性,可改用
return 444;(直接断连)











