Nginx反向代理掘取客户端的真实IP

一.客户端ip的传递

1.解析客户端ip的必要性
  • 前后端分离之后,采用nginx作为静态服务器,并通过反向代理的方式来实现接口跨域的方式,在降低开发成本的的同时也带来了诸多问题,例如客户端真实ip的获取。
  • 在一些特殊场景下,比如风控和支付流程,往往需要获取用户的ip信息,但是nginx的反向代理实现跨域的同时,也彻底改变了服务器的请求来源,隔离了用户和服务器的连接这并不是我们想要的,因此对于客户端ip的解析是必要的。
2.知识点:nginx的几个变量
  • remote_addr
    代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP,除非代理将你的IP附在请求header中一起转交给web服务器。
  • 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 字段获得。
  • X-Real-IP
    这又是一个自定义头部字段,通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端,这个要看经过代理的层级次数或是是否始终将真实IP一路传下来。(注意:如果未经严格处理,可以被伪造)

二.配合Nginx realip模块获取用户的真实ip

1.原理
  • 我们将各层代理的IP排除在外,就取到了真实的用户IP。这个可以使用nginx的一个模块realip_module 来实现。
  • 从XFF中抛弃指定的代理层 IP,那么最后一个符合规则的就是用户 IP。
  • nginx realip_module 模块需要在编译nginx的时候加上参数–with-http_realip_module。
    通过官网了解使用方法:
    在这里插入图片描述
2.实现
  • 重新编译nginx添加http的rea_lip模块
[root@server1 nginx-1.17.1]# ./configure --prefix=/usr/local/nginx --with-http_realip_module --with-file-aio
[root@server1 nginx-1.17.1]# make
[root@server1 nginx-1.17.1]# cd objs/
[root@server1 objs]# cp -f nginx /usr/local/nginx/sbin/nginx
[root@server1 objs]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.17.1
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 
configure arguments: --prefix=/usr/local/nginx --with-file-aio --with-http_realip_module
  • 在配置文件中添加该模块,文件内容编辑为如下:
    在这里插入图片描述
  • 检测语法错误并重启服务
[root@server1 objs]# vim /usr/local/nginx/conf/nginx.conf

[root@server1 objs]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

[root@server1 objs]# systemctl restart nginx.service 
  • 测试:在server1做好解析之后测试(在nginx服务器上访问,如果域名前的IP地址是server1自己的ip地址,那么真实的ip就为server1前一位的ip,如果域名前的ip地址不是server1的ip,那么真实的ip就是域名前的ip地址):
    在这里插入图片描述
    在这里插入图片描述
  • 在真实主机测试(在除nignx服务器之外的主机访问,获取到的real ip都是这台主机自己的ip)
    在这里插入图片描述
    在这里插入图片描述
3.配置文件的解释
  • 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.

三.反向代理

1.实验环境
主机名(IP)服务
server1(172.25.24.1)nginx+http_realip_module模块
server2(172.25.24.2)nginx代理服务器
真机(172.25.254.24)客户端
  • 将server1上编译好的nginx的目录发送给server2:[root@server1 objs]# scp -r /usr/local/nginx/ server2:/usr/local/
2.代理服务器(server2)
  • 按照官网的说明,修改server2的配置文件为如下:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 删除默认发布页的内容。
    在这里插入图片描述

  • 进行语法检测,开启服务。
    在这里插入图片描述

3.server1
  • 修改默认发布页面的内容
    在这里插入图片描述
  • 修改配置文件,添加以下内容:
    在这里插入图片描述
  • 进行语法检测,重启服务。
[root@server1 objs]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

[root@server1 objs]# systemctl restart nginx.service 
4.真机测试
  • 真机修改本地解析文件,测试:
    在这里插入图片描述
    在这里插入图片描述
  • 可以看到我们访问的域名对应的是server2主机的IP,但是访问到的内容却是server1的发布页。
  • 在server1上查看访问的日志。
[root@server1 objs]# cd /usr/local/nginx/logs/
[root@server1 logs]# vim access.log 

在这里插入图片描述注意:当我们注释掉nginx服务器的这两行时,获取到的ip就是代理服务器的ip。
在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值