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

news/2025/1/11 10:53:43/

我们访问互联网上的服务时,大多数时,客户端并不是直接访问到服务端的,而是客户端首先请求到反向代理,反向代理再转发到服务端实现服务访问,通过反向代理实现路由/负载均衡等策略。这样在服务端拿到的客户端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.conf19         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.conf19         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.conf44 #       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

 


http://www.ppmy.cn/news/297375.html

相关文章

IPv4中IP地址的分类

IP地址(百度百科词条) IP地址是指互联网协议地址(英语:Internet Protocol Address,又译为网际协议地址),是IP Address的缩写。IP地址是IP协议提供的一种统一的地址格式,它为互联网上…

IP前缀列表

IP前缀列表,所匹配的对象是IP地址前缀,也就是路由条目。 一个路由条目由目的网络地址(也被称为IP前缀)及掩码长度(也被称为前缀长度)共同标识。 使用ACL从一批路由中筛选出感兴趣的路由时,是无…

批量pingIP脚本

linux和windows批量ping脚本 linux下批量ping的shell脚本 方法一 1.将ip地址写入ip.txt vi ip.txt 2.编辑脚本内容 vi ping.sh写入 #!/bin/bash cat ip.txt |while read line; do ipecho $line |awk ‘{print $1}’ ping -c 3 -w 2 $ip &> /dev/null if [ $? -eq 0 ];t…

IP包头详解

一、IP包头详解 ip包头最小⻓度 20字节,具体多大,取决于可选项有多大 可选项最大⻓度:10*440个字节 IP最大的⻓度:20字节40个字节 60字节 所以是20~ 60字节,但 一般是:20字节 1.版本&#x…

子网掩码,网络ID,IP之间关系

要知道子网掩码,网络ID,IP之间关系,那么我们需要了解一些基础知识。 1、IP地址的种类 比如我电脑IPv4 地址的地址为192.168.126.1,为了让机器识别转化为8位二进制 11000000.10101000.01111110.00000001 那么如果全部都为1一共有…

IP地址划分

1 . 基本知识介绍 1.1网络中的每一个主机或路由器至少有一个IP地址; 在Internet中不允许有两个设备具有同样的IP地址; 1.2IP地址采用分层结构; IP地址是由网络号(net ID)与主机号&#xff0…

关于SOME/IP的理解

目录 1. 总体说明 2. 服务说明 2.1 Method 2.2 Event 2.3 Field 3. 解析SOME/IP格式 3.1 Message Type说明 3.2 Payload说明 4. SOME/IP 服务发现SD 4.1 主要功能 4.2 SD报文解析 4.2.1 Entry 4.2.2 Options 4.3 SD状态机 5. SOME/IP序列化 5.1 概念 5.2 说…

IP报头结构详解

IP报头结构如下图所示 下面具体分析IP包头中各部分的作用。 版本号(Version):长度4比特。标识目前采用的IP协议的版本号。一般的值为0100(IPv4),0110(IPv6) IP包头长度&#xff08…