用 CDN 后获取评论者真实 IP 的方法

今天,本站成功接入腾讯云 CDN,享受高速内容分发网络。

做网站的人都知道,对于 WordPress 而言,保存评论者真实 IP 的重要性。我们经常会遇见恶意进行大量的行为,对于直连的主机,我们可以直接通过 IP 过滤掉这些恶意评论。

而对于套了一层 CDN 或代理的网站,这些方法可能就失效了。因为 WordPress 记录的 IP 是来自 $_SERVER['REMOTE_ADDR'],而用上 CDN 后,这会变成了 CDN 节点的 IP。

那么真实的 IP 藏在哪里呢?我们该如何通过 Hack WordPress 来使 WordPress 获取到真实的评论者 IP 呢?

真假难辨的访问模式

对于访客而言,我们有这3种常见的访问模式:

  1. 直接连接网站(用户->服务器)
  2. 透过 CDN 连接网站(用户->CDN->服务器)
  3. 透过代理连接网站(用户->代理(->CDN)->服务器)

而会造成麻烦的访问模式,就是第2和第3种。

问题的溯源

前面已简单提过,原因是 WordPress 是通过 $_SERVER['REMOTE_ADDR'] 来记录 IP,而当遇到 CDN 时,这个值不再是访客的真实 IP,而变成了访客 CDN 节点的 IP。

而当一个 CDN 或者透明代理服务器把请求转到后面服务器的时候,这个 CDN 服务器会在 HTTP 的头中加入一个记录 $_SERVER['HTTP_X_FORWARDED_FOR'],它的格式是这样的:访客 IP, 代理服务器 1-IP,代理服务器 2-IP, 代理服务器 3-IP, … ,因此我们可以看到经过好多层代理之后, 访客真实 IP 在第一个位置, 后面会跟一串中间代理服务器的IP地址。

因此,我们从 $_SERVER['HTTP_X_FORWARDED_FOR'] 下手就可以取到用户真实的IP地址了。

Hack WordPress

经过查阅资料,WordPress 有一个关键的 Hook 可以供我们使用,那就是 pre_comment_user_ip,其在开发文档中的表述是:

Filters the comment author’s IP before it is set.

所以,我们只要将以下的代码放在主题的 functions.php 就能解决这个问题(终于进入正题了,好累)

add_filter( 'pre_comment_user_ip', 'nikbobo_get_correct_ip_for_comment' );

function nikbobo_get_correct_ip_for_comment() {
    if ( empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
        $ips = array( $_SERVER['REMOTE_ADDR'] );
    } else {
        $ips = explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] );
    }
    $ip = array_map( function ( $ip ) {
        return trim( $ip );
    }, $ips );

return $ip[0];
}

但是,如果用了一些高级的访客统计插件的话,可能问题就不止那么简单了,可能要通过修改插件的方式解决。反正我不用这些插件,管他呢~

此文章是由nikbobo发表在WordPress分类目录的。将固定链接加入收藏夹。

关于 nikbobo

Nikbobo,本名刘永强,记忆空间站长,男,1998 年出生于广东茂名,至今(2022 年)23 岁,目前(2022 年)就读于广州大学华软软件学院,常以“nikbobo”这个网名混迹互联网。如无特殊注明,Nikbobo 在本站发表的文章,遵循 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议。详情请参阅关于页面的作者介绍。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注