NGINX使用Realip_module模块获取经过多级代理的用户真实来源IP

  • 2019-09-02
  • 0
  • 0

环境配置:用户请求域名dl.ljc.com经过三层代理到达应用服务器。

规划图1.png

1、nginx的安装此处跳过。

配置web端站点显示文件(只在web服务器操作)

[root@web nginx]# vim /usr/share/nginx/html/index.html 
web 10.0.0.6

2、首先测试使用一台代理的情况:

用户直接将请求发送到proxy01的代理服务器。
代理图1.png
本地host解析:

ljcdeMBP:~ root# tail -1 /etc/hosts    
10.0.0.3 dl.ljc.com

编写配置文件:

##web端配置文件
[root@web ~]# vim /etc/nginx/conf.d/default.conf 
server {
        listen 80;
        server_name dl.ljc.com;
        root /usr/share/nginx/index;

        location / {
                index index.php index.html;
                }
        }

一级代理端:

 [root@proxy01 ~]# vim /etc/nginx/conf.d/proxy.conf 
server {
    listen       80;
    server_name dl.ljc.com;
        location / {
                proxy_pass http://10.0.0.6:80;
                proxy_http_version 1.1;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
    }

在浏览器输入解析域名访问:
浏览器.png
我们再来看下web端的访问日志:

10.0.0.3 - - [10/Jun/2019:16:56:53 +0800] "GET / HTTP/1.1" 304 0 "-" "10.0.0.1"

由此可见,在本地访问web端页面,成功由服务器proxy01代理。一级代理实现。
代理转发地址为10.0.0.3,实际来源IP的10.0.0.1

3、使用两台代理的情况

新开一台proxy02的机器:
二级代理
配置文件修改如下:

[root@proxy02 ~]# vim /etc/nginx/conf.d/default.conf 
server {
    listen       80;
    server_name dl.ljc.com;

        location / {
                proxy_pass http://10.0.0.3:80;
                proxy_http_version 1.1;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
        }

修改本地host解析:

ljcdeMBP:~ root# tail -4 /etc/hosts
#10.0.0.6 dl.ljc.com
#10.0.0.5 dl.ljc.com
10.0.0.4 dl.ljc.com
#10.0.0.3 dl.ljc.com

看访问日志:

10.0.0.3 - - [10/Jun/2019:16:46:52 +0800] "GET / HTTP/1.1" 304 0 "-" "10.0.0.1, 10.0.0.4"

10.0.0.3为来源的上一级客户端IP,10.0.0.4为代理服务器,10.0.0.1为实际来源IP
抓包分析:
web抓包1.png

4、使用三台代理情况:

新加proxy03:配置如下:

[root@dl4 ~]# vim /etc/nginx/conf.d/default.conf 
server {
    listen       80;
    server_name  dl.ljc.com;
        location / {
                proxy_pass http://10.0.0.4:80;
                proxy_http_version 1.1;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                 }
        }

修改本地host解析:

ljcdeMBP:~ root# tail -4 /etc/hosts    
#10.0.0.6 dl.ljc.com
10.0.0.5 dl.ljc.com
#10.0.0.4 dl.ljc.com
#10.0.0.3 dl.ljc.com

访问后查看web端日志信息:

10.0.0.3 - - [10/Jun/2019:16:59:45 +0800] "GET / HTTP/1.1" 304 0 "-" "10.0.0.1, 10.0.0.5, 10.0.0.4"

抓包查看:
抓包一级代理.png
可以看出中间经过了3个代理转发:10.0.0.5/10.0.0.4/10.0.0.3

5、另外我们还可以使用nginx Realip_module获取多级代理下的客户端真实IP地址。

在web服务端的server区块加入以下配置:

set_real_ip_from  10.0.0.3;     ####经过的代理ip,也可以写ip地址段10.0.0.0/24
set_real_ip_from  10.0.0.4;     ####经过的代理ip
set_real_ip_from  10.0.0.5;     ####经过的代理ip
real_ip_header    X-Forwarded-For;
real_ip_recursive on;

查看日志:

10.0.0.1 - - [10/Jun/2019:17:01:50 +0800] "GET / HTTP/1.1" 304 0 "-" "10.0.0.1, 10.0.0.5, 10.0.0.4"

发现使用Realip_module模块可以把日志开头的ip地址变为来源的真实ip:10.0.0.1,实际上是把上一级代理10.0.0.3的ip给替换了。

总结:

只有客户端直接请求到的那个nginx能够拿到客户端的真实IP,所以第一级代理配置了proxy_set_header X-Real-IP $remote_addr;所以其余均未配置。这个配置就会将客户端IP放到http的header里,这样到最后的应用里可以通过request.getHeader去拿到客户端真实IP。
proxy_set_header X-Real-IP $remote_addr;只在存在一级代理情况的情况下,可以获取到用户的真实IP,倘若有多级代理,获取到的值就不准确。

解释:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
变量X-Forwarded-For,设置后,每次经过proxy转发都会有记录,格式就是client1(客户端IP), proxy1(代理一IP), proxy2(代理二IP),会以逗号隔开各个地址。默认的X-Forwarded-For值为空。

评论

还没有任何评论,你来说两句吧

提供支持 - 友情链接 - 衫小寨