nginx反向代理相关
最近在使用nginx反向代理的时候,因为是多层反向代理,遇到一些关于获取真实IP的问题,于是研究了一下反向代理的header设置,记录如下。
参考1:http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html
参考2:https://blog.csdn.net/broadview2006/article/details/54570943
环境说明
- 分别有三台服务器:Nginx Proxy1、Nginx Proxy2、Nginx Backend,都安装了nginx服务
- 三台服务器都有内外网,Proxy1反向代理到Proxy2,Proxy2反向代理到Backend,Backend返回测试数据
- 我们会模拟client对三台服务器发出请求
nginx变量:remote_addr
我们先来了解一下nginx中的remote_addr变量
Proxy1 nginx配置如下
1 | location /test { |
Proxy2 nginx配置如下
1 | location /test { |
Backend nginx配置如下
1 | location /test { |
从Client服务器上请求如下地址,观察返回结果
- remote_addr:192.168.0.201
- remote_addr:192.168.0.201
- remote_addr:192.168.0.201
- remote_addr:192.168.0.201
- remote_addr:50.50.50.210
- remote_addr:192.168.0.210
从上面的请求结果可以看出
- remote_addr表示请求本服务器的上一层服务器或client的ip,比如用户请求过来那就是用户的ip,代理服务器方向代理过来,那就是反向代理服务器的ip
- 如果请求本服务器的内网,那就是取上一层服务器或client的内网ip
- 如果请求本服务器的外网,那就是取上一层服务器或client的外网ip
nginx反向代理:request header自动转发
Proxy1 nginx配置如下
1 | location /test { |
Proxy2 nginx配置如下
1 | location /test { |
Backend nginx配置如下
1 | location /test { |
从Client服务器上请求如下地址,观察返回结果
- remote_addr:192.168.0.201 || http_x_real_ip:50.50.50.210
从上面的请求结果可以看出
- 我们只在第一层proxy服务器Proxy1上反向代理中设置了header “X-Real-IP”(设置为$remote_addr)
- 在第二层proxy服务器Proxy2上,我们并没有设置header “X-Real-IP”
- 但是在backend中,我们却返回了正确的header值 $http_x_real_ip
- 说明request header在反向代理服务器中是自动转发到后面服务器的,参考如下官方说明:
- http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html#proxy_set_header
nginx反向代理:Host header
默认情况下,反向代理中Host header会被重新设置,默认如下:
1 | proxy_set_header Host $proxy_host; |
即都重新设置成proxy请求的Host,我们可以实验一下
Proxy1 nginx配置如下
1 | location /test { |
Proxy2 nginx配置如下
1 | location /test { |
Backend nginx配置如下
1 | location /test { |
从Client服务器上请求如下地址,观察返回结果
- host:192.168.0.202 || remote_addr:192.168.0.201 || http_x_real_ip:50.50.50.210
- host:192.168.0.202 || remote_addr:192.168.0.201 || http_x_real_ip:192.168.0.210
- host:192.168.0.202 || remote_addr:192.168.0.201 || http_x_real_ip:
- host:192.168.0.202 || remote_addr:192.168.0.201 || http_x_real_ip:
- host:50.50.50.202 || remote_addr:50.50.50.210 || http_x_real_ip:
- host:192.168.0.202 || remote_addr:192.168.0.210 || http_x_real_ip:
从上面的请求结果可以看出
- Proxy1发送给Proxy2的Host header为”192.168.0.201”,Proxy2发送给Backend的Host header为”192.168.0.202”
- 即host header默认会被设置成proxy请求的host
如果想在backend服务器中收到原始用户发送过来的Host header,那么做如下配置即可
Proxy1 nginx配置如下
1 | location /test { |
Proxy2 nginx配置如下
1 | location /test { |
Backend nginx配置如下
1 | location /test { |
从Client服务器上请求如下地址,观察返回结果
- host:50.50.50.200 || remote_addr:192.168.0.201 || http_x_real_ip:50.50.50.210
- host:192.168.0.200 || remote_addr:192.168.0.201 || http_x_real_ip:192.168.0.210
- host:50.50.50.201 || remote_addr:192.168.0.201 || http_x_real_ip:
- host:192.168.0.201 || remote_addr:192.168.0.201 || http_x_real_ip:
- host:50.50.50.202 || remote_addr:50.50.50.210 || http_x_real_ip:
- host:192.168.0.202 || remote_addr:192.168.0.210 || http_x_real_ip:
从上面的请求结果可以看出
- 在backend服务器中收到了原始用户发送过来的Host header
nginx反向代理:X-Real-IP 和 X-Forwarded-For
前面我们其实已经试验过,通过设置X-Real-IP来获取用户真实的ip
下面我们通过设置X-Forwarded-For来获取ip
- proxy_add_x_forwarded_for变量解释:
- proxy_add_x_forwarded_for将remote_addr变量值添加在客户端“X-Forwarded-For”请求头的后面,并以逗号分隔。 如果客户端请求未携带“X-Forwarded-For”请求头,proxy_add_x_forwarded_for变量值将与remote_addr变量相同。
- 简单点说,就是:proxy_add_x_forwarded_for = http_x_forwarded_for + remote_addr
Proxy1 nginx配置如下
1 | location /test { |
Proxy2 nginx配置如下
1 | location /test { |
Backend nginx配置如下
1 | location /test { |
从Client服务器上请求如下地址,观察返回结果
- host:50.50.50.210 || remote_addr:192.168.0.201 || http_x_real_ip:50.50.50.210 || http_x_forwarded_for:50.50.50.210, 192.168.0.200
- host:192.168.0.200 || remote_addr:192.168.0.201 || http_x_real_ip:192.168.0.210 || http_x_forwarded_for:192.168.0.210, 192.168.0.200