利用 Swoole 给应用写个防火墙

原理:

  • 定时检测活跃连接数, 如果单个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();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值