Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support hysteria2 for clash.meta #11

Merged
merged 7 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading