本文介绍了如何配置 NGINX 和 NGINX Plus 以接受 PROXY 协议,将负载平衡器或代理的 IP 地址重写为在 PROXY 协议头中接收到的 IP 地址,配置客户端 IP 地址的简单日志记录,启用 NGINX 和 TCP upstream 服务器之间的 PROXY 协议。
PROXY 协议允许 Nginx 和 Nginx Plus 接受来自代理服务器和负载平衡器的客户端连接信息,比如 HAproxy 和 Amazon Elastic Load Balancer (ELB) 通过 PROXY 协议,Nginx 可以从 HTTP,SSL,HTTP / 2,SPDY,WebSocket 和 TCP 中获取到源 IP 地址。获取到客户端的源 IP 地址,可以在为网页指定语言、设置 IP 黑名单或只是简单的日志和统计分析。 通过 PROXY 协议传输的数据是客户端的 IP 地址、代理服务器的 IP 地址和所有的端口号。Nginx 可以通过这个数据使用几种不同方法获取到客户端的源 IP 地址:
$proxy_protocol_addr 和 $proxy_protocol_addr_port 变量保存客户端源 IP 地址和端口。$remote_addr 和 $remote_port 变量保存负载平衡服务器的 IP 和端口。使用 realip 模块将 $remote_addr 和 $remote_port 变量从负载平衡器的IP和端口重写为原始客户端 IP 地址和端口。 $realip_remote_addr 和 $realip_remote_port 端口变量将保留负载均衡器的地址和端口,$proxy_protocol_addr 和 $proxy_protocol_port 变量将始终保留原始客户端 IP 和端口。要配置 Nginx 接受 PROXY 协议头,请将 proxy_protocol 参数添加到 http 或 stream 的 listen 指令中:
http { ... server { listen 80 proxy_protocol; listen 443 ssl proxy_protocol; ... } }对 TCP stream 流的配置:
stream { ... server { listen 12345 proxy_protocol; ... } }现在可以使用表示客户端 IP 地址和端口的 $proxy_protocol_addr 和 $proxy_protocol_port 变量,另外还可以配置 HTTP realip 或 stream realip 模块以将负载均衡器的 IP 替换为 $remote_addr 和 $remote_port 变量中的客户端 IP。
可以将负载均衡器的 IP 地址改为从 PROXY 协议接收到的客户端 IP 地址。这可以通过 ngx_http_realip_module 和 ngx_stream_realip_module 模块来实现。通过这些模块,$remote_addr 和 $remote_port 变量保存客户端源 IP 地址和端口。$realip_remote_addr 和 $realip_remote_port 变量保存负载平衡服务器的 IP 和端口。
如果没有这些模块,可以编译包含这些模块的 Nginx,参考这里。
当知道客户端的原始 IP 地址时,可以配置正确的日志记录:
通过 proxy_set_header 指令和 $proxy_protocol_addr 变量,可以把 Nginx 的客户端 IP 地址发送到 upstream 服务器:
proxy_set_header X-Real-IP $proxy_protocol_addr; proxy_set_header X-Forwarded-For $proxy_protocol_addr;对于 http 或 stream,可以使用 log_format 指令和 $proxy_protocol_addr 变量:
对于 TCP 数据流,可以开启在 Nginx 和一台上游服务器(upstream server)之间的 PROXY 协议。在 stream{} 上下文中的 server 块中添加 proxy_protocol 指令即可:
stream { server { listen 12345; proxy_pass example.com:12345; proxy_protocol on; } }这个例子假设 Nginx 前面有负载平衡器(例如,亚马逊 ELB)平衡所有传入的 HTTPS 流量。Nginx 接受端口 443 的 HTTPS 流量,端口 12345 的 TCP 流量,并接受 PROXY 协议(http {} 和 stream {} 块中的 listen 指令中的 proxy_protocol 参数)。
Nginx 终止 HTTPS 流量(ssl_certificate 和 ssl_certificate_key 指令),将解密后的数据发送到包括客户端的 IP 地址和端口(proxy_set_header 指令值)的后台服务器(对于http {} 使用 proxy_pass http://backend1;,对于 stream {} 使用 proxy_pass backend.example.com:12345)。
log_format 指令中指定的 proxy_protocol_addr 变量也会将客户端 IP 地址传给 http {} 和 stream {} 块中的日志。
此外,TCP 服务器(stream {} 块)发送自己的 PROXY 协议的流量到后端服务器(proxy_protocol 指令设置为 on)。
