【问题标题】:How do I allow only certain IP's to view webpages?如何只允许特定 IP 浏览网页?
【发布时间】:2011-12-13 00:35:31
【问题描述】:

我正在尝试让一个 PHP 脚本工作,它将人的 IP 与文本文件(每行一个 IP)进行比较。如果此人的 IP 不在文本文件中,那么他将被重定向到 denied.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,而是如何修复我的脚本!谢谢。

【问题讨论】:

  • 不应该unset($allowed);$allowed = false;
  • 为什么不使用.htaccess
  • 我不想用大量的 IP 填充 htaccess
  • @user1008120 填充文本文件有何不同?

标签: php arrays ip


【解决方案1】:

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');

【讨论】:

  • 您是否关闭了错误报告?如果它不起作用,那么应该会弹出警告或致命错误。
  • 我正在使用
    hellooooooo
  • 所以我看到的只是“helloooo”部分
  • 那个div不应该在那里,哈哈。
  • 您在发送输出后 运行标头调用?在发送任何输出之前,这需要位于文件的最开头。
  • 【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      对于 IP 过滤,最好在处理链中尽早进行。按优先顺序:

      1. 路由器
      2. 防火墙
      3. 网络服务器
      4. 脚本

      很可能您无权访问路由器或防火墙级别,但您可以使用 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,值是单词“ALLOWED”,作为名为“ipfiltermap”的映射
      2. 捕获当前请求的远程地址(客户端IP)
      3. 使用在步骤 2 中捕获的 IP,在 ipfiltermap 中查找它,并查看该 IP 是否没有“ALLOWED”字样
      4. 明确将您的“拒绝”页面从 IP 强制执行中豁免 - 如果不在这里,被禁用的 IP 将进入无限重定向循环
      5. 如果所有 3 个 RewriteConds 都匹配,则用户来自禁止 IP,应重定向到禁止页面。

      所有这些的相关 Apache 文档是 here

      【讨论】:

      • 等一下,我可以在 .htaccess 中使用它,它的工作原理是一样的吗?
      • 是的,它可以进入 .htaccess 或 .conf 文件。
      • 内部服务器错误,我把它放在htaccess中为:RerwriteMap ipfiltermap txt:/ip.txt RewriteCond %{REMOTE_ADDR} (.*) RewriteCond %{ipfiltermap:%1} !ALLOWED RewriteCond %{REQUEST_URI } !^/declined.html RewriteRule .* /forbidden.html [L]
      • 呃,想象一下每条重写规则后都有一个换行符
      • 我没有访问权限。 :/ 也许这台服务器很糟糕,我很快就会得到液体网络托管,他们应该对此有更好的支持。
      【解决方案4】:

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

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

      此外,它已经调试并可以正常工作。与在当前代码中发现错误相比,部署它所花费的时间更少——即使那样,你当前的代码也会——在每个访问控制请求上——重新——读取(并重新解析为数组)IP 地址的文本描述,将来自远程对等方的 IP 地址转换为文本版本,然后对整个数组执行非常慢的基于文本的比较。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-21
        • 2014-06-06
        • 1970-01-01
        • 1970-01-01
        • 2017-10-28
        相关资源
        最近更新 更多