nginx利用反向代理实现获取用户真实ip

我们访问互联网上的服务时,大多数时,客户端并不是直接访问到服务端的,而是客户端首先请求到反向代理,反向代理再转发到服务端实现服务访问,通过反向代理实现路由/负载均衡等策略。这样在服务端拿到的客户端IP将是反向代理IP,而不是真实客户端IP,因此需要想办法来获取到真实客户端IP

web服务器获得真正的用户和真实的ip ?
客户端访问服务端的数据流走向

可以看出,服务端根本获取不到真实的客户端ip,只能获取到上一层服务的ip,那么nginx怎样才能获取到真实的ip呢?

反向代理:获取上一节的ip,一层一层会找到真实client的ip;

问题背景:
在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆的判断,或者统计ip访问次数等,通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,使用request.getRemoteAddr()获取到的就一直是nginx服务器的ip的地址,那这时应该怎么办?
part1:解决方案

proxy_set_header X-real-ip $remote_addr;

其中这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取:

request.getAttribute(“X-real-ip”)

part2:原理介绍:
关于nginx反向代理的原理的介绍
proxy_set_header原理

用一台服务器server1模拟实现获取本机ip

在server1上:

[root@server1 ~]# tar zxf nginx-1.17.0.tar.gz
[root@server1 ~]# cd nginx-1.17.0
[root@server1 nginx-1.17.0]# yum install -y zlib-devel# 这是编译nginx的依赖包
[root@server1 nginx-1.17.0]# yum install -y openssl-devel  # 这是编译nginx的依赖
[root@server1 ~]# cd /usr/local/nginx/

[root@server1 conf]# vim nginx.conf
#当访问域名server1.example.com,实际访问的是直接返回client real ip: $remote_addr\n
配置文件-->虚拟主机
  server {
        listen 80;   #监听80端口
        server_name server1.example.com;  #定义域名
        set_real_ip_from 172.25.70.1;   #真正的ip地址;
        real_ip_header  X-Forwarded-For;
        real_ip_recursive on;
        location / {
                return 200 "client real ip: $remote_addr\n";
        }
}
[root@server1 conf]#/usr/local/nginx/sbin/nginx -t #启动失败;
[root@server1 conf]#  systemctl stop nginx

添加一个模块:-with-http_realip_module选项(后台Nginx服务器记录原始客户端的IP地址 )

[root@server1 nginx-1.17.0]# ./configure --prefix=/usr/local/nginx  --with-file-aio  --with-http_realip_module 
************************
--with-file-aio 启用file aio支持(一种APL文件传输格式)
--with-http_realip_module:它的意义在于能够使得后台服务器记录原始客户端的IP地址。
*************************

[root@server1 nginx-1.17.0]#  make && make install

[root@server1 nginx-1.17.0]# vim /usr/local/nginx/conf/nginx.conf

参数解释:

1.使用realip模块后,$remote_addr输出结果为真实客户端IP,可以使用$realip_remote_addr获取最后一个反向代理的IP; 
3.real_ip_headerX-Forwarded-For:告知Nginx真实客户端IP从哪个请求头获取; 
4.set_real_ip_from 172.25.78.0/24:告知Nginx哪些是反向代理IP,即排除后剩下的就是真实客户端IP
5.real_ip_recursive on:是否递归解析,当real_ip_recursive配置为off时,Nginx会把real_ip_header指定的请求头中的最后一个IP作为真实客户端IP;
当real_ip_recursive配置为on时,Nginx会递归解析real_ip_header指定的请求头,最后一个不匹配set_real_ip_from的IP作为真实客户端IP。 

添加虚拟机从X-Forwarded-For中获取到真实客户端IP(最后一行):

132   server {
133         listen 80;
134         server_name server1.example.com;
135         set_real_ip_from 172.25.70.1; ###set_real_ip_from:  功能:通过该指令指定信任的地址,将会被替代为精确的IP地址。从0.8.22版本后也可以使用信任的Unix套接字。这里设置的IP就是指前端Nginx 、Varnish或者 Squid 的 IP地址。
136         real_ip_header  X-Forwarded-For;  # real_ip_header::这个指令用于设置使用哪个头来替换IP地址。如果使用了X-Forwarded-For,那么该模块将会使用X-Forwarded-For头中的最后一个IP地址来替换前端代理的IP地址。
137         real_ip_recursive on;  # 是否递归解析,off表示默认从最后一个地址开始解析; # on表示从前往后依次递归获取ip
138         location / {
139                 return 200 "client real ip: $remote_addr\n"; # $remote_addr 代表客户端真实IP
140         }
141 
142 
143 }

