網站開啟 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 http://www.cloudflare.com/ips-v4`; do echo "set_real_ip_from $i;" >> /usr/local/nginx/conf/cloudflare_ip.conf; done for i in `curl http://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 地址了。
參考:
四、封禁真實 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才能生效。
更多方法也可以參考: