比尔盖子 博客

在用户使用代理,或者服务器使用反向代理或CDN的情况下,获得访客的正确IP

这个方法既可以获得使用代理访问网站访客的真实IP,也可以在服务器使用反向代理或CDN的情况获取访客的真实IP。

由IP不正确想到的

最近,比尔盖子博客使用了Cloudflare的免费CDN服务来加速博客的访问,但是从昨天开始比尔盖子留意到这样一个问题:

由于Cloudflare CDN的本质是代理服务器(反向代理),因此,网站系统评论获取评论信息时,就会将用户的IP统统获取为CDN服务器的IP,导致了无法正确获得浏览者的IP。

 

因为比尔盖子常使用HTTP代理,所以对代理还是有一些了解的。

代理一般分为“透明代理、匿名代理、超级匿名代理”。如果使用透明代理,服务器将依旧可以通过一些方式来获取用户的真实IP;如果使用匿名代理,服务器可以通过一些方式发现用户可能在使用代理服务器,但无法确定用户的真实IP;使用超级匿名代理时,服务器无论如何也无法检测出用户使用了代理服务器。

那么,Cloudflare CDN的反向代理会不会也是一个透明代理呢?能否采用识别使用代理服务器用户真实IP的一般方法,来获取在服务器使用Cloudflare CDN或反向代理时获取正确的用户IP呢?

原理

在PHP中用户的IP有三个属性:HTTP_CLIENT_IP、
HTTP_X_FORWARDED_FOR、REMOTE_ADDR。

REMOTE_ADDR是和服务器连接时,服务器看到的IP地址(如果使用代理,就是最后一台代理的IP);HTTP_CLIENT_IP为代理服务器的IP,不使用代理就没数据;HTTP_X_FORWARDED_FOR是使用代理时,用户的真实IP,不使用代理就没数据(如果用户使用的多层代理,则 用户–> A –> B –> 网站,那么数据就为“用户IP,A的IP”,即最后一台代理服务器之前数据流经过的所有服务器的IP地址)。

这三个值均可伪造,不过如果不是匿名代理或超级匿名代理,是不会对其伪造的。

测试

因此,比尔盖子编写了一个PHP脚本来测试。这个脚本可以使用http://biergaizi.com/ipaddress.php访问。需要注意的是,为了知道Cloudflare CDN是不是透明代理,这个脚本也被CDN加速了,因此本质上是你是用一个代理访问的。

源码如下:

<?php

global $ip;
global $ip2;
global $ip3;
$ip = getenv("HTTP_CLIENT_IP");
$ip2 = getenv("HTTP_X_FORWARDED_FOR");
$ip3 = getenv("REMOTE_ADDR");

echo "HTTP_CLIENT_IP:     ","<br>",$ip,"<br><br>";
echo "HTTP_X_FORWARDED_FOR:     ","<br>",$ip2,"<br><br>";
echo "REMOTE_ADDR:     ","<br>",$ip3,"<br><br>";

?>

测试的结果是:REMOTE_ADDR是代理服务器的IP,HTTP_X_FORWARDED_FOR是访问者真实的IP!也就是说,Cloudflare CDN本质上是透明代理,可以用HTTP_X_FORWARDED_FOR来获得访问者真实的IP!但是唯一奇怪的是,HTTP_CLIENT_IP是没有数据的,请懂的同学解答一下。

实现

有了刚才测试的结果,实现起来就容易多了。

WordPress中获取IP是通过获取REMOTE_ADDR实现的。我们只需要修改Wordpress中获取访问者IP的函数,增加一个逻辑判断:如果HTTP_X_FORWARDED_FOR有数据,就用HTTP_X_FORWARDED_FOR代替REMOTE_ADDR,这样就实现了获得浏览者的正确IP。

但关键是找不到Wordpress获取IP的函数在哪个文件,因此又找到了这样一种方法:因为Wordpress的wp-config.php配置文件是一个公共文件,大部分文件都会调用它,所以只需要修改wp-config.php就行了。修改的方法也异常简单,只需要在wp-config.php开头加上

if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) 
{
$list = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $list[0];
}

就搞定了。这段代码的意思是:如果HTTP_X_FORWARDED_FOR有数据(那就肯定是用代理了),那么就用HTTP_X_FORWARDED_FOR里的IP替换REMOTE_ADDR的IP。这样真实IP就把代理服务器的IP替换掉了。

这个方法正如开头强调的,这个方法不仅可以获得使用代理访问网站访客的真实IP,也可以在服务器使用反向代理或CDN的情况获取访客的真实IP。

Categories: 建站技术, 建站那点事

用Python3模拟《侏罗纪公园》中的黑客入侵情节 » « 八一建军节

1 Comment

  1. 你可以在需要获取访客ip的函数的php文件中看到,其实wordpress官方就是建议在wp-config.php中加入的,cloudflare的插件貌似很好,大侠可以考虑修改一下,变成通用的啊,不知大侠是否愿意呢!

发表评论

Your email address will not be published.

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Copyright © 2023 比尔盖子 博客

Theme by Anders NorenUp ↑