启用CDN后网站获取用户真实IP:Cloudflare CDN真实IP地址(Nginx,Apache)

近期在其云否维护客户的网站时,客户要求屏蔽国外IP的访问,因为从日志来看攻击的IP大部分都是来自国外,并且自己的目标用户为国内,所以只允许国内的IP访问网站可阻止绝大多数的CC和DDoS攻击。实际测试后,发现效果还是不错,攻击想要再次攻击成本增加了不少。

不过,随后发现了一个问题,就是使用了Cloudflare CDN后,网站获取到的IP地址都是Cloudflare的CDN节点的,不能得到真实用户的IP地址,防御效果大大折扣。好在Cloudflare已经为我们想到这一点了,将访问者的 IP 地址包含在 X-Forwarded-For 标头和 CF-Connecting-IP 标头。

有了 X-Forwarded-For 标头,如果是Nginx可以使用ngx_http_realip_module模块,如果是Apache,则可以使用mod_remoteip模块来获取用户的真实IP。本篇文章就来分享一下如何编译和启用ngx_http_realip_module模块和mod_remoteip模块来获取用户的真实IP地址。

一般来说CDN厂商都采用了X-Forwarded-For和X-Real_IP等标准协议,所以本文介绍了获取用户真实IP的访问基本上适用于其它的CDN厂商。更多的关于CDN加速和服务器优化加速的方法,这里有:

  1. Cloudflare Partner接入管理Cloudflare CDN-启用Railgun动态加速

  2. 又拍云CDN加速申请使用教程-一键镜像,静态动态CDN和免费SSL

  3. WordPress开启Nginx fastcgi_cache缓存加速方法-Nginx配置实例


一、Nginx编译ngx_http_realip_module

1.1 Oneinstack编译

如果用的是Oneinstack一键包,则可以用以下命令来编译ngx_http_realip_module:

  1. #下编译安装nginx的时候,都编译安装的哪些模块

  2. [root@wzfoume ~]# nginx -V

  3. nginx version: nginx/1.14.2

  4. built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC)

  5. built with OpenSSL 1.1.1a 20 Nov 2018

  6. TLS SNI support enabled

  7. configure arguments: --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-openssl=../openssl-1.1.1a --with-pcre=../pcre-8.42 --with-pcre-jit --with-ld-opt=-ljemalloc

  8. #进入到oneinstack的nginx安装目录下,如果没有请先解压

  9. [root@wzfoume src]# cd /root/oneinstack/src

  10. [root@wzfoume src]# tar xzf nginx-1.14.2.tar.gz

  11. [root@wzfoume src]# cd /root/oneinstack/src/nginx-1.14.2

  12. [root@wzfoume nginx-1.14.2]# ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_stub_status_module --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module --with-http_realip_module --with-http_flv_module --with-http_mp4_module --with-openssl=../openssl-1.1.1a --with-pcre=../pcre-8.42 --with-pcre-jit --with-ld-opt=-ljemalloc --with-http_realip_module

  13. make

  14. #如果出现错误,应该是依赖路径不对,请cd ..到上一个目录解压相应的软件

  15. tar xzf pcre-8.42.tar.gz

  16. tar xzf openssl-1.0.2q.tar.gz

  17. tar xzf openssl-1.1.1a.tar.gz

  18. #编译完成,备份原先配置,然后替换nginx二进制文件

  19. mv /usr/local/nginx/sbin/nginx{,_`date +%F`} #备份nginx

  20. cp objs/nginx /usr/local/nginx/sbin

  21. #查看是否已经把http_realip_module模块加入进去

  22. nginx -V


1.2 LNMP编译

如果你用的是LNMP一键包,在lnmp安装目录下找到lnmp.conf编辑它,在Nginx_Modules_Options里加上realip,保存后执行./upgrade.sh nginx来升级下Nginx就可以了。命令如下:

  1. Nginx_Modules_Options='--with-http_realip_module'


1.3 BT宝塔面板

