IP门禁:保姆式教你用PHP实现一个IP防火墙
发布时间:2022-08-10 11:00:24 所属栏目:PHP教程 来源:互联网
导读:最近我遇到一个需求,我的一台服务器总是遭到端口扫描和恶意登录攻击,对此可以怎么办呢?似乎除了内网隔离、增强密码认证、证书登录、设置防火墙iptables,网上找不到什么别的方案,对了,还用堡垒机的方案。 这些方案实际上都无法解决我的问题。这是一台公
最近我遇到一个需求,我的一台服务器总是遭到端口扫描和恶意登录攻击,对此可以怎么办呢?似乎除了内网隔离、增强密码认证、证书登录、设置防火墙iptables,网上找不到什么别的方案,对了,还用堡垒机的方案。 这些方案实际上都无法解决我的问题。这是一台公网服务器,并没有什么复杂的网络结构,所以不能建立内网隔离。调整账号的密码策略,自然是一个方案,但是人工操作太麻烦,而且我一般经常换电脑使用,如果修改密码,公司的和家里的电脑都要更新,很麻烦。设置防火墙自然是运维的基本操作,但是iptables的配置太麻烦,ufw工具还好些,firewall-cmd就麻烦些,而且有一个巨大的痛点,众所周知,大家的出网IP都会经常变,好不容易在命令行里一个字母一个字母的配置好了,睡了一觉,白费了。堡垒机更不是一个主流的方案,有点大材小用,用了堡垒机,反而不能随意使用系统,更何况还没听说过那个免费的堡垒机呢。【推荐:PHP视频教程】 那怎么办呢,作为一个资深的PHP开发者,服务器这块的应用还不是手到擒来,当初连内网穿透都能轻松实现,一个IP过滤系统,小意思。所以我打算自己开发这样一个项目,首先能够实现IP过滤,另外,可以轻松地将IP加入到白名单里,比如访问一个网页,就自动加入到白名单。 整个项目不到几个小时就研发完了,起码满足了我自己的需求,并且实现了这样几个特性: 多进程 支持并发 守护进程 可以通过网页面板管理IP 流量统计 拦截记录 现在我们来一步一步的实现这个系统。 第一步,首先能够简简单单的过滤IP 使用PHP监听端口并且转发数据的框架很多,对此我选择workerman,原因有3: 运行简单稳定 方法接口简单 内置进程守护 至于具体的安装方法,可以参考他的官方文档。 0f7d3163d512f1d5ed4ba46e69929b1.jpg workerman的使用方法非常简单,只要10行代码,就实现了IP转发+白名单过滤: $worker = new Worker('tcp:0.0.0.0:' . Config::get('door.port_in')); // 监听一个端口 $worker->count = 2; // 设置多进程 $worker->onConnect = function (TcpConnection $connection) { // 获取IP白名单 $list_ip = AppIp::where('status', 0)->cache(3)->column('ip'); $remote_ip = $connection->getRemoteIp(); // 拦截IP if (!in_array($remote_ip, $list_ip)) { $connection->close(); } // 放行连接,连接内部目标端口 $to_connection = new AsyncTcpConnection('tcp:127.0.0.1:' . Config::get('door.port_to')); // 互相转发流量 $connection->pipe($to_connection); $to_connection->pipe($connection); $to_connection->connect(); } 正如上面代码所示,只有简单几行,便实现了IP监听和转发,其中IP白名单通过数据库查询,并且缓存。 第二步,与ThinkPHP命令行整合在一起 为了项目开发方便,我都会使用ThinkPHP框架进行开发,它够简单,功能也比较齐全。 最终实现的命令行效果如下: 运行命令 php think door start php think door start --mode d // 守护进程重启 重启 php think door restart 停止 php think door stop workerman的命令参数与thinkphp并不兼容,但是实现这样的效果并不难,实际上很简单,代码如下: <?php declare(strict_types=1); namespace appcommoncommand; use thinkconsoleCommand; use thinkconsoleInput; use thinkconsoleinputArgument; use thinkconsoleinputOption; use thinkconsoleOutput; class Door extends Command { protected function configure() { // 指令配置 $this->setName('door') // 设置think的命令参数 ->addArgument('action', Argument::OPTIONAL, "start|stop|restart|reload|status|connections", 'start') ->addOption('mode', 'm', Option::VALUE_OPTIONAL, 'Run the workerman server in daemon mode.') ->setDescription('the door command'); } protected function execute(Input $input, Output $output) { // 指令输出 $output->writeln('door'); $action = $input->getArgument('action'); $mode = $input->getOption('mode'); // 重新构造命令行参数,以便兼容workerman的命令 global $argv; $argv = []; array_unshift($argv, 'think', $action); if ($mode == 'd') { $argv[] = '-d'; } else if ($mode == 'g') { $argv[] = '-g'; } // ...workerman的代码 } } (编辑:莆田站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |