diff --git a/app/Protocols/SingBox.php b/app/Protocols/SingBox.php index 228c214b3..a4ac306ed 100644 --- a/app/Protocols/SingBox.php +++ b/app/Protocols/SingBox.php @@ -1,8 +1,7 @@ buildOutbounds(); $config['outbounds'] = $outbounds; - return response($config, 200); + return json_encode($config); + //return response($config, 200); } protected function loadConfig() @@ -55,17 +55,35 @@ protected function buildOutbounds() $outbounds[] = &$selector; foreach ($this->servers as $item) { + if ($item['type'] === 'shadowsocks') { + $ssConfig = $this->buildShadowsocks($this->user['uuid'], $item); + $outbounds[] = $ssConfig; + $selector['outbounds'][] = $item['name']; + $urltest['outbounds'][] = $item['name']; + } + if ($item['type'] === 'trojan') { + $trojanConfig = $this->buildTrojan($this->user['uuid'], $item); + $outbounds[] = $trojanConfig; + $selector['outbounds'][] = $item['name']; + $urltest['outbounds'][] = $item['name']; + } + if ($item['type'] === 'vmess') { + $vmessConfig = $this->buildVmess($this->user['uuid'], $item); + $outbounds[] = $vmessConfig; + $selector['outbounds'][] = $item['name']; + $urltest['outbounds'][] = $item['name']; + } if ($item['type'] === 'vless') { $vlessConfig = $this->buildVless($this->user['uuid'], $item); $outbounds[] = $vlessConfig; $selector['outbounds'][] = $item['name']; $urltest['outbounds'][] = $item['name']; - } elseif ($item['type'] === 'hysteria') { + } + if ($item['type'] === 'hysteria') { $hysteriaConfig = $this->buildHysteria($this->user['uuid'], $item, $this->user); $outbounds[] = $hysteriaConfig; - $tag = $item['version'] == 2 ? "Hy2" : "Hy"; - $selector['outbounds'][] = "[$tag]{$item['name']}"; - $urltest['outbounds'][] = "[$tag]{$item['name']}"; + $selector['outbounds'][] = $item['name']; + $urltest['outbounds'][] = $item['name']; } } @@ -77,58 +95,184 @@ protected function buildOutbounds() return $outbounds; } - /** - * Vless订阅 - */ + protected function buildShadowsocks($password, $server) + { + if ($server['cipher'] === '2022-blake3-aes-128-gcm') { + $serverKey = Helper::getServerKey($server['created_at'], 16); + $userKey = Helper::uuidToBase64($password, 16); + $password = "{$serverKey}:{$userKey}"; + } + if ($server['cipher'] === '2022-blake3-aes-256-gcm') { + $serverKey = Helper::getServerKey($server['created_at'], 32); + $userKey = Helper::uuidToBase64($password, 32); + $password = "{$serverKey}:{$userKey}"; + } + $array = []; + $array['tag'] = $server['name']; + $array['type'] = 'shadowsocks'; + $array['server'] = $server['host']; + $array['server_port'] = $server['port']; + $array['method'] = $server['cipher']; + $array['password'] = $password; - protected function buildVless($password, $server) + return $array; + } + + + protected function buildVmess($uuid, $server) { - $tlsSettings = $server['tls_settings'] ?? []; - $tlsConfig = []; + $array = []; + $array['tag'] = $server['name']; + $array['type'] = 'vmess'; + $array['server'] = $server['host']; + $array['server_port'] = $server['port']; + $array['uuid'] = $uuid; + $array['security'] = 'auto'; + $array['alter_id'] = 0; + $array['transport']= []; if ($server['tls']) { + $tlsConfig = []; $tlsConfig['enabled'] = true; - - switch ($server['tls']) { - case 1: - $tlsConfig['insecure'] = (bool) ($tlsSettings['allowInsecure'] ?? false); - $tlsConfig['server_name'] = $tlsSettings['serverName'] ?? null; - break; - - case 2: - $tlsConfig['insecure'] = (bool) ($tlsSettings['allowInsecure'] ?? false); - $tlsConfig['server_name'] = $tlsSettings['server_name'] ?? null; - - if ( - isset($tlsSettings['public_key'], $tlsSettings['short_id']) && - !empty($tlsSettings['server_name']) - ) { - $tlsConfig['reality'] = [ - 'enabled' => true, - 'public_key' => $tlsSettings['public_key'], - 'short_id' => $tlsSettings['short_id'] - ]; - - $fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; - $tlsConfig['utls'] = [ - "enabled" => true, - "fingerprint" => $fingerprints[array_rand($fingerprints)] - ]; - } - break; + if ($server['tlsSettings']) { + $tlsSettings = $server['tlsSettings'] ?? []; + $tlsConfig['insecure'] = $tlsSettings['allowInsecure'] ? true : false; + $tlsConfig['server_name'] = $tlsSettings['serverName'] ?? null; + } + $array['tls'] = $tlsConfig; + } + if ($server['network'] === 'tcp') { + $tcpSettings = $server['networkSettings']; + if (isset($tcpSettings['header']['type']) && $tcpSettings['header']['type'] == 'http') $array['transport']['type'] = $tcpSettings['header']['type']; + if (isset($tcpSettings['header']['request']['path'])) $array['transport']['path'] = $tcpSettings['header']['request']['path']; + } + if ($server['network'] === 'ws') { + $array['transport']['type'] ='ws'; + if ($server['networkSettings']) { + $wsSettings = $server['networkSettings']; + if (isset($wsSettings['path']) && !empty($wsSettings['path'])) $array['transport']['path'] = $wsSettings['path']; + if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host'])) $array['transport']['headers'] = ['Host' => array($wsSettings['headers']['Host'])]; + $array['transport']['max_early_data'] = 2048; + $array['transport']['early_data_header_name'] = 'Sec-WebSocket-Protocol'; + } + } + if ($server['network'] === 'grpc') { + $array['transport']['type'] ='grpc'; + if ($server['networkSettings']) { + $grpcSettings = $server['networkSettings']; + if (isset($grpcSettings['serviceName'])) $array['transport']['service_name'] = $grpcSettings['serviceName']; } } - return [ + return $array; + } + + protected function buildVless($password, $server) + { + $array = [ "type" => "vless", "tag" => $server['name'], "server" => $server['host'], "server_port" => $server['port'], "uuid" => $password, - "flow" => $server['flow'], - "packet_encoding" => "xudp", - "tls" => $tlsConfig + "packet_encoding" => "xudp" ]; + + $tlsSettings = $server['tls_settings'] ?? []; + + if ($server['tls']) { + $tlsConfig = []; + $tlsConfig['enabled'] = true; + $array['flow'] = !empty($server['flow']) ? $server['flow'] : ""; + $tlsSettings = $server['tls_settings'] ?? []; + if ($server['tls_settings']) { + $tlsConfig['insecure'] = isset($tlsSettings['allow_insecure']) && $tlsSettings['allow_insecure'] == 1 ? true : false; + $tlsConfig['server_name'] = $tlsSettings['server_name'] ?? null; + if ($server['tls'] == 2) { + $tlsConfig['reality'] = [ + 'enabled' => true, + 'public_key' => $tlsSettings['public_key'], + 'short_id' => $tlsSettings['short_id'] + ]; + } + $fingerprints = ['chrome', 'firefox', 'safari', 'ios', 'edge', 'qq']; + $tlsConfig['utls'] = [ + "enabled" => true, + "fingerprint" => $fingerprints[array_rand($fingerprints)] + ]; + } + $array['tls'] = $tlsConfig; + } + + if ($server['network'] === 'tcp') { + $tcpSettings = $server['network_settings']; + if (isset($tcpSettings['header']['type']) && $tcpSettings['header']['type'] == 'http') $array['transport']['type'] = $tcpSettings['header']['type']; + if (isset($tcpSettings['header']['request']['path'])) $array['transport']['path'] = $tcpSettings['header']['request']['path']; + } + if ($server['network'] === 'ws') { + $array['transport']['type'] ='ws'; + if ($server['network_settings']) { + $wsSettings = $server['network_settings']; + if (isset($wsSettings['path']) && !empty($wsSettings['path'])) $array['transport']['path'] = $wsSettings['path']; + if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host'])) $array['transport']['headers'] = ['Host' => array($wsSettings['headers']['Host'])]; + $array['transport']['max_early_data'] = 2048; + $array['transport']['early_data_header_name'] = 'Sec-WebSocket-Protocol'; + } + } + if ($server['network'] === 'grpc') { + $array['transport']['type'] ='grpc'; + if ($server['network_settings']) { + $grpcSettings = $server['network_settings']; + if (isset($grpcSettings['serviceName'])) $array['transport']['service_name'] = $grpcSettings['serviceName']; + } + } + if ($server['network'] === 'h2') { + $array['transport']['type'] = 'http'; + if ($server['network_settings']) { + $h2Settings = $server['network_settings']; + if (isset($h2Settings['host'])) $array['transport']['host'] = array($h2Settings['host']); + if (isset($h2Settings['path'])) $array['transport']['path'] = $h2Settings['path']; + } + } + + return $array; + } + + protected function buildTrojan($password, $server) + { + $array = []; + $array['tag'] = $server['name']; + $array['type'] = 'trojan'; + $array['server'] = $server['host']; + $array['server_port'] = $server['port']; + $array['password'] = $password; + + $array['tls'] = [ + 'enabled' => true, + 'insecure' => $server['allow_insecure'] ? true : false, + 'server_name' => $server['server_name'] + ]; + + if(isset($server['network']) && in_array($server['network'], ["grpc", "ws"])){ + $array['transport']['type'] = $server['network']; + // grpc配置 + if($server['network'] === "grpc" && isset($server['network_settings']['serviceName'])) { + $array['transport']['service_name'] = $server['network_settings']['serviceName']; + } + // ws配置 + if($server['network'] === "ws") { + if(isset($server['network_settings']['path'])) { + $array['transport']['path'] = $server['network_settings']['path']; + } + if(isset($server['network_settings']['headers']['Host'])){ + $array['transport']['headers'] = ['Host' => array($server['network_settings']['headers']['Host'])]; + } + $array['transport']['max_early_data'] = 2048; + $array['transport']['early_data_header_name'] = 'Sec-WebSocket-Protocol'; + } + }; + + return $array; } protected function buildHysteria($password, $server, $user) @@ -136,35 +280,34 @@ protected function buildHysteria($password, $server, $user) $array = [ 'server' => $server['host'], 'server_port' => $server['port'], - 'up_mbps' => $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps'], - 'down_mbps' => $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps'], - "tls" => [ - "enabled" => true, + 'tls' => [ + 'enabled' => true, 'insecure' => $server['insecure'] ? true : false, - "server_name" => $server['server_name'] + 'server_name' => $server['server_name'] ] ]; - if ($server['version'] == 1) { + if (is_null($server['version']) || $server['version'] == 1) { $array['auth_str'] = $password; - $array['tag'] = "[Hy]" . $server['name']; + $array['tag'] = $server['name']; $array['type'] = 'hysteria'; - - if ($server['is_obfs']) { - $array['obfs'] = $server['server_key']; + $array['up_mbps'] = $user->speed_limit ? min($server['down_mbps'], $user->speed_limit) : $server['down_mbps']; + $array['down_mbps'] = $user->speed_limit ? min($server['up_mbps'], $user->speed_limit) : $server['up_mbps']; + if (isset($server['obfs']) && isset($server['obfs_password'])) { + $array['obfs'] = $server['obfs_password']; } $array['disable_mtu_discovery'] = true; - $array['tls']['alpn'] = [ServerHysteria::$alpnMap[$server['alpn']]]; + } elseif ($server['version'] == 2) { $array['password'] = $password; - $array['tag'] = "[Hy2]" . $server['name']; + $array['tag'] = $server['name']; $array['type'] = 'hysteria2'; $array['password'] = $password; - if ($server['is_obfs']) { - $array['obfs']['type'] = 'salamander'; - $array['obfs']['password'] = $server['server_key']; + if (isset($server['obfs'])) { + $array['obfs']['type'] = $server['obfs']; + $array['obfs']['password'] = $server['obfs_password']; } }