网站开启 CDN 之后,再去看看网站的访问日志,会发现全是 CDN 的 IP,这样其实挺难受的,都看不到真实的 IP 访问情况。所以老唐就花了些时间研究了一下怎么获取并记录用户访问的真实 IP 地址,因为老唐是基于 LNMP 搭建的网站环境,所以就是基于 NGINX 的方法。主要分为三步,第一是需要安装 NGINX 的一个模块,然后是修改 NGINX 配置来设置并启用这个模块,最后就是将获取到的真实 IP 地址记录到日志里。
下面教程都是基于 LNMP 一键包进行的。(一键安装 LNMP 建站环境,部署 PHP + MySQL)
一、安装 NGINX http_realip_module 模块
首先,我们需要安装 NGINX 的一个模块,叫 http_realip_module
。
在 LNMP 安装目录下找到 lnmp.conf
这个文件,编辑这个文件,在 Nginx_Modules_Options
里加上 realip
,修改的命令如下:
Nginx_Modules_Options='--with-http_realip_module'
保存后执行 ./upgrade.sh nginx
来升级下 NGINX 就可以了。升级需要输入新的 NGINX 版本号,如果不想改动版本,直接输入原来的版本号即可。
这样就算是装好了。
二、修改 LNMP 配置启用模块
安装好之后,需要启用 realip 模块。如果想为所有网站启用,那么直接修改 nginx.conf 文件(/usr/local/nginx/conf/nginx.conf
),如果只想对某些网站启用,那么修改对应的网站的 conf 文件即可。
方法一(推荐):
首先,在 nginx 配置目录创建下面文件:
touch /usr/local/nginx/conf/cloudflare_ip.conf
然后,以修改 nginx.conf 为例,在 server {}
里面加上下面这一行:
include cloudflare_ip.conf;
在 /root 目录下创建下面文件:
update_cloudflare_ip.sh
输入下面内容(直接复制粘贴即可):
#!/bin/bash echo "#Cloudflare" > /usr/local/nginx/conf/cloudflare_ip.conf; for i in `curl https://www.cloudflare.com/ips-v4`; do echo "set_real_ip_from $i;" >> /usr/local/nginx/conf/cloudflare_ip.conf; done for i in `curl https://www.cloudflare.com/ips-v6`; do echo "set_real_ip_from $i;" >> /usr/local/nginx/conf/cloudflare_ip.conf; done echo "" >> /usr/local/nginx/conf/cloudflare_ip.conf; echo "# use any of the following two" >> /usr/local/nginx/conf/cloudflare_ip.conf; echo "real_ip_header CF-Connecting-IP;" >> /usr/local/nginx/conf/cloudflare_ip.conf; echo "#real_ip_header X-Forwarded-For;" >> /usr/local/nginx/conf/cloudflare_ip.conf;
保存之后,配置 crontab 每周更新一次 Cloudflare 的 IP 地址(crontab -e
):
0 5 * * 1 /bin/bash /root/update_cloudflare_ip.sh
这样就算配置好 Cloudflare IP 的自动更新了,最后我们需要先手动运行一下这个文件先初始化一次:
/bin/bash /root/update_cloudflare_ip.sh
方法二:
如果不想搞这么麻烦,那么直接在 nginx.conf 的 server {}
里面加入下面几行即可:
location / { 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 104.16.0.0/12; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; set_real_ip_from 199.27.128.0/21; 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 2c0f:f248::/32; set_real_ip_from 2a06:98c0::/29; # use any of the following two real_ip_header CF-Connecting-IP; #real_ip_header X-Forwarded-For; }
至此,我们算是配置完成 NGINX 了,我们需要重启一下:
lnmp nginx restart
如果不报错就是成功了,报错的话根据错误信息自己再看看哪里有问题。
三、记录真实 IP 到日志
上一步结束我们只是启用并且配置了 realip 这个模块,但是还没有真正记录到 log 日志中,所以我们现在去看日志的话,会发现还是看不到真实 IP 地址。
接下来就继续修改一下日志格式,把真实 IP 地址记录到日志中。
还是修改 /usr/local/nginx/conf/nginx.conf
这个文件,在 http {}
中间加入下面几行:
map $HTTP_CF_CONNECTING_IP $clientRealIp { "" $remote_addr; ~^(?P[0-9.]+),?.*$ $firstAddr; } log_format main '$clientRealIp [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '$http_user_agent $remote_addr $request_time';
主要是为了通用性,如果关闭了 CDN,可以不需要修改获取IP的方式,所以才这么修改,不然直接用 $HTTP_CF_CONNECTING_IP
就行了(这个时候就不需要在日志格式里使用 $clientRealIp
)
然后在网站记录的日志定义使用 main
这个日志格式,比如(需要在网站单独的配置文件中修改):
access_log /home/wwwlogs/abc.com.log main;
然后我们再次重启一下 NGINX,就可以在网站日志中看到真实的 IP 地址了。
参考:
- https://blog.rhilip.info/archives/256/
- https://wzfou.com/cdn-real-ip/
- https://support.cloudflare.com/hc/en-us/articles/200170786-How-do-I-restore-original-visitor-IP-with-Nginx
- https://docs.nginx.com/nginx/admin-guide/monitoring/logging/
- https://www.bbsmax.com/A/A7zgbXXWd4/
四、封禁真实 IP 地址
后续如果我们还想更进一步封禁真实 IP 地址,可以使用下面的方法,因为开了 CDN 之后使用 iptables 是没法封禁真实 IP 地址的。
在强大的 Nginx 面前只要想得到,你就做得到!通过对 $clientRealIP
这个变量的判断,Nginx 就能实现隔山打牛的目的,而且规则简单易懂:
#如果真实IP为 121.42.0.18、121.42.0.19,那么返回403 if ($clientRealIp ~* "121.42.0.18|121.42.0.19") { #如果你的nginx安装了echo模块,还能如下输出语言,狠狠的发泄你的不满(但不兼容返回403,试试200吧)! #add_header Content-Type text/plain; #echo "son of a bitch,you mother fucker,go fuck yourself!"; return 403; break; }
把这个保存为 deny_ip.conf ,上传到 Nginx 的 conf 文件夹,然后在要生效的网站 server 模块中引入这个配置文件,并 Reload 重载 Nginx 即可生效:
#禁止某些用户访问 include deny_ip.conf;
如果再想添加其他要禁止的 IP,只需要编辑这个文件,插入要禁止的 IP,使用分隔符 | 隔开即可,记得每次修改都需要 reload 重载 Nginx才能生效。
更多方法也可以参考: