在.htaccess

时间:2016-05-23 01:28:49

标签: php .htaccess mod-rewrite

我有一个htaccess文件,其中有很多来自'拒绝来自'条目。其中大多数具有较低的八位字节。

为了尝试改善htaccess处理时间,对于未被禁止的IP,我试图实现一个php过滤器,它是从重写规则调用的。

我的htaccess重写规则:

    RewriteCond %{REMOTE_ADDR} ^37\.115\.  [OR]
    RewriteCond %{REMOTE_ADDR} ^46\.118\.
    RewriteRule (.*) check_banned.php?ip=%{REMOTE_ADDR}

    ... More rewrite rules

注意,没有' [L]'在重写规则的最后。如果IP没有被禁止,我希望htaccess继续处理规则。 当前的php文件:

    $ip = strip_tags(trim($_GET['ip']));

    // Read file with list of banned ips
    $file = ban_list.txt;
    $myfile = fopen($file, "r") or die("Unable to open file!");
    $ban_list = fread($myfile, filesize($file));
    fclose($myfile);

    // Check if ip is in ban list
    $pos = strpos($ban_list, $ip);

    if($pos === false) $ip_found = false;
    else $ip_found = true;

    if($ip_found){
        header('HTTP/1.0 403 Forbidden');
    }
    else {
        // What to do if ip is not banned?
    }

如果在禁令列表中找到了ip,这可以正常工作。但是,当ip没有被禁止时,我找不到处理这种情况的方法。我只是得到一个空白页面,标题为“200 ok'。

另外,我正在考虑将(。*)传递给文件check_banned.php,将php代码转换为函数,如果没有禁止ip,它将返回字符串。不得不承认我还没试过这个。

    RewriteRule (.*) check_banned.php?ip=%{REMOTE_ADDR}&str=$1

在php文件中:

    $string = strip_tags(trim($_GET['str']));

    if($ip_found){
        header('HTTP/1.0 403 Forbidden');
    }
    else {
        return $string;
    }

更新: 感谢Mike Nickaloff,这里有一些调整。不幸的是,我有一个共享主机帐户,无法访问服务器设置。

我将php过滤器脚本的文件权限设置为600,过滤似乎仍然有效。这可以解决这些漏洞吗?

如果没有禁止ip,php脚本会读取请求的页面并回显它。如果它不必这样做会很好,并且只向.htaccess发送一条消息,表明它应该继续处理规则。

对check_banned.php的更改:

    <?php
        ob_start(); // suppress any output
        $ip = strip_tags(trim($_SERVER["REMOTE_ADDR"]));

        // Read file with list of banned ips
        $file = ban_list.txt;
        $myfile = fopen($file, "r") or die("Unable to open file!");
        $ban_list = fread($myfile, filesize($file));
        fclose($myfile);

        // Check if ip is in ban list
        $pos = strpos($ban_list, $ip);

        if($pos === false) $ip_found = false;
        else $ip_found = true;

        if($ip_found){
            ob_end_clean(); // Allow output
            header('HTTP/1.0 403 Forbidden');
        }
        else{
            // ip Was not found in ban list
            $file = "";
            $uri = "";

            if(isset($_SERVER["REQUEST_URI"])){
                $uri = strip_tags(trim($_SERVER["REQUEST_URI"]));
            }

            if($uri == "" || $uri == "/")
                $file = $_SERVER['DOCUMENT_ROOT']."/index.php";
            else $file = $_SERVER['DOCUMENT_ROOT'].$uri;

            $myfile = fopen($file, "r") or die("Unable to open file!");
            $file = fread($myfile, filesize($file));
            fclose($myfile);

            ob_end_clean(); // Allow output
            echo $file;
        }
    ?>

2 个答案:

答案 0 :(得分:1)

这是你可以处理的一种方式:

通过加载正确的URL

让PHP加载请求的任何页面

