PHP如何阻止代理访问我的网站?

3
我正在寻找最好的方法来阻止代理访问我的网站。这是因为我在我的项目中使用了唯一的IP地址。您会推荐什么?谢谢!

4
当你说“使用独特的IP地址”时,是否意味着你假定每个IP地址代表一个独特的用户?如果是这样,请停止做出这种假设,因为你无法确保每个用户都有独特的IP。 - LukeH
1
使用cookie是为每个用户(机器上的每个浏览器)提供唯一ID的真正正确方法。 - Dan
7个回答

3

无法完全准确地确定连接到您的站点的人是否代理了其他人的请求。

您可以在实时处理中合理地做的最好的事情是查找 X-FORWARDED-FOR HTTP 标头,其中 一些 代理将使用该标头告知您代理正在代表其连接的客户端的 IP 地址。

$headers = apache_request_headers();
$forwarded = $headers['X-Forwarded-For'];

如果你认为每个IP地址对应不同的人,那么你就犯了错误的假设。连接到互联网上的设备比可用的IP地址多得多。一个学校里的每个人通常共享一个IP地址。一个大公司里的每个人通常共享一个IP地址。每个AOL拨号用户共享几个IP地址。每个MSN拨号用户共享几个IP地址。

嗨,丹,感谢您的评论。老实说,我并没有期待完美的解决方案,我知道那是难以实现的。但任何有帮助的东西都将是极好的。您能否为我提供检测标题的示例代码?再次感谢。 - user580523
+1 是的,维基百科上有一些很好的信息。 - alex
是的,许多人共享相同的IP地址,但他们同时访问您的网站的机会几乎为零。如果您有屏蔽代理的良好业务原因,我建议您这样做。 - Henley

2
你不应该依赖于唯一的IP地址。很多人在工作或学校背后有防火墙,所以一个IP地址并不意味着1台计算机或用户。
如果想要识别你的用户,请设置cookie或使用会话。

谢谢Byron,我为我的用户使用会话,但这是用于跟踪位置。 - user580523

2

互联网上有几种类型的代理,一些代码无法检测到所有代理。虚拟私人网络(VPN)、Web代理、Tor和开放代理是一些不能总是用常规工具检测到的代理的例子。处理和检测这些不同的代理的最佳方法是使用更新的这些代理地址的黑名单。一个例子是BlockScript


1

我不知道有没有一种百分之百可靠的方法来做到这一点,但以下方法几乎是完整的:

if (get_ip_address() !== get_ip_address(true))
{
    echo 'using proxy';
}

这个 get_ip_address() 函数是从这篇答案中调整过来的,代码如下:

function get_ip_address($proxy = false)
{
    if ($proxy === true)
    {
        foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED') as $key)
        {
            if (array_key_exists($key, $_SERVER) === true)
            {
                foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip)
                {
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
                    {
                        return $ip;
                    }
                }
            }
        }
    }

    return $_SERVER['REMOTE_ADDR'];
}

我遇到了一个错误(解析错误:语法错误,意外的T_AS) - user580523
@Alexwhin:我漏了一个括号,现在已经修复了。 - Alix Axel
似乎什么都没做,使用代理也没有显示任何内容,正常浏览也是如此 :/ - user580523
@Alexwhin:它本来不应该“显示”任何东西,再试一次使用第一个片段。 - Alix Axel
@Alix 我尝试添加一个回显,但似乎没有显示任何东西 :/ - user580523
显示剩余3条评论

0

我找到了一段从PhpMyAdmin中提取的代码,它利用PHP的一些功能来检测代理和代理后面的IP。对我来说,这段代码多次运行成功,但并非百分之百。我在这里贴出来供你测试和考虑。

当确定一个强大的代理或用户IP位于透明代理后面时,它返回FALSE。

请检查PhpMyAdmin的新版本以获取更新。

