From ede6abd7662152a9000b97fba5a52a2f47f03e51 Mon Sep 17 00:00:00 2001 From: DuckSoft Date: Sun, 27 Dec 2020 06:29:51 +0800 Subject: [PATCH] vless serializer support (with xtls) --- .../protocols/core/OutboundHandler.cpp | 77 ++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/src/plugins/protocols/core/OutboundHandler.cpp b/src/plugins/protocols/core/OutboundHandler.cpp index d75ef907..7e63ba56 100644 --- a/src/plugins/protocols/core/OutboundHandler.cpp +++ b/src/plugins/protocols/core/OutboundHandler.cpp @@ -3,6 +3,7 @@ #include "3rdparty/QJsonStruct/QJsonIO.hpp" #include +#include using namespace Qv2rayPlugin; @@ -58,7 +59,7 @@ const void BuiltinSerializer::SetOutboundInfo(const QString &protocol, const Qv2 } const QString BuiltinSerializer::SerializeOutbound(const QString &protocol, const QString &alias, const QString &, const QJsonObject &obj, - const QJsonObject &) const + const QJsonObject &objStream) const { if (protocol == "http" || protocol == "socks") { @@ -73,6 +74,80 @@ const QString BuiltinSerializer::SerializeOutbound(const QString &protocol, cons } return url.toString(); } + if (protocol == "vless") + { + QUrl url; + url.setFragment(QUrl::toPercentEncoding(alias)); + url.setScheme(protocol); + url.setHost(QJsonIO::GetValue(obj, { "vnext", 0, "address" }).toString()); + url.setPort(QJsonIO::GetValue(obj, { "vnext", 0, "port" }).toInt()); + url.setUserName(QJsonIO::GetValue(obj, {"vnext", 0, "users", 0, "id" }).toString()); + + // -------- COMMON INFORMATION -------- + QUrlQuery query; + const auto encryption = QJsonIO::GetValue(obj, {"vnext", 0, "users", 0, "encryption"}).toString("none"); + if (encryption != "none") query.addQueryItem("encryption", encryption); + + const auto network = QJsonIO::GetValue(objStream, "network").toString("tcp"); + if (network != "tcp") query.addQueryItem("type", network); + + const auto security = QJsonIO::GetValue(objStream, "security").toString("none"); + if (security != "none") query.addQueryItem("security", security); + + // -------- TRANSPORT RELATED -------- + if (network == "kcp") { + const auto seed = QJsonIO::GetValue(objStream, {"kcpSettings", "seed"}).toString(); + if (!seed.isEmpty()) query.addQueryItem("seed", QUrl::toPercentEncoding(seed)); + + const auto headerType = QJsonIO::GetValue(objStream, {"kcpSettings", "header", "type"}).toString("none"); + if (headerType != "none") query.addQueryItem("headerType", headerType); + } else if (network == "http") { + const auto path = QJsonIO::GetValue(objStream, {"httpSettings", "path"}).toString("/"); + query.addQueryItem("path", QUrl::toPercentEncoding(path)); + + const auto hosts = QJsonIO::GetValue(objStream, {"httpSetting", "host"}).toArray(); + QStringList hostList; + for (const auto item: hosts) { + const auto host = item.toString(); + if (!host.isEmpty()) hostList << host; + } + query.addQueryItem("host", QUrl::toPercentEncoding(hostList.join(","))); + } else if (network == "ws") { + const auto path = QJsonIO::GetValue(objStream, {"wsSettings", "path"}).toString("/"); + query.addQueryItem("path", QUrl::toPercentEncoding(path)); + + const auto host = QJsonIO::GetValue(objStream, {"wsSettings", "headers", "Host"}).toString(); + query.addQueryItem("host", host); + } else if (network == "quic") { + const auto quicSecurity = QJsonIO::GetValue(objStream, {"quicSettings", "security"}).toString("none"); + if (quicSecurity != "none") { + query.addQueryItem("quicSecurity", quicSecurity); + + const auto key = QJsonIO::GetValue(objStream, {"quicSettings", "key"}).toString(); + query.addQueryItem("key", QUrl::toPercentEncoding(key)); + + const auto headerType = QJsonIO::GetValue(objStream, {"quicSettings", "header", "type"}).toString("none"); + if (headerType != "none") query.addQueryItem("headerType", headerType); + } + } + + // -------- TLS RELATED -------- + const auto tlsKey = security == "xtls" ? "xtlsSettings" : "tlsSettings"; + + const auto sni = QJsonIO::GetValue(objStream, {tlsKey, "serverName"}).toString(); + if (!sni.isEmpty()) query.addQueryItem("sni", sni); + // TODO: ALPN Support + + // -------- XTLS Flow -------- + if (security == "xtls") { + const auto flow = QJsonIO::GetValue(obj, "vnext", 0, "users", 0, "flow").toString(); + query.addQueryItem("flow", flow); + } + + // ======== END OF QUERY ======== + url.setQuery(query); + return url.toString(QUrl::FullyEncoded); + } return "(Unsupported)"; }