如何配置Nginx默认拒绝访问,仅允许LAN用户免登录(基于X-Forwarded-For)
Nginx 基于 X-Forwarded-For 的访问控制优化需求
我们的Nginx运行在Docker容器中,流量通过pfSense上的HAProxy反向代理转发,需要实现局域网用户免登录、外部用户需登录的访问控制逻辑。
当前配置的问题
- 初始使用Docker Desktop时,外部访问的来源IP显示为Docker网关IP
172.17.0.1,因此配置set_real_ip_from 172.17.0.1来获取真实客户端IP; - 切换到Docker Engine后,外部访问的来源IP变为反向代理IP
192.168.1.1,不得不修改set_real_ip_from的值; - 核心安全隐患:若反向代理IP发生变更,Nginx无法正确获取真实客户端IP,会误将外部用户识别为局域网用户,直接允许免登录访问。
需求
将配置修改为默认拒绝访问,仅允许局域网用户免登录;同时确认两个问题:
- 是否需要开启
real_ip_recursive? - 有无其他替代方案(比如基于PHP的登录工具)?
现有Nginx配置
real_ip_header X-Forwarded-For; # IPs trusted to forward the visitor's remote IP (our reverse proxy) set_real_ip_from 172.17.0.1; set_real_ip_from 192.168.1.1; location / { satisfy any; # Allow visitors inside the LAN to access the site without a login allow 10.0.0.0/8; allow 127.0.0.1/32; allow 172.16.0.0/12; allow 192.168.0.0/16; # Require a login for visitors outside the LAN deny all; auth_basic "Login required"; auth_basic_user_file /etc/nginx/.htpasswd; # Basic config root /usr/share/nginx/html; index index.html; }
解决方案
1. 修正Nginx配置实现默认拒绝逻辑
调整配置,确保默认拒绝所有访问,仅对可信代理和局域网IP开放:
# 指定真实IP来源头部 real_ip_header X-Forwarded-For; # 开启递归解析:多级代理场景下,从X-Forwarded-For列表中筛选真实客户端IP real_ip_recursive on; # 仅保留当前实际使用的反向代理IP,避免冗余配置 set_real_ip_from 192.168.1.1; location / { # 默认拒绝所有访问 deny all; # 局域网IP免登录规则:同时满足IP允许+关闭认证 satisfy all; allow 10.0.0.0/8; allow 127.0.0.1/32; allow 172.16.0.0/12; allow 192.168.0.0/16; auth_basic off; # 外部用户登录验证块 location @external_login { auth_basic "Login required"; auth_basic_user_file /etc/nginx/.htpasswd; root /usr/share/nginx/html; index index.html; } # 非局域网IP跳转至登录验证 if ($remote_addr !~ ^(10\.|127\.0\.0\.1|172\.16\.|192\.168\.)) { rewrite ^ @external_login last; } # 局域网用户基础站点配置 root /usr/share/nginx/html; index index.html; }
2. 关于real_ip_recursive的说明
- 开启后,Nginx会解析
X-Forwarded-For中的IP列表,从最后一个IP开始校验,跳过所有在set_real_ip_from中的可信代理IP,最终取第一个非可信IP作为真实客户端IP; - 即便当前只有HAProxy一级代理,开启该参数也能避免恶意用户伪造
X-Forwarded-For头部绕过IP验证,同时兼容未来可能的多级代理场景,建议开启。
3. 替代方案:基于PHP的登录工具
如果需要更灵活的用户管理能力(如角色权限、会话持久化、密码找回等),可以用PHP实现登录系统:
- 逻辑:PHP先检查客户端IP是否属于局域网,是则直接放行;否则校验会话状态,未登录则跳转至登录页面;
- 注意:PHP获取真实IP时,需先验证
HTTP_X_FORWARDED_FOR头部是否来自可信代理,避免被伪造。
内容的提问来源于stack exchange,提问作者Danny Beckett
相关产品推荐
相关产品推荐

