多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

nats-server 如何启用 proxy_protocol 获取反向代理后的真实客户端地址

nats-server 如何启用 proxy_protocol 获取反向代理后的真实客户端地址 nats-server 如何启用 proxy_protocol 获取反向代理后的真实客户端地址【免费下载链接】nats-serverHigh-Performance server for NATS.io, the cloud and edge native messaging system.项目地址: https://gitcode.com/GitHub_Trending/na/nats-server当 nats-server 部署在 HAProxy、nginx 等反向代理之后时服务端看到的对端地址始终是代理的地址无法得知发起连接的原始客户端。nats-server 支持在客户端监听端口上启用 PROXY protocol通过配置项proxy_protocol开启后服务器会在每个客户端连接上先读取代理附加的 PROXY 头v1 文本格式或 v2 二进制格式用头中携带的真实源 IP 和端口覆盖该连接的客户端地址供认证、审计和监控使用。前提条件反向代理到 nats-server 客户端端口默认 4222的所有连接都必须以 PROXY 头开始。PROXY 头按规范以明文发送位于 TLS 握手之前nats-server 的解析逻辑也是先读头、再处理 TLS 或普通协议见 server.go 中的注释。直连 4222 端口的客户端不要发送 NATS 协议数据以外的 PROXY 头服务器对无法识别的 PROXY 头不会中断连接会把读到的字节回放给后续协议层处理但行为上等同于普通连接。PROXY 头读取有 5 秒的读超时proxyProtoReadTimeout见 client_proxyproto.go慢客户端或异常流量会在此超时后被断开。第一步在服务器配置中启用 proxy_protocol在 nats-server 配置文件中加入顶层选项proxy_protocol: true该选项在 opts.go 中被解析为Options.ProxyProtocol布尔值见 opts.go。启用后只影响客户端连接入口与proxy_required用户级代理要求同一文件中解析是不同的配置项不要混淆。如果启用该选项与 TLS 同时使用注意服务器支持两种组合TLS 必需仅 TLS 连接PROXY 头在 TLS 握手前读取测试用例 TestClientProxyProtoV1WithRequiredTLS 覆盖了这一路径。允许非 TLSallow_non_tls服务器会先嗅探第一个字节判断 TLS启用 PROXY 后该字节属于 PROXY 头本身解析完头后会用头之后的第一个字节重新判断是否为 TLS见 server.go两种连接都可以工作。第二步启动服务器并确认已生效启动 nats-server 加载配置后服务器日志中会出现一条 NOTICE 级别提示代码见 server.goPROXY protocol enabled for client connections这条日志是确认配置生效的最直接依据没有它说明配置没有被加载。验证真实客户端地址是否被提取PROXY 头解析成功后客户端结构体中的地址字段会被改写为头里的源地址server.goif addr ! nil { c.nc proxyConn{ Conn: conn, remoteAddr: addr, } // These were set already by initClient, override them. c.host addr.srcIP.String() c.port addr.srcPort }仓库中端到端测试 TestClientProxyProtoV2EndToEnd 展示了完整的验证路径可以作为操作参照启动一个ProxyProtocol: true的服务器用 TCP 客户端连接后先发送 PROXY v2 头源地址203.0.113.50:54321目的地址为本机 4222再发送 NATSCONNECT消息并读到INFO响应最后遍历服务器内部s.clients确认存在一个c.host 203.0.113.50且c.port 54321的客户端记录。线上环境对应的验证方式是确认代理端已配置proxy protocol后建立连接然后通过监控接口/connz查看该连接的cid/客户端地址是否与发起方真实地址一致Connz的实现见 monitor.go。另外开启 PROXY protocol 后服务器会调整 INFO 报文内容初始 INFO 中不再包含客户端 IP避免把代理 IP 泄漏给客户端改为在解析完 PROXY 头后补发包含真实client_ip的 INFO见 server.go 和 server.go 的注释。客户端能正常完成CONNECT并收到OK说明整个链路按预期工作。服务器接受哪些 PROXY 头解析逻辑全部在 client_proxyproto.go 中支持范围如下PROXY protocol v1文本格式形如PROXY TCP4 192.168.1.100 10.0.0.1 54321 4222\r\n必须恰好是 5 个字段协议、源 IP、目的 IP、源端口、目的端口TCP4要求两个地址都是 IPv4TCP6要求两个地址都是 IPv6::ffff:192.0.2.1这类 IPv4 映射地址可用于TCP6行总长含 CRLF不超过 107 字节PROXY UNKNOWN表示健康检查等同于 v2 的 LOCAL 命令连接按原始对端地址使用。PROXY protocol v2二进制格式12 字节固定签名版本字节为 2仅支持PROXY0x01和LOCAL0x00两种命令LOCAL同样用于健康检查传输层协议只支持 STREAMTCP地址族支持 IPv4地址数据 12 字节和 IPv636 字节UNSPEC 会跳过地址数据不支持的地址族如 Unix socket会被拒绝错误信息为unsupported PROXY protocol feature。版本自动检测服务器读取每个新连接的前 6 个字节匹配PROXY前缀走 v1 解析匹配 v2 签名前 6 字节走 v2 解析client_proxyproto.go。排查连接被断开或地址不对时看什么头解析失败服务器会记录一条 WARN 日志并关闭连接ProtocolViolationError reading PROXY protocol header from 代理地址: 错误详情具体错误串来自 client_proxyproto.go例如invalid PROXY protocol header、invalid signature、TCP4 with IPv6 address、only STREAM protocol supported等可据此判断是格式错误还是地址族不匹配。头读取超时代理没有按配置发送 PROXY 头、或网络异常导致 5 秒内未收全头部时对应客户端连接会被断开。先确认代理一侧的proxy protocol配置是否真正生效。本地直连测试不带 PROXY 头的普通 NATS 客户端仍可连接未识别的 PROXY 头字节会被回放给协议解析器见 server.go 对errProxyProtoUnrecognized的处理但其客户端地址记录为直连地址不含原始客户端信息。IPv6 映射地址双栈代理对 IPv4 客户端可能发出::ffff:x.x.x.x形式的地址这在TCP6下是合法输入不代表配置错误client_proxyproto.go。边界与限制proxy_protocol作用于客户端监听端口不影响路由route、集群、网关或 leaf 端口。读取超时 5 秒、v1 行长 107 字节、v2 仅支持 STREAM 等均为实现中固定值不可配置。该特性与proxy_required按用户要求连接经过代理是两个独立开关本文只涉及proxy_protocol。【免费下载链接】nats-serverHigh-Performance server for NATS.io, the cloud and edge native messaging system.项目地址: https://gitcode.com/GitHub_Trending/na/nats-server创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表