如果你用的是BT宝塔面板,可以使用以下命令来编译ngx_http_realip_module:

  1. #宝塔面板安装模块

  2. #先查看一下本机的Nginx配置情况

  3. [root@cs ~]# nginx -V

  4. nginx version: nginx/1.14.2

  5. built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)

  6. built with OpenSSL 1.0.2l 25 May 2017

  7. TLS SNI support enabled

  8. configure arguments: --user=www --group=www --prefix=/www/server/nginx --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/nginx-http-concat --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-pcre=pcre-8.40 --with-ld-opt=-ljemalloc

  9. #开始下载Nginx,这里用的是1.15.1,你也可以下载其它的版本

  10. wget http://nginx.org/download/nginx-1.15.1.tar.gz

  11. tar -xzvf nginx-1.15.1.tar.gz

  12. cd nginx-1.15.1

  13. #下面的命令只是在上面的Nginx -v得到的配置详情后加上了--with-http_realip_module,目的是为了保持原来的配置不变同时又增加新的模块

  14. ./configure --user=www --group=www --prefix=/www/server/nginx --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --add-module=/www/server/nginx/src/nginx-http-concat --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-pcre=pcre-8.40 --with-ld-opt=-ljemalloc --with-http_realip_module

  15. #只编译不安装

  16. make

  17. #先停用Nginx,然后替换新的Nginx并查看模块是否已经加载。命令如下:

  18. mv /www/server/nginx/sbin/nginx /www/server/nginx/sbin/nginx-wzfou.backup

  19. cp objs/nginx /www/server/nginx/sbin/nginx

  20. nginx -V

  21. #重启Nginx


二、Nginx设置set_real_ip_from

编译好了ngx_http_realip_module,现在我们只需要在Nginx配置文件中添加set_real_ip_from代码,示例如下:

  1. set_real_ip_from 222.222.222.222; #这里是需要填写具体的CDN服务器IP地址,可添加多个

  2. set_real_ip_from 222.222.111.111;

  3. real_ip_header X-Forwarded-For;

  4. real_ip_recursive on;


如果你用的是CloudFlare免费CDN,请将以下代码加入到你的Nginx配置文件当中。

  1. location / {

  2. set_real_ip_from 103.21.244.0/22;

  3. set_real_ip_from 103.22.200.0/22;

  4. set_real_ip_from 103.31.4.0/22;

  5. set_real_ip_from 104.16.0.0/12;

  6. set_real_ip_from 108.162.192.0/18;

  7. set_real_ip_from 131.0.72.0/22;

  8. set_real_ip_from 141.101.64.0/18;

  9. set_real_ip_from 162.158.0.0/15;

  10. set_real_ip_from 172.64.0.0/13;

  11. set_real_ip_from 173.245.48.0/20;

  12. set_real_ip_from 188.114.96.0/20;

  13. set_real_ip_from 190.93.240.0/20;

  14. set_real_ip_from 197.234.240.0/22;

  15. set_real_ip_from 198.41.128.0/17;

  16. set_real_ip_from 199.27.128.0/21;

  17. set_real_ip_from 2400:cb00::/32;

  18. set_real_ip_from 2606:4700::/32;

  19. set_real_ip_from 2803:f800::/32;

  20. set_real_ip_from 2405:b500::/32;

  21. set_real_ip_from 2405:8100::/32;

  22. set_real_ip_from 2c0f:f248::/32;

  23. set_real_ip_from 2a06:98c0::/29;

  24. # use any of the following two

  25. real_ip_header CF-Connecting-IP;

  26. #real_ip_header X-Forwarded-For;

  27. }

  28. #不要忘记重启nginx

  29. service nginx restart


