From 692d466ca53cd97533757829c2853808acaf0177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=94=E5=A7=AC=E6=A1=91?= Date: Sat, 18 Jul 2020 12:27:28 +0800 Subject: [PATCH] =?UTF-8?q?Vnet=E8=AE=A2=E9=98=85=E9=80=82=E9=85=8D+Trojan?= =?UTF-8?q?=E8=AE=A2=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Controller.php | 99 ++- .../Controllers/User/SubscribeController.php | 4 +- app/Http/Controllers/UserController.php | 2 +- .../2020_07_18_032504_create_node_table.php | 73 ++ public/install.php | 824 +++++++++--------- resources/views/admin/node/nodeInfo.blade.php | 12 +- sql/db.sql | 14 +- update.sh | 3 +- 8 files changed, 574 insertions(+), 457 deletions(-) create mode 100644 database/migrations/2020_07_18_032504_create_node_table.php diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 1cb4e9541..561e00fcb 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -139,69 +139,94 @@ public function uploadFile(UploadedFile $file): string { * @return string */ public function getUserNodeInfo($uid, $nodeId, $infoType): string { - $user = User::whereId($uid)->first(); - $node = SsNode::whereId($nodeId)->first(); + $user = User::whereId($uid)->firstOrFail(); + $node = SsNode::whereId($nodeId)->firstOrFail(); $scheme = null; // 获取分组名称 $group = $node->getLevel->name; $host = $node->server?: $node->ip; $data = null; switch($node->type){ + case 2: + // 生成v2ray scheme + if($infoType !== 1){ + // 生成v2ray scheme + $data = $this->v2raySubUrl($node->name, $host, $node->v2_port, $user->vmess_id, $node->v2_alter_id, + $node->v2_net, $node->v2_type, $node->v2_host, $node->v2_path, $node->v2_tls? "tls" : ""); + }else{ + $data = "服务器:".$host.PHP_EOL."IPv6:".($node->ipv6?: "").PHP_EOL."端口:".$node->v2_port.PHP_EOL."加密方式:".$node->v2_method.PHP_EOL."用户ID:".$user->vmess_id.PHP_EOL."额外ID:".$node->v2_alter_id.PHP_EOL."传输协议:".$node->v2_net.PHP_EOL."伪装类型:".$node->v2_type.PHP_EOL."伪装域名:".($node->v2_host?: "").PHP_EOL."路径:".($node->v2_path?: "").PHP_EOL."TLS:".($node->v2_tls? "tls" : "").PHP_EOL; + } + break; + case 3: + if($infoType !== 1){ + $data = $this->trojanSubUrl($user->passwd, $host, $node->port, $node->name); + }else{ + $data = "备注:".$node->name.PHP_EOL."服务器:".$host.PHP_EOL."密码:".$user->passwd.PHP_EOL."端口:".$node->port.PHP_EOL; + } + break; case 1: + case 4: + $protocol = $node->protocol; + $method = $node->method; + $obfs = $node->obfs; if($node->single){ $port = $node->port; - $protocol = $node->protocol; - $method = $node->method; - $obfs = $node->obfs; $passwd = $node->passwd; $protocol_param = $user->port.':'.$user->passwd; }else{ $port = $user->port; - $protocol = $user->protocol; - $method = $user->method; - $obfs = $user->obfs; $passwd = $user->passwd; $protocol_param = $node->protocol_param; + if($node->type === 1){ + $protocol = $user->protocol; + $method = $user->method; + $obfs = $user->obfs; + } } - if($infoType != 1){ + if($infoType !== 1){ // 生成ss/ssr scheme - if($node->compatible){ - $data = 'ss://'.base64url_encode($method.':'.$passwd.'@'.$host.':'.$port).'#'.$group; - }else{ - $data = 'ssr://'.base64url_encode($host.':'.$port.':'.$protocol.':'.$method.':'.$obfs.':'.base64url_encode($passwd).'/?obfsparam='.base64url_encode($node->obfs_param).'&protoparam='.base64url_encode($protocol_param).'&remarks='.base64url_encode($node->name).'&group='.base64url_encode($group).'&udpport=0&uot=0'); - } + $data = $node->compatible? $this->ssSubUrl($host, $port, $method, $passwd, + $group) : $this->ssrSubUrl($host, $port, $protocol, $method, $obfs, $passwd, $node->obfs_param, + $protocol_param, $node->name, $group, $node->is_udp); }else{ // 生成文本配置信息 $data = "服务器:".$host.PHP_EOL."IPv6:".$node->ipv6.PHP_EOL."服务器端口:".$port.PHP_EOL."密码:".$passwd.PHP_EOL."加密:".$method.PHP_EOL.($node->compatible? '' : "协议:".$protocol.PHP_EOL."协议参数:".$protocol_param.PHP_EOL."混淆:".$obfs.PHP_EOL."混淆参数:".$node->obfs_param.PHP_EOL); } break; - case 2: - // 生成v2ray scheme - if($infoType != 1){ - // 生成v2ray scheme - $data = 'vmess://'.base64url_encode(json_encode([ - "v" => "2", - "ps" => $node->name, - "add" => $host, - "port" => $node->v2_port, - "id" => $user->vmess_id, - "aid" => $node->v2_alter_id, - "net" => $node->v2_net, - "type" => $node->v2_type, - "host" => $node->v2_host, - "path" => $node->v2_path, - "tls" => $node->v2_tls? "tls" : "" - ], JSON_PRETTY_PRINT)); - }else{ - $data = "服务器:".$host.PHP_EOL."IPv6:".($node->ipv6?: "").PHP_EOL."端口:".$node->v2_port.PHP_EOL."加密方式:".$node->v2_method.PHP_EOL."用户ID:".$user->vmess_id.PHP_EOL."额外ID:".$node->v2_alter_id.PHP_EOL."传输协议:".$node->v2_net.PHP_EOL."伪装类型:".$node->v2_type.PHP_EOL."伪装域名:".($node->v2_host?: "").PHP_EOL."路径:".($node->v2_path?: "").PHP_EOL."TLS:".($node->v2_tls? "tls" : "").PHP_EOL; - } - break; - case 3: - break; default: } return $data; } + + public function v2raySubUrl($name, $host, $port, $uuid, $alter_id, $net, $type, $domain, $path, $tls): string { + return 'vmess://'.base64url_encode(json_encode([ + "v" => "2", + "ps" => $name, + "add" => $host, + "port" => $port, + "id" => $uuid, + "aid" => $alter_id, + "net" => $net, + "type" => $type, + "host" => $domain, + "path" => $path, + "tls" => $tls? "tls" : "" + ], JSON_PRETTY_PRINT)); + } + + public function trojanSubUrl($password, $domain, $port, $remark): string { + return 'trojan://'.urlencode($password).'@'.$domain.':'.$port.'#'.urlencode($remark); + } + + public function ssSubUrl($host, $port, $method, $passwd, $group): string { + return 'ss://'.base64url_encode($method.':'.$passwd.'@'.$host.':'.$port).'#'.$group; + } + + public function ssrSubUrl( + $host, $port, $protocol, $method, $obfs, $passwd, $obfs_param, $protocol_param, $name, $group, $is_udp + ): string { + return 'ssr://'.base64url_encode($host.':'.$port.':'.$protocol.':'.$method.':'.$obfs.':'.base64url_encode($passwd).'/?obfsparam='.base64url_encode($obfs_param).'&protoparam='.base64url_encode($protocol_param).'&remarks='.base64url_encode($name).'&group='.base64url_encode($group).'&udpport='.$is_udp.'&uot=0'); + } } diff --git a/app/Http/Controllers/User/SubscribeController.php b/app/Http/Controllers/User/SubscribeController.php index 214c28803..f622b0c2a 100644 --- a/app/Http/Controllers/User/SubscribeController.php +++ b/app/Http/Controllers/User/SubscribeController.php @@ -73,7 +73,9 @@ public function getSubscribeByCode(Request $request, $code) { // 获取这个账号可用节点 $query = SsNode::query()->whereStatus(1)->whereIsSubscribe(1)->where('level', '<=', $user->level); - if($this->subType){ + if($this->subType === 1){ + $query = $query->whereIn('type', [1, 4]); + }elseif($this->subType){ $query = $query->whereType($this->subType); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 68d87943c..da82754f5 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -588,7 +588,7 @@ public function buy($goods_id) { public function help(): \Illuminate\Http\Response { //$view['articleList'] = Article::type(1)->orderByDesc('sort')->orderByDesc('id')->limit(10)->paginate(5); $data = []; - if(SsNode::query()->whereType(1)->whereStatus(1)->exists()){ + if(SsNode::query()->whereIn('type',[1,4])->whereStatus(1)->exists()){ $data[] = 'ss'; //array_push } diff --git a/database/migrations/2020_07_18_032504_create_node_table.php b/database/migrations/2020_07_18_032504_create_node_table.php new file mode 100644 index 000000000..08cac50d2 --- /dev/null +++ b/database/migrations/2020_07_18_032504_create_node_table.php @@ -0,0 +1,73 @@ +bigIncrements('id'); + $table->unsignedTinyInteger('type')->default(1)->comment('服务类型:1-Shadowsocks(R)、2-V2ray、3-Trojan、4-VNet'); + $table->string('name', 128)->comment('名称'); + $table->char('country_code', 5)->default('un')->comment('国家代码'); + $table->string('server')->nullable()->comment('服务器域名地址'); + $table->char('ip', 15)->nullable()->comment('服务器IPV4地址'); + $table->ipAddress('ipv6')->nullable()->comment('服务器IPV6地址'); + $table->string('relay_server')->nullable()->comment('中转地址'); + $table->unsignedSmallInteger('relay_port')->nullable()->default(0)->comment('中转端口'); + $table->unsignedTinyInteger('level')->default(0)->comment('等级:0-无等级,全部可见'); + $table->unsignedBigInteger('speed_limit')->default(0)->comment('节点限速,为0表示不限速,单位Byte'); + $table->unsignedSmallInteger('client_limit')->default(0)->comment('设备数限制'); + $table->string('description')->nullable()->comment('节点简单描述'); + $table->string('method', 32)->default('aes-256-cfb')->comment('加密方式'); + $table->string('protocol', 64)->default('origin')->comment('协议'); + $table->string('protocol_param', 128)->nullable()->comment('协议参数'); + $table->string('obfs', 64)->default('plain')->comment('混淆'); + $table->string('obfs_param')->nullable()->comment('混淆参数'); + $table->unsignedDecimal('traffic_rate', 6)->default(1.00)->comment('流量比率'); + $table->boolean('is_subscribe')->default(1)->comment('是否允许用户订阅该节点:0-否、1-是'); + $table->boolean('is_ddns')->default(0)->comment('是否使用DDNS:0-否、1-是'); + $table->boolean('is_relay')->default(0)->comment('是否中转节点:0-否、1-是'); + $table->boolean('is_udp')->default(1)->comment('是否启用UDP:0-不启用、1-启用'); + $table->unsignedSmallInteger('push_port')->default(0)->comment('消息推送端口'); + $table->boolean('detection_type')->default(1)->comment('节点检测: 0-关闭、1-只检测TCP、2-只检测ICMP、3-检测全部'); + $table->boolean('compatible')->default(0)->comment('兼容SS'); + $table->boolean('single')->default(0)->comment('启用单端口功能:0-否、1-是'); + $table->unsignedSmallInteger('port')->nullable()->comment('单端口的端口号或连接端口号'); + $table->string('passwd')->nullable()->comment('单端口的连接密码'); + $table->unsignedTinyInteger('sort')->default(0)->comment('排序值,值越大越靠前显示'); + $table->boolean('status')->default(1)->comment('状态:0-维护、1-正常'); + $table->unsignedSmallInteger('v2_alter_id')->default(16)->comment('V2Ray额外ID'); + $table->unsignedSmallInteger('v2_port')->default(0)->comment('V2Ray服务端口'); + $table->string('v2_method', 32)->default('aes-128-gcm')->comment('V2Ray加密方式'); + $table->string('v2_net', 16)->default('tcp')->comment('V2Ray传输协议'); + $table->string('v2_type', 32)->default('none')->comment('V2Ray伪装类型'); + $table->string('v2_host')->comment('V2Ray伪装的域名'); + $table->string('v2_path')->comment('V2Ray的WS/H2路径'); + $table->boolean('v2_tls')->default(0)->comment('V2Ray后端TLS:0-未开启、1-开启'); + $table->text('tls_provider')->nullable()->comment('V2Ray节点的TLS提供商授权信息'); + $table->timestamps(); + $table->index('is_subscribe', 'idx_sub'); + $table->engine = 'InnoDB'; + $table->charset = 'utf8mb4'; + $table->collation = 'utf8mb4_unicode_ci'; + }); + + DB::statement("ALTER TABLE `node` comment '节点信息表'"); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() { + Schema::dropIfExists('node'); + } +} diff --git a/public/install.php b/public/install.php index e9f223adc..4a42067ce 100644 --- a/public/install.php +++ b/public/install.php @@ -1,6 +1,6 @@ $elem) { - $content .= "[" . $key . "]\n"; - foreach ($elem as $key2 => $elem2) { - if (is_array($elem2)) { - for ($i = 0; $i < count($elem2); $i++) { - $content .= $key2 . "[] = \"" . $elem2[$i] . "\"\n"; - } - } elseif ($elem2 == "") - $content .= $key2 . " = \n"; - else - $content .= $key2 . " = \"" . $elem2 . "\"\n"; - } - } - } else { - foreach ($assoc_arr as $key => $elem) { - if (is_array($elem)) { - for ($i = 0; $i < count($elem); $i++) { - $content .= $key . "[] = \"" . $elem[$i] . "\"\n"; - } - } elseif ($elem == "") - $content .= $key . " = \n"; - else - $content .= $key . " = \"" . $elem . "\"\n"; - } - } - - if (!$handle = fopen($path, 'w')) { - return false; - } - - if (!fwrite($handle, $content)) { - return false; - } - - fclose($handle); - - return true; +function write_ini_file($assoc_arr, $path, $has_sections = false) { + $content = ""; + if($has_sections){ + foreach($assoc_arr as $key => $elem){ + $content .= "[".$key."]\n"; + foreach($elem as $key2 => $elem2){ + if(is_array($elem2)){ + for($i = 0; $i < count($elem2); $i++){ + $content .= $key2."[] = \"".$elem2[$i]."\"\n"; + } + }elseif($elem2 == ""){ + $content .= $key2." = \n"; + }else{ + $content .= $key2." = \"".$elem2."\"\n"; + } + } + } + }else{ + foreach($assoc_arr as $key => $elem){ + if(is_array($elem)){ + for($i = 0; $i < count($elem); $i++){ + $content .= $key."[] = \"".$elem[$i]."\"\n"; + } + }elseif($elem == ""){ + $content .= $key." = \n"; + }else{ + $content .= $key." = \"".$elem."\"\n"; + } + } + } + + if(!$handle = fopen($path, 'w')){ + return false; + } + + if(!fwrite($handle, $content)){ + return false; + } + + fclose($handle); + + return true; } $sitename = "OtakuCloud"; // 检测目录是否存在 $checkDirs = [ - 'vendor', + 'vendor', ]; // 错误信息 $errInfo = ''; // 数据库配置文件 -$ConfigFile = ROOT_PATH . '.env'; +$ConfigFile = ROOT_PATH.'.env'; // 数据库标准配置文件 -$exampleConfigFile = ROOT_PATH . '.env.example'; +$exampleConfigFile = ROOT_PATH.'.env.example'; // 锁定的文件 -$lockFile = ROOT_PATH . '.env'; -if (is_file($lockFile)) { - $errInfo = "当前已经安装{$sitename},如果需要重新安装,请手动移除.env文件"; -} elseif (version_compare(PHP_VERSION, '7.1.3', '<')) { - $errInfo = "当前PHP版本(" . PHP_VERSION . ")过低,请使用PHP7.1.3及以上版本"; -} elseif (!is_file($exampleConfigFile)) { - $errInfo = "缺失标准配置文件.env.example"; -} elseif (!extension_loaded("PDO")) { - $errInfo = "当前PHP环境未启用PDO组件,无法进行安装"; -} elseif (!is_really_writable(ROOT_PATH)) { - $open_basedir = ini_get('open_basedir'); - if ($open_basedir) { - $dirArr = explode(PATH_SEPARATOR, $open_basedir); - if ($dirArr && in_array(__DIR__, $dirArr)) { - $errInfo = '当前服务器因配置了open_basedir,导致无法读取应用根目录'; - } - } - - if (!$errInfo) { - $errInfo = '权限不足,无法写入配置文件.env'; - } -} else { - $dirArr = []; - foreach ($checkDirs as $k => $v) { - if (!is_dir(ROOT_PATH . $v)) { - $errInfo = '请先在' . $sitename . '根目录下执行 php composer.phar install 安装依赖'; - break; - } - } +$lockFile = ROOT_PATH.'.env'; +if(is_file($lockFile)){ + $errInfo = "当前已经安装{$sitename},如果需要重新安装,请手动移除.env文件"; +}elseif(version_compare(PHP_VERSION, '7.1.3', '<')){ + $errInfo = "当前PHP版本(".PHP_VERSION.")过低,请使用PHP7.1.3及以上版本"; +}elseif(!is_file($exampleConfigFile)){ + $errInfo = "缺失标准配置文件.env.example"; +}elseif(!extension_loaded("PDO")){ + $errInfo = "当前PHP环境未启用PDO组件,无法进行安装"; +}elseif(!is_really_writable(ROOT_PATH)){ + $open_basedir = ini_get('open_basedir'); + if($open_basedir){ + $dirArr = explode(PATH_SEPARATOR, $open_basedir); + if($dirArr && in_array(__DIR__, $dirArr)){ + $errInfo = '当前服务器因配置了open_basedir,导致无法读取应用根目录'; + } + } + + if(!$errInfo){ + $errInfo = '权限不足,无法写入配置文件.env'; + } +}else{ + $dirArr = []; + foreach($checkDirs as $k => $v){ + if(!is_dir(ROOT_PATH.$v)){ + $errInfo = '请先在'.$sitename.'根目录下执行 php composer.phar install 安装依赖'; + break; + } + } } // 当前是POST请求 -if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') { - if ($errInfo) { - echo $errInfo; - exit; - } - - $err = ''; - $APP_KEY = md5(time() . mt_rand(1, 1000000)); - $DB_HOST = isset($_POST['mysqlHost']) ? $_POST['mysqlHost'] : '127.0.0.1'; - $DB_PORT = isset($_POST['mysqlHostport']) ? $_POST['mysqlHostport'] : 3306; - $hostArr = explode(':', $DB_HOST); - if (count($hostArr) > 1) { - $DB_HOST = $hostArr[0]; - $DB_PORT = $hostArr[1]; - } - $DB_USERNAME = isset($_POST['mysqlUsername']) ? $_POST['mysqlUsername'] : 'root'; - $DB_PASSWORD = isset($_POST['mysqlPassword']) ? $_POST['mysqlPassword'] : ''; - $DB_DATABASE = isset($_POST['mysqlDatabase']) ? $_POST['mysqlDatabase'] : 'ssrpanel'; -// $adminUsername = isset($_POST['adminUsername']) ? $_POST['adminUsername'] : 'admin'; -// $adminPassword = isset($_POST['adminPassword']) ? $_POST['adminPassword'] : 'admin'; -// $adminPasswordConfirmation = isset($_POST['adminPasswordConfirmation']) ? $_POST['adminPasswordConfirmation'] : 'admin'; -// $adminEmail = isset($_POST['adminEmail']) ? $_POST['adminEmail'] : 'admin@admin.com'; -// if ($adminPassword !== $adminPasswordConfirmation) { -// echo "两次输入的密码不一致"; -// exit; -// } else if (!preg_match("/^\w+$/", $adminUsername)) { -// echo "用户名只能输入字母、数字、下划线"; -// exit; -// } else if (!preg_match("/^[\S]+$/", $adminPassword)) { -// echo "密码不能包含空格"; -// exit; -// } else if (strlen($adminUsername) < 3 || strlen($adminUsername) > 12) { -// echo "用户名请输入3~12位字符"; -// exit; -// } else if (strlen($adminPassword) < 6 || strlen($adminPassword) > 16 || stripos($adminPassword, ' ') !== false) { -// echo "密码请输入6~16位字符,不能包含空格"; -// exit; -// } - try { - // 检测能否读取安装文件 - $sql = @file_get_contents(INSTALL_PATH . 'db.sql'); - if (!$sql) { - throw new Exception("无法读取所需的sql/db.sql,请检查是否有读权限"); - } - - $pdo = new PDO("mysql:host={$DB_HOST};port={$DB_PORT}", $DB_USERNAME, $DB_PASSWORD, [ - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" - ]); - - // 检测是否支持innodb存储引擎 - $pdoStatement = $pdo->query("SHOW VARIABLES LIKE 'innodb_version'"); - $result = $pdoStatement->fetch(); - if (!$result) { - throw new Exception("当前数据库不支持innodb存储引擎,请开启后再重新尝试安装"); - } - - $pdo->query("CREATE DATABASE IF NOT EXISTS `{$DB_DATABASE}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"); - $pdo->query("USE `{$DB_DATABASE}`"); - $pdo->exec($sql); - - $config = @file_get_contents($exampleConfigFile); - if (!$config) { - throw new Exception("无法写入读取配置.env.example文件,请检查是否有读权限"); - } - - $callback = function ($matches) use ($APP_KEY, $DB_HOST, $DB_PORT, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE) { - $field = $matches[1]; - $replace = ${"{$field}"}; - return "{$matches[1]}={$replace}" . PHP_EOL; - }; - - $config = preg_replace_callback("/(APP_KEY|DB_HOST|DB_DATABASE|DB_USERNAME|DB_PASSWORD|DB_PORT)=(.*)(\s+)/", $callback, $config); - - // 检测能否成功写入数据库配置 - $result = @file_put_contents($ConfigFile, $config); - if (!$result) { - throw new Exception("无法写入数据库信息到.env文件,请检查是否有写权限"); - } - - echo "success"; - } catch (PDOException $e) { - $err = $e->getMessage(); - } catch (Exception $e) { - $err = $e->getMessage(); - } - - echo $err; - exit; +if(isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST'){ + if($errInfo){ + echo $errInfo; + exit; + } + + $err = ''; + $APP_KEY = md5(time().mt_rand(1, 1000000)); + $DB_HOST = isset($_POST['mysqlHost'])? $_POST['mysqlHost'] : '127.0.0.1'; + $DB_PORT = isset($_POST['mysqlHostport'])? $_POST['mysqlHostport'] : 3306; + $hostArr = explode(':', $DB_HOST); + if(count($hostArr) > 1){ + $DB_HOST = $hostArr[0]; + $DB_PORT = $hostArr[1]; + } + $DB_USERNAME = isset($_POST['mysqlUsername'])? $_POST['mysqlUsername'] : 'root'; + $DB_PASSWORD = isset($_POST['mysqlPassword'])? $_POST['mysqlPassword'] : ''; + $DB_DATABASE = isset($_POST['mysqlDatabase'])? $_POST['mysqlDatabase'] : 'proxypanel'; + // $adminUsername = isset($_POST['adminUsername']) ? $_POST['adminUsername'] : 'admin'; + // $adminPassword = isset($_POST['adminPassword']) ? $_POST['adminPassword'] : 'admin'; + // $adminPasswordConfirmation = isset($_POST['adminPasswordConfirmation']) ? $_POST['adminPasswordConfirmation'] : 'admin'; + // $adminEmail = isset($_POST['adminEmail']) ? $_POST['adminEmail'] : 'admin@admin.com'; + // if ($adminPassword !== $adminPasswordConfirmation) { + // echo "两次输入的密码不一致"; + // exit; + // } else if (!preg_match("/^\w+$/", $adminUsername)) { + // echo "用户名只能输入字母、数字、下划线"; + // exit; + // } else if (!preg_match("/^[\S]+$/", $adminPassword)) { + // echo "密码不能包含空格"; + // exit; + // } else if (strlen($adminUsername) < 3 || strlen($adminUsername) > 12) { + // echo "用户名请输入3~12位字符"; + // exit; + // } else if (strlen($adminPassword) < 6 || strlen($adminPassword) > 16 || stripos($adminPassword, ' ') !== false) { + // echo "密码请输入6~16位字符,不能包含空格"; + // exit; + // } + try{ + // 检测能否读取安装文件 + $sql = @file_get_contents(INSTALL_PATH.'db.sql'); + if(!$sql){ + throw new Exception("无法读取所需的sql/db.sql,请检查是否有读权限"); + } + + $pdo = new PDO("mysql:host={$DB_HOST};port={$DB_PORT}", $DB_USERNAME, $DB_PASSWORD, [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" + ]); + + // 检测是否支持innodb存储引擎 + $pdoStatement = $pdo->query("SHOW VARIABLES LIKE 'innodb_version'"); + $result = $pdoStatement->fetch(); + if(!$result){ + throw new Exception("当前数据库不支持innodb存储引擎,请开启后再重新尝试安装"); + } + + $pdo->query("CREATE DATABASE IF NOT EXISTS `{$DB_DATABASE}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"); + $pdo->query("USE `{$DB_DATABASE}`"); + $pdo->exec($sql); + + $config = @file_get_contents($exampleConfigFile); + if(!$config){ + throw new Exception("无法写入读取配置.env.example文件,请检查是否有读权限"); + } + + $callback = function($matches) use ($APP_KEY, $DB_HOST, $DB_PORT, $DB_USERNAME, $DB_PASSWORD, $DB_DATABASE) { + $field = $matches[1]; + $replace = ${"{$field}"}; + return "{$matches[1]}={$replace}".PHP_EOL; + }; + + $config = preg_replace_callback("/(APP_KEY|DB_HOST|DB_DATABASE|DB_USERNAME|DB_PASSWORD|DB_PORT)=(.*)(\s+)/", + $callback, $config); + + // 检测能否成功写入数据库配置 + $result = @file_put_contents($ConfigFile, $config); + if(!$result){ + throw new Exception("无法写入数据库信息到.env文件,请检查是否有写权限"); + } + + echo "success"; + }catch(PDOException $e){ + $err = $e->getMessage(); + }catch(Exception $e){ + $err = $e->getMessage(); + } + + echo $err; + exit; } ?> - - - 安装<?php echo $sitename; ?> - - - - + + + 安装<?php + echo $sitename; ?> + + + +
-

安装

-
-
- -
- -
- - - - -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - - - -
+

安装

+
+
+ +
+ +
+ + + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + +
diff --git a/resources/views/admin/node/nodeInfo.blade.php b/resources/views/admin/node/nodeInfo.blade.php index 32835585b..f387c5d95 100644 --- a/resources/views/admin/node/nodeInfo.blade.php +++ b/resources/views/admin/node/nodeInfo.blade.php @@ -139,7 +139,7 @@ class="col-md-5 form-control" name="country_code" id="country_code">
  • - +
  • @@ -154,6 +154,12 @@ class="col-md-5 form-control" name="country_code" id="country_code">
  • +
  • +
    + + +
    +

  • @@ -469,6 +475,7 @@ class="col-md-5 form-control" name="country_code" id="country_code"> $('.obfs_param').hide(); } }); + // ajax同步提交 function Submit() { $.ajax({ @@ -596,6 +603,9 @@ function switchSetting(id) { case 3: $trojan_setting.show(); break; + case 4: + $ssr_setting.show(); + break; default: } }); diff --git a/sql/db.sql b/sql/db.sql index d4991c592..80097f356 100644 --- a/sql/db.sql +++ b/sql/db.sql @@ -26,12 +26,12 @@ CREATE TABLE `ss_node` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' COMMENT '服务类型:1-ShadowsocksR、2-V2ray', + `type` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' COMMENT '服务类型:1-Shadowsocks(R)、2-V2ray、3-Trojan、4-VNet', `name` VARCHAR(128) NOT NULL DEFAULT '' COMMENT '名称', `country_code` CHAR(5) NOT NULL DEFAULT 'un' COMMENT '国家代码', `server` VARCHAR(255) NULL DEFAULT NULL COMMENT '服务器域名地址', `ip` CHAR(15) NULL DEFAULT NULL COMMENT '服务器IPV4地址', - `ipv6` VARCHAR(128) NULL DEFAULT NULL COMMENT '服务器IPV6地址', + `ipv6` VARCHAR(45) NULL DEFAULT NULL COMMENT '服务器IPV6地址', `relay_server` VARCHAR(255) NULL DEFAULT NULL COMMENT '中转地址', `relay_port` SMALLINT(5) UNSIGNED NULL DEFAULT 0 COMMENT '中转端口', `level` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '等级:0-无等级,全部可见', @@ -63,7 +63,7 @@ CREATE TABLE `ss_node` `v2_type` VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT 'V2Ray伪装类型', `v2_host` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'V2Ray伪装的域名', `v2_path` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'V2Ray的WS/H2路径', - `v2_tls` BIT NOT NULL DEFAULT 0 COMMENT 'V2Ray后端TLS:0-未开启、1-开启', + `v2_tls` BIT NOT NULL DEFAULT 0 COMMENT 'V2Ray连接TLS:0-未开启、1-开启', `tls_provider` TEXT NULL DEFAULT NULL COMMENT 'V2Ray节点的TLS提供商授权信息', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, @@ -141,12 +141,12 @@ CREATE TABLE `user` `password` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '密码', `port` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' COMMENT '代理端口', `passwd` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '代理密码', - `vmess_id` VARCHAR(64) NOT NULL DEFAULT '', + `vmess_id` CHAR(36) NOT NULL DEFAULT '', `transfer_enable` BIGINT(20) UNSIGNED NOT NULL DEFAULT '1099511627776' COMMENT '可用流量,单位字节,默认1TiB', `u` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '已上传流量,单位字节', `d` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' COMMENT '已下载流量,单位字节', `t` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '最后使用时间', - `ip` CHAR(128) DEFAULT NULL COMMENT '最后连接IP', + `ip` CHAR(15) DEFAULT NULL COMMENT '最后连接IP', `enable` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '代理状态', `method` VARCHAR(30) NOT NULL DEFAULT 'aes-256-cfb' COMMENT '加密方式', `protocol` VARCHAR(30) NOT NULL DEFAULT 'origin' COMMENT '协议', @@ -976,7 +976,7 @@ CREATE TABLE `user_subscribe_log` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `sid` INT(10) UNSIGNED DEFAULT NULL COMMENT '对应user_subscribe的id', - `request_ip` CHAR(128) DEFAULT NULL COMMENT '请求IP', + `request_ip` CHAR(45) DEFAULT NULL COMMENT '请求IP', `request_time` DATETIME DEFAULT NULL COMMENT '请求时间', `request_header` TEXT COMMENT '请求头部信息', PRIMARY KEY (`id`), @@ -1210,7 +1210,7 @@ CREATE TABLE `user_login_log` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', - `ip` VARCHAR(128) NOT NULL, + `ip` VARCHAR(45) NOT NULL, `country` VARCHAR(128) NOT NULL, `province` VARCHAR(128) NOT NULL, `city` VARCHAR(128) NOT NULL, diff --git a/update.sh b/update.sh index f85da3256..d083ee0c2 100644 --- a/update.sh +++ b/update.sh @@ -5,6 +5,5 @@ git pull php composer.phar install php artisan key:generate php artisan view:clear -php artisan route:cache -php artisan config:cache +php artisan optimize chown -R www:www ./ \ No newline at end of file