排查IP白名单拦截问题,关键在于确认请求到达时实际匹配的IP及被拦层级:先验证真实客户端IP是否被代理覆盖(需配置set_real_ip_from和real_ip_header),再分层检查网络入口、系统防火墙、服务监听、应用层规则;同时排除健康检查探针误伤,并用贴近真实路径的curl测试验证。

排查IP白名单拦截问题,关键不是“看规则写了没”,而是确认请求到达时实际匹配的是哪个IP、在哪一层被拦下。白名单失效往往不是配置错,而是链路中某处IP变了、策略没生效、或检查点根本没走到。
先确认真实客户端IP有没有被代理覆盖
很多问题根源在于Nginx或应用日志里看到的$remote_addr其实是SLB、CDN或反向代理的IP,不是用户真实出口IP。白名单如果只写allow 203.0.113.25;,但实际进来的请求头是X-Forwarded-For: 203.0.113.25,而Nginx没做IP还原,那永远不匹配。
- 检查Nginx是否启用
set_real_ip_from,把可信代理网段加进去,例如:set_real_ip_from 10.0.0.0/8; - 确认
real_ip_header设为X-Forwarded-For或X-Real-IP(按你前端设备实际发的头) - 验证生效:在日志中加
$realip_remote_addr字段,看它是否已变成真实IP
分层定位拦截发生在哪一层
Linux服务访问路径通常是:网络入口 → 系统防火墙(iptables/firewalld)→ 服务监听端口(如sshd、nginx)→ 应用层控制(如Nginx allow/deny)。每一层都可能独立拦截,需逐层排除。
- 用
tcpdump -i any port 22 or port 80抓包,看目标IP的SYN包是否发到服务器——没到,说明被网络设备或云平台ACL拦了 - 查防火墙:运行
iptables -L INPUT -n --line-numbers或firewall-cmd --list-all,确认白名单规则存在且顺序正确(DROP默认策略下,allow必须在deny前) - 查服务监听:用
ss -tlnp | grep :22确认sshd确实在监听,且没绑定127.0.0.1导致只响应本地 - 查Nginx是否真加载了allow规则:执行
nginx -T 2>/dev/null | grep -A2 -B2 'allow\|deny',看规则是否出现在生效的server/location块中
注意健康检查与内部探针的误伤
负载均衡器、K8s Ingress、云厂商SLB常自带健康检查,它们用固定内网IP(如100.64.0.1、192.168.0.100)定期GET某个路径。如果你的白名单没包含这些地址,它们会持续失败,进而触发下线或告警,但你却以为是业务访问被拦。
- 查Nginx access.log,过滤出返回403的请求,看
remote_addr是不是一批相似的内网IP - 查云控制台或Ingress配置,确认健康检查源IP段,并将其加入白名单(如
allow 100.64.0.0/10;) - 对后台接口,可单独配一个不校验IP的
location /healthz { return 200; },避免和业务逻辑耦合
验证方式要贴近真实请求路径
用curl -v http://your-domain.com/admin测试,和用浏览器访问结果可能完全不同——浏览器带Cookie、User-Agent,还可能走HTTP/2;而curl默认最简。更可靠的方式是模拟全链路:
- 从目标白名单IP机器上执行:
curl -I -x "" http://localhost:8080/path(绕过代理) - 若用域名访问,加
--resolve domain.com:80:目标服务器IP,跳过DNS干扰 - 对比
curl -H "X-Forwarded-For: 203.0.113.25" http://localhost/和不带头的结果,验证real_ip配置是否起效


















