1.什么叫做nginx反向代理获取客户端的真实IP?
我们访问互联网的服务时,大多数时,客户端并不是直接访问到服务端的,而是客户端首先请求到反向代理
反向代理再转发到服务端实现服务访问,通过反向代理实现路由/负载均衡等策略
这样在服务端拿到的客户端IP将是反向代理IP,而不是真实客户端IP,因此需要想办法来获取到真实客户端IP
2.为什么服务端要解析客户端ip?
前后端分离之后,采用nginx作为静态服务器,并通过反向代理的方式来实现接口跨域的方式
在降低开发成本的的同时也带来了诸多问题,例如客户端真实ip的获取
在一些特殊场景下,比如风控和支付流程,往往需要获取用户的ip信息,但是nginx的反向代理实现跨域的同时
也彻底改变了服务器的请求来源,隔离了用户和服务器的连接这并不是我们想要的,因此对于客户端ip的解析是必要的
3.nginx中的几个变量?
(1)remote_addr
代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的
当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)
就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站
这样web服务器就会把remote_addr设为这台代理机器的IP,除非代理将你的IP附在请求header中一起转交给web服务器
(2)X-Forwarded-For(简称XFF)
X-Forwarded-For 是一个 HTTP 扩展头部,HTTP协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入 用来表示 HTTP 请求端真实 IP,如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用 并被写入 RFC
7239(Forwarded HTTP Extension)标准之中 XFF的格式为 X-Forwarded-For: client,
proxy1, proxy2
XFF 的内容由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP
(注意:如果未经严格处理,可以被伪造) 如果一个 HTTP 请求到达服务器之前,经过了三个代理
Proxy1、Proxy2、Proxy3,IP 分别为 IP1、IP2、IP3,用户真实 IP 为 IP0 那么按照 XFF
标准,服务端最终会收到以下信息 X-Forwarded-For: IP0, IP1, IP2 Proxy3 直连服务器,它会给 XFF 追加
IP2,表示它是在帮 Proxy2 转发请求 列表中并没有 IP3,IP3 可以在服务端通过 Remote Address 字段获得
(3)X-Real-IP
这又是一个自定义头部字段,通常被 HTTP 代理用来表示与它产生 TCP 连接的设备
IP这个设备可能是其他代理,也可能是真正的请求端,这个要看经过代理的层级次数或是是否始终将真实IP一路传下来
(注意:如果未经严格处理,可以被伪造)
4.利用Nginx中的realip模块获取用户的真实ip
我们将各层代理的IP排除在外,就取到了真实的用户IP,这个可以使用nginx的一个模块realip_module 来实现
从XFF中抛弃指定的代理层 IP,那么最后一个符合规则的就是用户 IP nginx realip_module
模块需要在编译nginx的时候加上参数–with-http_realip_module
set_real_ip_from 后面是可信 IP 规则,可以有多条
real_ip_recursive 是递归的去除所配置中的可信IP,如果只有一层代理,也可以不写这个参数
指的就是在访问本机时对来自本机的ip进行real_ip_module模块的解析
real_ip_header X-Forwarded-For; //只接受从X-Forwarded-For中的第一个ip也就是距离web页最远的ip即客户端ip
首层代理将握手 IP 附在 X-Forwarded-For 上一直向后传递
(或者将 X-Forwarded-For 设置为握手 IP 向后传递),后面的每一层累加握手 IP 往后传递
首层代理将握手 IP 设置为 HTTP 请求头的 X-Real-IP 中向后传递
后面的每一层原样传递下去(有则原样传递,无则设置为握手 IP )
握手IP:即请求方的 remote_addr.
5.nginx作为真正的反向代理服务器获取用户ip
(1)基本实验环境
主机信息 | 主机的功能(服务) |
---|---|
server1(172.25.8.1) | 用作nginx+http_realip_module模块 |
server2(172.25.8.2) | 用作nginx代理服务器 |
真机(172.25.8.250) | 用作客户端测试 |
(2)在server1上面进行配置
修改nginx服务器默认发布页面的内容
修改配置文件,添加内容
进行语法检测,重启服务
将server1上编译好的nginx的目录发送给server2
(3)在server2(代理服务器)上面进行配置
代理服务器的配置参考官网
删除代理服务器上面的web资源
(4)在真机上面进行测试
写解析
可以看到访问的域名对应的是server2主机的IP,但是访问到的内容却是server1的发布页
在server1上查看访问日志
可以看出nginx服务器可以直接得到客户端的ip
再次测试