发布于2小时前2小时 背景:同一个接口,为什么测试结果不一致?一个典型求助场景:业务通过 Nginx 发布接口,管理员给 /internal/ 配置了内网地址白名单。授权测试时,不带特殊请求头返回 403,加上 X-Forwarded-For: 10.20.30.40 却返回 200。这类问题先别急着归因于应用鉴权失效。更常见的原因是:Nginx 错误信任了客户端提供的来源地址,随后又把这个地址用于访问控制。下面用仅监听本机的实验复现,并说明生产环境怎么定位、怎么修。测试范围仅限自建环境或明确授权的系统。验证使用无敏感内容的静态文件,不需要访问真实管理接口或读取业务数据。问题定位:先确定是谁返回了 403画出实际链路:测试端 → 负载均衡或反向代理 → Nginx → 应用。确认每一跳是否追加、覆盖或透传来源地址头。检查 Nginx 生效配置,而不是只看某个配置文件:使用 nginx -T,重点搜索 set_real_ip_from、real_ip_header、real_ip_recursive、allow 和 deny。对照访问日志与错误日志。标准访问控制模块拒绝时,错误日志通常能看到 access forbidden by rule。应用返回的 403 则需要结合上游状态和应用日志判断。确认是否存在更具体的 location、重写或代理规则,使两个请求实际上走了不同路径。注意:nginx -T 输出可能包含内部域名、上游地址等信息。发到问答帖之前应脱敏,但要保留相关指令的作用域和先后关系。技术分析:IP 白名单检查的地址可能已经被改写Nginx 的 Real IP 模块可以根据受信代理提供的请求头替换客户端地址。配置中的几个字段分别决定:set_real_ip_from:哪些连接来源有资格声明原始客户端地址。real_ip_header:从哪个请求头读取地址。real_ip_recursive:存在多跳代理时,如何沿地址链寻找非受信地址。问题往往出在把 set_real_ip_from 写成了 0.0.0.0/0。这样任意 IPv4 连接来源都被当成可信代理。Real IP 模块改写地址后,allow/deny 就可能按照请求者自己填写的地址作出判断。real_ip_recursive on 不是防伪开关。真正的安全边界是可信代理名单,以及可信代理是否正确处理外部传入的地址头。操作步骤:在本机复现错误配置实验需要安装带有 http_realip_module 的 Nginx。先检查构建参数;如果未包含该模块,下面配置会报未知指令。nginx -V 2>&1 | grep -- --with-http_realip_module mkdir -p /tmp/acl-lab/internal printf 'authorized lab only\n' > /tmp/acl-lab/internal/check.txt cat > /tmp/acl-lab/nginx.conf <<'EOF' worker_processes 1; pid /tmp/acl-lab/nginx.pid; error_log /tmp/acl-lab/error.log notice; events { worker_connections 128; } http { log_format acl '$time_iso8601 peer=$realip_remote_addr ' 'effective=$remote_addr xff="$http_x_forwarded_for" ' 'status=$status request="$request"'; access_log /tmp/acl-lab/access.log acl; server { listen 127.0.0.1:8080; server_name localhost; root /tmp/acl-lab; # 故意错误的实验配置,禁止照搬到生产环境。 set_real_ip_from 0.0.0.0/0; real_ip_header X-Forwarded-For; real_ip_recursive on; location /internal/ { allow 10.20.30.0/24; deny all; try_files $uri =404; } } } EOF nginx -t -p /tmp/acl-lab/ -c /tmp/acl-lab/nginx.conf nginx -p /tmp/acl-lab/ -c /tmp/acl-lab/nginx.conf # 本机地址不在白名单,预期 403。 curl --noproxy '*' -i # 错误信任请求头后,预期 200,响应仅为实验文本。 curl --noproxy '*' -i \ -H 'X-Forwarded-For: 10.20.30.40' \ cat /tmp/acl-lab/access.log # 实验结束后停止独立实例。 nginx -s stop -p /tmp/acl-lab/ -c /tmp/acl-lab/nginx.conf这里用静态文件产生响应,没有在 location 中写 return 200。原因是 return 在重写阶段就可能结束请求,用它验证 allow/deny 容易得出错误结论。日志应该怎么看?第二次请求中,日志通常会同时出现:peer=127.0.0.1 effective=10.20.30.40 xff="10.20.30.40" status=200$realip_remote_addr 保留 Real IP 改写前的连接地址,$remote_addr 则是改写后供后续处理使用的地址。两者结合,才能看出请求实际上由本机发起,却以白名单地址通过了检查。单独看到 X-Forwarded-For 中有内网地址,并不能证明存在漏洞。应同时具备三项证据:连接来源不应被放行、有效客户端地址被不可信输入改写、访问结果因此发生变化。风险与修复建议如果服务直接接收客户端连接,没有可信反向代理,应移除不必要的 Real IP 配置,按连接地址执行网络访问控制。如果确实存在代理,假设链路为“客户端 → 边缘代理 10.20.0.10 → 后端 Nginx”,且不存在更前置的 CDN,可以采用以下配置思路:# 边缘代理:在面向客户端的入口覆盖外部传入的同名头。 # 放在相应 proxy_pass 所在的 location 中,并检查配置继承关系。 proxy_set_header X-Forwarded-For $remote_addr; # 后端 Nginx:仅信任真实代理的来源地址。 set_real_ip_from 10.20.0.10/32; real_ip_header X-Forwarded-For; real_ip_recursive on; # 后端受限路径:允许的是客户端网段,不是代理网段。 location /internal/ { allow 10.60.0.0/24; deny all; # 保留实际业务的静态文件或上游处理配置。 }这段配置只适用于上述拓扑。有 CDN、多级负载均衡或 SNAT 时,需要逐跳确认地址来源,不能直接套用。尤其不要把整段办公网、容器网段都无条件列为可信代理。通过防火墙或安全组限制后端入口,只允许实际代理访问对应业务端口,避免绕过边缘策略。管理接口保留独立身份认证和权限检查。IP 白名单是附加限制,不是管理员身份的证明。生产日志记录连接地址、有效客户端地址、请求标识和必要的上游状态;来源头属于不可信输入,日志应限制访问和保留周期。修复后至少验证:非白名单客户端正常访问被拒绝、伪造来源头仍被拒绝、合法白名单客户端经代理正常访问、直接访问后端被阻断。总结:求助时提供哪些信息最有效?这类问题的关键不是“请求里有没有内网 IP”,而是“谁有资格声明这个 IP,以及哪个组件拿它作了授权判断”。在问答中心提问时,附上脱敏链路图、相关生效配置、两组对照请求和对应日志,通常就能把问题收敛到具体一跳。只有响应码截图,没有连接来源和配置上下文,很容易把代理信任错误误判成应用鉴权漏洞。 网络请求、日志与边界流量分析示意 服务器、云资产与权限边界梳理示意
1小时前1小时 这种现象通常不是“加了 XFF 就进入内网”,而是接口把可伪造的客户端 IP 当成了访问控制依据。先区分一下:你访问的是公网入口后面的受限接口,还是服务端真的根据请求去访问另一个内网地址?前者多半是代理信任配置问题,不能仅凭这个现象判定为 SSRF。 建议用同一个接口做对照,固定登录态、请求方法和请求体,只改变 XFF。下面地址替换为授权目标: URL=' curl -i "$URL" curl -i "$URL" -H 'X-Forwarded-For: 203.0.113.10' curl -i "$URL" -H 'X-Forwarded-For: 127.0.0.1' curl -i "$URL" -H 'X-Forwarded-For: 10.0.0.1' 不要只看状态码,还要比较响应内容、业务结果和服务端日志。若只有回环或私网地址能通过,优先找“内网 IP 放行”的判断;若任意 XFF 都能通过,则更像是错误的分支判断,或者不同请求被转发到了不同后端。 有配置权限的话,重点查两处: 入口有没有覆盖客户端传来的 XFF。如果 Nginx 是唯一公网入口且直接接受客户端连接,可以用下面的方式向后端传递实际连接来源;如果前面还有 CDN/LB,则需要先按明确的代理地址范围恢复真实 IP,不能直接照搬。 location / { proxy_set_header X-Forwarded-For $remote_addr; proxy_pass } 后端信任了哪些代理。检查 Nginx 的 set_real_ip_from、real_ip_header、real_ip_recursive,以及应用框架的代理信任配置。尤其留意信任所有来源、直接读取 XFF 第一个值,或用字符串前缀匹配私网地址的代码。后端端口若能被客户端直连,入口覆盖请求头也挡不住绕过。 定位时把 TCP 对端 IP、原始 XFF、框架解析后的客户端 IP,以及最终命中的放行规则记到同一条请求日志里,基本就能确认是哪一层信错了。修复上,可信代理链要收紧;敏感接口仍应做身份和权限校验,不能仅凭“看起来是内网 IP”就放行。
创建帐户或登录后发表意见