博客一直在使用 CDN (减速),不是为了给网站加速,因为我站内本身图片等大文件就少,而且(几乎)所有的静态资源都已经放在单独的 CDN 域名上托管了,而页面是动态内容没有缓存,经过 CDN 中转一道铁定是起到了减速作用,但为了安全起见,你懂得...
众所周知,使用 CDN 后, 一般程序默认使用 $_SERVER['REMOTE_ADDR']
or $_SERVER['HTTP_CLIENT_IP']
获取 IP 的话,都是 CDN 服务器的 IP,而我其实一直不是很关心这个,但是最近看到很多垃圾评论都进来了,还 IP 都一样,就看着很不爽了,于是决定把这个 “脚底的沙子” 掏一掏...
于是,打开 Google,输入 “Typecho CDN IP”,果然你遇到的问题一定都是别人解决过的,准备开抄...
当我看到解决方案,这简单除暴有效通用的方法真是过于真实...
//防止 CDN 造成无法获取客户真实 IP 地址
if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$list = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $list[0];
}
是的,所有的搜索结果都是这个,文章标题,文章内容,一毛一样,都不知道是谁抄谁的了,有效是真的有效,但是是真的一言难尽,我不服,我要找到正统的解决方案,不行我就去改代码!!!
其实思路很简单,搜索程序内获取客户端 IP 的相关代码,那附近一定藏着什么秘密。
代码全局搜索 “REMOTE_ADDR”,在 /var/Typecho/Request.php:659
行 setIp
方法内,找到到了相关的设置。
这个方法的主要代码是一个 switch
,先尝试从 $this->getServer(__TYPECHO_IP_SOURCE__)
中获取 IP,然后才尝试从 $this->getServer('REMOTE_ADDR')
中获取IP,而查看 getServer
相关的代码,发现基本功能就是获取 $_SERVER
内的相关变量。
那么,我们只要在配置文件提前定义好常量 __TYPECHO_IP_SOURCE__
的值,那么程序就会优先从这个对应 $_SERVER
的成员中获取值。
只要在配置文件(/config.inc.php
)加入如下代码即可:
/** 定义 IP 来源 */
define('__TYPECHO_IP_SOURCE__', 'HTTP_X_FORWARDED_FOR');
这也是官方提前预留出的获取 IP 的方案,显然也是官方所希望的✅正确用法。
当然,由于众所周知的原因,HTTP_X_FORWARDED_FOR
是非常不安全的,因为它有被伪造 IP 的风险,想一下,如果某一天你下掉了 CDN ,而又忘记修改这里,那么你的程序就有可能获取到客户端伪造的 IP,而有这样漏洞的程序在网上可是数不胜数,而很多导致漏洞的代码都是新(cai)手(niao)在搜索时,遇到了和上面一样广为传(chao)播(xi)的错误代码所害。
好在大多数 CDN 厂商都会给提供客户端真实IP,除了会把客户端IP加到 HTTP_X_FORWARDED_FOR
外,一般还会有自己定义的 Header 头,比如阿里云的就是 HTTP_ALI_CDN_REAL_IP
(这个头是可信的,无法被客户端伪造 / 覆盖 / 修改的)。
所以,我们还可以这样配置(推荐):
在配置文件 (/config.inc.php
) 中加入如下配置。
/** 定义 IP 来源 */
define('__TYPECHO_IP_SOURCE__', 'HTTP_ALI_CDN_REAL_IP');
不同的 CDN 厂商会有不同的头,一般官方文档会有给出对应的 Header Name,可以尝试找一下文档,如果找不到也没关系,手动输出你服务器获取到的 $_SERVER
头信息,这里面一定会有一些蛛丝马迹。
比如阿里云,附加了好几个自定义的头信息:
- HTTP_ALI_SWIFT_USE_UPSTREAM_TPROXY=on (作用未知)
- HTTP_ALI_TPROXY_ORIGIN_PORT=443 (应该是源端口)
- HTTP_ALI_TPROXY_ORIGIN_HOST=www.qs5.org (应该是客户端请求的真实域名)
- HTTP_ALI_TPROXY_ORIGIN_SCHEME=https (应该是客户端发起的协议)
- HTTP_ALI_CDN_REAL_IP=xxx (客户端的真实IP)
- HTTP_ALI_SWIFT_STAT_HOST=www.qs5.org (应该是 CDN 配置后台用的域名吧?)
- HTTP_ALI_SWIFT_LOG_HOST=www.qs5.org (应该是 后台配置的日志域名?)
至于具体用途,我也没有研究过,不好乱说误导人,只能把我大概能猜到用途的写到括号里面了。
改完我还没测试IP对不对呢
经测试,IP是对的,客户端IP,说明修改有效。
舒服舒服
赞,这才是正确的方法。直接改 _SERVER 太不优雅了