最近、ある要件が発生しました。サーバーの 1 つが常にポート スキャンと悪意のあるログイン攻撃の対象になっています。これについてはどうすればよいですか?イントラネット分離、強化されたパスワード認証、証明書ログイン、およびファイアウォール
これらの解決策はどれも実際には私の問題を解決しません。これはパブリック ネットワーク サーバーであり、複雑なネットワーク構造を持っていないため、イントラネットの分離を確立できません。アカウントのパスワードポリシーを調整することで解決するのは当然ですが、手動で行うのは面倒で、普段パソコンを買い替えるのですが、パスワードを変更すると会社と自宅の両方のパソコンを更新する必要があり、非常に面倒です。ファイアウォールの設定は当然基本的な運用保守作業ですが、
PHP
- マルチプロセス
- サポート同時実行性
- デーモンプロセス
- Webパネルから管理可能
- IP
#トラフィック統計 - 傍受記録
- それでは、このシステムを段階的に実装してみましょう。
最初のステップは、単に
IP
をフィルタリングすることです。
PHP を使用してポートをリッスンし、データを転送するためのフレームワークが多数あります。私が
- シンプルなメソッド インターフェース
- 構築済み-in process Guard
- 具体的なインストール方法については、公式ドキュメントを参照してください。
著作権声明: この記事はオリジナルであり、
phpreturn.com workerman は使い方が非常に簡単です。$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
フレームワークを使用します。開発用途としては十分シンプルで機能も比較的充実しています。 最终实现的命令行效果如下:
版权声明:本文由phpreturn.com(
运行命令 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 兼容的方式
第三步,实现管理面板
使用
最终效果如下:
以上是
对于面板的管理,这里多做介绍,这算是
版权声明:本文由phpreturn.com(
第四步,进阶,更好的性能和流量统计
我们的
流量统计
首先我们将第一个步中,流量转发部分的代码改造成如下的样子:
<?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(); } } }); };
他做的事情很简单,读取缓存,更新数据到数据库,并且更新
下一步,更好的性能设计
以上,只有几行代码,几个小时(如果不含设计系统的时间,代码量可能只有一两个小时
更好的内存驱动
这里使用的是
但是使用内存缓存,
但实际上,
更好的客户端
目前拦截
实际上,我们可以将客户端的代码,另外开一个项目,使客户端和面板独立开。在面板上实现通用得
ただし、負荷も大きくなりますので、この場合は当然クライアント環境が安全ではないと考えられるため、権限認証やログイン認証を行う必要があります。インターフェイスの開発には、より多くのコードを記述する必要もあります。
概要
この記事では主に、
実際には、より良い方法があります。それは、
iptables
ssh
この記事は転載されており、元のタイトルは次のとおりです:IP
元のアドレス: https://phpreturn.com/index/a62e1ddd672933.html元のプラットフォーム:アクセス制御: PHPを使用して IP を実装する方法を段階的に説明します。ファイアウォール
##PHP 武器ライブラリ