@@ -323,6 +323,37 @@ void anytlsConstruct(
323323 node.MinIdleSession = to_int (min_idle_session);
324324}
325325
326+ void vlessConstruct (
327+ Proxy &node,
328+ const std::string &group,
329+ const std::string &remarks,
330+ const std::string &server,
331+ const std::string &port,
332+ const std::string &uuid,
333+ const std::string &sni,
334+ const std::string &alpn,
335+ const std::string &fingerprint,
336+ const std::string &flow,
337+ const std::string &xtls,
338+ const std::string &public_key,
339+ const std::string &short_id,
340+ tribool tfo,
341+ tribool scv,
342+ const std::string &underlying_proxy
343+ ) {
344+ commonConstruct (node, ProxyType::VLESS, group, remarks, server, port, tribool (), tfo, scv, tribool (), underlying_proxy);
345+ node.UUID = uuid;
346+ node.SNI = sni;
347+ if (!alpn.empty ()) {
348+ node.Alpn = StringArray{alpn};
349+ }
350+ node.Fingerprint = fingerprint;
351+ node.Flow = flow;
352+ node.XTLS = to_int (xtls);
353+ node.PublicKey = public_key;
354+ node.ShortID = short_id;
355+ }
356+
326357void explodeVmess (std::string vmess, Proxy &node)
327358{
328359 std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni;
@@ -1176,6 +1207,7 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
11761207 std::string obfs_password, cwnd; // hysteria2
11771208 std::string uuid,/* ip , password*/ heartbeat_interval, disable_sni, reduce_rtt, request_timeout, udp_relay_mode, congestion_controller, max_udp_relay_packet_size, max_open_streams, fast_open; // TUIC
11781209 std::string idle_session_check_interval, idle_session_timeout, min_idle_session;
1210+ std::string flow, xtls, short_id;
11791211
11801212 string_array dns_server;
11811213 tribool udp, tfo, scv;
@@ -1242,7 +1274,24 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
12421274
12431275 vmessConstruct (node, group, ps, server, port, " " , id, aid, net, cipher, path, host, edge, tls, sni, udp, tfo, scv, tribool (), underlying_proxy);
12441276 break ;
1245- case " ss" _hash:
1277+ case " vless" _hash: {
1278+ group = VLESS_DEFAULT_GROUP;
1279+ singleproxy[" uuid" ] >>= uuid;
1280+ singleproxy[" servername" ] >>= sni;
1281+ if (singleproxy[" alpn" ].IsSequence ())
1282+ singleproxy[" alpn" ][0 ] >>= alpn;
1283+ else
1284+ singleproxy[" alpn" ] >>= alpn;
1285+ singleproxy[" fingerprint" ] >>= fingerprint;
1286+ singleproxy[" flow" ] >>= flow;
1287+ if (singleproxy[" reality-opts" ].IsDefined ()) {
1288+ singleproxy[" reality-opts" ][" public-key" ] >>= public_key;
1289+ singleproxy[" reality-opts" ][" short-id" ] >>= short_id;
1290+ }
1291+ vlessConstruct (node, group, ps, server, port, uuid, sni, alpn, fingerprint, flow, xtls, public_key, short_id, tfo, scv, underlying_proxy);
1292+ break ;
1293+ }
1294+ case " ss" _hash:
12461295 group = SS_DEFAULT_GROUP;
12471296
12481297 singleproxy[" cipher" ] >>= cipher;
@@ -1801,6 +1850,85 @@ void explodeAnyTLS(std::string anytls, Proxy &node) {
18011850 }
18021851}
18031852
1853+ void explodeStdVLESS (std::string vless, Proxy &node) {
1854+ std::string add, port, uuid, sni, alpn, fingerprint, remarks, addition, flow, xtls, public_key, short_id;
1855+ tribool tfo, scv;
1856+ std::string decoded, userinfo, hostinfo;
1857+ string_array user_parts;
1858+
1859+ vless = vless.substr (8 );
1860+ string_size pos;
1861+
1862+ pos = vless.rfind (" #" );
1863+ if (pos != vless.npos ) {
1864+ remarks = urlDecode (vless.substr (pos + 1 ));
1865+ vless.erase (pos);
1866+ }
1867+
1868+ pos = vless.rfind (" ?" );
1869+ if (pos != vless.npos ) {
1870+ addition = vless.substr (pos + 1 );
1871+ vless.erase (pos);
1872+ }
1873+
1874+ decoded = urlSafeBase64Decode (vless);
1875+
1876+ // 尝试从URL参数中获取uuid
1877+ uuid = getUrlArg (addition, " uuid" );
1878+
1879+ // 如果URL参数中没有uuid,尝试从decoded中解析
1880+ if (uuid.empty () && strFind (decoded, " @" ) && strFind (decoded, " :" )) {
1881+ userinfo = decoded.substr (0 , decoded.find (' @' ));
1882+ hostinfo = decoded.substr (decoded.find (' @' ) + 1 );
1883+
1884+ if (strFind (userinfo, " :" )) {
1885+ user_parts = split (userinfo, " :" );
1886+ if (user_parts.size () >= 2 ) {
1887+ uuid = user_parts[1 ];
1888+ }
1889+ } else {
1890+ uuid = userinfo;
1891+ }
1892+
1893+ if (regGetMatch (hostinfo, R"( ^(.*?):(\d+)$)" , 3 , 0 , &add, &port) != 0 )
1894+ return ;
1895+ } else if (regGetMatch (vless, R"( ^(.*?):(\d+)$)" , 3 , 0 , &add, &port) != 0 ) {
1896+ return ;
1897+ }
1898+
1899+ if (uuid.empty ()) return ;
1900+
1901+ if (!addition.empty ()) {
1902+ sni = getUrlArg (addition, " peer" );
1903+ alpn = getUrlArg (addition, " alpn" );
1904+ fingerprint = getUrlArg (addition, " hpkp" );
1905+ flow = getUrlArg (addition, " flow" );
1906+ xtls = getUrlArg (addition, " xtls" );
1907+ public_key = getUrlArg (addition, " pbk" );
1908+ short_id = getUrlArg (addition, " sid" );
1909+ tfo = tribool (getUrlArg (addition, " tfo" ));
1910+ scv = tribool (getUrlArg (addition, " insecure" ));
1911+
1912+ if (remarks.empty ()) {
1913+ remarks = urlDecode (getUrlArg (addition, " remark" ));
1914+ if (remarks.empty ())
1915+ remarks = urlDecode (getUrlArg (addition, " remarks" ));
1916+ }
1917+ }
1918+
1919+ if (remarks.empty ())
1920+ remarks = add + " :" + port;
1921+
1922+ vlessConstruct (node, VLESS_DEFAULT_GROUP, remarks, add, port, uuid, sni, alpn, fingerprint, flow, xtls, public_key, short_id, tfo, scv, " " );
1923+ }
1924+
1925+ void explodeVLESS (std::string vless, Proxy &node) {
1926+ vless = regReplace (vless, " (vless)://" , " vless://" );
1927+ // replace /? with ?
1928+ vless = regReplace (vless, " /\\ ?" , " ?" , true , false );
1929+ explodeStdVLESS (vless, node);
1930+ }
1931+
18041932// peer = (public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, allowed-ips = "0.0.0.0/0, ::/0", endpoint = engage.cloudflareclient.com:2408, client-id = 139/184/125),(public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, endpoint = engage.cloudflareclient.com:2408)
18051933void parsePeers (Proxy &node, const std::string &data)
18061934{
@@ -2698,10 +2826,12 @@ void explode(const std::string &link, Proxy &node)
26982826 explodeTrojan (link, node);
26992827 else if (strFind (link, " hysteria2://" ) || strFind (link, " hy2://" ))
27002828 explodeHysteria2 (link, node);
2701- else if (strFind (link, " tuic://" ) || strFind (link, " tuic:// " ) )
2829+ else if (strFind (link, " tuic://" ))
27022830 explodeTUIC (link, node);
2703- else if (strFind (link, " anytls://" ) || strFind (link, " anytls:// " ) )
2831+ else if (strFind (link, " anytls://" ))
27042832 explodeAnyTLS (link, node);
2833+ else if (strFind (link, " vless://" ))
2834+ explodeVLESS (link, node);
27052835 else if (isLink (link))
27062836 explodeHTTPSub (link, node);
27072837}
0 commit comments