function get_ip()
{
global $REMOTE_ADDR;
global $HTTP_X_FORWARDED_FOR, $HTTP_X_FORWARDED, $HTTP_FORWARDED_FOR, $HTTP_FORWARDED;
global $HTTP_VIA, $HTTP_X_COMING_FROM, $HTTP_COMING_FROM;
global $HTTP_SERVER_VARS, $HTTP_ENV_VARS;
// Get some server/environment variables values
if(empty($REMOTE_ADDR))
    {
    if(!empty($_SERVER)&&isset($_SERVER['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
        }
    elseif(!empty($_ENV)&&isset($_ENV['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $_ENV['REMOTE_ADDR'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $HTTP_SERVER_VARS['REMOTE_ADDR'];
        }
    elseif(!empty($HTTP_ENV_VARS)&&isset($HTTP_ENV_VARS['REMOTE_ADDR']))
        {
        $REMOTE_ADDR = $HTTP_ENV_VARS['REMOTE_ADDR'];
        }
    elseif(@getenv('REMOTE_ADDR'))
        {
        $REMOTE_ADDR = getenv('REMOTE_ADDR');
        }
    } // end if
if(empty($HTTP_X_FORWARDED_FOR))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $_ENV['HTTP_X_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_X_FORWARDED_FOR']))
        {
        $HTTP_X_FORWARDED_FOR = $HTTP_ENV_VARS['HTTP_X_FORWARDED_FOR'];
        }
    elseif(@getenv('HTTP_X_FORWARDED_FOR'))
        {
        $HTTP_X_FORWARDED_FOR = getenv('HTTP_X_FORWARDED_FOR');
        }
    } // end if
if(empty($HTTP_X_FORWARDED))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $_SERVER['HTTP_X_FORWARDED'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $_ENV['HTTP_X_FORWARDED'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $HTTP_SERVER_VARS['HTTP_X_FORWARDED'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_X_FORWARDED']))
        {
        $HTTP_X_FORWARDED = $HTTP_ENV_VARS['HTTP_X_FORWARDED'];
        }
    elseif(@getenv('HTTP_X_FORWARDED'))
        {
        $HTTP_X_FORWARDED = getenv('HTTP_X_FORWARDED');
        }
    } // end if
if(empty($HTTP_FORWARDED_FOR))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $_SERVER['HTTP_FORWARDED_FOR'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $_ENV['HTTP_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $HTTP_SERVER_VARS['HTTP_FORWARDED_FOR'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_FORWARDED_FOR']))
        {
        $HTTP_FORWARDED_FOR = $HTTP_ENV_VARS['HTTP_FORWARDED_FOR'];
        }
    elseif(@getenv('HTTP_FORWARDED_FOR'))
        {
        $HTTP_FORWARDED_FOR = getenv('HTTP_FORWARDED_FOR');
        }
    } // end if
if(empty($HTTP_FORWARDED))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $_SERVER['HTTP_FORWARDED'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $_ENV['HTTP_FORWARDED'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $HTTP_SERVER_VARS['HTTP_FORWARDED'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_FORWARDED']))
        {
        $HTTP_FORWARDED = $HTTP_ENV_VARS['HTTP_FORWARDED'];
        }
    elseif(@getenv('HTTP_FORWARDED'))
        {
        $HTTP_FORWARDED = getenv('HTTP_FORWARDED');
        }
    } // end if
if(empty($HTTP_VIA))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_VIA']))
        {
        $HTTP_VIA = $_SERVER['HTTP_VIA'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_VIA']))
        {
        $HTTP_VIA = $_ENV['HTTP_VIA'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_VIA']))
        {
        $HTTP_VIA = $HTTP_SERVER_VARS['HTTP_VIA'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_VIA']))
        {
        $HTTP_VIA = $HTTP_ENV_VARS['HTTP_VIA'];
        }
    elseif(@getenv('HTTP_VIA'))
        {
        $HTTP_VIA = getenv('HTTP_VIA');
        }
    } // end if
if(empty($HTTP_X_COMING_FROM))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $_SERVER['HTTP_X_COMING_FROM'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $_ENV['HTTP_X_COMING_FROM'];
        }
    elseif(!empty($HTTP_SERVER_VARS) && isset($HTTP_SERVER_VARS['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $HTTP_SERVER_VARS['HTTP_X_COMING_FROM'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_X_COMING_FROM']))
        {
        $HTTP_X_COMING_FROM = $HTTP_ENV_VARS['HTTP_X_COMING_FROM'];
        }
    elseif(@getenv('HTTP_X_COMING_FROM'))
        {
        $HTTP_X_COMING_FROM = getenv('HTTP_X_COMING_FROM');
        }
    } // end if
if(empty($HTTP_COMING_FROM))
    {
    if(!empty($_SERVER) && isset($_SERVER['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $_SERVER['HTTP_COMING_FROM'];
        }
    elseif(!empty($_ENV) && isset($_ENV['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $_ENV['HTTP_COMING_FROM'];
        }
    elseif(!empty($HTTP_COMING_FROM) && isset($HTTP_SERVER_VARS['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $HTTP_SERVER_VARS['HTTP_COMING_FROM'];
        }
    elseif(!empty($HTTP_ENV_VARS) && isset($HTTP_ENV_VARS['HTTP_COMING_FROM']))
        {
        $HTTP_COMING_FROM = $HTTP_ENV_VARS['HTTP_COMING_FROM'];
        }
    elseif(@getenv('HTTP_COMING_FROM'))
        {
        $HTTP_COMING_FROM = getenv('HTTP_COMING_FROM');
        }
    } // end if
// Gets the default ip sent by the user
if(!empty($REMOTE_ADDR))
    {
    $direct_ip = $REMOTE_ADDR;
    }
// Gets the proxy ip sent by the user
$proxy_ip='';
if(!empty($HTTP_X_FORWARDED_FOR))$proxy_ip = $HTTP_X_FORWARDED_FOR;
elseif(!empty($HTTP_X_FORWARDED))$proxy_ip = $HTTP_X_FORWARDED;
elseif(!empty($HTTP_FORWARDED_FOR))$proxy_ip = $HTTP_FORWARDED_FOR;
elseif(!empty($HTTP_FORWARDED))$proxy_ip = $HTTP_FORWARDED;
elseif(!empty($HTTP_VIA))$proxy_ip = $HTTP_VIA;
elseif(!empty($HTTP_X_COMING_FROM))$proxy_ip = $HTTP_X_COMING_FROM;
elseif(!empty($HTTP_COMING_FROM))$proxy_ip = $HTTP_COMING_FROM;
// Returns the true IP if it has been found, else FALSE
if (empty($proxy_ip))
    {
    // True IP without proxy
    return $direct_ip;
    }
else
    {
    $is_ip = ereg('^([0-9]{1,3}\.){3,3}[0-9]{1,3}', $proxy_ip, $regs);
    if($is_ip && (count($regs) > 0))
        {
        // True IP behind a proxy
        return $regs[0];
        }
    else
        {
        // Can't define IP: there is a proxy but we don't have
        // information about the true IP
        return FALSE;
        }
    } // end if... else...
}

我该如何调用函数?或者显示输出。 - user580523
返回值的类型/结构与 $_SERVER['REMOTE_ADDR'] 相同。您甚至可以在应用程序开头编写 $_SERVER['REMOTE_ADDR'] = get_ip(),它将正常工作! - Dan
从2021年的角度来看,这似乎很糟糕。 - jekaby

0

添加到 .htaccess 文件中

RewriteEngine on
RewriteCond %{HTTP:VIA}                 !^$ [OR]
RewriteCond %{HTTP:FORWARDED}           !^$ [OR]
RewriteCond %{HTTP:USERAGENT_VIA}       !^$ [OR]
RewriteCond %{HTTP:X_FORWARDED_FOR}     !^$ [OR]
RewriteCond %{HTTP:PROXY_CONNECTION}    !^$ [OR]
RewriteCond %{HTTP:XPROXY_CONNECTION}   !^$ [OR]
RewriteCond %{HTTP:HTTP_PC_REMOTE_ADDR} !^$ [OR]
RewriteCond %{HTTP:HTTP_CLIENT_IP}      !^$
RewriteRule ^(.*)$ - [F]

0

这个问题在于,如果您拥有合法的IP并包含此标头,并使此标头胜过IP,则会得到不正确的结果。

将两者分别存储可能是值得的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接