在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值

  1. PROXY Protocol 回溯

    • 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。
    • Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息,并用 $realip_remote_addr$realip_remote_port 覆盖 $remote_addr$remote_port,下游模块获知真源地址。
  2. 兼容性

    • 对 TCP/UDP/UNIX Domain Socket(set_real_ip_from unix:)均可生效。
    • 同时支持 CIDR 方式批量信任,也可指定单 IP。
  3. 应用价值

    • 限流/黑名单:结合 limit_conn_zone $realip_remote_addr 而非代理 IP。
    • 日志真实化access_log 使用 $realip_remote_addr 记录客户端原始 IP。
    • 多层转发:当部署多级反代或自研网关时,只需在最前端开启 PROXY,即可保证中间层获得正确源地址。

二、指令解读

stream {
    # 1) 开启 PROXY Protocol 支持
    server {
        listen 12345 proxy_protocol;

        # 2) 定义可信代理网段
        set_real_ip_from 192.168.1.0/24;
        set_real_ip_from 2001:db8::/32; 
        set_real_ip_from  unix:;        # 信任本地 UNIX 域套接字

        # 3) 在此之后,$remote_addr/$remote_port 即为真实值
        proxy_pass backend;
    }
}
  • listen … proxy_protocol:必须在 listen 中开启,才会解析 PROXY 头。

  • set_real_ip_from:可多次使用,声明 信任来源,只有来自这些地址的连接才会替换。

  • 变量

    • $realip_remote_addr:保留头部中指明的客户端 IP;
    • $realip_remote_port:保留客户端端口;
    • 替换后,后续所有引用 $remote_addr 都取自 $realip_remote_addr

三、典型场景

  1. 限流与黑名单

    stream {
        limit_conn_zone $realip_remote_addr zone=ip:10m;
        server {
            listen 3306 proxy_protocol;
            set_real_ip_from 10.0.0.0/8;
            limit_conn ip 1;  # 单 IP 仅一条并发
            proxy_pass mysql-backend;
        }
    }
    
  2. 日志埋点

    stream {
        log_format realip '$realip_remote_addr:$realip_remote_port -> $server_addr';
        access_log /var/log/nginx/stream.log realip;
        server {
            listen 6379 proxy_protocol;
            set_real_ip_from 172.16.0.0/12;
            proxy_pass redis-backend;
        }
    }
    
  3. 多级代理链

    • 前端 LB → 中间网关 → Nginx Stream
    • 只在最外层 LB 输出 PROXY Protocol,后面层级都能拿到同一个真实源地址,无需在每层都开启。

四、进阶用法

  • 动态信任列表
    可结合 keyval 或 njs 动态更新 set_real_ip_from 段中 CIDR,例如根据 API 下发临时可信代理 IP。

  • 协议混合
    在同一实例可分 stream { server { listen 9000 proxy_protocol; … } } 和常规 TCP 端口并存,仅对指定端口生效。

  • 与 MQTT/HTTP 模块联动
    对于 TLS 透传 SNI(ssl_preread)或 MQTT 预读(mqtt_preread),将真实用户 IP 替换后再做鉴权或路由。

五、常见坑与排查

问题原因解决办法
$remote_addr 取到 LB IP未开启 proxy_protocolset_real_ip_from 未包含 LB 地址确认 listen … proxy_protocolset_real_ip_from 区段
IPv6 未生效忽略了 2001:db8::/32 之类 IPv6 段加入对应 IPv6 CIDR 或 ::/0(信任所有)
UNIX Socket 透传失败仅 TCP/UDP,需加 set_real_ip_from unix:指定 unix: 才信任本地套接字
多级反代仍然显示内网 IP中间层被覆盖,或上层未输出 PROXY 头确保最前层代理使用 PROXY Protocol v2,并全链路透传

六、结语

ngx_stream_realip_module 是构建 透明、可观测 四层网关的基石,可在不引入第三方组件的前提下可靠还原客户端真实源地址,为限流、鉴权、审计、灰度等上层功能提供准确数据。正确配置 proxy_protocolset_real_ip_from,即可让 Nginx 一线完成真实 IP 的回溯与替换,为复杂网络架构保驾护航。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello.Reader

请我喝杯咖啡吧😊

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值