一般来说CloudFlare的IP地址是不会变的,你可以在这里找到:https://www.cloudflare.com/ips/,但是为了以防万一,wzfou.com建议设置一个自动更新CloudFlare的IP的定时任务,自动将最新的IP添加到Nginx的配置文件当中。代码如下:

  1. #在nginx配置目录创建cloudflare_ip.conf文件

  2. touch /usr/local/nginx/conf/cloudflare_ip.conf

  3. #修改原有的vhost配置,将原来第五步配置的信息改为

  4. include cloudflare_ip.conf;

  5. #创建自更新脚本update_cloudflare_ip.sh(假定该文件放在 /root 目录下),内容如下:

  6. #!/bin/bash

  7. echo "#Cloudflare" > /usr/local/nginx/conf/cloudflare_ip.conf;

  8. for i in `curl https://www.cloudflare.com/ips-v4`; do

  9. echo "set_real_ip_from $i;" >> /usr/local/nginx/conf/cloudflare_ip.conf;

  10. done

  11. for i in `curl https://www.cloudflare.com/ips-v6`; do

  12. echo "set_real_ip_from $i;" >> /usr/local/nginx/conf/cloudflare_ip.conf;

  13. done

  14. echo "" >> /usr/local/nginx/conf/cloudflare_ip.conf;

  15. echo "# use any of the following two" >> /usr/local/nginx/conf/cloudflare_ip.conf;

  16. echo "real_ip_header CF-Connecting-IP;" >> /usr/local/nginx/conf/cloudflare_ip.conf;

  17. echo "#real_ip_header X-Forwarded-For;" >> /usr/local/nginx/conf/cloudflare_ip.conf;

  18. #配置crontab 每周一的上午5点更新

  19. 0 5 * * 1 /bin/bash /root/update_cloudflare_ip.sh


三、Apache配置mod_remoteip模块

3.1 apache 2.4

apache 2.4自带mod_remoteip模块不需要安装,按照下文操作:

  1. #启用模块

  2. vim /usr/local/apache/conf/httpd.conf

  3. Include conf/extra/httpd-remoteip.conf

  4. #添加如下内容

  5. vim /usr/local/apache/conf/extra/httpd-remoteip.conf

  6. LoadModule remoteip_module modules/mod_remoteip.so

  7. RemoteIPHeader X-Forwarded-For

  8. RemoteIPInternalProxy 127.0.0.1/24

  9. #CloudFlare IP Ranges

  10. RemoteIPInternalProxy 103.21.244.0/22

  11. RemoteIPInternalProxy 103.22.200.0/22

  12. RemoteIPInternalProxy 103.31.4.0/22

  13. RemoteIPInternalProxy 104.16.0.0/12

  14. RemoteIPInternalProxy 108.162.192.0/18

  15. RemoteIPInternalProxy 131.0.72.0/22

  16. RemoteIPInternalProxy 141.101.64.0/18

  17. RemoteIPInternalProxy 162.158.0.0/15

  18. RemoteIPInternalProxy 172.64.0.0/13

  19. RemoteIPInternalProxy 173.245.48.0/20

  20. RemoteIPInternalProxy 188.114.96.0/20

  21. RemoteIPInternalProxy 190.93.240.0/20

  22. RemoteIPInternalProxy 197.234.240.0/22

  23. RemoteIPInternalProxy 198.41.128.0/17 #你的CDN的IP,可以重复添加

  24. #修改日志格式,在日志格式中加上%a,然后重启apache即可

  25. LogFormat "%h %a %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined

  26. LogFormat "%h %a %l %u %t "%r" %>s %b" common

  27. LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %I %O" combined


3.2 apache 2.2

apache 2.2需要安装mod_remoteip模块,方法如下:

  1. wget https://github.com/ttkzw/mod_remoteip-httpd22/raw/master/mod_remoteip.c

  2. /usr/local/apache/bin/apxs -i -c -n mod_remoteip.so mod_remoteip.c

  3. #启用模块

  4. vim /usr/local/apache/conf/httpd.conf

  5. Include conf/extra/httpd-remoteip.conf

  6. #添加如下内容,然后重启apache即可

  7. vim /usr/local/apache/conf/extra/httpd-remoteip.conf

  8. LoadModule remoteip_module modules/mod_remoteip.so

  9. RemoteIPHeader X-Forwarded-For

  10. RemoteIPInternalProxy 127.0.0.1 #你的CDN的IP,可以重复添加


