必须把allow放在deny all之前,且网段须精确匹配CIDR格式,否则白名单失效;因Nginx按顺序逐行匹配、命中即终止,deny all写在前面会导致后续allow永不执行,且需配合set_real_ip_from与real_ip_header才能基于真实IP控制访问。

直接说结论:必须把 allow 放在 deny all 之前,且网段写法要精确匹配 CIDR 格式,否则白名单形同虚设。
为什么 allow 10.0.0.0/16 有时不生效
根本原因是 Nginx 的 allow/deny 指令严格按顺序逐行匹配,一旦命中就终止判断。常见错误是把 deny all 写在前面,或者混用不同层级(http 块里写了 allow,又在 location 里重复写但顺序错乱)。
- 错误示例:
deny all; allow 10.0.0.0/16;→ 所有请求在第一行就被拒绝,第二行永不执行 - 正确顺序必须是:所有
allow在前,deny all作为兜底且唯一放在最后 -
/16表示前 16 位固定,即10.0.0.0到10.0.255.255;写成10.0.0.0/24就只放行10.0.0.0–10.0.0.255,容易漏掉运维同事的真实出口网段
location /admin 块里配置的典型陷阱
管理后台路径往往带前缀(如 /admin、/manage、/wp-admin),但很多人忽略 location 匹配的优先级和继承规则:
- 如果
server块里已写deny all,而location /admin里只写allow 10.0.0.0/16,Nginx 会先匹配外层 deny,内层 allow 不起作用 - 务必确保
location /admin块中完整包含白名单 + 兜底,不要依赖外层设置 - 示例正确写法:
location /admin {<br> allow 10.0.0.0/16;<br> allow 172.16.0.0/12;<br> deny all;<br> proxy_pass http://backend_admin;<br>}
如何验证网段是否真被放行
不能只靠 curl 测试单个 IP,得覆盖边界值和常见误配场景:
- 用真实客户端从
10.0.255.255(/16 最大地址)发起请求,确认返回 200 而非 403 - 故意用
10.1.0.1(超出 /16 范围)测试,必须返回 403 - 检查 Nginx 错误日志:
tail -f /var/log/nginx/error.log,若看到access forbidden by rule,说明规则已加载但未匹配到允许项 - 注意:如果前端有 CDN 或反向代理(如阿里云 SLB),
$remote_addr是代理 IP,需配合real_ip_header X-Forwarded-For;和set_real_ip_from才能拿到真实客户端网段
最易被忽略的一点:Nginx 不校验网段合法性,allow 10.0.0.0/33 这种非法掩码不会报错,但会导致整个规则块失效——配置后务必用 nginx -t 验证,再用真实流量交叉验证。


















