因为各种原因已经使用 CDN 很多年了,一直有一个问题困扰着我,那就是上了CDN 的项目在后端获取到的客户端 IP 并不是客户的真实 IP,换句话说那是 CDN 回源节点的 IP。
这个问题其实早就在 WordPress 里发现了,以前一直没空研究,近期因为有自己写的项目涉及到这块了,就想着解决一下这个问题。
研究过程
看了一下阿里云的文档,大概知道回源的时候的请求会带上一个 Header,于是为了得到这个 Header 我在挂了 CDN 的网站下建立一个 php 文件用于测试。
<?php
print_r($_SERVER);
通过这个文件我们就能拿到所有的 Headers
Array
(
...
[HTTP_ALI_CDN_REAL_IP] => 183.14.*.*
[HTTP_X_FORWARDED_FOR] => 183.14.*.*
[REMOTE_ADDR] => 112.49.*.*
...
)
重点需要关注这三个 Headers,HTTP_ALI_CDN_REAL_IP
, HTTP_X_FORWARDED_FOR
是回源节点发送的自定义 Headers 即客户端的真实 IP,REMOTE_ADDR
是 Nginx 拿到的 “客户端” 的 IP。
而这个 REMOTE_ADDR
是 WordPress, Symfony(Laravel) 等项目获取客户端 IP 的函数所需要的。
后面又了解到了绝大多数 CDN 的厂商都会在回源的时候带上这个 HTTP_X_FORWARDED_FOR
这个 Header。
解决
那这就很简单了,为了尽可能减少对项目的改动,以及让线上的项目都能立刻获取到客户端的真实 IP,我就直接对 Nginx 的配置文件进行修改。
以 Nginx + PHP(fastcgi) 为例,这个代码添加在了 location
的块下。
set $real_ip $remote_addr;
if ($HTTP_X_FORWARDED_FOR != "") {
set $real_ip $HTTP_X_FORWARDED_FOR;
}
if ($HTTP_ALI_CDN_REAL_IP != "") {
set $real_ip $HTTP_ALI_CDN_REAL_IP;
}
fastcgi_param REMOTE_ADDR $real_ip;
验证
在 WordPress 发一个评论
那么这次获取到的 IP 即为真实地址。
文章最后修订于 2020年4月18日
评论 (0)