如何仅允许某些IP查看网页?

时间:2011-10-22 03:52:08

标签: php arrays ip

我正在尝试使用PHP脚本来将人员的IP与文本文件(每行一个IP)进行比较。如果此人的IP不在文本文件中,那么他将被重定向到decline.html。我知道我可以使用.htaccess,但IP列表可能真的很长。

这是我到目前为止的代码:

<?php
$ipArray = file('ip.txt');
unset($allowed);
foreach ($ipArray as $ipTest) if (substr_count($_SERVER['REMOTE_ADDR'],trim($ipTest))     != "0") $allowed = true;
if ($allowed != true) {
header('location: /declined.html');  // the banned display page
die();
}
?>

我希望能够在我只想要某些IP看到的每个页面中调用此脚本,这就是我想要的:

<? include('ip_allow.php'); ?>

当我的IP不在ip.txt中时,当我在HTML页面中调用PHP脚本时,它不会将我重定向到/declined.html!我怎样才能解决这个问题?同样,我的问题不是如何使用.htaccess,而是如何修复我的脚本!感谢。

4 个答案:

答案 0 :(得分:5)

对于IP过滤,最好在处理链中尽早完成。按优先顺序排列:

  1. 路由器
  2. 防火墙
  3. 网络服务器
  4. 脚本
  5. 您很可能无法访问路由器或防火墙级别,但您可以使用Apache的mod_rewrite使用外部文件创建动态块。设置“启用的IP”文件,如下所示:

    a.b.c.d ALLOWED
    b.c.d.e ALLOWED
    c.d.e.f ALLOWED
    etc...
    

    它基本上是“键值”,其中键是IP地址

    然后你的mod_rewrite规则(我已将它们编号以供参考)

    1. RerwriteMap ipfiltermap txt:/path/to/your/ips/list
    2. RewriteCond %{REMOTE_ADDR} (.*)
    3. RewriteCond %{ipfiltermap:%1} !ALLOWED
    4. RewriteCond %{REQUEST_URI} !^/declined.html
    5. RewriteRule .* /forbidden.html [L]
    

    他们的工作如下:

    1. 将允许的IP定义为“键值”对,其中键是允许的IP,值是“允许”,作为名为“ipfiltermap”的映射
    2. 捕获当前请求的远程地址(客户端IP)
    3. 使用在步骤2中捕获的IP,在ipfiltermap中查找,并查看IP是否没有“允许”一词
    4. 特别豁免IP执行中的“拒绝”页面 - 如果不在此处,则禁用的IP将进入无限重定向循环
    5. 如果所有3个RewriteConds匹配,则该用户来自禁用的IP,应该被重定向到fobidden页面。
    6. 所有这些的相关Apache文档是here

答案 1 :(得分:1)

如果您将配置直接放在Apache配置中,它不会导致.htaccess查找的速度惩罚 - 但这意味着您需要在每次执行时重新加载Apache配置列表已修改。 (虽然Marc's answer很好地避免了这种情况。)

mod_authz_host.c针对中等快速搜索进行了优化。如果您在每次执行时都在脚本中读取文本文件,那么您的速度已经比Apache快几倍。 Apache读取配置一次,将IP地址转换为二进制格式一次,然后可以使用非常快速的整数运算来确定是否允许主机。

此外,它已经调试并正在运行。它比您在当前代码中找到错误所花费的时间更少 - 即便如此,您当前的代码将 - 在每个访问控制的请求上 - 重新读取(并重新解析为数组)IP地址的文本描述,将远程对等体的IP地址转换为文本版本,然后对整个数组执行非常慢的基于文本的比较。

如果速度非常重要,那么您应该调查通过系统防火墙进行访问控制。 iptables已优化例程以在允许或拒绝的主机列表中查找匹配的IP地址,并且在执行任何协议分析时不会浪费任何时间。当然,如果某些内容可供所有人使用,这是一种更加沉重的“全有或全无”方法,需要在侦听端口之间进行恼人的内容分离。

答案 2 :(得分:0)

file()命令在每行的末尾包含\n字符,因此每行实际上都是0.0.0.0\n,每次都返回false。

使用此:

$ipArray = file('ip.txt', FILE_IGNORE_NEW_LINES); // Try specifying an ABSOLUTE path to this file.
$allowed = false; // Rather than unset($allowed), this will prevent notice errors too!
foreach ($ipArray as $ipTest) if ($_SERVER['REMOTE_ADDR'] == $ipTest) $allowed = true;

另外,只需在标题行中指出,Location应以大写字母开头,您应该为文件指定完整URI

header('Location: http://example.com/declined.html');

答案 3 :(得分:0)

我猜你有错误的目录中的文件,或PHP无法正常工作或其他一些更基本的配置问题,因为我测试了你的代码,它对我来说很好。