From 711151c7d6a5d2a8eec6cbe6329f591299f8fd8e Mon Sep 17 00:00:00 2001 From: Fearless Date: Mon, 19 May 2025 09:25:52 +0800 Subject: [PATCH] add anytls support --- .../V1/Client/ClientController.php | 3 +- .../V1/Server/UniProxyController.php | 5 +++ app/Models/Server.php | 25 ++++++++++++ app/Protocols/ClashMeta.php | 22 ++++++++++ app/Protocols/Shadowrocket.php | 40 +++++++++++++++++++ app/Protocols/SingBox.php | 27 +++++++++++++ app/Protocols/Stash.php | 23 ++++++++++- app/Utils/CacheKey.php | 6 ++- 8 files changed, 148 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/V1/Client/ClientController.php b/app/Http/Controllers/V1/Client/ClientController.php index a72463d..f8acd2d 100644 --- a/app/Http/Controllers/V1/Client/ClientController.php +++ b/app/Http/Controllers/V1/Client/ClientController.php @@ -28,6 +28,7 @@ class ClientController extends Controller 'trojan' => '[trojan]', 'tuic' => '[tuic]', 'socks' => '[socks]', + 'anytls' => '[anytls]' ]; // 支持hy2 的客户端版本列表 @@ -48,7 +49,7 @@ class ClientController extends Controller 'flclash' => '0.8.0' ]; - private const ALLOWED_TYPES = ['vmess', 'vless', 'trojan', 'hysteria', 'shadowsocks', 'hysteria2', 'tuic']; + private const ALLOWED_TYPES = ['vmess', 'vless', 'trojan', 'hysteria', 'shadowsocks', 'hysteria2', 'tuic', 'anytls']; public function subscribe(Request $request) diff --git a/app/Http/Controllers/V1/Server/UniProxyController.php b/app/Http/Controllers/V1/Server/UniProxyController.php index 860199f..bb6bdf3 100644 --- a/app/Http/Controllers/V1/Server/UniProxyController.php +++ b/app/Http/Controllers/V1/Server/UniProxyController.php @@ -147,6 +147,11 @@ class UniProxyController extends Controller 'zero_rtt_handshake' => false, 'heartbeat' => "3s", ], + 'anytls' => [ + 'server_port' => (int) $serverPort, + 'server_name' => $protocolSettings['tls']['server_name'], + 'padding_scheme' => $protocolSettings['padding_scheme'], + ], 'socks' => [ 'server_port' => (int) $serverPort, ], diff --git a/app/Models/Server.php b/app/Models/Server.php index d814f44..3316a7b 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -56,6 +56,7 @@ class Server extends Model public const TYPE_VMESS = 'vmess'; public const TYPE_TUIC = 'tuic'; public const TYPE_SHADOWSOCKS = 'shadowsocks'; + public const TYPE_ANYTLS = 'anytls'; public const TYPE_SOCKS = 'socks'; public const TYPE_NAIVE = 'naive'; public const TYPE_HTTP = 'http'; @@ -93,6 +94,7 @@ class Server extends Model self::TYPE_VMESS, self::TYPE_TUIC, self::TYPE_SHADOWSOCKS, + self::TYPE_ANYTLS, self::TYPE_SOCKS, self::TYPE_NAIVE, self::TYPE_HTTP, @@ -188,6 +190,29 @@ class Server extends Model ] ] ], + self::TYPE_ANYTLS => [ + 'padding_scheme' => [ + 'type' => 'array', + 'default' => [ + "stop=8", + "0=30-30", + "1=100-400", + "2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000", + "3=9-9,500-1000", + "4=500-1000", + "5=500-1000", + "6=500-1000", + "7=500-1000" + ] + ], + 'tls' => [ + 'type' => 'object', + 'fields' => [ + 'server_name' => ['type' => 'string', 'default' => null], + 'allow_insecure' => ['type' => 'boolean', 'default' => false] + ] + ] + ], self::TYPE_SOCKS => [ 'tls' => ['type' => 'integer', 'default' => 0], 'tls_settings' => [ diff --git a/app/Protocols/ClashMeta.php b/app/Protocols/ClashMeta.php index 8d4d636..5495134 100644 --- a/app/Protocols/ClashMeta.php +++ b/app/Protocols/ClashMeta.php @@ -80,6 +80,10 @@ class ClashMeta implements ProtocolInterface array_push($proxy, self::buildTuic($user['uuid'], $item)); array_push($proxies, $item['name']); } + if ($item['type'] === 'anytls'){ + array_push($proxy, self::buildAnyTLS($user['uuid'], $item)); + array_push($proxies, $item['name']); + } if ($item['type'] === 'socks') { array_push($proxy, self::buildSocks5($user['uuid'], $item)); array_push($proxies, $item['name']); @@ -391,6 +395,24 @@ class ClashMeta implements ProtocolInterface return $array; } + public static function buildAnyTLS($password, $server) + { + + $protocol_settings = data_get($server, 'protocol_settings', []); + $array = [ + 'name' => $server['name'], + 'type' => 'anytls', + 'server' => $server['host'], + 'port' => $server['port'], + 'password' => $password, + 'udp' => true, + ]; + $array['skip-cert-verify'] = (bool) data_get($protocol_settings, 'tls.allow_insecure', false); + + + return $array; + } + public static function buildMieru($password, $server) { $protocol_settings = data_get($server, 'protocol_settings', []); diff --git a/app/Protocols/Shadowrocket.php b/app/Protocols/Shadowrocket.php index 9328b89..2a05500 100644 --- a/app/Protocols/Shadowrocket.php +++ b/app/Protocols/Shadowrocket.php @@ -51,6 +51,12 @@ class Shadowrocket implements ProtocolInterface if ($item['type'] === 'hysteria') { $uri .= self::buildHysteria($user['uuid'], $item); } + if ($item['type'] === 'tuic') { + $uri.= self::buildTuic($user['uuid'], $item); + } + if ($item['type'] === 'anytls') { + $uri.= self::buildAnyTLS($user['uuid'], $item); + } } return base64_encode($uri); } @@ -276,4 +282,38 @@ class Shadowrocket implements ProtocolInterface } return $uri; } + public static function buildTuic($password, $server) + { + $protocol_settings = $server['protocol_settings']; + $name = rawurlencode($server['name']); + $params = [ + 'alpn' => data_get($protocol_settings, 'alpn'), + 'sni' => data_get($protocol_settings, 'tls.server_name'), + 'insecure' => data_get($protocol_settings, 'tls.allow_insecure') + ]; + if (data_get($protocol_settings, 'version') === 4) { + $params['token'] = $password; + }else{ + $params['uuid'] = $password; + $params['password'] = $password; + } + $query = http_build_query($params); + $uri = "tuic://{$server['host']}:{$server['port']}?{$query}#{$name}"; + $uri.= "\r\n"; + return $uri; + } + + public static function buildAnyTLS($password, $server) + { + $protocol_settings = $server['protocol_settings']; + $name = rawurlencode($server['name']); + $params = [ + 'sni' => data_get($protocol_settings, 'tls.server_name'), + 'insecure' => data_get($protocol_settings, 'tls.allow_insecure') + ]; + $query = http_build_query($params); + $uri = "anytls://{$password}@{$server['host']}:{$server['port']}?{$query}#{$name}"; + $uri.= "\r\n"; + return $uri; + } } diff --git a/app/Protocols/SingBox.php b/app/Protocols/SingBox.php index b399716..9edc353 100644 --- a/app/Protocols/SingBox.php +++ b/app/Protocols/SingBox.php @@ -83,6 +83,10 @@ class SingBox implements ProtocolInterface $tuicConfig = $this->buildTuic($this->user['uuid'], $item); $proxies[] = $tuicConfig; } + if ($item['type'] === 'anytls') { + $anytlsConfig = $this->buildAnyTLS($this->user['uuid'], $item); + $proxies[] = $anytlsConfig; + } if ($item['type'] === 'socks') { $socksConfig = $this->buildSocks($this->user['uuid'], $item); $proxies[] = $socksConfig; @@ -372,6 +376,29 @@ class SingBox implements ProtocolInterface return $array; } + protected function buildAnyTLS($password, $server): array + { + $protocol_settings = data_get($server, 'protocol_settings', []); + $array = [ + 'type' => 'anytls', + 'tag' => $server['name'], + 'server' => $server['host'], + 'password' => $password, + 'server_port' => $server['port'], + 'tls' => [ + 'enabled' => true, + 'insecure' => (bool) data_get($protocol_settings, 'tls.allow_insecure', false), + 'alpn' => data_get($protocol_settings, 'alpn', ['h3']), + ] + ]; + + if ($serverName = data_get($protocol_settings, 'tls.server_name')) { + $array['tls']['server_name'] = $serverName; + } + + return $array; + } + protected function buildSocks($password, $server): array { $protocol_settings = data_get($server, 'protocol_settings', []); diff --git a/app/Protocols/Stash.php b/app/Protocols/Stash.php index 45a72ad..f70e8db 100644 --- a/app/Protocols/Stash.php +++ b/app/Protocols/Stash.php @@ -76,6 +76,10 @@ class Stash implements ProtocolInterface array_push($proxy, self::buildTuic($user['uuid'], $item)); array_push($proxies, $item['name']); } + if ($item['type'] === 'anytls') { + array_push($proxy, self::buildAnyTLS($user['uuid'], $item)); + array_push($proxies, $item['name']); + } if ($item['type'] === 'socks') { array_push($proxy, self::buildSocks5($user['uuid'], $item)); array_push($proxies, $item['name']); @@ -213,7 +217,7 @@ class Stash implements ProtocolInterface break; case 2: $array['tls'] = true; - $array['reality-opts']= [ + $array['reality-opts'] = [ 'public-key' => data_get($protocol_settings, 'reality_settings.public_key'), 'short-id' => data_get($protocol_settings, 'reality_settings.short_id') ]; @@ -333,6 +337,23 @@ class Stash implements ProtocolInterface return $array; } + public static function buildAnyTLS($password, $server) + { + $protocol_settings = $server['protocol_settings']; + $array = [ + 'name' => $server['name'], + 'type' => 'anytls', + 'server' => $server['host'], + 'port' => $server['port'], + 'password' => $password, + 'sni' => data_get($protocol_settings, 'tls_settings.server_name'), + 'skip-cert-verify' => (bool) data_get($protocol_settings, 'tls_settings.allow_insecure', false), + 'udp' => true, + ]; + + return $array; + } + public static function buildSocks5($password, $server) { $protocol_settings = $server['protocol_settings']; diff --git a/app/Utils/CacheKey.php b/app/Utils/CacheKey.php index 384f012..b67d7af 100644 --- a/app/Utils/CacheKey.php +++ b/app/Utils/CacheKey.php @@ -4,7 +4,7 @@ namespace App\Utils; class CacheKey { - CONST KEYS = [ + const KEYS = [ 'EMAIL_VERIFY_CODE' => '邮箱验证码', 'LAST_SEND_EMAIL_VERIFY_TIMESTAMP' => '最后一次发送邮箱验证码时间', 'SERVER_VMESS_ONLINE_USER' => '节点在线用户', @@ -31,6 +31,10 @@ class CacheKey 'MULTI_SERVER_TUIC_ONLINE_USER' => 'TUIC节点多服务器在线用户', 'SERVER_TUIC_LAST_CHECK_AT' => 'TUIC节点最后检查时间', 'SERVER_TUIC_LAST_PUSH_AT' => 'TUIC节点最后推送时间', + 'SERVER_ANYTLS_ONLINE_USER' => 'ANYTLS节点在线用户', + 'MULTI_SERVER_ANYTLS_ONLINE_USER' => 'ANYTLS节点多服务器在线用户', + 'SERVER_ANYTLS_LAST_CHECK_AT' => 'ANYTLS节点最后检查时间', + 'SERVER_ANYTLS_LAST_PUSH_AT' => 'ANYTLS节点最后推送时间', 'SERVER_SOCKS_ONLINE_USER' => 'socks节点在线用户', 'MULTI_SERVER_SOCKS_ONLINE_USER' => 'socks节点多服务器在线用户', 'SERVER_SOCKS_LAST_CHECK_AT' => 'socks节点最后检查时间',