diff --git a/src/generator/config/subexport.cpp b/src/generator/config/subexport.cpp index 37e71259d..d4799a652 100644 --- a/src/generator/config/subexport.cpp +++ b/src/generator/config/subexport.cpp @@ -107,7 +107,7 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const Proxy & std::string target, ret_real_rule; static const std::string groupid_regex = R"(^!!(?:GROUPID|INSERT)=([\d\-+!,]+)(?:!!(.*))?$)", group_regex = R"(^!!(?:GROUP)=(.+?)(?:!!(.*))?$)"; static const std::string type_regex = R"(^!!(?:TYPE)=(.+?)(?:!!(.*))?$)", port_regex = R"(^!!(?:PORT)=(.+?)(?:!!(.*))?$)", server_regex = R"(^!!(?:SERVER)=(.+?)(?:!!(.*))?$)"; - static const string_array types = {"", "SS", "SSR", "VMESS", "TROJAN", "SNELL", "HTTP", "HTTPS", "SOCKS5","VLESS","HYSTERIA"}; + static const string_array types = {"", "SS", "SSR", "VMESS", "TROJAN", "SNELL", "HTTP", "HTTPS", "SOCKS5","VLESS","HYSTERIA","HYSTERIA2"}; if (startsWith(rule, "!!GROUP=")) { regGetMatch(rule, group_regex, 3, 0, &target, &ret_real_rule); real_rule = ret_real_rule; @@ -352,6 +352,24 @@ void proxyToClash(std::vector &nodes, YAML::Node &yamlnode, const ProxyGr if (!x.OBFSParam.empty()) singleproxy["obfs"] = x.OBFSParam; break; + case ProxyType::Hysteria2: + singleproxy["type"] = "hysteria2"; + singleproxy["password"] = x.Password; + if (!x.UpMbps.empty()) + singleproxy["up"] = x.UpMbps; + if (!x.DownMbps.empty()) + singleproxy["down"] = x.DownMbps; + if (!x.Host.empty()) + singleproxy["sni"] = x.Host; + if (!scv.is_undef()) + singleproxy["skip-cert-verify"] = scv.get(); + if (!x.Alpn.empty()) + singleproxy["alpn"].push_back(x.Alpn); + if (!x.OBFSParam.empty()) + singleproxy["obfs"] = x.OBFSParam; + if (!x.OBFSPassword.empty()) + singleproxy["obfs-password"] = x.OBFSPassword; + break; case ProxyType::VLESS: singleproxy["type"] = "vless"; singleproxy["uuid"] = x.UserId; diff --git a/src/parser/config/proxy.h b/src/parser/config/proxy.h index 02ad6cf35..52265ec36 100644 --- a/src/parser/config/proxy.h +++ b/src/parser/config/proxy.h @@ -15,6 +15,7 @@ enum ProxyType VMess, VLESS, Hysteria, + Hysteria2, Trojan, Snell, HTTP, @@ -36,6 +37,8 @@ inline String getProxyTypeName(int type) return "VLESS"; case ProxyType::Hysteria: return "Hysteria"; + case ProxyType::Hysteria2: + return "Hysteria2"; case ProxyType::Trojan: return "Trojan"; case ProxyType::Snell: @@ -107,6 +110,8 @@ struct Proxy String PublicKey; String ShortId; + String OBFSPassword; + }; #define SS_DEFAULT_GROUP "SSProvider" @@ -114,6 +119,7 @@ struct Proxy #define V2RAY_DEFAULT_GROUP "V2RayProvider" #define XRAY_DEFAULT_GROUP "XRayProvider" #define HYSTERIA_DEFAULT_GROUP "HysteriaProvider" +#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider" #define SOCKS_DEFAULT_GROUP "SocksProvider" #define HTTP_DEFAULT_GROUP "HTTPProvider" #define TROJAN_DEFAULT_GROUP "TrojanProvider" diff --git a/src/parser/subparser.cpp b/src/parser/subparser.cpp index 121e1ecbb..6a3bafe19 100644 --- a/src/parser/subparser.cpp +++ b/src/parser/subparser.cpp @@ -79,6 +79,18 @@ void hysteriaConstruct(Proxy &node, const std::string &group, const std::string node.FakeType = type; } +void hysteria2Construct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &password, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &obfsPassword, tribool udp, tribool tfo, tribool scv) +{ + commonConstruct(node, ProxyType::Hysteria2, group, remarks, add, port, udp, tfo, scv, tribool()); + node.Password = password; + node.Host = (host.empty() && !isIPv4(add) && !isIPv6(add)) ? add.data() : trim(host); + node.UpMbps = up; + node.DownMbps = down; + node.Alpn = alpn; + node.OBFSParam = obfsParam; + node.OBFSPassword = obfsPassword; +} + void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls,const std::string &pbk, const std::string &sid, const std::string &fp ,tribool udp, tribool tfo, tribool scv, tribool tls13) { commonConstruct(node, ProxyType::VLESS, group, remarks, add, port, udp, tfo, scv, tls13); @@ -188,6 +200,19 @@ void explodeHysteria(std::string hysteria, Proxy &node) } } +void explodeHysteria2(std::string hysteria2, Proxy &node) +{ + hysteria2 = regReplace(hysteria2, "(hysteria2|hy2)://", "hysteria2://"); + + // replace /? with ? + hysteria2 = regReplace(hysteria2, "/\\?", "?", true, false); + if(regMatch(hysteria2, "hysteria2://(.*?)[:](.*)")) + { + explodeStdHysteria2(hysteria2, node); + return; + } +} + void explodeVmess(std::string vmess, Proxy &node) { std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni, alpn; @@ -1035,6 +1060,7 @@ void explodeClash(Node yamlnode, std::vector &nodes) std::string flow, mode; //trojan std::string user; //socks std::string auth,up,down,obfsParam,insecure;//hysteria + std::string obfsPassword;//hysteria2 tribool udp, tfo, scv; Node singleproxy; uint32_t index = nodes.size(); @@ -1317,6 +1343,18 @@ void explodeClash(Node yamlnode, std::vector &nodes) hysteriaConstruct(node, group, ps, server, port, type, auth, host, up, down, alpn, obfsParam, insecure, udp, tfo, scv); break; + case "hysteria2"_hash: + group = HYSTERIA2_DEFAULT_GROUP; + singleproxy["password"] >>= password; + singleproxy["up"] >>= up; + singleproxy["down"] >>= down; + singleproxy["obfs"] >>= obfsParam; + singleproxy["obfs-password"] >>= obfsPassword; + singleproxy["sni"] >>= host; + singleproxy["alpn"][0] >>= alpn; + + hysteria2Construct(node, group, ps, server, port, password, host, up, down, alpn, obfsParam, obfsPassword, udp, tfo, scv); + break; default: continue; } @@ -1404,6 +1442,61 @@ void explodeStdHysteria(std::string hysteria, Proxy &node) return; } +void explodeStdHysteria2(std::string hysteria2, Proxy &node) +{ + std::string add, port, password, host, insecure, up, down, alpn, obfsParam, obfsPassword, remarks; + std::string addition; + tribool scv; + hysteria2 = hysteria2.substr(12); + string_size pos; + + pos = hysteria2.rfind("#"); + if(pos != hysteria2.npos) + { + remarks = urlDecode(hysteria2.substr(pos + 1)); + hysteria2.erase(pos); + } + + pos = hysteria2.rfind("?"); + if(pos != hysteria2.npos) + { + addition = hysteria2.substr(pos + 1); + hysteria2.erase(pos); + } + + if(strFind(hysteria2, "@")) + { + if(regGetMatch(hysteria2, R"(^(.*?)@(.*)[:](\d+)$)", 4, 0, &password, &add, &port)) + return; + } + else + { + password = getUrlArg(addition,"password"); + if(password.empty()) + return; + + if(!strFind(hysteria2, ":")) + return; + + if(regGetMatch(hysteria2, R"(^(.*)[:](\d+)$)", 3, 0, &add, &port)) + return; + } + + scv = getUrlArg(addition, "insecure"); + up = getUrlArg(addition,"up"); + down = getUrlArg(addition,"down"); + alpn = getUrlArg(addition,"alpn"); + obfsParam = getUrlArg(addition,"obfs"); + obfsPassword = getUrlArg(addition,"obfs-password"); + host = getUrlArg(addition,"sni"); + + if(remarks.empty()) + remarks = add + ":" + port; + + hysteria2Construct(node, HYSTERIA2_DEFAULT_GROUP, remarks, add, port, password, host, up, down, alpn, obfsParam, obfsPassword, tribool(), tribool(), scv); + return; +} + void explodeStdVless(std::string vless, Proxy &node) { std::string add, port, type, id, aid, net, flow, pbk, sid, fp, mode, path, host, tls, remarks; @@ -2335,6 +2428,8 @@ void explode(const std::string &link, Proxy &node) explodeVless(link, node); else if(strFind(link, "hysteria://")) explodeHysteria(link, node); + else if(strFind(link, "hysteria2://") || strFind(link, "hy2://")) + explodeHysteria2(link, node); else if(strFind(link, "ss://")) explodeSS(link, node); else if(strFind(link, "socks://") || strFind(link, "https://t.me/socks") || strFind(link, "tg://socks")) diff --git a/src/parser/subparser.h b/src/parser/subparser.h index 56291f13c..685f27225 100644 --- a/src/parser/subparser.h +++ b/src/parser/subparser.h @@ -21,6 +21,7 @@ enum class ConfType }; void hysteriaConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &auth, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &insecure ,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); +void hysteria2Construct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &password, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &obfsPassword, const std::string &insecure ,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, const std::string &alpn, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls,const std::string &pkd, const std::string &sid, const std::string &fp, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); void ssrConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &protocol, const std::string &method, const std::string &obfs, const std::string &password, const std::string &obfsparam, const std::string &protoparam, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); @@ -32,6 +33,7 @@ void snellConstruct(Proxy &node, const std::string &group, const std::string &re void explodeVmess(std::string vmess, Proxy &node); void explodeVless(std::string vless, Proxy &node); void explodeHysteria(std::string hysteria, Proxy &node); +void explodeHysteria2(std::string hysteria2, Proxy &node); void explodeSSR(std::string ssr, Proxy &node); void explodeSS(std::string ss, Proxy &node); void explodeTrojan(std::string trojan, Proxy &node); @@ -39,6 +41,7 @@ void explodeQuan(const std::string &quan, Proxy &node); void explodeStdVMess(std::string vmess, Proxy &node); void explodeStdVless(std::string vless, Proxy &node); void explodeStdHysteria(std::string hysteria, Proxy &node); +void explodeStdHysteria2(std::string hysteria2, Proxy &node); void explodeShadowrocket(std::string kit, Proxy &node); void explodeKitsunebi(std::string kit, Proxy &node); /// Parse a link