启用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服务器上的。

  • 微信扫码捐赠
  • 微信扫码捐赠
  • 如果帮到了您,您可以赞助我一下!
  • 支付宝扫码捐赠
  • 支付宝扫码捐赠
  • 不论多少,我都向您表示特别的感谢!

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: