Nginx中realip获取

我们都知道,在Nginx中,想获取来源的IP,我们可以通过$remote_addr 来获取,但是很多时候,请求会经过多个中间代理或CDN,从而导致我们根本无法准确的获取客户端的真实IP, 为解决这种问题,Nginx提供了realip模块来实现客户端IP的获取,详细信息参见:ngx_http_realip_module

此模块提供了三个指令:set_real_ip_from, real_ip_header,real_ip_recursive,其功能如下:

  • set_real_ip_from:指定IP的来源信息,用于排除中间代理IP,可以填写IP或网段。
  • real_ip_header:指定从Header的哪个属性里面取IP信息,常用的是 X-Forwarded-For
  • real_ip_recursive:是否递归的排除中间代理IP信息,默认值为off,如果值设置为off,则只会排除直接上层代理的IP信息,如果值为on,则会从右至左依次排除用户配置的中间IP,直到遇到第一个非指定的IP,将此IP设置为真实IP。

虽然只有三个指令,但是其功能都是比较晦涩难懂的,下面我通过一个实验,来揭示此模块的功能及用法:

实现环境:

  • 访问源IP:10.38.160.252

  • 代理一:10.38.165.227(四层代理,非Nginx),其后端指向代理二的三台机器

  • 代理二:

    • 10.38.160.94
    • 10.38.160.101
    • 10.38.160.96
  • 代理三:10.38.160.174

  • 代理四:10.232.51.224

  • 目的:10.232.51.224: 8090

连接过程示意图:
在这里插入图片描述
Nginx关键配置内容:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-For $remote_addr
  • remote_addr:远程地址,如果未经处理,此值为与Nginx直接连接的上层的IP地址

  • proxy_add_x_forwarded_for:其值为 从上一代理获取到的 X-Forwarded-For 值 追加上 remote_addr 的值,中间使用,分割

能获取到客户端真实IP的条件如下:

  1. 所有七层代理(代理2-3) 需要配置如下配置,以使其可以完整记录经过各个代理时的真实IP信息
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  1. 末端代理(代理4)需要配置如下配置,过滤掉中间配置
set_real_ip_from 10.38.160.94; // 过滤代理2
set_real_ip_from 10.38.160.101; // 过滤代理2
set_real_ip_from 10.38.160.96; // 过滤代理2

set_real_ip_from 10.38.160.174; // 过滤代理3

real_ip_header X-Forwarded-For; // 指定从哪个header里面取real ip
real_ip_recursive on; // 是否递归查找
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr; // 通过上面配置,最终Realip会被存储在$remote_addr中

通过如上的配置,我们就可以实现对真实IP的获取,真实IP就存储在 X-Real-IP 中

问题:

  1. 如果条件1不满足呢?

如果所有都没有配置X-Forwarded-For,那将无法获取到真实IP,只能获取到代理3的IP,如果部分节点设置了,只能获取到第一个设置的节点的上一个节点的IP信息,如从代理3开始设置了,那获取到的 realip 只能获取到代理2的IP信息

  1. 如果 real_ip_recursive为off或不设置呢?

如果 real_ip_recursive未设置或值不为on,那么即使set_real_ip_from设置了很多,也只会去除上个节点的IP信息,如我在代理4设置了如下信息:

set_real_ip_from 10.38.160.94;
set_real_ip_from 10.38.160.101;
set_real_ip_from 10.38.160.96;
set_real_ip_from 10.38.160.174;
real_ip_header X-Forwarded-For;
real_ip_recursive off;
proxy_set_header X-Real-IP $remote_addr;

那么,获取到的真实IP只会是代理2中的任意一个,即:10.38.160.94、10.38.160.101 或 10.38.160.96,即使set_real_ip_from设置了这三个IP,但是还是不会继续往上递归去除,只会对上个节点起作用

  1. 如果set_real_ip_from没有设置,或设置不完全呢?

set_real_ip_from的功能是从X-Forwarded-For中去除掉中间层IP信息,如果中间IP设置不全,则会导致某个未设置的中间IP被当成客户端真实IP

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章