Nginx postread阶段 http_realip_module获取用户端真实IP

网友投稿 828 2022-11-29

Nginx postread阶段 http_realip_module获取用户端真实IP

Nginx postread阶段 http_realip_module获取用户端真实IP

realip模块和如何获取用户端真实IP

postread阶段的realip模块可以帮助我们发现用户真实的IP地址,这为我们后续的一些模块实现例如限速,限流等等功能提供了可能性。(ip,src port,根据该条连接的src ip就能够判断出用户的IP地址了。但是实际是中间还包含反向代理,因为网络当中存在着很多的反向代理,反向代理会导致会导致与上游的机器又建立了一个新的TCP连接,所以上游的服务器想通过TCP连接里面的src ip是无法拿到原始用户IP地址的

比如说我们在家里上网的时候,家里的路由器给我分配了内网IP地址192.168.0.x。当我通过运营商比如电信,电信可能为我分配了一个公网的IP地址,然后我去访问某一个网站的时候,可能我会先命中到它的CDN,这个网站使用CDN来加速,比如对一些图片加速。由CDN到反向代理服务器建立了TCP的连接,再由反向代理服务器到Nginx建立了TCP连接。

如果通过拿IP地址拿到的是反向代理的IP地址2.2.2.2,其实我们要拿用户的IP地址不是用户内网的IP地址是于压缩公网IP地址115.204.33.1。如果我要做限速或者做并发连接的控制需要基于运营商分配的IP来控制。

现在Nginx拿到是remote_addr变量的值2.2.2.2,其实我想要拿到的用户IP地址是115.204.33.1,怎么样才可以做到呢??

通过以下两点,HTTP协议里面的X-Forwarded-For头部和X-Real-IP头部:

X-Real-IP只能添加一个IP,客户端用户真实的IP。X-Forwarded-For是逐步添加的,包含了客户端用户真实IP和经过的所有反向代理服务器的IP。所以要获取客户端用户真实的IP可以通过X-Real-IP获取也可以通过X-Forwarded-For获取。

CDN 下 nginx 获取用户真实 IP 地址

随着 nginx 的迅速崛起,越来越多公司将 apache 更换成 nginx. 同时也越来越多人使用 nginx 作为负载均衡, 并且代理前面可能还加上了 CDN 加速,但是随之也遇到一个问题: nginx 如何获取用户的真实 IP 地址。 实例环境: 用户 IP 120.22.11.11 CDN 前端 61.22.22.22 CDN 中转 121.207.33.33 公司 NGINX 前端代理 192.168.50.121(外网 121.207.231.22)

1、使用 CDN 自定义 IP 头来获取 假如说你的 CDN 厂商使用 nginx,那么在 nginx 上将$remote_addr 赋值给你指定的头,方法如下: proxy_set_header remote-user-ip $remote_addr;

proxy_set_header也可以自定义参数,如:proxy_set_header test paroxy_test;

如果想要支持下划线的话,需要增加如下配置

underscores_in_headers on;

后端 PHP 代码 getRemoteUserIP.php

访问 getRemoteUserIP.php,结果如下: 120.22.11.11       //取到了真实的用户 IP,如果 CDN 能给定义这个头的话,那这个方法最佳

2、通过 HTTP_X_FORWARDED_FOR 获取 IP 地址 一般情况下 CDN 服务器都会传送 HTTP_X_FORWARDED_FOR 头,这是一个 ip 串,后端的真实服务器获取 HTTP_X_FORWARDED_FOR 头,截取字符串第一个不为 unkown 的 IP 作为用户真实 IP 地址, 例如: 120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121(用户 IP,CDN 前端 IP,CDN 中转,公司 NGINX 代理)

getFor.php

访问 getFor.php 结果如下: 120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121

如果你是 php 程序员,你获取第一个不为 unknow 的 ip 地址,这边就是 120.22.11.11.

3.使用 nginx 自带模块 realip 获取用户 IP 地址

The ​​ngx_is used to change the client address and optional port to those sent in the specified header field.This module is not built by default, it should be enabled with the ​​--with-parameter.Example Configuration:

set_real_ip_from 192.168.1.0/24; set_real_ip_from 192.168.2.1; set_real_ip_from 2001:0db8::/32; real_ip_header X-Forwarded-For; real_ip_recursive on;

Directives

Syntax:

set_real_ip_from address | CIDR | unix:;​

Default:


Context:

​style="background-color: rgb(231, 243, 237); padding: 0px 3px; border-radius: 4px; overflow-wrap: break-word; text-indent: 0px;">​server​​​, ​​location​

Syntax:

real_ip_recursive on | off;​

Default:

real_ip_recursive off;

Context:

​style="background-color: rgb(231, 243, 237); padding: 0px 3px; border-radius: 4px; overflow-wrap: break-word; text-indent: 0px;">​server​​​, ​​location​

If recursive search is disabled, the original client address that matches one of the trusted addresses is replaced by the last address sent in the request header field defined by the ​​real_ip_header​​ directive. If recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field.

Syntax:

real_ip_header field | X-Real-IP | X-Forwarded-For | proxy_protocol;​

Default:

real_ip_header X-Real-IP;

Context:

​style="background-color: rgb(231, 243, 237); padding: 0px 3px; border-radius: 4px; overflow-wrap: break-word; text-indent: 0px;">​server​​​, ​​location​

Defines the request header field whose value will be used to replace the client address.

安装 nginx 之时加上 realip 模块,我的参数如下: ./configure --prefix=/usr/local/nginx --with-nginx 配置server {listen 80;server_name test.com;access_log /data/logs/nginx/test.com.access.log main;index index.php index.html index.html;root /data/site/test.com;location /{ root /data/site/test.com;}location = /getRealip.php{ set_real_ip_from 192.168.50.0/24; set_real_ip_from 61.22.22.22; #CDN 前端 set_real_ip_from 121.207.33.33; #CDN 中转 set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For; real_ip_recursive on; fastcgi_pass unix:/var/run/phpfpm.sock; fastcgi_index index.php; include fastcgi.conf;}}

getRealip.php 内容

访问 test.com/getRealip.php,返回: 120.22.11.11 如果注释 real_ip_recursive on 或者 real_ip_recursive off,访问 test.com/getRealip.php,返回: 121.207.33.33

很不幸,获取到了中继的 IP,real_ip_recursive 的效果看明白了吧?

set_real_ip_from:真实服务器上一级代理的 IP 地址或者 IP 段,可以写多行 real_ip_header:从哪个 header 头检索出要的 IP 地址 real_ip_recursive:默认值是off,递归排除 IP 地址,ip 串从右到左开始排除 set_real_ip_from 里面出现的 IP,如果出现了未出现这些 ip 段的 IP,那么这个 IP 将被认为是用户的 IP。例如我这边的例子,真实服务器获取到的 IP 地址串如下: 120.22.11.11,61.22.22.22,121.207.33.33,192.168.50.121

在 real_ip_recursive on 的情况下:61.22.22.22,121.207.33.33,192.168.50.121 都出现在 set_real_ip_from 中,仅仅 120.22.11.11 没出现,那么他就被认为是用户的 ip 地址,并且赋值到 remote_addr 变量

在 real_ip_recursive off 或者不设置的情况下:192.168.50.121 出现在 set_real_ip_from 中排除掉,接下来的 ip 地址便认为是用户的 ip 地址

如果仅仅如下配置: set_real_ip_from 192.168.50.0/24; set_real_ip_from 127.0.0.1; real_ip_header X-Forwarded-For; real_ip_recursive on; 访问结果如下: 121.207.33.33

三种在 CDN 环境下获取用户 IP 方法总结

CDN 自定义 header 头 优点:获取到最真实的用户 IP 地址,用户绝对不可能伪装 IP 缺点:需要 CDN 厂商提供

获取 forwarded-for 头 优点:可以获取到用户的 IP 地址 缺点:程序需要改动,以及用户 IP 有可能是伪装的

使用 realip 获取 优点:程序不需要改动,直接使用 remote_addr 即可获取 IP 地址 缺点: ip 地址有可能被伪装,而且需要知道所有 CDN 节点的 ip 地址或者 ip 段

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Shell Redis单机版本部署
下一篇:Redis 单机部署redis实例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~