Heim  >  Artikel  >  Backend-Entwicklung  >  IP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementieren

IP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementieren

藏色散人
藏色散人nach vorne
2022-08-06 14:52:013804Durchsuche

Kürzlich ist einer meiner Server ständig einem Port-Scanning und böswilligen Anmeldeangriffen ausgesetzt. Was kann ich dagegen tun? Es scheint, dass außer Intranet-Isolation, erweiterter Passwort-Authentifizierung, Zertifikat-Anmeldung und dem Einrichten von Firewalls (iptables) keine anderen Lösungen online verfügbar sind. Übrigens verwende ich auch die Bastion-Host-Lösung. Keine dieser Lösungen löst tatsächlich mein Problem. Dies ist ein öffentlicher Netzwerkserver und weist keine komplizierte Netzwerkstruktur auf, sodass keine Intranet-Isolation hergestellt werden kann. Das Anpassen der Passwortrichtlinie des Kontos ist natürlich eine Lösung, aber die manuelle Bedienung ist zu mühsam und ich wechsle normalerweise den Computer. Wenn ich das Passwort ändere, müssen sowohl der Firmen- als auch der Heimcomputer aktualisiert werden, was sehr mühsam ist. Das Einrichten einer Firewall ist natürlich ein grundlegender Vorgang für Betrieb und Wartung, aber die Konfiguration von

iptables

ist zu mühsam, ufw ist ein besseres Tool, firewall-cmd ist mühsamer und es gibt einen großen Schmerzpunkt. Wie wir alle wissen, ändert sich die ausgehende IP-Adresse von jedem Alles ändert sich schließlich Buchstabe für Buchstabe in der Befehlszeile. Nach langem Schlaf war alles umsonst. Die Bastion-Maschine ist keine Mainstream-Lösung. Wenn Sie eine Bastion-Maschine verwenden, können Sie das System nicht nach Belieben verwenden, ganz zu schweigen davon, dass ich noch nie von der kostenlosen Bastion-Maschine gehört habe. [Empfehlung: PHP-Video-Tutorial]Was soll ich tun? Als erfahrener PHP

-Entwickler ist die Serveranwendung noch nicht ohne weiteres mit einem

IP-Filtersystem zu erreichen. Deshalb habe ich vor, selbst ein solches Projekt zu entwickeln. Außerdem kann ich IP problemlos zur Whitelist hinzufügen die Whitelist. Das gesamte Projekt wurde in weniger als ein paar Stunden entwickelt. Zumindest entsprach es meinen eigenen Anforderungen und implementierte mehrere Funktionen: Mehrere Prozesse

Unterstützt Parallelität

    Daemon-Prozess
  • kann über das Web-Panel verwaltet werden
  • IP
  • Verkehrsstatistiken
  • Abhöraufzeichnungen
  • Lassen Sie uns nun dieses System Schritt für Schritt implementieren.
  • Der erste Schritt besteht darin, einfach
  • IP

zu filtern. Es gibt viele Frameworks, die

PHP verwenden, um den Port abzuhören und Daten weiterzuleiten. Dafür habe ich workerman

aus

3 Gründen gewählt: Einfach Führen Sie Stable ausEinfache Methodenschnittstelle

    Eingebauter Prozess-Daemon
  • Informationen zur spezifischen Installationsmethode finden Sie in der offiziellen Dokumentation.
  • Urheberrechtserklärung: Dieser Artikel ist original und wurde von
  • phpreturn.com
(

PHP

Arsenal Official Website) veröffentlicht. Alle Rechte liegen bei

phpreturn (PHPArsenal). Diese Website erlaubt jede Form des Nachdrucks/ Zitierung des Artikels, wobei jedoch gleichzeitig die Quelle angegeben werden muss.

workerman

ist sehr einfach zu verwenden. Es sind nur IP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementieren10

Codezeilen erforderlich, um

IP-Weiterleitung+Whitelist-Filterung zu implementieren:

$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();
}
Wie im obigen Code gezeigt, mit nur ein paar einfachen Leitungen, IP-Überwachung und -Weiterleitung implementiert, wobei die IP-Whitelist über die Datenbank abgefragt und zwischengespeichert wird.

Der zweite Schritt besteht darin, es in die ThinkPHP-Befehlszeile zu integrieren. Zur Vereinfachung der Projektentwicklung verwende ich das ThinkPHP-Framework für die Entwicklung. Es ist einfach genug und verfügt über relativ vollständige Funktionen.

IP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementieren

最终实现的命令行效果如下:

版权声明:本文由phpreturn.comPHP武器库官网)原创和首发,所有权利归phpreturnPHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

