From d81974d8bc615cc9b1b2c88c1fdc776f0c12ded5 Mon Sep 17 00:00:00 2001 From: xboard Date: Sat, 18 Jan 2025 21:36:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20add=20shadowsockstidalab=E3=80=81trojan?= =?UTF-8?q?tidala=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Server/ShadowsocksTidalabController.php | 65 +++++++++++ .../V1/Server/TrojanTidalabController.php | 108 ++++++++++++++++++ app/Http/Middleware/Server.php | 1 - app/Http/Routes/V1/ServerRoute.php | 15 +++ 4 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/V1/Server/ShadowsocksTidalabController.php create mode 100644 app/Http/Controllers/V1/Server/TrojanTidalabController.php diff --git a/app/Http/Controllers/V1/Server/ShadowsocksTidalabController.php b/app/Http/Controllers/V1/Server/ShadowsocksTidalabController.php new file mode 100644 index 0000000..9566958 --- /dev/null +++ b/app/Http/Controllers/V1/Server/ShadowsocksTidalabController.php @@ -0,0 +1,65 @@ +input('node_info'); + Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_CHECK_AT', $server->id), time(), 3600); + $users = ServerService::getAvailableUsers($server->group_ids); + $result = []; + foreach ($users as $user) { + array_push($result, [ + 'id' => $user->id, + 'port' => $server->server_port, + 'cipher' => $server->cipher, + 'secret' => $user->uuid + ]); + } + $eTag = sha1(json_encode($result)); + if (strpos($request->header('If-None-Match'), $eTag) !== false ) { + return response(null,304); + } + return response([ + 'data' => $result + ])->header('ETag', "\"{$eTag}\""); + } + + // 后端提交数据 + public function submit(Request $request) + { + $server = $request->input('node_info'); + $data = json_decode(request()->getContent(), true); + Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_ONLINE_USER', $server->id), count($data), 3600); + Cache::put(CacheKey::get('SERVER_SHADOWSOCKS_LAST_PUSH_AT', $server->id), time(), 3600); + $userService = new UserService(); + $formatData = []; + + foreach ($data as $item) { + $formatData[$item['user_id']] = [$item['u'], $item['d']]; + } + $userService->trafficFetch($server->toArray(), 'shadowsocks', $formatData); + + return response([ + 'ret' => 1, + 'msg' => 'ok' + ]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/V1/Server/TrojanTidalabController.php b/app/Http/Controllers/V1/Server/TrojanTidalabController.php new file mode 100644 index 0000000..3cd2cbc --- /dev/null +++ b/app/Http/Controllers/V1/Server/TrojanTidalabController.php @@ -0,0 +1,108 @@ +input('node_info'); + if ($server->type !== 'trojan') { + return $this->fail([400, '节点不存在']); + } + Cache::put(CacheKey::get('SERVER_TROJAN_LAST_CHECK_AT', $server->id), time(), 3600); + $users = ServerService::getAvailableUsers($server->group_id); + $result = []; + foreach ($users as $user) { + $user->trojan_user = [ + "password" => $user->uuid, + ]; + unset($user->uuid); + array_push($result, $user); + } + $eTag = sha1(json_encode($result)); + if (strpos($request->header('If-None-Match'), $eTag) !== false) { + return response(null, 304); + } + return response([ + 'msg' => 'ok', + 'data' => $result, + ])->header('ETag', "\"{$eTag}\""); + } + + // 后端提交数据 + public function submit(Request $request) + { + $server = $request->input('node_info'); + if ($server->type !== 'trojan') { + return $this->fail([400, '节点不存在']); + } + $data = json_decode(request()->getContent(), true); + Cache::put(CacheKey::get('SERVER_TROJAN_ONLINE_USER', $server->id), count($data), 3600); + Cache::put(CacheKey::get('SERVER_TROJAN_LAST_PUSH_AT', $server->id), time(), 3600); + $userService = new UserService(); + $formatData = []; + foreach ($data as $item) { + $formatData[$item['user_id']] = [$item['u'], $item['d']]; + } + $userService->trafficFetch($server->toArray(), 'trojan', $formatData); + + return response([ + 'ret' => 1, + 'msg' => 'ok' + ]); + } + + // 后端获取配置 + public function config(Request $request) + { + $server = $request->input('node_info'); + if ($server->type !== 'trojan') { + return $this->fail([400, '节点不存在']); + } + $request->validate([ + 'node_id' => 'required', + 'local_port' => 'required' + ], [ + 'node_id.required' => '节点ID不能为空', + 'local_port.required' => '本地端口不能为空' + ]); + try { + $json = $this->getTrojanConfig($server, $request->input('local_port')); + } catch (\Exception $e) { + \Log::error($e); + return $this->fail([500, '配置获取失败']); + } + + return (json_encode($json, JSON_UNESCAPED_UNICODE)); + } + + private function getTrojanConfig($server, int $localPort) + { + $protocolSettings = $server->protocol_settings; + $json = json_decode(self::TROJAN_CONFIG); + $json->local_port = $server->server_port; + $json->ssl->sni = data_get($protocolSettings, 'server_name', $server->host); + $json->ssl->cert = "/root/.cert/server.crt"; + $json->ssl->key = "/root/.cert/server.key"; + $json->api->api_port = $localPort; + return $json; + } +} \ No newline at end of file diff --git a/app/Http/Middleware/Server.php b/app/Http/Middleware/Server.php index fde0196..5ae86fd 100644 --- a/app/Http/Middleware/Server.php +++ b/app/Http/Middleware/Server.php @@ -41,7 +41,6 @@ class Server ], 'node_id' => 'required', 'node_type' => [ - 'required', 'nullable', function ($attribute, $value, $fail) use ($request) { if (!ServerModel::isValidType($value)) { diff --git a/app/Http/Routes/V1/ServerRoute.php b/app/Http/Routes/V1/ServerRoute.php index 9001825..29973dc 100644 --- a/app/Http/Routes/V1/ServerRoute.php +++ b/app/Http/Routes/V1/ServerRoute.php @@ -24,6 +24,21 @@ class ServerRoute $route->post('alive', [UniProxyController::class, 'alive']); $route->get('alivelist', [UniProxyController::class, 'alivelist']); }); + $router->group([ + 'prefix' => 'ShadowsocksTidalab', + 'middleware' => 'server:shadowsocks' + ], function ($route) { + $route->get('user', [ShadowsocksTidalabController::class, 'user']); + $route->post('submit', [ShadowsocksTidalabController::class, 'submit']); + }); + $router->group([ + 'prefix' => 'TrojanTidalab', + 'middleware' => 'server:trojan' + ], function ($route) { + $route->get('config', [TrojanTidalabController::class, 'config']); + $route->get('user', [TrojanTidalabController::class, 'user']); + $route->post('submit', [TrojanTidalabController::class, 'submit']); + }); }); } }