Nginx中如何获取客户端真实IP?
在nginx中,可以通过 $remote_addr 变量来获取客户端的IP,获取了客户端IP之后,才可以做限速、限流相关的配置等。但是如果用户A通过反向代理B访问到上游服务C ,假设上游服务是我们的nginx服务,那么上游服务 $remote_addr 获取到的是反向代理B的IP,因为直接访问C的是反向代理B而不是客户端A。
此时我们去获取用户A的IP,就要从header请求头的X-Forwarded-For和X-Real-IP来获取。
remote_addr 默认拿到的是上一级的ip地址, 来自于TCP连接,表示与服务端建立TCP连接的设备IP,因此,Remote Address无法伪造。
X-Forwarded-For
X-Forwarded-For(XFF) 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。
XFF如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。
在消息流从客户端流向服务器的过程中被拦截的情况下,服务器端的访问日志只能记录代理服务器或者负载均衡服务器的IP地址。如果想要获得最初发起请求的客户端的IP地址的话,那么 X-Forwarded-For 就派上了用场。通常它的格式类似这样:
X-Forwarded-For: IP0(client), IP1(proxy1), IP2(proxy2)
X-Forwarded-For
会记录用户ip与每次转发用的代理服务器ip, 也就是说,经过多层代理的话,X-Forwarded-For会叠加经过的ip,每经过一层ip,代理服务器会叠加上一级访问者的ip,但是不会叠加自己的ip。
X-Real-IP
X-Real-IP无论经过多少层代理,X-Real-IP记录的都是原始客户端A的ip。
X-Real-IP是Nginx独有的,不是RFC规范,所以与client间如果还有其他非Nginx软件实现的代理,将取不到X-Real-IP头部
所以在上游服务器获取起始客户端IP一般是使用 X-Forwarded-For 而不是 X-Real-IP。
realip模块
用途
:使用了代理的情况下可以获取到用户的真实IP地址
。
使用
:realip
功能需要 Nginx
添加 ngx_http_realip_module
模块,默认情况下是不被编译,如果需要添加,请在编译时添加 --with-http_realip_module
选项开启它。
PS:编译安装Nginx到指定路径的步骤:
1、 ./configure --prefix=/home/ap/nginx2 --with-http_realip_module
2、 make && make install #编译和安装
realip 指令解释
- •
set_real_ip_from
:设置上一级反向代理服务器,即可信任服务器IP(取客户端IP时候会从X-Forwarded-For排除掉可信地址ip) - •
real_ip_header :X-Forwarded-For/X-Real-IP/proxy_protocol
:告知Nginx真实客户端IP从哪个请求头获取。默认是X-Real-IP。但我们一般设置为X-Forwarded-For。 - •
real_ip_recursive:是否递归解析
- •
off
:默认是off, 会将real_ip_header
指定的HTTP头中的最后一个IP作为真实IP,一般都会开启 - •
on
:会将real_ip_header
指定的HTTP头中的从右边开始数第一个不是信任服务器的IP当成真实IP
- •
在 X-Forward-For 的最左边才是真实用户的地址,右边都是代理地址,当我们把 real_ip_header 设置为 X-Forward-For 时,如果没有启用 环回地址 real_ip_recursive,我们取到的 $remote_addr 是 X-Forward-For 中最右边的 ip,无论是否设置了 set_real_ip_from;如果启用了环回地址 real_ip_recursive on,那么就获取 而是从右边开始数,第一个非可信地址的IP ,也就是排除设置了 set_real_ip_from(可信地址外的)
realip 变量
$realip_remote_addr # 上一级代理的ip
$realip_remote_port # 上一级代理的端口
$remote_addr # 如果不使用realip模块,$remote_addr是上一级代理的ip,使用了realip模块,是real_ip_header指令指定的起始客户端ip
使用示例
- • 客户端(A)在本地Windows机器上 :192.168.2.1
- • 两层反向代理和上游服务都在192.168.2.129
- • 代理(P1): 192.168.2.129:8089
- • 代理(P2): 192.168.2.129:8080 # 也就是P1的上游服务
- • 终端上游服务(C): 192.168.2.129:8088/remote_addr # 也就是P2的上游服务
访问路径如下:
A->P1->P2->具体服务C
# 定义终端上游服务 upstream rd { server 192.168.2.129:8088; } # 定义代理P1的上游服务(代理P2) upstream rd2 { server 192.168.2.129:8080; } # 代理P1 server { listen 8089; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 必须要定义,否则realip无法通过X-Forwarded-For请求头获取起始客户端ip proxy_pass http://rd2; } } # 代理P2 server { listen 8080; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 必须要定义,否则realip无法通过X-Forwarded-For请求头获取起始客户端ip proxy_pass http://rd/remote_addr; #访问终端上游服务的remote_addr页面 } } # 终端上游服务 server { listen 8088; set_real_ip_from 192.168.2.129; #指定了两个可信任的IP,第二个是一个ip段 set_real_ip_from 223.73.208.0/24; #real_ip_header X-Real-IP; real_ip_header X-Forwarded-For; real_ip_recursive on; location /remote_addr { # 返回状态码200 以及一些信息。 return 200 "Your remote_addr is $remote_addr\nYour realip_remote_addr is $realip_remote_addr\nYour realip_remote_port is $realip_remote_port\nYour X-Forwarded-For $http_x_forwarded_for"; } }
proxy_set_header 可以在代理服务发送请求时添加相应的header头,上面通过proxy_set_header添加了X-Forwarded-For/X-Real-Ip/Host这三个header头。
在我本地 192.168.2.1 主机对代理B1发postman请求,P1会请求P2再请求到C。得到的信息为 Your remote_addr is 192.168.2.1 # 起始客户端IP Your realip_remote_addr is 192.168.2.129 #直接请求终端的代理IP,即P2的ip Your realip_remote_port is 48348 Your X-Forwarded-For 192.168.2.1, 192.168.2.129 # X-Forwarded-For请求头的值,这里是起始客户端IP和代理B1的IP
评论列表 (0条):
加载更多评论 Loading...