Nginx接受代理协议
本文介绍了如何配置NGINX和NGINX Plus以接受PROXY协议,将负载均衡器或代理的IP地址重写为PROXY协议标头中接收到的负载均衡器或代理,配置客户端IP地址的简单日志记录以及启用PROXY协议在NGINX和TC
介绍
通过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_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地址和端口反正。
先决条件
- 要接受PROXY协议v2,NGINX Plus R16和更高版本或NGINX Open Source 1.13.11和更高版本
- 要接受用于HTTP,NGINX Plus R3和更高版本或NGINX Open Source 1.5.12和更高版本的PROXY协议
- 对于TCP客户端PROXY协议支持,NGINX Plus R7和更高版本或NGINX Open Source 1.9.3和更高版本
- 接受用于TCP,NGINX Plus R11和更高版本或NGINX Open Source 1.11.4和更高版本的PROXY协议
- 默认情况下,NGINX Open Source中不包括用于HTTP和流(TCP)的Real-IP模块。有关详细信息,请参见安装NGINX开源。NGINX Plus不需要额外的步骤。
配置NGINX以接受代理协议
要配置NGINX接受PROXY协议报头中,添加proxy_protocol
参数的listen
指令在一个server
块中或块。http {}stream {}
http {
#...
服务器 {
监听 80 proxy_protocol ;
监听 443 ssl proxy_protocol ;
#...
}
}
流 {
#...
服务器 {
听 12345 proxy_protocol ;
#...
}
}
现在,您可以将$proxy_protocol_addr和$proxy_protocol_port变量用于客户端IP地址和端口,并另外配置HTTP和Stream Real-IP模块以通过客户端的IP地址和端口替换$remote_addr和$remote_port变量中的负载均衡器的IP地址。
将负载均衡器的IP地址更改为客户端IP地址
您可以将负载平衡器或TCP代理的地址替换为从PROXY协议收到的客户端IP地址。这可以通过HTTP和Stream Real-IP模块来完成。使用这些模块,$remote_addr和$remote_port变量保留客户端的实际IP地址和端口,而$realip_remote_addr和$realip_remote_port变量保留负载均衡器的IP地址和端口。
要将IP地址从负载均衡器的IP地址更改为客户端的IP地址,请执行以下操作:
- 确保已将NGINX配置为接受PROXY协议标头。请参阅配置NGINX接受PROXY协议。
- 确保您的NGINX安装包括HTTP和Stream Real-IP模块:
nginx -V 2 > &1 | grep- 'http_realip_module'nginx
-V 2 > &1 | grep- 'stream_realip_module'
如果不是,请使用这些模块重新编译NGINX。有关详细信息,请参见安装NGINX开源。NGINX Plus不需要额外的步骤。
服务器 {
#...
set_real_ip_from 192 .168.1.0 / 24 ;
#...
}
- 在上下文中,通过为伪指令指定参数,将负载均衡器的IP地址更改为从PROXY协议标头接收的客户端的IP地址:
http {}
proxy_protocol
real_ip_header
http {
服务器 {
#...
real_ip_header proxy_protocol ;
}
}
记录原始IP地址
当您知道客户端的原始IP地址时,可以配置正确的日志记录:
- 对于HTTP,配置NGINX以使用$proxy_protocol_addr带有proxy_set_header伪指令的变量将客户端IP地址传递给上游服务器:
http {
proxy_set_header X-Real-IP $ proxy_protocol_addr ;
proxy_set_header X-Forwarded-For $ proxy_protocol_addr ;
}
- 将$proxy_protocol_addr变量添加到
log_format
指令(HTTP或Stream):
- 在
http
块中:
HTTP {
#...
log_format 结合 ' $ proxy_protocol_addr - $ REMOTE_USER [ $ time_local] '
' “ $要求” $状态 $ body_bytes_sent '
' “ $ HTTP_REFERER” “ $ HTTP_USER_AGENT”' ;
}
- 在
stream
块中:
流 {
#...
log_format 基本 ' $ proxy_protocol_addr - $ REMOTE_USER [ $ time_local] '
' $协议 $状态 $ bytes_sent $ bytes_received '
' $ session_time' ;
}
用于与上游TCP连接的PROXY协议
对于TCP流,可以为NGINX和上游服务器之间的连接启用PROXY协议。要启用PROXY协议,请将proxy_protocol指令包含server
在该级别的块中:stream {}
流 {
服务器 {
监听 12345 ;
proxy_pass example.com :12345 ;
proxy_protocol 开启;
}
}
例
HTTP {
log_format 合并 ' $ proxy_protocol_addr - $ REMOTE_USER [ $ time_local] '
' “ $请求” $状态 $ body_bytes_sent '
' “ $ HTTP_REFERER” “ $ HTTP_USER_AGENT”' ;
#...
服务器 {
server_name localhost ;
听 80 proxy_protocol ;
监听 443 ssl proxy_protocol ;
ssl_certificate /etc/nginx/ssl/public.example.com.pem ;
ssl_certificate_key /etc/nginx/ssl/public.example.com.key ;
位置 / app / {
proxy_pass http:// backend1 ;
proxy_set_header 主机 $ host ;
proxy_set_header X-Real-IP $ proxy_protocol_addr ;
proxy_set_header X-Forwarded-For $ proxy_protocol_addr ;
}
}
}
流 {
log_format 基本 ' $ proxy_protocol_addr - $ REMOTE_USER [ $ time_local] '
' $协议 $状态 $ bytes_sent $ bytes_received '
' $ session_time' ;
#...
服务器 {
听 12345 ssl proxy_protocol ;
ssl_certificate /etc/nginx/ssl/cert.pem ;
ssl_certificate_key /etc/nginx/ssl/cert.key ;
proxy_pass backend.example.com :12345 ;
proxy_protocol 开启;
}
}
该示例假定NGINX前面有一个负载平衡器来处理所有传入的HTTPS流量,例如Amazon ELB。NGINX在端口443()上接受HTTPS流量,在端口12345上接受TCP流量,并接受通过PROXY协议从负载均衡器传递的客户端IP地址(和块中指令的参数)。listen 443 ssl;
proxy_protocol
listen
http {}
stream {}
NGINX终止HTTPS流量(ssl_certificate和ssl_certificate_key指令),并将解密的数据代理到后端服务器:
- 对于HTTP:
proxy_pass http://backend1;
- 对于TCP:
proxy_pass backend.example.com:12345
它包括带有proxy_set_header指令的客户端IP地址和端口。
指令中$proxy_protocol_addr指定的变量log_format还将HTTP和TCP的客户端IP地址传递到日志。
此外,TCP服务器(该块)将其自己的PROXY协议数据发送到其后端服务器(该指令)。stream {}
proxy_protocol on