利用 Swoole 给应用写个防火墙

ARGUS

原理:

  • 定时检测活跃连接数, 如果单个IP连接数超过20临时封禁, 超过100永久封禁(在TCP连接时候直接关闭)

<?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) {
    # 永久封禁
    # 为了能工作, dispatch_mode_mode不能设置为1或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) {
    # 永久封禁
    if( $this->_GLOBAL_SESSION['ban_forever'][$req->server['remote_addr']] == 1 ){
        return;
    }
    # 封禁十分钟
    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();
阅读 1.8k

千里码博客
A.R.G.U.S.网络安全小组

便宜的SSL证书 www.ssl.com.ru

1.6k 声望
154 粉丝
0 条评论

便宜的SSL证书 www.ssl.com.ru

1.6k 声望
154 粉丝
文章目录
宣传栏