四、网站仅允许Cloudflare CDN的IP访问

上面我们是通过安装ngx_http_realip_module和mod_remoteip模块获取到了用户真实的IP地址,但是有的时候我们需要借助Cloudflare 的安全防护功能来防止CC或者DDoS攻击,即仅允许Cloudflare CDN的IP访问我们的访问。

Nginx直接拒绝和允许IP访问代码示例如下:

  1. location / {

  2. deny 192.168.1.1;

  3. allow 192.168.1.0/24;

  4. allow 10.1.1.0/16;

  5. allow 2001:0db8::/32;

  6. #Railgun IP

  7. deny all;

  8. }


如果我们仅允许Cloudflare CDN的IP访问网站,我们可以直接在nginx配置中将Cloudflare CDN的IP添加到允许的范围内。

  1. #直接加入

  2. # https://www.cloudflare.com/ips

  3. # IPv4

  4. allow 103.21.244.0/22;

  5. allow 103.22.200.0/22;

  6. allow 103.31.4.0/22;

  7. allow 104.16.0.0/12;

  8. allow 108.162.192.0/18;

  9. allow 131.0.72.0/22;

  10. allow 141.101.64.0/18;

  11. allow 162.158.0.0/15;

  12. allow 172.64.0.0/13;

  13. allow 173.245.48.0/20;

  14. allow 188.114.96.0/20;

  15. allow 190.93.240.0/20;

  16. allow 197.234.240.0/22;

  17. allow 198.41.128.0/17;

  18. # IPv6

  19. allow 2400:cb00::/32;

  20. allow 2405:8100::/32;

  21. allow 2405:b500::/32;

  22. allow 2606:4700::/32;

  23. allow 2803:f800::/32;

  24. allow 2c0f:f248::/32;

  25. allow 2a06:98c0::/29;


自动更新Cloudflare CDN的IP。手动添加Cloudflare CDN的IP到Nginx配置当中简单方便,但是一旦Cloudflare CDN的IP有变化时还得自己手动处理,我们可以创建一个脚本,定时去更新Cloudflare CDN的IP,自动添加到Nginx配置中,代码如下:

  1. touch /usr/local/nginx/conf/allow_ip.conf

  2. #修改网站nginx配置,加入以下代码:

  3. include /usr/local/nginx/conf/allow_ip.conf;

  4. vim /data/script/allow_cf_ip.sh

  5. #!/bin/bash

  6. echo "#Cloudflare" > /usr/local/nginx/conf/allow_ip.conf;

  7. for i in `curl https://www.cloudflare.com/ips-v4`; do

  8. echo "allow $i;" >> /usr/local/nginx/conf/allow_ip.conf;

  9. done

  10. for i in `curl https://www.cloudflare.com/ips-v6`; do

  11. echo "allow $i;" >> /usr/local/nginx/conf/allow_ip.conf;

  12. done

  13. #添加定时任务

  14. 0 5 * * 1 /bin/bash /data/script/allow_cf_ip.sh


五、总结

使用了CDN加速后,我们的网站获取到的用户IP变成了CDN的IP了,想要获取到用户的真实IP就得利用Nginx和Apache的模式功能。当然,如果你用的是PHP,例如Wordpress,直接将以下代码加入到你的Wordpress配置文件当中即可。

  1. if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))

  2. {

  3. $list = explode(‘,’,$_SERVER['HTTP_X_FORWARDED_FOR']);

  4. $_SERVER['REMOTE_ADDR'] = $list[0];

  5. }


这里还要特别提醒一下,如果你启用了Cloudflare Railgun动态加速(挖站否的Cloudflare Partner接入管理就提供此免费服务),记得将Railgun的服务器IP加入到配置当中,因为启用了Railgun后网站获取到的IP地址都来自Railgun服务器上的。
    A+
发布日期:2019年3月12日  所属分类: 实用技术
标签: