PHP 中的防洪 DDoS

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12553606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 03:48:07  来源:igfitidea点击:

Anti-flood DDoS in PHP

phpddos

提问by Unknown3r

<?php
if (!isset($_SESSION)) {
        session_start();
}
// anti flood protection
if($_SESSION['last_session_request'] > time() - 2){
        // users will be redirected to this page if it makes requests faster than 2 seconds
        header("location: http://www.example.com/403.html");
        exit;
}
$_SESSION['last_session_request'] = time();
?>

I've already tested this script as you higher the second It Will keep redirecting to http://www.example.com/403.htmlwithout any reason.

我已经测试了这个脚本,当你第二个更高时它会http://www.example.com/403.html毫无理由地继续重定向。

Can anyone tell me why?

谁能告诉我为什么?

回答by nand

Let's think about this logically for a second...

让我们从逻辑上思考一下这个问题......

The attacker's request is already being sent to the web-server and through to the PHP script. The bottle-neck which causes failure in DDoS attacks is the web-server.

攻击者的请求已经被发送到网络服务器并通过 PHP 脚本。导致 DDoS 攻击失败的瓶颈是网络服务器。

The idea behind a DDoS attack is just that - to cause a denial of service, in which the website/server is unable to process any new requests. So in escense, this approach is irrational. You need to go up the ladder of request handling.

DDoS 攻击背后的想法就是 - 导致拒绝服务,其中网站/服务器无法处理任何新请求。所以从本质上讲,这种做法是不合理的。您需要爬上请求处理的阶梯。

If you have a server to your disposal, it's easier. You could simply implement a rate limiting rule on the kernel firewall/iptables. But assuming you do not have access to that, Apache is still at your disposal - although not as efficient.

如果您有一台可供您使用的服务器,那就更容易了。您可以简单地在内核防火墙/iptables 上实施速率限制规则。但假设您无权访问它,Apache 仍可供您使用 - 尽管效率不高。

Implementing a rule within .htaccess is a bettersolution, but still not perfect. But depending on the DDoS attack, there's no real solution at the developer's disposal to block it.

在 .htaccess 中实现规则是一个更好的解决方案,但仍然不完美。但是根据 DDoS 攻击,开发人员没有真正的解决方案来阻止它。

回答by manuelbcd

I'm using a good anti-flood script that des not need cookies (perfect for webservices). It's not perfect against advanced DDOS attacks but it's enough for preventing beginners attacks and automatic multiple requests.

我正在使用一个很好的防洪脚本,它不需要 cookie(非常适合网络服务)。它对于高级 DDOS 攻击并不完美,但足以防止初学者攻击和自动多个请求。

For using it, before it's needed to create "flood" folder with a "ctrl" file inside and a "lock" subfolder. Also needed to be setted with correct permissions.

为了使用它,在需要创建带有“ctrl”文件和“lock”子文件夹的“flood”文件夹之前。还需要设置正确的权限。

Already tested by me.

已经被我测试过了。

define("SCRIPT_ROOT", dirname(__FILE__));

// number of allowed page requests for the user
define("CONTROL_MAX_REQUESTS", 3);
// time interval to start counting page requests (seconds)
define("CONTROL_REQ_TIMEOUT", 2);
// seconds to punish the user who has exceeded in doing requests
define("CONTROL_BAN_TIME", 5);
// writable directory to keep script data 
define("SCRIPT_TMP_DIR", SCRIPT_ROOT."/flood");
// you don't need to edit below this line
define("USER_IP", $_SERVER["REMOTE_ADDR"]);
define("CONTROL_DB", SCRIPT_TMP_DIR."/ctrl");
define("CONTROL_LOCK_DIR", SCRIPT_TMP_DIR."/lock");
define("CONTROL_LOCK_FILE", CONTROL_LOCK_DIR."/".md5(USER_IP));
@mkdir(CONTROL_LOCK_DIR);
@mkdir(SCRIPT_TMP_DIR);


if (file_exists(CONTROL_LOCK_FILE)) {
    if (time()-filemtime(CONTROL_LOCK_FILE) > CONTROL_BAN_TIME) {
        // this user has complete his punishment
        unlink(CONTROL_LOCK_FILE);
    } else {
        // too many requests
        echo "<h1>DENIED</h1>";
        echo "Please try later.";
        touch(CONTROL_LOCK_FILE);
        die;
    }
}

function antiflood_countaccess() {
    // counting requests and last access time
    $control = Array();

    if (file_exists(CONTROL_DB)) {
        $fh = fopen(CONTROL_DB, "r");
        $control = array_merge($control, unserialize(fread($fh, filesize(CONTROL_DB))));
        fclose($fh);
    }

    if (isset($control[USER_IP])) {
        if (time()-$control[USER_IP]["t"] < CONTROL_REQ_TIMEOUT) {
            $control[USER_IP]["c"]++;
        } else {
            $control[USER_IP]["c"] = 1;
        }
    } else {
        $control[USER_IP]["c"] = 1;
    }
    $control[USER_IP]["t"] = time();

    if ($control[USER_IP]["c"] >= CONTROL_MAX_REQUESTS) {
        // this user did too many requests within a very short period of time
        $fh = fopen(CONTROL_LOCK_FILE, "w");
        fwrite($fh, USER_IP);
        fclose($fh);
    }
    // writing updated control table
    $fh = fopen(CONTROL_DB, "w");
    fwrite($fh, serialize($control));
    fclose($fh);
}

