获取CDN用户真实IP

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取CDN用户真实IP相关的知识,希望对你有一定的参考价值。

参考技术A (一)简要说明  

  如果你的Web服务器前端有代理服务器或CDN时日志中的$remote_addr可能就不是客户端的真实IP了。比较常用的解决方法有以下三几种,本文将主要介绍如何使用nginx自带realip模块来解决这一问题:

1,用CDN自定义IP头来获取

2,通过HTTP_X_FORWARDED_FOR获取IP地址

3,使用Nginx自带模块realip获取用户IP地址

    ngx_realip模块究竟有什么实际用途呢?为什么我们需要去改写请求的来源地址呢?答案是:当Nginx处理的请求经过了某个HTTP代理服务器的转发时,这个模块就变得特别有用。

    当原始用户的请求经过代理(squid,proxy)转发之后,nginx接收到的请求的来源地址也就变成了该代理服务器的IP,于是乎nginx 就无法获取用户请求的真实IP地址了。

   所以,一般我们会在Nginx之前的代理服务器中把请求的原始来源地址编码进某个特殊的HTTP请求头中,然后再在Nginx中把这个请求头中编码的地址恢复出来。这样Nginx中的后续处理阶段(包括Nginx背后的各种后端应用)就会认为这些请求直接来自那些原始的地址,代理服务器就仿佛不存在一样。ngx_realip模块正是用来处理这个需求的。

(二)安装realip模块

[root@k8s-admin ~]# nginx -V

nginx version: nginx/1.16.1

built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)

built with OpenSSL 1.0.2k-fips  26 Jan 2017

TLS SNI support enabled

configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-stream_ssl_preread_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-google_perftools_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -m64 -mtune=generic' --with-ld-opt='-Wl,-z,relro -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'

(三)配置语法

set_real_ip_from 192.168.1.0/24; #真实服务器上一级代理的IP地址或者IP段,可以写多行。 set_real_ip_from 192.168.2.1; 

real_ip_header   X-Forwarded-For;  #从哪个header头检索出所要的IP地址。

real_ip_recursive on;      #递归的去除所配置中的可信IP。排除set_real_ip_from里面出现的IP。如果出现了未出现这些IP段的IP,那么这个IP将被认为是用户的IP。

一下就是配置实例:

server 

                listen 80;

                server_name  localhost;

                index index.html index.htm index.php;

                #include deny.ip;

                access_log /data/nginx.access.log;

                  location ~ .* 

                    proxy_pass http://192.168.180.20;

                    proxy_set_header X-Real-IP $remote_addr;

                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

                   #proxy_set_header X-Forward-For $remote_addr;

                    proxy_set_header Host $host;

                    set_real_ip_from  192.168.180.0/24;

                    set_real_ip_from 192.168.181.0/24;

                    real_ip_header    X-Forwarded-For;

                    real_ip_recursive on;

                        

        

如果服务器获取的IP地址如下:

192.168.180.4

192.168.181.30

118.242.26.94

在real_ip_recursive on的情况下,192.168.180.4和192.168.181.30这两个IP地址都在set_real_ip_from中出现,仅仅118.242.26.94没有出现,那么这个IP就被认为是用户的IP地址,并且赋值到remote_addr变量。

在real_ip_recursive off或者不设置的情况下,192.168.180.4出现在了set_real_ip_from中会被排除掉,其它的IP地址便认为是用户的ip地址。

服务器架构前面加了防火墙,Nginx如何获取客户端真实ip???

在大部分实际业务场景中,网站访问请求并不是简单地从用户(访问者)的浏览器直达网站的源站服务器,中间可能经过所部署的CDN、高防IP、WAF等代理服务器。例如,网站可能采用这样的部署架构:用户 > CDN/高防IP/WAF > 源站服务器。这种情况下,访问请求在经过多层加速或代理转发后,源站服务器该如何获取发起请求的真实客户端IP?

一般情况下,透明的代理服务器在将用户的访问请求转发到下一环节的服务器时,会在HTTP的请求头中添加一条X-Forwarded-For记录,用于记录用户的真实IP,其记录格式为X-Forwarded-For:用户IP。如果期间经历多个代理服务器,则X-Forwarded-For将以该格式记录用户真实IP和所经过的代理服务器IP:X-Forwarded-For:用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ……。

因此,常见的Web应用服务器可以使用X-Forwarded-For的方式获取访问者真实IP。

Nginx配置方案

  • 1、确认nginx安装时已经安装http_realip_module模块

为实现负载均衡,Nginx使用http_realip_module模块来获取真实IP。# nginx -V | grep http_realip_module命令查看是否已安装该模块。如未安装,则需要重新编译Nginx服务并加装该模块。方法如下:

wget http://nginx.org/download/nginx-1.14.2.tar.gz
tar zxvf nginx-1.14.2.tar.gz
cd nginx-1.14.2
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --without-http-cache --with-http_ssl_module --with-http_realip_module
make
make install
kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`
kill -QUIT `cat /usr/local/nginx/logs/ nginx.pid.oldbin`
  • 2、修改Nginx对应server的配置

打开www.conf配置文件,在location / {} 中加入以下内容:

set_real_ip_from ip_range1;    #真实服务器上一级代理的IP地址或者IP段,可以写多行
set_real_ip_from ip_range2;
...
set_real_ip_from ip_rangex;
real_ip_header    X-Forwarded-For;    #从哪个header头检索出需要的IP地址
real_ip_recursive on;    #递归排除set_real_ip_from里面出现的IP,其余没有出现的认为是用户真实IP

说明: 其中,ip_range1,2,...,x 指WAF的回源IP地址,需要分多条分别添加。

如何获取WAF的回源IP地址???

打开WAF界面-->设置-->产品信息-->即可查看到回源IP段,将这里的IP段按照上面的方式写进nginx配置当中即可,查看nginx访问日志就是客户端真实ip了。

  • 3、修改日志记录格式

log_format一般在nginx.conf配置文件中的http配置部分。在log_format中,添加x-forwarded-for字段,替换原来remote-address字段,即将log_format修改为以下内容:

log_format  main  '$http_x_forwarded_for - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" ';

以上是关于获取CDN用户真实IP的主要内容,如果未能解决你的问题,请参考以下文章

使用Nginx自带的Realip模块获取用户真实IP

如何查询使用了cdn的网站的真实ip

如何在CloudFlare下Nginx实现访客真实IP网站日志?

如何绕过用CDN的域名 获取真实IP地址

绕过cdn查找网站真实ip借助网络空间搜索引擎

使用了CloudFlare 的CDN,怎么找出网站的真实IP