原理:
定时检测活跃连接数, 如果单个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();