> 백엔드 개발 > PHP 튜토리얼 > IP 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.

IP 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.

藏色散人
풀어 주다: 2023-04-11 07:22:01
앞으로
3878명이 탐색했습니다.

최근에 요구 사항이 발생했습니다. 내 서버 중 하나가 항상 포트 스캐닝 및 악의적인 로그인 공격을 받기 쉽습니다. 인트라넷 격리, 강화된 비밀번호 인증, 인증서 로그인, 방화벽iptables 설정 외에 온라인에서 사용할 수 있는 다른 솔루션은 없는 것 같습니다. 그런데 저는 요새 호스트 솔루션도 사용합니다.

이러한 솔루션 중 어느 것도 실제로 내 문제를 해결하지 못합니다. 공용 네트워크 서버로 복잡한 네트워크 구조를 갖고 있지 않아 인트라넷 격리가 불가능합니다. 계정의 비밀번호 정책을 조정하는 것이 당연히 해결 방법이지만, 수동 조작이 너무 번거롭고, 컴퓨터를 바꾸는 경우가 많습니다. 비밀번호를 변경하면 회사 컴퓨터와 집 컴퓨터를 모두 업데이트해야 하므로 매우 번거롭습니다. 방화벽 설정은 당연히 운영과 유지관리를 위한 기본 작업이지만 iptables 구성이 너무 번거롭고, ufw가 더 나은 도구이고, firewall-cmd가 더 번거롭고 페인포인트가 큽니다. 우리 모두 알고 있듯이 모든 사람의 아웃바운드 IP 주소 모든 것이 자주 변경됩니다. 마침내 명령줄에서 문자별로 구성했지만 모두 헛되었습니다. Bastion Machine은 주류 솔루션이 아닙니다. Bastion Machine을 사용하면 무료 Bastion Machine에 대해 들어본 적이 없다는 것은 말할 것도 없고 시스템을 마음대로 사용할 수 없습니다. [추천: PHP 비디오 튜토리얼]

어떻게 해야 하나요?

PHP 선배 개발자로서 아직 서버 애플리케이션을 쉽게 사용할 수 없습니다. IP 필터링 시스템 하나로도 쉽게 인트라넷 침투가 가능합니다. 그래서 저는 먼저 IP 필터링을 구현할 수 있습니다. 또한, 화이트리스트에 IP를 쉽게 추가할 수 있습니다. 예를 들어 웹 페이지를 방문하면 자동으로 추가됩니다. 화이트리스트.

전체 프로젝트는 최소한 내 요구 사항을 충족하고 여러 기능을 구현했습니다.

    다중 프로세스
  • 동시성 지원
  • 데몬 프로세스
  • 웹 패널을 통해 관리 가능
  • IP
  • 교통 통계
  • 차단 기록
이제 이 시스템을 단계별로 구현해 보겠습니다.

첫 번째 단계는

IP

포트를 수신하고 데이터를 전달하기 위해

PHP를 사용하는 많은 프레임워크가 있습니다. 이를 위해 저는 3 이유로 workerman을 선택했습니다.

    쉬움 Run Stable
  • 간단한 메소드 인터페이스
  • 내장 프로세스 데몬
구체적인 설치 방법은 공식 문서를 참고하세요.

저작권 설명: 이 기사는 원본이며

phpreturn.com(PHPArsenal 공식 웹사이트)에 게시되었습니다. 모든 권리는 phpreturn(PHPArsenal)에 속합니다. 이 사이트는 모든 형태의 재인쇄/를 허용합니다. 인용문은 출처를 함께 표시해야 합니다.

IP 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.

workerman은 사용이 매우 간단합니다. IPforwarding+화이트리스트 필터링을 구현하는 데는 10줄의 코드만 필요합니다.

$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프레임워크를 사용하여 개발하겠습니다. 충분히 간단하고 비교적 완전한 기능을 가지고 있습니다.

IP 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.

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

版权声明:本文由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 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.IP 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.

以上是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操作数据。这样客户端就不需要连接数据库。好处多多。

하지만 이 경우에는 당연히 클라이언트 환경이 안전하지 않다고 생각하기 때문에 권한 인증과 로그인 인증을 수행해야 합니다. 인터페이스를 개발하려면 더 많은 코드를 작성해야 합니다.

요약

이 글은 주로 IP방화벽 구현에 대한 나의 아이디어를 소개합니다. 이러한 기술을 사용하려면 개발자에게 풍부한 웹 사이트 개발 경험이 필요합니다. 이 요구 사항은 높지는 않지만 특정 기준이 있는 기본 네트워크 개발 경험도 필요합니다. Workerman은 매우 간단하지만 WorkermanHTTP이 아닙니다. 이는 일반적인 웹사이트 개발이 아니며 특정 학습과 사고의 변화가 필요합니다. 하지만 나에게는 쉽게 운전하는 것이 쉽습니다. 배우고 배포하고 테스트할 다른 ​​솔루션을 찾는다면 직접 개발하는 것보다 빠르지 않을 수 있습니다.

저작권 설명: 이 기사는 원본이며 phpreturn.com(PHPArsenal 공식 웹사이트)에 게시되었습니다. 모든 권리는 phpreturn(PHPArsenal)에 속합니다. 이 사이트는 모든 형태의 재인쇄/를 허용합니다. 인용문은 출처를 함께 표시해야 합니다.

IP화이트리스트를 관리하는 방법 패널을 통해 추가할 수도 있고, 패널 페이지를 방문하여 자동으로 아웃바운드 IPIP를 얻어 화이트리스트에 추가할 수도 있습니다. .

사실 더 좋은 방법이 있는데, rss 서버를 만들고 rss에 가입한 고객의 발신 네트워크 IP를 자동으로 얻어 화이트리스트에 추가하는 것입니다. 그런데 rss를 쓰는 버릇도 없고, 휴대폰에 좋은 rss리더도 없고, IP화이트리스트 업데이트할 때마다 열어보고 싶지도 않아서 나는 이 솔루션을 사용하지 않았습니다.

오픈소스로 만들었습니다. 필요하신 분은 https://gitee.com/augushong/ip-door를 참고해주세요.

More

iptables에 비해 이 시스템은 단순한 요새 머신과 동등한 더욱 편리한 IP 화이트리스트 관리 경험을 제공합니다. 그는 "나"만이 연결할 수 있도록 일부 포트를 숨길 수 있습니다.

예를 들어 ssh 포트를 숨기고 ip액세스 제어를 통해 전달합니다. 또 다른 예는 80 포트를 숨기고 ip 액세스 제어를 통해 전달하는 것입니다.

현재 내 시스템은 여러 포트의 동시 바인딩 및 전달을 구현하지 않았지만 핵심 아이디어는 동일하며 참조로 사용할 수 있습니다.

저작권 설명: 이 기사는 원본이며 phpreturn.com(PHPArsenal 공식 웹사이트)에 게시되었습니다. 모든 권리는 phpreturn(PHPArsenal)에 속합니다. 이 사이트는 모든 형태의 재인쇄/를 허용합니다. 인용문은 출처를 함께 표시해야 합니다.

위 내용은 IP 접근 제어: Nanny 스타일은 PHP로 IP 방화벽을 구현하는 방법을 가르쳐줍니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
php
원천:phpreturn.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