diff --git a/sub2proxy.js b/sub2proxy.js index 3bbde5a..f5c3489 100644 --- a/sub2proxy.js +++ b/sub2proxy.js @@ -53,6 +53,12 @@ function clashToSingbox(node) { if (node.sni) tls.server_name = node.sni; if (node.hasOwnProperty('skip-cert-verify')) tls.insecure = !!node['skip-cert-verify']; if (node.alpn) tls.alpn = node.alpn; + if (node['client-fingerprint']) { + tls.utls = { + enabled: true, + fingerprint: node['client-fingerprint'] + }; + } sb.tls = tls; } else if (t === 'vless') { sb.type = 'vless'; @@ -109,6 +115,12 @@ function clashToSingbox(node) { if (node.sni) tls.server_name = node.sni; if (node.hasOwnProperty('skip-cert-verify')) tls.insecure = !!node['skip-cert-verify']; if (node.alpn) tls.alpn = node.alpn; + if (node['client-fingerprint']) { + tls.utls = { + enabled: true, + fingerprint: node['client-fingerprint'] + }; + } sb.tls = tls; } else if (t === 'vmess') { sb.type = 'vmess'; @@ -121,6 +133,12 @@ function clashToSingbox(node) { tls.enabled = true; if (node.servername) tls.server_name = node.servername; if (node.hasOwnProperty('skip-cert-verify')) tls.insecure = !!node['skip-cert-verify']; + if (node['client-fingerprint']) { + tls.utls = { + enabled: true, + fingerprint: node['client-fingerprint'] + }; + } } sb.tls = tls; @@ -134,8 +152,32 @@ function clashToSingbox(node) { } } else { sb.type = t; + + // Process generic TLS conversion if any TLS feature is detected + const hasTls = node.tls || node.servername || node.sni || node['client-fingerprint'] || node['skip-cert-verify']; + if (hasTls) { + const tls = { enabled: true }; + if (node.servername || node.sni) tls.server_name = node.servername || node.sni; + if (node.hasOwnProperty('skip-cert-verify')) tls.insecure = !!node['skip-cert-verify']; + if (node.alpn) tls.alpn = node.alpn; + if (node['client-fingerprint']) { + tls.utls = { + enabled: true, + fingerprint: node['client-fingerprint'] + }; + } + sb.tls = tls; + } + + // Copy other fields but filter out Clash proprietary/incompatible fields + const excludeKeys = [ + 'name', 'port', 'type', 'server', 'tls', 'servername', 'sni', + 'skip-cert-verify', 'client-fingerprint', 'alpn', 'udp', + 'reality-opts', 'ws-opts', 'grpc-opts', 'h2-opts', 'http-opts', + 'packet-encoding' + ]; for (const k in node) { - if (!['name', 'port', 'type', 'server'].includes(k)) { + if (!excludeKeys.includes(k)) { sb[k] = node[k]; } }