如何只允许特定IP查看网页?

发布于 2024-12-11 10:41:41 字数 691 浏览 0 评论 0原文

我正在尝试让 PHP 脚本工作,它将人的 IP 与文本文件进行比较(每行一个 IP)。如果该人的 IP 不在文本文件中,那么他会被重定向到 returned.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'); ?>

当我在中调用PHP脚本时当我的 IP 不在 ip.txt 中时,HTML 页面不会将我重定向到 /declined.html!我该如何解决这个问题?再说一遍,我的问题不是如何使用 .htaccess,而是如何修复我的脚本!谢谢。

I'm trying to get a PHP script to work where it compares the IP of the person against a text file(one IP per line). If the person's IP is not in the text file, then he gets redirected to declined.html. I know I could use .htaccess for this but the IP list could get really, really long.

This is the code that I have so far:

<?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();
}
?>

I want to be able to call this script in every page that I only want certain IP's to see, this is what I'm trying to call it with:

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

When I call the PHP script in the HTML page when my IP is NOT in ip.txt, it does not redirect me to /declined.html! How can I fix this? Again, my question is not how to use .htaccess, but how to fix my script! Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

放赐 2024-12-18 10:41:41

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

  1. 路由器
  2. 防火墙
  3. Web 服务器
  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 是否没有“允许”一词。
  4. 特别是让您的“拒绝”页面免受 IP 强制执行 - 如果不在这里,被禁用的 IP 将进入无限重定向循环
  5. 。 RewriteConds 的 3 匹配,则用户来自禁止的 IP,并且应该被重定向到禁止的页面。

所有这些的相关 Apache 文档位于此处

For IP filtering, it's best to do it as early as possible in the processing chain. In order of preference:

  1. router
  2. firewall
  3. webserver
  4. script

Most likely you don't have access to the router or firewall levels, but you CAN use Apache's mod_rewrite to have a dynamic block using an external file. Set up your "enabled IPs" file as follows:

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

It's basically "key value", where the key is the IP address

Then your mod_rewrite rules (I've numbered them for reference)

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]

They work as follows:

  1. Defines the allowed IPs as a "key value" pair, where the keys are the allowed IPs, and the value is the word "ALLOWED", as a mapping named "ipfiltermap"
  2. Captures the remote address of the current request (the client IP)
  3. Using the IP captured in step 2, look it up in the ipfiltermap, and see if the the IP does NOT have the word 'ALLOWED'
  4. Specifically exempt your 'declined' page from the IP enforcement - if this wasn't here, disabllowed IPs would enter an infinite redirect loop
  5. If all 3 of the RewriteConds match, then the user is from a forbidden IP, and should be redirected to the fobidden page.

Relevant Apache docs for all this are here.

紫轩蝶泪 2024-12-18 10:41:41

如果您将配置直接放入 Apache 配置中,则不会因 .htaccess 查找而降低速度 - 但这意味着每当列表被修改时您都需要重新加载 Apache 配置。 (尽管Marc的回答很好地避免了这种情况。)

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

此外,它已经调试完毕并且可以运行。部署它所花费的时间比在当前代码中查找错误所花费的时间要少 - 即使这样,您当前的代码也会 - 在每个访问控制请求上 - 重新读取(并重新解析为数组)IP 地址的文本描述,将来自远程对等点的 IP 地址转换为文本版本,然后对整个数组执行非常慢的基于文本的比较。

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

If you place your configuration in your Apache configuration directly, it won't incur the speed penalties of .htaccess lookups -- but that would mean you'd need to reload the Apache configuration whenever the list is modified. (Though Marc's answer avoids this very nicely.)

The mod_authz_host.c is optimized for moderately fast searching. If you're reading a text file in your script every execution, you're already several times slower than Apache. Apache reads the configuration once, converts the IP addresses to a binary format once, and can then use very fast integer arithmetic to determine if hosts are allowed or not.

Furthermore, it's already debugged and working. It'd take you less time to deploy it than it would to find the bug in your current code -- and even then, your current code would -- on every access-controlled request -- re-read (and re-parse into an array) the textual description of IP addresses, convert the IP address from the remote peer into a text version, and then perform a very slow text-based comparison over the entire array.

If speed is of real importance, then you should investigate doing the access control via your system firewall. iptables has optimized routines to find matching IP addresses among a list of allowed or denied hosts and won't waste any time performing any protocol analysis. Of course, this is a much heavier all-or-nothing approach that would require an annoying separation of content among listening ports if some content is available for all.

怼怹恏 2024-12-18 10:41:41

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

I would guess you have files in the wrong directory, or PHP not working or some other more basic configuration issue, since I tested your code and it works fine for me.

与酒说心事 2024-12-18 10:41:41

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

The file() command includes the \n character at the end of each line, so each line is actually something like 0.0.0.0\n which is returning false every time.

Use this:

$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;

Also just to point out in your header line, Location should start with a capital letter and you should specify a full URI to the file:

header('Location: http://example.com/declined.html');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文