背景
站点启用了 CDN 后,面向访问者会隐藏服务器的真实 IP 地址,同时服务器也无法看到来访用户的真实 IP 地址,只能看到 CDN 服务提供商的节点地址,这样不利于一些服务端的功能实现。好在 Cloudflare 将访问者的 IP 地址包含在了 X-Forwarded-For 和 CF-Connecting-IP 标头中,通过 Nginx 的 http_realip_module 模块配合,前端程序还是可以获取到来访用户的真实 IP 地址。
准备工作
首先要确认 Nginx 已安装了 http_realip_module 模块nginx -V
configure arguments: ... --with-http_realip_module ...
如果未安装 http_realip_module 模块,则需要重新编译安装 Nginx 或为 Nginx 安装动态模块,方法参考 为 Nginx 添加 Brotli 动态模块 。
方法1
访问 https://www.cloudflare.com/ips/ 获取 Cloudflare 的所有节点最新 IP 地址:
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/12
172.64.0.0/13
131.0.72.0/22
2400:cb00::/32
2606:4700::/32
2803:f800::/32
2405:b500::/32
2405:8100::/32
2a06:98c0::/29
2c0f:f248::/32
打开站点配置文件 /etc/nginx/conf.d/<website>.conf
插入以下内容
# cloudflare ips
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
# use any of the following two
#real_ip_header CF-Connecting-IP;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
修改完毕,测试并重新加载配置文件:
nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
nginx -s reload
方法2
一般来说 Cloudflare 的 IP 地址是不会变的,但是为了以防万一,可以创建一个脚本,自动获取最新的 Cloudflare 节点 IP 地址并输出到单独的 conf 文件,同时将这个 conf 文件 include 进 Nginx 的站点配置里。
新建用来存放 Cloudflare 节点 IP 地址的空文件:mkdir /etc/nginx/others; touch /etc/nginx/others/ip_cloudflare.conf
编辑站点配置文件 /etc/nginx/conf.d/<website>.conf
插入以下内容:
include others/ip_cloudflare.conf;
然后创建脚本 update_ip_cloudflare.sh
写入以下内容:
#!/bin/bash
echo "# cloudflare ips" > /etc/nginx/others/ip_cloudflare.conf;
echo "set_real_ip_from 127.0.0.1;" > /etc/nginx/others/ip_cloudflare.conf;
for i in `curl https://www.cloudflare.com/ips-v4`; do
echo "set_real_ip_from $i;" >> /etc/nginx/others/ip_cloudflare.conf;
done
for i in `curl https://www.cloudflare.com/ips-v6`; do
echo "set_real_ip_from $i;" >> /etc/nginx/others/ip_cloudflare.conf;
done
echo "" >> /etc/nginx/others/ip_cloudflare.conf;
echo "# use any of the following two" >> /etc/nginx/others/ip_cloudflare.conf;
echo "#real_ip_header CF-Connecting-IP;" >> /etc/nginx/others/ip_cloudflare.conf;
echo "real_ip_header X-Forwarded-For;" >> /etc/nginx/others/ip_cloudflare.conf;
echo "" >> /etc/nginx/others/ip_cloudflare.conf;
echo "real_ip_recursive on;" >> /etc/nginx/others/ip_cloudflare.conf;
nginx -s reload
修改脚本权限 chmod +x update_ip_cloudflare.sh
最后添加定时任务,每天早上 6 点钟自动执行脚本:
crontab -e
添加如下行
0 6 * * * /bin/bash /root/update_ip_cloudflare.sh >/dev/null
重启 crond 服务 service crond restart
版权声明:本文为原创文章,版权归 BenhoN 所有。
本文链接:https://blog.benhon.net/archives/get_clients_realip_in_nginx_behind_cdn.html
所有原创文章采用知识共享 署名-非商业性使用 4.0 国际 许可协议进行许可,你可以自由地转载和修改,但请务必注明文章来源并且不可用于商业目的。