在这里插入图片描述

 

[root@server1 nginx-1.17.0]# cd /usr/local/nginx/conf/
[root@server1 conf]#  systemctl restart nginx.service
[root@server1 conf]# vim /etc/hosts
172.25.70.1     server1  server1.example.com
[root@server1 conf]# curl -H 'X-Forwarded-For:1.1.1.1,172.25.70.1' server1.example.com
client real ip: 1.1.1.1     #虚拟主机添加成功

在这里插入图片描述

 

[root@server1 conf]# scp -r /usr/local/nginx/ server2: #将其nginx的安装路径发过去

以上操作仅仅实现了获取本机ip和使用X-Forwarded-For的功能,现在我们来模拟实际生产中在有反向代理的阻碍下获取真实客户端ip,这里我们用一个反向代理来模拟

配置server2(nginx反向代理服务器):

[root@server2 nginx]# cd /usr/local/nginx/
[root@server2 nginx]# ls
[root@server2 nginx]# id nginx  #查看是否有nginx用户,没有重新建立;
uid=1000(nginx) gid=1000(nginx) groups=1000(nginx)
[root@server2 nginx]# cd conf/
[root@server2 conf]# vim nginx.conf

 19         upstream westos{
 20                 server 172.25.70.1:80;
 21         }

135   server {
136         listen 80;
137         server_name server1.example.com;
138         set_real_ip_from 172.25.70.1;
139         real_ip_header  X-Forwarded-For;
140         real_ip_recursive on;
141         location / {
142 
143                 proxy_pass http://westos;
144         }
145 }

在这里插入图片描述

 

[root@server2 conf]# ../sbin/nginx
[root@server2 conf]# netstat -tnlp
[root@server2 conf]# curl localhost
server2.example.com

在这里插入图片描述

#客户端(70)测试: 

[root@foundation70 ~]# curl 172.25.70.2
server2.example.com

在server2上:
 

[root@server2 conf]# vim nginx.conf
135 server {undefined
136 listen 80;
137 server_name server2.example.com;
138 # set_real_ip_from 172.25.70.1;
139 # real_ip_header X-Forwarded-For;
140 # real_ip_recursive on;
141 location / {undefined
142
143 proxy_pass http://westos;
144 }
145 }

在这里插入图片描述

 


[root@server2 conf]# curl 172.25.70.1
server1.example.com
[root@server2 conf]# ../sbin/nginx -s reload

在客户端测试

[root@foundation70 ~]# vim /etc/hosts
172.25.70.2     server2 server2.example.com
[root@foundation70 ~]# curl server2.example.com
server2.example.com
[root@foundation70 ~]# curl server2.example.com
server1.example.com

获取真正的客户端ip

在server1上:

[root@server1 conf]# vim nginx.conf
注释掉131-140行
 44         set_real_ip_from 172.25.70.2;
 45         real_ip_header  X-Forwarded-For;
 46         real_ip_recursive on;

在这里插入图片描述

 在server2上:

[root@server2 conf]# vim nginx.conf
 19         upstream westos{
 20                 server 172.25.70.1:80;
 21         }

135   server {
136         listen 80;
137         server_name server2.example.com;
138 #       set_real_ip_from 172.25.70.1;
139 #       real_ip_header  X-Forwarded-For;
140 #       real_ip_recursive on;
141         location / {
142                 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;     #添加该变量是为了真正的获得用户的IP
143                 proxy_pass http://westos;
144         }
145 }
[root@server2 conf]# ../sbin/nginx -t
[root@server2 conf]# ../sbin/nginx -s reload

测试:


[root@foundation70 ~]# curl server2.example.com(172.25.70.2)
server1.example.com

在server1上的日志:
[root@server1 logs]# cat access.log     #是真正访问的是客户端
172.25.70.250 - - [26/Sep/2019:22:05:25 +0800] "GET / HTTP/1.0" 200 20 "-" "curl/7.29.0"  #获得ip是客户端的

获得是server1的获得了server2(反向代理)的ip

在server1上:

[root@server1 conf]# vim nginx.conf
 44 #       set_real_ip_from 172.25.70.2;
 45 #        real_ip_header  X-Forwarded-For;
 46 #        real_ip_recursive on;
再次测试:
[root@foundation70 ~]# curl server2.example.com
server1.example.com

在server1上的日志:
[root@server1 logs]# cat access.log 
172.25.70.2 - - [26/Sep/2019:22:14:09 +0800] "GET / HTTP/1.0" 200 20 "-" "curl/7.29.0"

在这里插入图片描述

 


原文链接:https://blog.csdn.net/qq_38548994/article/details/101491890

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值