From 665284db31131f08b5fcbd974bcb4f6cdca883a2 Mon Sep 17 00:00:00 2001 From: amorlzu Date: Tue, 17 Mar 2026 18:57:31 +0800 Subject: [PATCH] fix: export VLESS reality-opts when short-id is not present Previously, the export code required both public-key AND short-id to be present before exporting reality-opts and client-fingerprint. This caused configurations with only public-key (without short-id) to lose the entire REALITY configuration during conversion. Changes: - Changed condition to only require public-key (short-id is optional) - short-id is now only output if present - client-fingerprint is properly exported when REALITY is used - For sing-box format, use parsed ClientFingerprint instead of random Fixes issue where VLESS REALITY configs lost public-key and client-fingerprint fields during format conversion. Co-Authored-By: Claude Opus 4.6 --- src/generator/config/subexport.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/generator/config/subexport.cpp b/src/generator/config/subexport.cpp index 36f6269a5..24fc02bf1 100644 --- a/src/generator/config/subexport.cpp +++ b/src/generator/config/subexport.cpp @@ -697,9 +697,12 @@ void proxyToClash(std::vector &nodes, YAML::Node &yamlnode, const ProxyGr // Fallback for backward compatibility singleproxy["flow"] = x.Flow; } - if (!x.PublicKey.empty() && !x.ShortID.empty()) { + // Export reality-opts if public-key is present (short-id is optional) + if (!x.PublicKey.empty()) { singleproxy["reality-opts"]["public-key"] = x.PublicKey; - singleproxy["reality-opts"]["short-id"] = x.ShortID; + if (!x.ShortID.empty()) { + singleproxy["reality-opts"]["short-id"] = x.ShortID; + } if (!x.ClientFingerprint.empty()) { singleproxy["client-fingerprint"] = x.ClientFingerprint; } else if (!x.Fingerprint.empty()) { @@ -2804,19 +2807,26 @@ void proxyToSingBox(std::vector &nodes, rapidjson::Document &json, std::v tls.AddMember("alpn", alpn, allocator); } - if (!x.PublicKey.empty() && !x.ShortID.empty()) { + // Export reality if public-key is present (short-id is optional) + if (!x.PublicKey.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); + 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("enabled",true,allocator); - std::array fingerprints = {"chrome", "firefox", "safari", "ios", "edge", "qq"}; - utls.AddMember("fingerprint", rapidjson::Value(fingerprints[rand() % fingerprints.size()].c_str(), allocator), allocator); + utls.AddMember("enabled", true, allocator); + // Use ClientFingerprint if available, otherwise use a random fingerprint + if (!x.ClientFingerprint.empty()) { + utls.AddMember("fingerprint", rapidjson::StringRef(x.ClientFingerprint.c_str()), allocator); + } else if (!x.Fingerprint.empty()) { + utls.AddMember("fingerprint", rapidjson::StringRef(x.Fingerprint.c_str()), allocator); + } else { + 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); }