From 0ea729ea068853652b49ef77ac03533ee0df0d9b Mon Sep 17 00:00:00 2001 From: riolurs Date: Fri, 13 Jun 2025 20:54:39 +0800 Subject: [PATCH] Fix VLESS config generation error --- src/generator/config/subexport.cpp | 39 +++++++++++++-------- src/parser/subparser.cpp | 55 +++++++++++++++++------------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/generator/config/subexport.cpp b/src/generator/config/subexport.cpp index 4c6ad5c..5a98276 100644 --- a/src/generator/config/subexport.cpp +++ b/src/generator/config/subexport.cpp @@ -611,8 +611,9 @@ void proxyToClash(std::vector &nodes, YAML::Node &yamlnode, const ProxyGr break; case ProxyType::VLESS: singleproxy["type"] = "vless"; - singleproxy["packet-encoding"] = "xudp"; singleproxy["tls"] = true; + if (udp) + singleproxy["packet-encoding"] = "xudp"; if (!x.UUID.empty()) singleproxy["uuid"] = x.UUID; if (!x.SNI.empty()) @@ -621,14 +622,15 @@ void proxyToClash(std::vector &nodes, YAML::Node &yamlnode, const ProxyGr singleproxy["alpn"] = x.Alpn; if (!x.Fingerprint.empty()) singleproxy["fingerprint"] = x.Fingerprint; - if (!x.Flow.empty()) - singleproxy["flow"] = x.Flow; if (x.XTLS == 2) { singleproxy["flow"] = "xtls-rprx-vision"; + } else if (!x.Flow.empty()) { + singleproxy["flow"] = x.Flow; } if (!x.PublicKey.empty() && !x.ShortID.empty()) { singleproxy["reality-opts"]["public-key"] = x.PublicKey; singleproxy["reality-opts"]["short-id"] = x.ShortID; + singleproxy["client-fingerprint"] = "random"; } if (!scv.is_undef()) singleproxy["skip-cert-verify"] = scv.get(); @@ -2626,9 +2628,11 @@ void proxyToSingBox(std::vector &nodes, rapidjson::Document &json, std::v if (!x.SNI.empty()) proxy.AddMember("sni", rapidjson::StringRef(x.SNI.c_str()), allocator); - if (!x.Flow.empty()) + if (x.XTLS == 2) { + proxy.AddMember("flow", rapidjson::StringRef("xtls-rprx-vision"), allocator); + } else if (!x.Flow.empty()) { proxy.AddMember("flow", rapidjson::StringRef(x.Flow.c_str()), allocator); - + } // TLS 配置 rapidjson::Value tls(rapidjson::kObjectType); tls.AddMember("enabled", true, allocator); @@ -2643,16 +2647,21 @@ void proxyToSingBox(std::vector &nodes, rapidjson::Document &json, std::v alpn.PushBack(rapidjson::StringRef(item.c_str()), allocator); tls.AddMember("alpn", alpn, allocator); } - if (x.XTLS == 2){ - if (!x.PublicKey.empty() && !x.ShortID.empty()) { - rapidjson::Value reality(rapidjson::kObjectType); - reality.AddMember("enabled", true, allocator); - if (!x.PublicKey.empty()) - reality.AddMember("public_key", rapidjson::StringRef(x.PublicKey.c_str()), allocator); - if (!x.ShortID.empty()) - reality.AddMember("short_id", rapidjson::StringRef(x.ShortID.c_str()), allocator); - tls.AddMember("reality", reality, allocator); - } + + if (!x.PublicKey.empty() && !x.ShortID.empty()) { + rapidjson::Value reality(rapidjson::kObjectType); + reality.AddMember("enabled", true, allocator); + if (!x.PublicKey.empty()) + reality.AddMember("public_key", rapidjson::StringRef(x.PublicKey.c_str()), allocator); + if (!x.ShortID.empty()) + reality.AddMember("short_id", rapidjson::StringRef(x.ShortID.c_str()), allocator); + tls.AddMember("reality", reality, allocator); + + rapidjson::Value utls(rapidjson::kObjectType); + utls.AddMember("enable",true,allocator); + std::array fingerprints = {"chrome", "firefox", "safari", "ios", "edge", "qq"}; + utls.AddMember("fingerprint", rapidjson::Value(fingerprints[rand() % fingerprints.size()].c_str(), allocator), allocator); + tls.AddMember("utls", utls, allocator); } proxy.AddMember("tls", tls, allocator); diff --git a/src/parser/subparser.cpp b/src/parser/subparser.cpp index ae2cf9d..4185c7b 100644 --- a/src/parser/subparser.cpp +++ b/src/parser/subparser.cpp @@ -1829,7 +1829,7 @@ void explodeStdAnyTLS(std::string anytls, Proxy &node) { // 其他参数 sni = getUrlArg(addition, "peer"); alpn = getUrlArg(addition, "alpn"); - fingerprint = getUrlArg(addition, "hpkp"); + fingerprint = urlDecode(getUrlArg(addition, "hpkp")); tfo = tribool(getUrlArg(addition, "tfo")); scv = tribool(getUrlArg(addition, "insecure")); @@ -1871,35 +1871,44 @@ void explodeStdVLESS(std::string vless, Proxy &node) { vless.erase(pos); } - decoded = urlSafeBase64Decode(vless); - - // 尝试从URL参数中获取uuid - uuid = getUrlArg(addition, "uuid"); - - // 如果URL参数中没有uuid,尝试从decoded中解析 - if (uuid.empty() && strFind(decoded, "@") && strFind(decoded, ":")) { - userinfo = decoded.substr(0, decoded.find('@')); - hostinfo = decoded.substr(decoded.find('@') + 1); - - if (strFind(userinfo, ":")) { - user_parts = split(userinfo, ":"); - if (user_parts.size() >= 2) { - uuid = user_parts[1]; - } - } else { - uuid = userinfo; - } - + pos = vless.find("@"); + if (pos != vless.npos) { + // 直接从URL中提取UUID + uuid = vless.substr(0, pos); + hostinfo = vless.substr(pos + 1); if (regGetMatch(hostinfo, R"(^(.*?):(\d+)$)", 3, 0, &add, &port) != 0) return; - } else if (regGetMatch(vless, R"(^(.*?):(\d+)$)", 3, 0, &add, &port) != 0) { - return; + } else { + decoded = urlSafeBase64Decode(vless); + uuid = getUrlArg(addition, "uuid"); + + if (uuid.empty() && strFind(decoded, "@") && strFind(decoded, ":")) { + userinfo = decoded.substr(0, decoded.find('@')); + hostinfo = decoded.substr(decoded.find('@') + 1); + + if (strFind(userinfo, ":")) { + user_parts = split(userinfo, ":"); + if (user_parts.size() >= 2) { + uuid = user_parts[1]; + } + } else { + uuid = userinfo; + } + + if (regGetMatch(hostinfo, R"(^(.*?):(\d+)$)", 3, 0, &add, &port) != 0) + return; + } else if (regGetMatch(vless, R"(^(.*?):(\d+)$)", 3, 0, &add, &port) != 0) { + return; + } } if (uuid.empty()) return; if (!addition.empty()) { - sni = getUrlArg(addition, "peer"); + sni = getUrlArg(addition, "sni"); + if (sni.empty()) { + sni = getUrlArg(addition, "peer"); + } alpn = getUrlArg(addition, "alpn"); fingerprint = getUrlArg(addition, "hpkp"); flow = getUrlArg(addition, "flow");