这仅在从服务器请求PHP脚本时才有效,因此必须稍微更改htaccess规则以仅匹配.php文件。 无论如何,匹配。*是一个坏主意,但这种方法并不是最安全的方法。您可能希望投资免费防火墙,如UFW,它允许您阻止整个服务器的IP地址,而不是基于每个请求。

使用防火墙是一种更有效,更安全的阻止IP地址的方法。

PHP充当防火墙的方法容易受到DDoS攻击和递归攻击。例如 - 如果有人请求页面check_ip.php会发生什么?它必须重定向到某个地方 - 所以它会重定向到check_ip.php,它会重定向到check_ip.php,它会重定向到check_ip.php - 所以长话短说,

请勿使用此方法 - 这是用于演示目的而不是替换防火墙。

理论上,如果我们确实使用了这种不安全的方法,我们将采用以下方法:

<。>在.htaccess中将其更改为

 RewriteRule ^([\s\S]+)(.php|.phps)$ /check_banned.php [L]

... More rewrite rules

然后在check_banned.php中你可以这样做:

<?php
$ip = strip_tags(trim($_SERVER["REMOTE_ADDR"]));

// Read file with list of banned ips
$file = ban_list.txt;
$myfile = fopen($file, "r") or die("Unable to open file!");
$ban_list = fread($myfile, filesize($file));
fclose($myfile);

// Check if ip is in ban list
$pos = strpos($ban_list, $ip);

if($pos === false) $ip_found = false;
else $ip_found = true;

if($ip_found){
    header('HTTP/1.0 403 Forbidden');
}
else {
    // What to do if ip is not banned?
    $sPage = $_SERVER["PATH_TRANSLATED"];
    if (file_exists($sPage)) {
            include_once($sPage);
    }


}

 ?>

警告 - 请记住 - 请勿使用此方法,因为它易受攻击 -

编辑:为了响应OP上的编辑,这是一种在没有防火墙的情况下进行IP过滤的安全方法:

在文件 check_banned.php

<?php
$ip = strip_tags(trim($_SERVER["REMOTE_ADDR"]));

// Read file with list of banned ips
$file = ban_list.txt;
$myfile = fopen($file, "r") or die("Unable to open file!");
$ban_list = fread($myfile, filesize($file));
fclose($myfile);

// Check if ip is in ban list
$pos = strpos($ban_list, $ip);

if($pos === false) $ip_found = false;
else $ip_found = true;

if($ip_found){
    header('HTTP/1.0 403 Forbidden');

    // here is the important change
    die("script terminated  because IP is in ban list");
}
else {
    // if IP not banned,  do nothing.



}

 ?>

然后,在您希望保护的每个PHP脚本的顶部,您可以在最顶端执行此操作:

<?php  
  include_once("check_banned.php");
?>

如果IP匹配禁止列表并且不进一步处理任何内容,这将基本上导致脚本使用“die”命令终止,然后如果他们的IP不在禁止列表中,它将继续加载页面。

我看过网站使用这种技术 - wordpress网站是一个框架的一个很好的例子,它使用类似的策略来执行每个请求的预处理。

我会远离mod_rewrite规则,除非它们真的有必要,因为如果你不小心它们可以打开一大堆漏洞。

答案 1 :(得分:0)

虽然您有相当数量的代码(并且可能已经开始),但我认为您走的正确。

我使用http://www.ip-approval.com提供了一种允许和/或阻止IP的方法,并且还可以选择将这些访问者重定向到不同的网页或网站。

请参阅:http://www.ip-approval.com/instructions

在.htaccess文件中,我添加了:

php_value auto_prepend_file /check_banned.php

...将代码添加到网站的每个页面。如果您有folders / pages.html,可以将check_banned.php文件添加到该文件夹​​,或者添加:

php_value auto_prepend_file none

...到文件夹中的.htaccess文件,它不会被添加到该文件夹​​中。

所以,如果你想要php_value,auto_prepend_file可以正常工作

正如其他人所说,你可以在每个页面上添加以下内容:

<?php  
  include_once("check_banned.php");
?>