如何用PHP实现一个IP防火墙
导读:本文共7309字符,通常情况下阅读需要24分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要:这篇“如何用PHP实现一个IP防火墙”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何用PHP实现一个IP防火墙”文章吧。 第一步,首先能够简简单单的过滤IP使用PHP监... ...
目录
(为您整理了一些要点),点击可以直达。这篇“如何用PHP实现一个IP防火墙”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何用PHP实现一个IP防火墙”文章吧。
第一步,首先能够简简单单的过滤IP
使用
运行简单稳定
方法接口简单
内置进程守护
$worker=newWorker('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();//拦截IPif(!in_array($remote_ip,$list_ip)){$connection->close();}//放行连接,连接内部目标端口$to_connection=newAsyncTcpConnection('tcp:127.0.0.1:'.Config::get('door.port_to'));//互相转发流量$connection->pipe($to_connection);$to_connection->pipe($connection);$to_connection->connect();}
正如上面代码所示,只有简单几行,便实现了
第二步,与ThinkPHP 命令行整合在一起
为了项目开发方便,我都会使用
最终实现的命令行效果如下:
运行命令phpthinkdoorstartphpthinkdoorstart--moded//守护进程重启重启phpthinkdoorrestart停止phpthinkdoorstop
<?phpdeclare(strict_types=1);namespaceapp\common\command;usethink\console\Command;usethink\console\Input;usethink\console\input\Argument;usethink\console\input\Option;usethink\console\Output;classDoorextendsCommand{protectedfunctionconfigure(){//指令配置$this->setName('door')//设置think的命令参数->addArgument('action',Argument::OPTIONAL,"start|stop|restart|reload|status|connections",'start')->addOption('mode','m',Option::VALUE_OPTIONAL,'Runtheworkermanserverindaemonmode.')->setDescription('thedoorcommand');}protectedfunctionexecute(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';}elseif($mode=='g'){$argv[]='-g';}//...workerman的代码}}
在上面的代码中,主要做了两件事:
实现
ThinkPHP 的命令设置
将命令参数重新构造为
workerman 兼容的方式
第三步,实现管理面板
使用
最终效果如下:
第四步,进阶,更好的性能和流量统计
我们的
流量统计
首先我们将第一个步中,流量转发部分的代码改造成如下的样子:
<?php//向TO发起连接$to_connection=newAsyncTcpConnection('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=newAsyncTcpConnection('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=newWorker();$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_ipas$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();}}});};
他做的事情很简单,读取缓存,更新数据到数据库,并且更新
下一步,更好的性能设计
以上,只有几行代码,几个小时(如果不含设计系统的时间,代码量可能只有一两个小时
更好的内存驱动
这里使用的是
版权声明:本文由phpreturn.com(
但是使用内存缓存,
但实际上,
更好的客户端
目前拦截
实际上,我们可以将客户端的代码,另外开一个项目,使客户端和面板独立开。在面板上实现通用得
但是这样也带来的更多的工作量,这种情况下,我们自然而然的认为客户端的环境不安全,所以要做权限认证,登录认证。接口开发也要写更多的代码。
以上就是关于“如何用PHP实现一个IP防火墙”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
如何用PHP实现一个IP防火墙的详细内容,希望对您有所帮助,信息来源于网络。