Récemment, j'ai rencontré une exigence. Un de mes serveurs est toujours soumis à une analyse de port et à des attaques de connexion malveillantes. Que puis-je faire à ce sujet ? Il semble qu'à part l'isolation intranet, l'authentification améliorée par mot de passe, la connexion par certificat et la configuration de pare-feu
Aucune de ces solutions ne résout réellement mon problème. Il s'agit d'un serveur de réseau public et ne possède pas de structure de réseau compliquée. L'isolation intranet ne peut donc pas être établie. Ajuster la politique de mot de passe du compte est naturellement une solution, mais l'opération manuelle est trop gênante et je change généralement d'ordinateur si je change le mot de passe, les ordinateurs de l'entreprise et ceux de la maison doivent être mis à jour, ce qui est très gênant. La configuration d'un pare-feu est naturellement une opération de base pour l'exploitation et la maintenance, mais la configuration de
PHP
- Processus multiples
- Prise en charge de la concurrence
- Le processus démon
- peut être géré via le panneau Web
- IP.
- Enregistrements d'interceptions
IP
Il existe de nombreux frameworks utilisant PHP
- Facile à utiliser. exécutez Stable
- Interface de méthode simple
- Démon de processus intégré
workerman
est très simple à utiliser. Il ne faut que10
$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
ThinkPHP pour le développement. Il est assez simple et possède des fonctions relativement complètes.
最终实现的命令行效果如下:
运行命令 php think door start php think door start --mode d // 守护进程重启 重启 php think door restart 停止 php think door stop
<?php declare(strict_types=1); namespace app\common\command; use think\console\Command; use think\console\Input; use think\console\input\Argument; use think\console\input\Option; use think\console\Output; 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的代码 } }
在上面的代码中,主要做了两件事:
- 实现
ThinkPHP 的命令设置 - 将命令参数重新构造为
workerman 兼容的方式
第三步,实现管理面板
使用
最终效果如下:
以上是
对于面板的管理,这里多做介绍,这算是
第四步,进阶,更好的性能和流量统计
我们的
流量统计
首先我们将第一个步中,流量转发部分的代码改造成如下的样子:
<?php // 向TO发起连接 $to_connection = new AsyncTcpConnection('tcp://127.0.0.1:' . Config::get('door.port_to')); $to_connection->onMessage = function ($source, $data) use ($connection, $remote_ip) { // 接收到来自TO的数据,返回的数据 $connection->send($data); // 将流量统计存储到内存里 Cache::inc(md5($remote_ip) . '-to', strlen($data)); }; // 流程和流量控制 $to_connection->onClose = function ($source) use ($connection) { $connection->close(); }; $connection->onBufferFull = function ($dest) use ($to_connection) { $to_connection->pauseRecv(); }; $connection->onBufferDrain = function ($dest) use ($to_connection) { $to_connection->resumeRecv(); }; $connection->onMessage = function ($source, $data) use ($to_connection, $remote_ip) { // 接收来自IN的数据,请求的数据 $to_connection->send($data); // 将流量统计存储到内存里 Cache::inc(md5($remote_ip) . '-in', strlen($data)); }; // 流程和流量控制 $connection->onClose = function ($source) use ($to_connection) { $to_connection->close(); }; $to_connection->onBufferFull = function ($dest) use ($connection) { $connection->pauseRecv(); }; $to_connection->onBufferDrain = function ($dest) use ($connection) { $connection->resumeRecv(); };
在第一部的代码中,只用两行便实现了这些代码:
// 放行连接,连接内部目标端口 $to_connection = new AsyncTcpConnection('tcp:127.0.0.1:' . Config::get('door.port_to')); // 互相转发流量 $connection->pipe($to_connection); $to_connection->pipe($connection);
这里使用的是
这里我们将统计的数据存储到缓存里,而不是直接连接数据库更新,这是为了更好的连接性能。我们会另外开启一个进程将这些改动更新到数据库。后面会介绍到。
拦截统计
我们将第一步中的加载
<?php $worker->onConnect = function (TcpConnection $connection) { $disable_cache_key = 'disable_ip_list'; $list_ip = Cache::get($disable_cache_key); if (empty($list_ip)) { $connection->close(); } $remote_ip = $connection->getRemoteIp(); if (!in_array($remote_ip, $list_ip)) { AppIpReject::initRecord($remote_ip); $connection->close(); } };
在这里我们不连接数据库查询,而是直接从本地缓存读取白名单,这样会有更好的性能。我们会在另一个进程中更新这份白名单。
另外我们可以看到,拦截的
高性能处理缓存数据
上面我们介绍,我们会另外开启一个进程,维护
<?php $worker_ip = new Worker(); $worker_ip->name = 'report'; $worker_ip->onWorkerStart = function () { Timer::add(5, function () { $disable_cache_key = 'disable_ip_list'; $list_ip = AppIp::where('status', 1)->column('ip'); Cache::set($disable_cache_key, $list_ip); foreach ($list_ip as $ip) { $ip_md5 = md5($ip); $in_length = Cache::pull("$ip_md5-in"); // 请求的数据 $to_length = Cache::pull("$ip_md5-to"); // 返回的数据 if (!empty($in_length) || !empty($to_length)) { $model_ip = AppIp::where('ip', $ip)->find(); $model_ip->in_buffer += $in_length; $model_ip->to_buffer += $to_length; $model_ip->save(); } } }); };
他做的事情很简单,读取缓存,更新数据到数据库,并且更新
下一步,更好的性能设计
以上,只有几行代码,几个小时(如果不含设计系统的时间,代码量可能只有一两个小时
更好的内存驱动
这里使用的是
但是使用内存缓存,
但实际上,
更好的客户端
目前拦截
实际上,我们可以将客户端的代码,另外开一个项目,使客户端和面板独立开。在面板上实现通用得
Mais cela entraîne également plus de charge de travail. Dans ce cas, nous pensons naturellement que l'environnement client n'est pas sûr, nous devons donc effectuer une authentification des autorisations et une authentification de connexion. Le développement d’interfaces nécessite également d’écrire davantage de code.
Résumé
Cet article présente principalement mes idées pour implémenter le pare-feu
Comment gérer la liste blanche ? Vous pouvez l'ajouter via le panneau, ou vous pouvez visiter une page du panneau pour obtenir automatiquement l'IP
, et d'obtenir automatiquement le réseau sortant
Plus
Par rapport à
iptables, ce système offre simplement une expérience de gestion de liste blanche
et transférez-le via le contrôle d'accès
Déclaration de droits d'auteur : cet article est original et publié par
phpreturn.com Contrôle d'accès : Apprenez-vous étape par étape à utiliserPHPpour implémenter un
IP firewallAdresse originale : https://phpreturn.com/index/ a62e1ddd672933.html Plateforme originale :