网站套了 Cloudflare 的 CDN,用户的真实 IP 藏在 CDN 后面,俺们只能获取到 CF 的 IP,那么怎么获取用户的真实 IP 呢? 下面细讲。
1、用户直接访问对外服务的普通网站
浏览器 –> DNS解析 –> WEB数据处理 –> 数据吐到浏览器渲染展示
2、用户访问使用了CDN的网站
浏览器 –> DNS解析 –> CDN节点 –> WEB数据处理 –> 数据吐到浏览器渲染展示
3、用户通过代理上网访问了我们的网站
浏览器 –> 代理上网 –> DNS解析 –> 上述2种模式均可能
对于第一种模式,我要禁止这个用户的访问很简单,Nginx 的 deny 指令来禁止即可:
deny 1.1.1.1;
deny 1.1.1.1/24;
[indent]但套上CDN后这样的屏蔽方式就不行了,以 Cloudflare 为例,访问你服务器的就是 CF IP了,为了识别真实 IP 这就需要用到 $http_x_forwarded_for 配置了。
当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 HTTP 的头中加入一个记录
X-Forwarded-For : 用户IP, 代理服务器IP
如果中间经历了不止一个代理服务器,这个记录会是这样
X-Forwarded-For : 用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ….
可以看到经过好多层代理之后, 用户的真实 IP 在第一个位置, 后面会跟一串中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个 IP 地址做限制就可以了。
配合使用了 $remote_addr (获取访问服务器上的IP,也就是第一种访问模式),也就是你既可以获取 CF IP 和真实 IP 还有代理 IP,那么下面讲讲怎么在 log 里获取真实 IP 以及屏蔽藏在 CF 后的访问 IP。
Nginx的log获取真实IP配置如下:
在 HTTP 段可参照下面写法,可获取CDN IP 和真实 IP:
log_format quic '$http_x_forwarded_for [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'$http_user_agent $remote_addr $request_time "$quic" ';
error_log /var/log/nginx/error.log crit;
access_log /var/log/nginx/access.log quic buffer=32k flush=5s;
屏蔽获取的真实IP:
#如果真实IP为 1.1.1.1、2.2.2.2,那么返回403或444
if ($http_x_forwarded_for ~* "1.1.1.1|2.2.2.2") {
#如果你的nginx安装了echo模块,还能如下输出语言,发泄一下你的不满(但不兼容返回403,试试200吧)!
#add_header Content-Type text/plain;
#echo "son of a bitch,you mother fucker,go fuck yourself!";
return 444;
break;
}
把这个保存为 deny_ip.conf ,上传到 Nginx 的 conf.d 文件夹,然后在要生效的网站 server 模块中引入这个配置文件,并 Reload 重载 Nginx 即可生效:
include /etc/nginx/conf.d/*.conf;