Write a firewall for the application using swoole

Time:2021-8-6

Principle:

  • Regularly detect the number of active connections. If the number of single IP connections exceeds 20, it is temporarily blocked and more than 100 are permanently blocked (closed directly during TCP connection)

<?php
$server = new swoole_http_server("0.0.0.0", 9502);
$server->_GLOBAL_SESSION = [];
$server->_GLOBAL_SESSION['ban']         = [];
$server->_GLOBAL_SESSION['ban_forever'] = [];

$server->_GLOBAL_SESSION['init_waf_u2'] = '/init_waf_KKDL_d'.mt_rand(100000, 9999999);

$server->on('connect', function ($server, $fd, $fi) {
    #Permanent ban
    #In order to work, dispatch_ mode_ Mode cannot be set to 1 or 3
    $connection_info = $server->connection_info($fd);
    if( $this->_GLOBAL_SESSION['ban_forever'][$connection_info['remote_ip']] == 1 ){
        $server->close($fd);
        return;
    }
});
$server->on('request', function ($req, $res) use ($server) {
    #Permanent ban
    if( $this->_GLOBAL_SESSION['ban_forever'][$req->server['remote_addr']] == 1 ){
        return;
    }
    #Ban for ten minutes
    if( $this->_GLOBAL_SESSION['ban'][$time-$time%600][$req->server['remote_addr']] == 1 ){
        $res->status(204); $res->end(); return;
    }
    $time = time();

    if ($req->server['request_uri'] == $server->_GLOBAL_SESSION['init_waf_u2'] ){
        $timer_id = $this->tick(500, function(){

            if($this->connection_list(-1, 50) < 51) return 0;
            $connection_list = $this->connection_list(-1, 20000);
            $connection_data = []; // ip -> connection_count

            foreach ($connection_list as $connection_id) {
                $connection = $this->connection_info($connection_id);
                if (!isset($connection_data[$connection['remote_ip']])) {
                    $connection_data[$connection['remote_ip']] = 0;
                } else if ($connection_data[$connection['remote_ip']] > 20) {
                    $this->_GLOBAL_SESSION['ban'][$time-$time%600][$connection['remote_ip']] = 1;
                } else if ($connection_data[$connection['remote_ip']] > 100) {
                    $this->_GLOBAL_SESSION['ban_forever'][$connection['remote_ip']] = 1;
                }
                $connection_data[$connection['remote_ip']] ++;
                
                $str = "";
                $str .= $connection['remote_ip'];
                $str .= " => ";
                $str .= $connection_data[$connection['remote_ip']];
                $str .= "\n";

                echo $connection['remote_ip'];
                echo " => ";
                echo $connection_data[$connection['remote_ip']];
                echo "\n";
            }
        });
        $res->end($timer_id);
        return true;
    }
});

echo "\n\nYou need to run following command to init waf:\n";
echo "curl -s http://127.0.0.1:9502".$server->_GLOBAL_SESSION['init_waf_u2'];
$server->start();

Recommended Today

A detailed explanation of the differences between Perl and strawberry Perl and ActivePerl

Perl is the abbreviation of practical extraction and report language “practical report extraction language”. Application of activestateperl and strawberry PERL on Windows platformcompiler。 Perl   The relationship between the latter two is that C language and Linux system have their own GCC. The biggest difference between activestate Perl and strawberry Perl is that strawberry Perl […]