Skip to content

Commit

Permalink
feat: support hysteria2 for clash.meta (#11)
Browse files Browse the repository at this point in the history
* feat: support hysteria2 for clash.meta

* Removed fast-open from Hysteria2 and added cwnd. Allow parsing url with password and port.

* Revert cwnd.

* Fix hysteria2.substr

* Allow password in addition for Hysteria2.

* Fixed wrong add when password is set in additions part; Added missing sni param.

* Better insecure logic.
  • Loading branch information
dzhuang authored Dec 9, 2023
1 parent 64a0c99 commit f0a9ffb
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/generator/config/subexport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -352,6 +352,24 @@ void proxyToClash(std::vector<Proxy> &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;
Expand Down
6 changes: 6 additions & 0 deletions src/parser/config/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum ProxyType
VMess,
VLESS,
Hysteria,
Hysteria2,
Trojan,
Snell,
HTTP,
Expand All @@ -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:
Expand Down Expand Up @@ -107,13 +110,16 @@ struct Proxy
String PublicKey;
String ShortId;

String OBFSPassword;

};

#define SS_DEFAULT_GROUP "SSProvider"
#define SSR_DEFAULT_GROUP "SSRProvider"
#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"
Expand Down
95 changes: 95 additions & 0 deletions src/parser/subparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1035,6 +1060,7 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &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();
Expand Down Expand Up @@ -1317,6 +1343,18 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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"))
Expand Down
3 changes: 3 additions & 0 deletions src/parser/subparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -32,13 +33,15 @@ 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);
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
Expand Down

0 comments on commit f0a9ffb

Please sign in to comment.