# proxyAdmin **Repository Path**: oywb33/proxy-admin ## Basic Information - **Project Name**: proxyAdmin - **Description**: php实现的反向代理管家系统 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-11-11 - **Last Updated**: 2025-11-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Webman 多规则反向代理系统 ## 项目简介 基于 Webman 框架开发的高性能反向代理系统,支持按**域名、路径、IP、端口**多维度匹配转发规则,适配中小规模服务的代理需求,可快速集成业务逻辑(如权限校验、日志记录),兼顾灵活性与性能。 ## 核心特性 - 多维度匹配:支持域名(含通配符)、路径前缀、客户端IP、服务器端口匹配,支持多条件组合 - 高性能转发:基于 Swoole 协程 + Guzzle 连接池,低延迟、高并发,资源占用低 - 实用功能:自动转发客户端IP(X-Forwarded-For/X-Real-IP)、超时控制、规则灵活开关 - 易扩展:配置驱动设计,新增/修改代理规则无需改动代码 - 兼容友好:支持 HTTP/HTTPS 目标服务,适配 Webman 生态 ## 技术栈 - 核心框架:Webman ^1.5(基于 Swoole ^4.8) - HTTP 客户端:Guzzle ^7.0 - 运行环境:PHP ^7.4 || ^8.0,Swoole ^4.8(启用协程) ## 快速开始 ### 1. 环境准备 - 安装 PHP 7.4+(推荐 8.0+) - 安装 Swoole 扩展(启用协程、OpenSSL 支持): ```bash pecl install swoole-4.8.13 ``` - 安装 Composer(依赖管理工具) ### 2. 项目部署 ```bash # 克隆项目(或下载源码) git clone <项目仓库地址> cd webman-proxy # 安装依赖(含 Webman、Guzzle) composer install --no-dev ``` ### 3. 配置代理规则 修改 `config/proxy.php` 配置文件,添加自定义代理规则: ```php return [ 'rules' => [ // 示例1:按域名代理 [ 'match' => ['domain' => 'api.example.com'], 'target' => 'http://192.168.1.100:8080', 'enable' => true ], // 示例2:按路径代理 [ 'match' => ['path' => '/admin/*'], 'target' => 'http://192.168.1.101:9000', 'enable' => true ], // 示例3:按IP段代理 [ 'match' => ['ip' => '10.0.0.*'], 'target' => 'http://192.168.1.102:8000', 'enable' => true ], // 示例4:多条件组合(域名+路径) [ 'match' => ['domain' => 'pay.example.com', 'path' => '/v2/*'], 'target' => 'http://192.168.1.103:6000', 'enable' => true ] ], 'timeout' => 5, // 代理超时时间(秒) 'forward_client_ip' => true, // 是否转发客户端IP 'default_target' => null // 未匹配规则时默认转发目标(null为不代理) ]; ``` ### 4. 启动服务 ```bash # 开发环境(带调试) php start.php start # 生产环境(后台运行) php start.php start -d # 停止服务 php start.php stop # 重启服务 php start.php restart # 查看服务状态 php start.php status ``` ### 5. 验证代理 访问配置的匹配地址,例如: - 访问 `http://api.example.com/user` → 转发到 `http://192.168.1.100:8080/user` - 访问 `http://localhost/admin/login` → 转发到 `http://192.168.1.101:9000/admin/login` - 从 IP `10.0.0.5` 访问 `http://localhost` → 转发到 `http://192.168.1.102:8000` ## 详细配置说明 ### 代理规则配置(config/proxy.php) | 配置项 | 说明 | |-----------------|----------------------------------------------------------------------| | `rules` | 代理规则数组,按顺序匹配(先定义的规则优先) | | `rules[].match` | 匹配条件,支持 `domain`(域名)、`path`(路径)、`ip`(客户端IP)、`port`(服务器端口) | | `rules[].target`| 目标服务地址(如 `http://192.168.1.100:8080`),末尾不要带 `/` | | `rules[].enable`| 是否启用该规则(`true`/`false`) | | `timeout` | 代理请求超时时间(秒),默认 5 秒 | | `forward_client_ip` | 是否转发客户端真实IP(添加 X-Forwarded-For/X-Real-IP 头),默认 true | | `default_target`| 未匹配任何规则时的默认转发目标(`null` 表示不代理,直接放行请求) | ### 匹配规则说明 - 通配符支持:域名、IP 可使用 `*` 通配符(如 `*.example.com`、`192.168.*.*`) - 路径匹配:按前缀匹配(如 `/admin/*` 匹配 `/admin/user`、`/admin/order/list`) - 多条件组合:`match` 中配置多个条件时,需同时满足才会触发代理 - 端口匹配:匹配服务器监听的端口(如配置 `port: 8081`,则访问 `http://localhost:8081` 时触发代理) ## 扩展与定制 ### 1. 新增匹配维度(如请求方法) 修改 `app/middleware/ProxyMiddleware.php` 扩展匹配逻辑: ```php // 1. 在 getRequestInfo 方法中添加请求方法字段 private function getRequestInfo(Request $request): array { return [ 'domain' => $request->host(), 'path' => $request->path(), 'ip' => $request->getRealIp(), 'port' => $request->connection->getLocalPort(), 'method' => $request->method() // 新增:请求方法(GET/POST/PUT/DELETE) ]; } // 2. 在 matchCondition 方法中添加请求方法匹配逻辑 private function matchCondition(string $actual, string $type, $expected): bool { // 转换为字符串比较 $actual = (string)$actual; $expected = (string)$expected; // 处理请求方法匹配(忽略大小写) if ($type === 'method') { return strtoupper($actual) === strtoupper($expected); } // 通配符匹配(如 *.example.com 匹配 a.example.com) if (strpos($expected, '*') !== false) { $pattern = str_replace(['*', '.'], ['[^.]+', '\.'], $expected); return (bool)preg_match("/^{$pattern}$/", $actual); } // 精确匹配 return $actual === $expected; } ``` // 3. 在 config/proxy.php 中使用新匹配维度 ```php 'rules' => [ // 示例:仅允许 POST 方法访问时代理 [ 'match' => ['domain' => 'api.example.com', 'method' => 'POST'], 'target' => 'http://192.168.1.100:8080', 'enable' => true ] ] ``` ### 2. 添加代理日志记录 #### 步骤1:安装日志依赖 ```bash composer require monolog/monolog ``` #### 步骤2:在代理中间件中添加日志逻辑 ```php // app/middleware/ProxyMiddleware.php use Monolog\Logger; use Monolog\Handler\RotatingFileHandler; use Webman\App; private function proxyRequest(Request $request, string $target, array $proxyConfig): Response { // 初始化日志(按日期轮转) $logger = new Logger('proxy'); $logPath = runtime_path() . '/logs/proxy/'; if (!is_dir($logPath)) { mkdir($logPath, 0755, true); } $logger->pushHandler(new RotatingFileHandler($logPath . 'proxy.log', 30)); // 保留30天日志 // 记录请求日志 $requestId = uniqid('proxy_'); $logger->info('Proxy request start', [ 'request_id' => $requestId, 'client_ip' => $request->getRealIp(), 'method' => $request->method(), 'request_uri' => $request->uri(), 'target' => $target, 'timestamp' => date('Y-m-d H:i:s') ]); try { // 原有代理转发逻辑... $response = $this->client->request(...); // 记录响应日志 $logger->info('Proxy request success', [ 'request_id' => $requestId, 'status_code' => $response->getStatusCode(), 'response_time' => round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2) . 'ms' ]); return new Response( $response->getStatusCode(), $response->getHeaders(), $response->getBody()->getContents() ); } catch (\Exception $e) { // 记录错误日志 $logger->error('Proxy request failed', [ 'request_id' => $requestId, 'error_msg' => $e->getMessage(), 'error_trace' => $e->getTraceAsString() ]); return new Response(502, [], "Proxy Error: " . $e->getMessage()); } } ``` ### 3. 支持 HTTPS 目标服务 #### 步骤1:确保 Swoole 启用 OpenSSL 支持 安装 Swoole 时需添加 `--enable-openssl` 编译参数: ```bash pecl install swoole-4.8.13 --enable-openssl ``` #### 步骤2:修改代理配置 在 `proxyRequest` 方法中启用 SSL 验证(生产环境推荐): ```php $response = $this->client->request( $request->method(), $targetUrl, [ 'headers' => $headers, 'body' => $request->rawBody(), 'verify' => true, // 生产环境开启 SSL 证书验证 // 若目标服务使用自签名证书,可指定证书路径 // 'verify' => '/path/to/certificate.pem' ] ); ``` ### 4. 集成权限校验(示例) 在代理前添加权限校验逻辑,例如仅允许指定IP访问代理服务: ```php // app/middleware/ProxyMiddleware.php public function process(Request $request, callable $handler) { // 权限校验:仅允许白名单IP访问代理 $allowIps = ['192.168.1.0/24', '10.0.0.1']; $clientIp = $request->getRealIp(); if (!$this->isIpAllowed($clientIp, $allowIps)) { return new Response(403, [], 'Forbidden: IP not allowed'); } // 后续代理逻辑... } // IP白名单校验(支持IP段) private function isIpAllowed(string $ip, array $allowIps): bool { foreach ($allowIps as $allowIp) { if (strpos($allowIp, '/') === false) { // 精确IP匹配 if ($ip === $allowIp) return true; } else { // IP段匹配(如 192.168.1.0/24) list($subnet, $mask) = explode('/', $allowIp); $ipLong = ip2long($ip); $subnetLong = ip2long($subnet); $maskLong = (0xFFFFFFFF << (32 - $mask)) & 0xFFFFFFFF; if (($ipLong & $maskLong) === ($subnetLong & $maskLong)) { return true; } } } return false; } ``` ## 常见问题 ### 1. 服务启动失败 - 检查端口是否被占用:使用 `netstat -tuln | grep 8080`(替换为你的端口)查看 - 检查 PHP 版本和 Swoole 版本是否满足要求 - 检查依赖是否安装完整:执行 `composer install` 重新安装依赖 ### 2. 代理转发失败(502错误) - 检查目标服务是否正常运行:直接访问 `target` 配置的地址,确认服务可用 - 检查网络连通性:在服务器上执行 `curl 目标服务地址`,确认网络可达 - 查看日志:检查 `runtime/logs/proxy.log` 中的错误信息,定位问题 ### 3. 客户端IP获取错误 - 确保 `forward_client_ip` 配置为 `true` - 若服务部署在反向代理(如 Nginx)后,需在 Nginx 中配置 `X-Real-IP` 和 `X-Forwarded-For` 头: ```nginx proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ``` ### 4. 协程阻塞问题 - 确保 Swoole 配置中 `hook_flags` 设为 `SWOOLE_HOOK_ALL` - 避免使用未被协程化的阻塞函数(如 `sleep()`、`file_get_contents()`),替换为 Swoole 协程版函数 ## 性能优化建议 1. **调整 Swoole 配置**:在 `config/swoole.php` 中优化参数 ```php return [ 'worker_num' => swoole_cpu_num() * 2, // 工作进程数(建议为 CPU 核心数的 2 倍) 'max_coroutine' => 50000, // 每个工作进程最大协程数 'hook_flags' => SWOOLE_HOOK_ALL, // 自动 Hook 所有阻塞操作 'buffer_output_size' => 2 * 1024 * 1024, // 输出缓冲区大小 ]; ``` 2. **复用 HTTP 连接**:Guzzle 客户端启用连接池,减少 TCP 连接建立开销 ```php // 初始化 Guzzle 时添加连接池配置 $this->client = new Client([ 'handler' => $handler, 'timeout' => 5, 'connect_timeout' => 3, 'http_errors' => false, 'headers' => [ 'User-Agent' => 'Webman-Proxy/1.0' ], 'pool_size' => 50, // 连接池大小 'keepalive' => true, // 启用长连接 ]); ``` 3. **关闭不必要的日志**:生产环境关闭调试日志,仅保留错误日志和关键业务日志 4. **使用缓存**:对频繁转发的静态资源或接口响应,添加缓存层(如 Redis),减少转发开销 ## 部署建议 ### 生产环境部署 1. **环境要求**: - 操作系统:Linux(CentOS 7+/Ubuntu 16.04+) - PHP 版本:8.0+(性能更优) - Swoole 版本:4.8+ 或 5.x - 内存:建议 ≥ 2GB(根据并发量调整) 2. **进程守护**:使用 `supervisor` 管理 Webman 进程,确保服务意外退出后自动重启 ```ini ; /etc/supervisor/conf.d/webman-proxy.conf [program:webman-proxy] command=php /path/to/webman-proxy/start.php start -d autostart=true autorestart=true user=www redirect_stderr=true stdout_logfile=/var/log/webman-proxy.log ``` 3. **端口配置**:生产环境建议使用 80/443 端口(需root权限启动),或通过 Nginx 反向代理到 Webman 端口 ```nginx server { listen 80; server_name api.example.com; location / { proxy_pass http://127.0.0.1:8787; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` 4. **SSL 配置**:通过 Nginx 配置 HTTPS 证书,Webman 内部