利用 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();

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

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

1.6k 声望
154 粉丝
0 条评论
推荐阅读
个人如何免费接入微信支付, 不用交300块钱
也不是没有办法, 微信现在推出了"服务商"模式, 也就是给线下小微商户开通微信收款的权限. 而微信为了方便服务商拓展业务, 给了服务商替商户发起支付的 API 接口, 支付完成再通知到服务商. 然后第二天, 到账的钱会...

ARGUS3阅读 8k

php实现只需要一个QQ号就可以获得用户信息
{代码...} DEMO:[链接]此处输入你的QQ号

TANKING27阅读 7.3k评论 5

初学后端,如何做好表结构设计?
这篇文章介绍了设计数据库表结构应该考虑的4个方面,还有优雅设计的6个原则,举了一个例子分享了我的设计思路,为了提高性能我们也要从多方面考虑缓存问题。

王中阳Go4阅读 1.7k评论 2

封面图
一分钟搞明白!快速掌握 Go WebAssembly
最近因为各种奇怪的原因,更多的接触到了 WebAssembly。虽然之前很多博客也翻过写过各种文章,但总感觉欠些味道。于是今天梳理了一版,和大家一起展开学习。

煎鱼4阅读 2.1k

面试官:请说一下如何优化结构体的性能?
使用内存对齐机制优化结构体性能,妙啊!前言之前分享过2篇结构体文章:10秒改struct性能直接提升15%,产品姐姐都夸我好棒 和 Go语言空结构体这3种妙用,你知道吗? 得到了大家的好评。这篇继续分享进阶内容:结...

王中阳Go4阅读 3.8k评论 2

封面图
Laravel入门及实践,快速上手ThinkSNS+二次开发
【摘要】自从ThinkSNS+不使用ThinkPHP框架而使用Laravel框架之后,很多人都说技术门槛抬高了,其实你与TS+的距离仅仅只是学习一个新框架而已,所以,我们今天来说说Laravel的入门。

ThinkSNS1阅读 2.4k

我让chatGPT用PHP写一个MVC框架,不仅写出来,还能跑!
没想到写出来的框架确实挺简单的,但是又没觉得哪里不对,于是我尝试把这个框架放到服务器试试能不能跑起来,最后还真的可以跑起来,为了让大家能够看到这个框架的演示,我直接爬一个热搜,然后便于展示数据。

TANKING1阅读 1.7k

封面图

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

1.6k 声望
154 粉丝
宣传栏