Taken from here: https://github.com/damog/planetalinux/blob/master/www/principal/suscripcion/lib/antiflood.hack.php

取自这里:https: //github.com/damog/planetalinux/blob/master/www/principal/suscripcion/lib/antiflood.hack.php

回答by Dave Holitish

What spudinksi said still holds true, however here is what your looking for:

spudinksi 所说的仍然适用,但是这里是您要查找的内容:

 <?php


 if (!isset($_SESSION)) {
         session_start();
 }

 if($_SESSION['last_session_request'] > (time() - 5)){
    if(empty($_SESSION['last_request_count'])){
        $_SESSION['last_request_count'] = 1;
    }elseif($_SESSION['last_request_count'] < 5){
        $_SESSION['last_request_count'] = $_SESSION['last_request_count'] + 1;
    }elseif($_SESSION['last_request_count'] >= 5){
            header("location: http://www.example.com/403.html");
            exit;
         }
 }else{
    $_SESSION['last_request_count'] = 1;
 }

 $_SESSION['last_session_request'] = time();

 ?>

回答by Rhythm Shahriar

There is a script called IOSec, which is quite old, but it might help.

有一个名为IOSec的脚本,它已经很老了,但它可能会有所帮助。

回答by Narvulkan_MVCore

This will count page reloads & also save time after 3 seconds .... if it gives problems or to easy for newbies to bypass then leave comment..

这将计算页面重新加载并在 3 秒后节省时间......如果它出现问题或让新手容易绕过然后发表评论..

if(empty($_SESSION['AFsys_time']) || $_SESSION['AFsys_time'] == '0') {
    $tGoal = time() + 3; // Pluss Seconds
    $_SESSION['AFsys_time'] = $tGoal;
}

if(empty($_SESSION['AFsys_pReloads']) || $_SESSION['AFsys_pReloads'] == 0 ) { $_SESSION['AFsys_pReloads'] = 1; } else { $_SESSION['AFsys_pReloads']++; };

if($_SESSION['AFsys_time'] < time()){
    $_SESSION['AFsys_time'] = 0; // Session Reset
    $_SESSION['AFsys_pReloads'] = 0; // Session Reset
}

if($_SESSION['AFsys_pReloads'] > '5' && $_SESSION['AFsys_time'] > time()){
    $_SESSION['AFsys_time'] = 0; // Session Reset
    $_SESSION['AFsys_pReloads'] = 0; // Session Reset
    header("location: http://www.example.com/403.html");
    exit; 
}

回答by Sr. Presidente

For stop DDos add a null route for that ip, like this:

对于停止 DDos,为该 ip 添加一个空路由,如下所示:

route add -host ???.???.???.??? reject

回答by Dan Barzilay

just change >to <:

只需更改><

<?php        

if (!isset($_SESSION)) {
        session_start();
}
// anti flood protection
if($_SESSION['last_session_request'] < time() - 2){
        // users will be redirected to this page if it makes requests faster than 2 seconds
        header("location: http://www.example.com/403.html");
        exit;
}
$_SESSION['last_session_request'] = time();
?>

回答by M-A-X

Session may be not work, because we haven't session coockie.

会话可能不起作用,因为我们还没有会话 coockie。

I recommend such

我推荐这样的

$load = sys_getloadavg();
if ($load[0] > 20) {
    header('HTTP/1.1 503 Too busy, try again later');
    die('Server too busy. Please try again later.');
}

Or you can

或者你可以

shell_exec('/sbin/iptables -I INPUT -j DROP -s ' . $ip);

for ddosing $ip

为 ddos​​ing $ip

回答by mohammad inanloo

this code not work for curl looping like this. session will create again on every curl exec;

此代码不适用于像这样的 curl 循环。session 将在每个 curl exec 上再次创建;

for ($i=0;$i<999999999999999;$i++){

    /**/
    $c=curl_init();
    curl_setopt($c,CURLOPT_URL,"URL YOU WANT ATTACK");
    curl_setopt($c,CURLOPT_DNS_USE_GLOBAL_CACHE,TRUE);//dns
    curl_setopt($c,CURLOPT_HEADER,0);//get the header
    curl_setopt($c,CURLOPT_CONNECTTIMEOUT ,10);//get the header
    curl_setopt($c,CURLOPT_NOBODY,0);//and *only* get the header
    curl_setopt($c,CURLOPT_RETURNTRANSFER,1);//get the response as a string from curl_exec(), rather than echoing it
    curl_setopt($c,CURLOPT_FRESH_CONNECT,1);//don't use a cached version of the url
    curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko Firefox/11.0');
    curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded;charset=UTF-8' ));

    echo "\n $i";

}