在 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.1
89.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 块的主要内容,如果未能解决你的问题,请参考以下文章