运行命令
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 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(&#39;door&#39;)
            // 设置think的命令参数
            ->addArgument(&#39;action&#39;, Argument::OPTIONAL, "start|stop|restart|reload|status|connections", &#39;start&#39;)
            ->addOption(&#39;mode&#39;, &#39;m&#39;, Option::VALUE_OPTIONAL, &#39;Run the workerman server in daemon mode.&#39;)
            ->setDescription(&#39;the door command&#39;);
    }
    protected function execute(Input $input, Output $output)
    {
        // 指令输出
        $output->writeln(&#39;door&#39;);
        $action = $input->getArgument(&#39;action&#39;);
        $mode = $input->getOption(&#39;mode&#39;);
        // 重新构造命令行参数,以便兼容workerman的命令
        global $argv;
        $argv = [];
        array_unshift($argv, &#39;think&#39;, $action);
        if ($mode == &#39;d&#39;) {
            $argv[] = &#39;-d&#39;;
        } else if ($mode == &#39;g&#39;) {
            $argv[] = &#39;-g&#39;;
        }
        // ...workerman的代码
    }
}

在上面的代码中,主要做了两件事:

  • 实现ThinkPHP的命令设置
  • 将命令参数重新构造为workerman兼容的方式

第三步,实现管理面板

使用PHP实现一个管理面板太简单了,PHP到处都是这样的后台框架,这里我选择ulthon_admin,这是我自己开发维护的,它基于ThinkPHP6,很简单,为定制而生,不搞所谓的“插件”和“市场”生态,能够自动生成CURD代码,并且内置几了几个有趣的皮肤。

最终效果如下:

IP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementierenIP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementieren

以上是ulthon_admin内置的两款皮肤效果,分别是:科幻、像素。

对于面板的管理,这里多做介绍,这算是PHP开发者的基本功,谁还不会个CURD啊。

版权声明:本文由phpreturn.comPHP武器库官网)原创和首发,所有权利归phpreturnPHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

第四步,进阶,更好的性能和流量统计

我们的IP拦截客户端需要运行在服务器上,并且直接连接数据库,如果每次收到请求都要查询数据库,那么很有可能导致连接不通畅,尤其是客户端和数据库本身位置较远的时候。在第一步的代码中,我们只是简单的使用了查询缓存,但是还不够,还可以优化。并且我们可以在管理面板的截图中看到,我们是可以统计流量和拦截次数的,现在我们要实现这些功能:

流量统计

首先我们将第一个步中,流量转发部分的代码改造成如下的样子:

<?php
// 向TO发起连接
$to_connection = new AsyncTcpConnection(&#39;tcp://127.0.0.1:&#39; . Config::get(&#39;door.port_to&#39;));
$to_connection->onMessage = function ($source, $data) use ($connection, $remote_ip) {
    // 接收到来自TO的数据,返回的数据
    $connection->send($data);
    // 将流量统计存储到内存里
    Cache::inc(md5($remote_ip) . &#39;-to&#39;, 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) . &#39;-in&#39;, 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(&#39;tcp:127.0.0.1:&#39; . Config::get(&#39;door.port_to&#39;));
// 互相转发流量
$connection->pipe($to_connection);
$to_connection->pipe($connection);

这里使用的是workerman内置的流量转发,它很好用,但是这里我们要统计流量,所以我们手动转发流量。

这里我们将统计的数据存储到缓存里,而不是直接连接数据库更新,这是为了更好的连接性能。我们会另外开启一个进程将这些改动更新到数据库。后面会介绍到。

拦截统计

我们将第一步中的加载IP白名单的逻辑改成下面这样:

版权声明:本文由phpreturn.comPHP武器库官网)原创和首发,所有权利归phpreturnPHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

<?php
$worker->onConnect = function (TcpConnection $connection) {
    $disable_cache_key = &#39;disable_ip_list&#39;;
    $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();
    }
};

在这里我们不连接数据库查询,而是直接从本地缓存读取白名单,这样会有更好的性能。我们会在另一个进程中更新这份白名单。

另外我们可以看到,拦截的IP调用了一个静态方法,这里的功能很简单,判断数据库中该IP是否存在,如果不存在则新增,如果存在,则更新拦截次数+·1。这里就不多介绍了。这里也没有必要做什么性能优化,反正本来就是拦截的IP,优化个毛。

高性能处理缓存数据

上面我们介绍,我们会另外开启一个进程,维护IP白名单,并且将流量统计提交到数据库。这就是这个进程:

<?php
$worker_ip = new Worker();
$worker_ip->name = &#39;report&#39;;
$worker_ip->onWorkerStart = function () {
    Timer::add(5, function () {
        $disable_cache_key = &#39;disable_ip_list&#39;;
        $list_ip = AppIp::where(&#39;status&#39;, 1)->column(&#39;ip&#39;);
        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(&#39;ip&#39;, $ip)->find();
                $model_ip->in_buffer += $in_length;
                $model_ip->to_buffer += $to_length;
                $model_ip->save();
            }
        }
    });
};

他做的事情很简单,读取缓存,更新数据到数据库,并且更新IP白名单。这里不需要考虑它和数据库之间的性能问题,这是额外的进程,不影响端口的连接和转发。

下一步,更好的性能设计

以上,只有几行代码,几个小时(如果不含设计系统的时间,代码量可能只有一两个小时。还能再怎么优化呢?实际上还是可以优化的。

更好的内存驱动

这里使用的是ThinkPHP内置的文件缓存,存储到磁盘上,以上方法,在大量连接并发时,肯定受制于磁盘的性能。所以自然而然,我们可以使用内存缓存。

版权声明:本文由phpreturn.comPHP武器库官网)原创和首发,所有权利归phpreturnPHP武器库)所有,本站允许任何形式的转载/引用文章,但必须同时注明出处。

但是使用内存缓存,redis可以吗?并不好。这里是客户端,它只是想简简单单实现一个拦截转发,还要再部署redis,不可取。

但实际上,workerman本身内置了数据共享组件,这是一个很好的方案。相当于一个极简的redis。完美符合我们的需求。但是我并没有实现这个功能,目前的系统已经符合我的场景。

更好的客户端

目前拦截IP客户端和管理面板集成在一起,使用相同的配置,面板基于ThinkPHP,客户端只是ThinkPHP的一个命令。我之所以这样做,是希望直接在Workerman中使用ThinkPHP的众多特性(数据库、缓存

实际上,我们可以将客户端的代码,另外开一个项目,使客户端和面板独立开。在面板上实现通用得API。客户端通过API操作数据。这样客户端就不需要连接数据库。好处多多。

Aber das bringt auch mehr Arbeitsaufwand mit sich. In diesem Fall denken wir natürlich, dass die Client-Umgebung unsicher ist, also müssen wir eine Berechtigungsauthentifizierung und eine Anmeldeauthentifizierung durchführen. Die Schnittstellenentwicklung erfordert auch das Schreiben von mehr Code.

Zusammenfassung

In diesem Artikel werden hauptsächlich meine Ideen zur Implementierung einer IP-Firewall vorgestellt. Diese Technologien erfordern von Entwicklern umfassende Erfahrung in der Website-Entwicklung. Diese Anforderungen sind nicht hoch, sie benötigen jedoch auch grundlegende Erfahrung in der Netzwerkentwicklung, die einen bestimmten Schwellenwert hat. Workerman ist sehr einfach, aber Workerman ist kein HTTP Dies ist keine gewöhnliche Website-Entwicklung und erfordert gewisses Lernen und Umdenken. Aber für mich ist es einfach, mit Leichtigkeit zu fahren. Wenn ich nach anderen Lösungen zum Lernen, Bereitstellen und Testen suche, ist das möglicherweise nicht schneller, als sie selbst zu entwickeln.

Urheberrechtserklärung: Dieser Artikel ist original und wurde von

phpreturn.com (PHPArsenal Official Website) veröffentlicht. Alle Rechte liegen bei phpreturn (PHPArsenal). Diese Website erlaubt jede Form des Nachdrucks/ Zitierung des Artikels, wobei jedoch gleichzeitig die Quelle angegeben werden muss.

IPWie verwalte ich die Whitelist? Sie können sie über das Panel hinzufügen oder eine Seite des Panels besuchen, um die ausgehende IPIP automatisch abzurufen und zur Whitelist hinzuzufügen .

Tatsächlich gibt es eine bessere Möglichkeit, nämlich einen

rss-Server zu erstellen und automatisch die ausgehende Netzwerk-IP von Kunden zu erhalten, die rss abonnieren, und sie zur Whitelist hinzuzufügen. Aber ich habe nicht die Angewohnheit, RSS zu verwenden, und ich habe keinen guten RSSReader auf meinem Telefon, und ich möchte ihn nicht jedes Mal öffnen, wenn ich die IPWhitelist aktualisiere, also Ich habe diese Lösung nicht verwendet.

Ich habe es als Open Source bereitgestellt. Wenn Sie es benötigen, können Sie sich an folgende Adresse wenden: https://gitee.com/augushong/ip-door.

Mehr

Im Vergleich zu

iptables bietet dieses System einfach eine komfortablere IP-Whitelist-Verwaltungserfahrung, die einer einfachen Bastion-Maschine entspricht. Er kann einige Ports ausblenden, sodass nur „ich“ eine Verbindung herstellen kann. Verstecken Sie beispielsweise den Port von

ssh

und leiten Sie ihn über die ip-Zugriffskontrolle weiter. Ein weiteres Beispiel besteht darin, den 80-Port auszublenden und ihn über die ip-Zugriffskontrolle weiterzuleiten. Derzeit hat mein System die gleichzeitige Bindung und Weiterleitung mehrerer Ports nicht implementiert, aber die Grundidee ist dieselbe und kann als Referenz verwendet werden.

Urheberrechtserklärung: Dieser Artikel ist original und wurde von

phpreturn.com

(

PHPArsenal Official Website) veröffentlicht. Alle Rechte liegen bei phpreturn (PHPArsenal). Diese Website erlaubt jede Form des Nachdrucks/ Zitierung des Artikels, wobei jedoch gleichzeitig die Quelle angegeben werden muss. Dieser Artikel wurde nachgedruckt, der Originaltitel lautet:

IP

Das obige ist der detaillierte Inhalt vonIP-Zugriffskontrolle: Im Nanny-Stil erfahren Sie, wie Sie eine IP-Firewall mit PHP implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:phpreturn.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen