阿里云 SLB 用 TCP 模式转发到 nginx,应用日志里的客户端 IP 全是 100.64 开头的内网地址,风控按 IP 限流失效,攻击来源也追不到。

一开始怀疑是「SLB 没开启 proxy protocol v2,后端根本没有原始地址可用」,查了一圈,方向不对。

原因不止一个,得分开看。四层转发只改目的地址,不做应用层头注入,源 IP 在 nginx 看来就是 SLB 的地址。少数情况下是nginx 的 realip 模块没配 set_real_ip_from,拿不到 proxy protocol 里的原始地址。

另外,后端是容器,NodePort 又做了一次 SNAT,地址被换了两遍。

上来先确认 ngx_http_realip 模块是否编译进来

nginx -V 2>&1 | tr ' ' '\n' | grep -i realip

随后在 SLB 监听上开启 proxy protocol

aliyun slb SetListenerAttribute --LoadBalancerId lb-xxx --ListenerPort 80 --AclId '' --Protocol tcp

nginx 里信任来源并取真实地址

printf 'set_real_ip_from 100.64.0.0/10;\nreal_ip_header proxy_protocol;\n' > /etc/nginx/conf.d/realip.conf && nginx -t && nginx -s reload

等前面都确认过,再确认日志里已经出现外部客户端 IP

tail -5 /var/log/nginx/access.log | awk '{print $1}'

恢复的判定其实很直接。access.log 第一列变成真实客户端公网地址,风控的限流阈值按 IP 生效,抓包能看到 proxy protocol 头被正确解析。

提醒一点。开 proxy protocol 之后,未经 SLB 直连后端的健康检查会失败,源站端口最好只对 SLB 网段开放;七层模式没有这个问题。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189