在 PHP 中阻止来自我的网站的特定 IP 块

Posted

技术标签:

【中文标题】在 PHP 中阻止来自我的网站的特定 IP 块【英文标题】:Block specific IP block from my website in PHP 【发布时间】:2011-02-21 15:07:42 【问题描述】:

例如,我想阻止来自 base 89.95 (89.95..) 的每个 IP。 我的服务器上没有 .htaccess 文件,所以我必须使用 php

if ($_SERVER['REMOTE_ADDR'] == "89.95.25.37") die();

会阻止特定的 IP。如何阻止整个 IP 块?

【问题讨论】:

【参考方案1】:

试试strpos()

if(strpos($_SERVER['REMOTE_ADDR'], "89.95") === 0)

    die();

如果您注意到,=== 运算符会确保 89.95 位于 IP 地址的开头。这意味着您可以根据需要指定任意数量的 IP 地址,并且无论后面是什么数字,它都会阻止。

例如,所有这些都将被阻止:

89.95 -> 89.95.12.34, 89.95.1234.1, 89.95.1.189.95.6 -> 89.95.65.34, 89.95.61.1, 89.95.6987

(虽然其中一些不是有效的 IP 地址)

【讨论】:

呵呵,我很惊讶strpos 这里的工作速度比substr @zerkms 这并不奇怪 - 如果测试失败,strpos 可以立即返回,并且不必进行任何字符串复制或分配。另外,我只想指出,如果您将=== 切换为==,行为会发生变化,所以不要这样做。使用三个等号。 @gnud:对于长字符串 strpos 会更慢,因为它应该遍历整个字符串来搜索针。我知道===== 有什么区别。 @zerkms 是的,===== 是作为一个单独的注释来补充答案,而不是针对你 :=)【参考方案2】:

使用ip2long() 将点分十进制转换为真实IP 地址。然后你就可以轻松地做范围了。

只需在上限和下限上执行ip2long() 即可获取值,然后将它们用作代码中的常量。

如果你熟悉子网掩码,你可以这样做:

// Deny 10.12.*.*
$network = ip2long("10.12.0.0");
$mask = ip2long("255.255.0.0");
$ip = ip2long($_SERVER['REMOTE_ADDR']);
if (($network & $mask) == ($ip & $mask)) 
  die("Unauthorized");

或者如果你熟悉这种格式10.12.0.0/16:

// Deny 10.12.*.*
$network = ip2long("10.12.0.0");
$prefix = 16;
$ip = ip2long($_SERVER['REMOTE_ADDR']);
if ($network >> (32 - $prefix)) == ($ip >> (32 - $prefix)) 
  die("Unauthorized");

您可以将这些转换为函数并拥有非常易于管理的代码,从而可以轻松添加 IP 地址和自定义范围。

【讨论】:

谢谢!我们就是这样做的。 仅调查$_SERVER'REMOTE_HOST' 就足够了吗?因为也许用户使用了代理。因此,您还必须检查一些其他参数,例如REMOTE_ADDR 或these。我对吗?还是做我链接的东西没用? 是的,只需使用 REMOTE_ADDR。【参考方案3】:

将虚线四边形转换为整数:

$ip = sprintf('%u', ip2long($_SERVER['REMOTE_ADDR']));

// only allow 10.0.0.0 – 10.255.255.255
if (!($ip >= 167772160 && $ip <=  184549375)) 
    die('Forbidden.');

【讨论】:

这里使用整数的原因是什么?让代码更加模糊? 并不是说这会降低此答案的实用性,而是授权听起来更像是一个选择加入的词,其中授权了一组选定的人。在这种情况下,他不是只授权少数人,而是取消授权或禁止少数人。因此,我认为更好的词是“禁止”。 @webbiedave:哈哈。再次:这里使用整数的原因是什么? @zerkms,您将如何处理 A 类或 B 类范围?如果您将 IP 地址保持为点分十进制格式,您将编写大量代码。 @zerkms,问题是“如何阻止整个 IP 块?”【参考方案4】:

创建一个子字符串 :) 例如,为了阻止 89.95.25.*,您创建 IP 的子字符串,切断最后两个数字并将其与“89.95.25”进行比较。

【讨论】:

【参考方案5】:
$user_ip = $_SERVER['REMOTE_ADDR']; // get user ip

$denyIPs = array("111.111.111", "222.222.222", "333.333.333");
if (in_array ($user_ip, $denyIPs)) 
   // blocked ip

else 
   // not blocked

【讨论】:

【参考方案6】:

这对我来说一直很有效: 这将检查正确的服务器变量并将其与已知 IP 列表进行比较。是的,PHP 确实理解通配符,因此在 IP 中使用 * 有助于阻止 IP 范围。

// The blacklisted ips.
$denied_ips = array(
'1.2.3.4',
'2.3.*',
);

// The function to get the visitor's IP.
function getUserIP()
    //check ip from share internet
    if (!empty($_SERVER['HTTP_CLIENT_IP']))
      $ip=$_SERVER['HTTP_CLIENT_IP'];
    
    //to check ip is pass from proxy
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
      $ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
     else 
      $ip=$_SERVER['REMOTE_ADDR'];
    
    return $ip;

//The user
$visitorIp = getUserIP();

// Now let's search if this IP is blackliated
$status = array_search($visitorIp, $denied_ips);

// Let's check if $status has a true OR false value.
if($status !== false)
    echo '<div class="error">Your IP has been banned! Stop spamming us!</div>';
    // header("Location: http://zombo.com");
    // exit; 

Perishable Press 上还有一篇很棒的文章: http://perishablepress.com/how-to-block-ip-addresses-with-php/

【讨论】:

“是的,PHP 确实理解通配符,因此在 IP 中使用 * 有助于阻止 IP 范围。”您确定吗?可能是特定版本的php?【参考方案7】:

使用 revive 的代码,使用它来进行通配符搜索

// Now let's search if this IP is blackliated
$status = false;
foreach($denied_ips as $val)

    if (strpos($val,'*') !== false)
    
        if(strpos($visitorIp, array_shift(explode("*", $val))) === 0)
        
            $status = true;
            break;
        
    
    else
    
        if(strcmp($visitorIp, $val) === 0)
        
            $status = true;
            break;
        
    

【讨论】:

【参考方案8】:
$deny = array("111.111.111", "222.222.222", "333.333.333");

if (in_array($_SERVER['REMOTE_ADDR'], $deny)) 
    header("location:http://www.google.com/");
    exit();

【讨论】:

以上是关于在 PHP 中阻止来自我的网站的特定 IP 块的主要内容,如果未能解决你的问题,请参考以下文章

Apple 的 iCloud 阻止来自我网站的电子邮件

暂时阻止特定网站的编程方式?

Magneto - 来自特定状态的阻止订单

pfSense阻止对某个网站的访问

使用PHP取得用户IP地址的所在地区

如何授予对 nGinx 中 GeoIP [国家] 阻止的特定 IP 地址的访问权限?