Skip to content

Commit c207bfc

Browse files
lonelamtindy2013
andauthored
Add Hysteria & Hysteria 2 support (#731)
* feat: add hysteria & hysteria 2 support * Fix build error * Remove deleted rules repository --------- Co-authored-by: Tindy X <49061470+tindy2013@users.noreply.github.com>
1 parent 79a7e88 commit c207bfc

8 files changed

+467
-20
lines changed

scripts/build.alpine.release.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -xe
44
apk add gcc g++ build-base linux-headers cmake make autoconf automake libtool python2 python3
55
apk add mbedtls-dev mbedtls-static zlib-dev rapidjson-dev zlib-static pcre2-dev
66

7-
git clone https://github.com/curl/curl --depth=1 --branch curl-8_4_0
7+
git clone https://github.com/curl/curl --depth=1 --branch curl-8_6_0
88
cd curl
99
cmake -DCURL_USE_MBEDTLS=ON -DHTTP_ONLY=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_USE_LIBSSH2=OFF -DBUILD_CURL_EXE=OFF . > /dev/null
1010
make install -j2 > /dev/null

scripts/build.macos.release.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ sudo install -d /usr/local/include/date/
4141
sudo install -m644 libcron/externals/date/include/date/* /usr/local/include/date/
4242
cd ..
4343

44-
git clone https://github.com/ToruNiina/toml11 --depth=1
44+
git clone https://github.com/ToruNiina/toml11 --branch="v3.7.1" --depth=1
4545
cd toml11
4646
cmake -DCMAKE_CXX_STANDARD=11 .
4747
sudo make install -j6 > /dev/null

scripts/build.windows.release.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22
set -xe
33

4-
git clone https://github.com/curl/curl --depth=1 --branch curl-8_4_0
4+
git clone https://github.com/curl/curl --depth=1 --branch curl-8_6_0
55
cd curl
66
cmake -DCMAKE_BUILD_TYPE=Release -DCURL_USE_LIBSSH2=OFF -DHTTP_ONLY=ON -DCURL_USE_SCHANNEL=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_CURL_EXE=OFF -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" -DHAVE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF .
77
make install -j4
@@ -38,7 +38,7 @@ cmake -DRAPIDJSON_BUILD_DOC=OFF -DRAPIDJSON_BUILD_EXAMPLES=OFF -DRAPIDJSON_BUILD
3838
make install -j4
3939
cd ..
4040

41-
git clone https://github.com/ToruNiina/toml11 --depth=1
41+
git clone https://github.com/ToruNiina/toml11 --branch v3.8.1 --depth=1
4242
cd toml11
4343
cmake -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" -DCMAKE_CXX_STANDARD=11 .
4444
make install -j4

scripts/rules_config.conf

-5
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ match=Clash/config/**
1212
dest=base/config/
1313
keep_tree=false
1414

15-
[DivineEngine]
16-
url=https://github.com/DivineEngine/Profiles
17-
commit=f4d75f7d48a3f42129e030bef751d4d22bca02da
18-
match=Surge/Ruleset/**
19-
2015
[NobyDa]
2116
url=https://github.com/NobyDa/Script
2217
branch=master

src/generator/config/subexport.cpp

+184-10
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,19 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const Proxy &
116116
std::string target, ret_real_rule;
117117
static const std::string groupid_regex = R"(^!!(?:GROUPID|INSERT)=([\d\-+!,]+)(?:!!(.*))?$)", group_regex = R"(^!!(?:GROUP)=(.+?)(?:!!(.*))?$)";
118118
static const std::string type_regex = R"(^!!(?:TYPE)=(.+?)(?:!!(.*))?$)", port_regex = R"(^!!(?:PORT)=(.+?)(?:!!(.*))?$)", server_regex = R"(^!!(?:SERVER)=(.+?)(?:!!(.*))?$)";
119-
static const std::map<ProxyType, const char *> types = {{ProxyType::Shadowsocks, "SS"},
120-
{ProxyType::ShadowsocksR, "SSR"},
121-
{ProxyType::VMess, "VMESS"},
122-
{ProxyType::Trojan, "TROJAN"},
123-
{ProxyType::Snell, "SNELL"},
124-
{ProxyType::HTTP, "HTTP"},
125-
{ProxyType::HTTPS, "HTTPS"},
126-
{ProxyType::SOCKS5, "SOCKS5"},
127-
{ProxyType::WireGuard, "WIREGUARD"}};
119+
static const std::map<ProxyType, const char *> types = {
120+
{ProxyType::Shadowsocks, "SS"},
121+
{ProxyType::ShadowsocksR, "SSR"},
122+
{ProxyType::VMess, "VMESS"},
123+
{ProxyType::Trojan, "TROJAN"},
124+
{ProxyType::Snell, "SNELL"},
125+
{ProxyType::HTTP, "HTTP"},
126+
{ProxyType::HTTPS, "HTTPS"},
127+
{ProxyType::SOCKS5, "SOCKS5"},
128+
{ProxyType::WireGuard, "WIREGUARD"},
129+
{ProxyType::Hysteria, "HYSTERIA"},
130+
{ProxyType::Hysteria2, "HYSTERIA2"}
131+
};
128132
if(startsWith(rule, "!!GROUP="))
129133
{
130134
regGetMatch(rule, group_regex, 3, 0, &target, &ret_real_rule);
@@ -478,6 +482,77 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
478482
if(x.Mtu > 0)
479483
singleproxy["mtu"] = x.Mtu;
480484
break;
485+
case ProxyType::Hysteria:
486+
singleproxy["type"] = "hysteria";
487+
if (!x.Ports.empty())
488+
singleproxy["ports"] = x.Ports;
489+
if (!x.Protocol.empty())
490+
singleproxy["protocol"] = x.Protocol;
491+
if (!x.OBFSParam.empty())
492+
singleproxy["obfs-protocol"] = x.OBFSParam;
493+
if (!x.Up.empty())
494+
singleproxy["up"] = x.Up;
495+
if (x.UpSpeed)
496+
singleproxy["up-speed"] = x.UpSpeed;
497+
if (!x.Down.empty())
498+
singleproxy["down"] = x.Down;
499+
if (x.DownSpeed)
500+
singleproxy["down-speed"] = x.DownSpeed;
501+
if (!x.AuthStr.empty())
502+
{
503+
singleproxy["auth-str"] = x.AuthStr;
504+
singleproxy["auth"] = base64Encode(x.AuthStr);
505+
}
506+
if (!x.OBFS.empty())
507+
singleproxy["obfs"] = x.OBFS;
508+
if (!x.SNI.empty())
509+
singleproxy["sni"] = x.SNI;
510+
if (!scv.is_undef())
511+
singleproxy["skip-cert-verify"] = scv.get();
512+
if (!x.Fingerprint.empty())
513+
singleproxy["fingerprint"] = x.Fingerprint;
514+
if (!x.Alpn.empty())
515+
singleproxy["alpn"] = x.Alpn;
516+
if (!x.Ca.empty())
517+
singleproxy["ca"] = x.Ca;
518+
if (!x.CaStr.empty())
519+
singleproxy["ca-str"] = x.CaStr;
520+
if (x.RecvWindowConn)
521+
singleproxy["recv-window-conn"] = x.RecvWindowConn;
522+
if (x.RecvWindow)
523+
singleproxy["recv-window"] = x.RecvWindow;
524+
if (!x.DisableMtuDiscovery.is_undef())
525+
singleproxy["disable-mtu-discovery"] = x.DisableMtuDiscovery.get();
526+
if (!x.TCPFastOpen.is_undef())
527+
singleproxy["fast-open"] = x.TCPFastOpen.get();
528+
if (x.HopInterval)
529+
singleproxy["hop-interval"] = x.HopInterval;
530+
break;
531+
case ProxyType::Hysteria2:
532+
singleproxy["type"] = "hysteria2";
533+
if (!x.Up.empty())
534+
singleproxy["up"] = x.UpSpeed;
535+
if (!x.Down.empty())
536+
singleproxy["down"] = x.DownSpeed;
537+
if (!x.Password.empty())
538+
singleproxy["password"] = x.Password;
539+
if (!x.OBFS.empty())
540+
singleproxy["obfs"] = x.OBFS;
541+
if (!x.OBFSParam.empty())
542+
singleproxy["obfs-password"] = x.OBFSParam;
543+
if (!x.SNI.empty())
544+
singleproxy["sni"] = x.SNI;
545+
if (!scv.is_undef())
546+
singleproxy["skip-cert-verify"] = scv.get();
547+
if (!x.Alpn.empty())
548+
singleproxy["alpn"] = x.Alpn;
549+
if (!x.Ca.empty())
550+
singleproxy["ca"] = x.Ca;
551+
if (!x.CaStr.empty())
552+
singleproxy["ca-str"] = x.CaStr;
553+
if (x.CWND)
554+
singleproxy["cwnd"] = x.CWND;
555+
break;
481556
default:
482557
continue;
483558
}
@@ -860,6 +935,20 @@ std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf
860935
ini.set(real_section, "keepalive", std::to_string(x.KeepAlive));
861936
ini.set(real_section, "peer", "(" + generatePeer(x) + ")");
862937
break;
938+
case ProxyType::Hysteria2:
939+
if(surge_ver < 4)
940+
continue;
941+
proxy = "hysteria, " + hostname + ", " + port + ", password=" + password;
942+
if(x.DownSpeed)
943+
proxy += ", download-bandwidth=" + x.DownSpeed;
944+
945+
if(!scv.is_undef())
946+
proxy += ",skip-cert-verify=" + std::string(scv.get() ? "true" : "false");
947+
if(!x.Fingerprint.empty())
948+
proxy += ",server-cert-fingerprint-sha256=" + x.Fingerprint;
949+
if(!x.SNI.empty())
950+
proxy += ",sni=" + x.SNI;
951+
break;
863952
default:
864953
continue;
865954
}
@@ -2168,7 +2257,6 @@ void proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::v
21682257
udp.define(x.UDP);
21692258
tfo.define(x.TCPFastOpen);
21702259
scv.define(x.AllowInsecure);
2171-
21722260
rapidjson::Value proxy(rapidjson::kObjectType);
21732261
switch (x.Type)
21742262
{
@@ -2255,6 +2343,92 @@ void proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::v
22552343
proxy.AddMember("mtu", x.Mtu, allocator);
22562344
break;
22572345
}
2346+
case ProxyType::Hysteria:
2347+
{
2348+
addSingBoxCommonMembers(proxy, x, "hysteria", allocator);
2349+
if (!x.Up.empty())
2350+
proxy.AddMember("up_mbps", x.UpSpeed, allocator);
2351+
if (!x.Down.empty())
2352+
proxy.AddMember("down_mbps", x.DownSpeed, allocator);
2353+
if (!x.OBFS.empty())
2354+
{
2355+
proxy.AddMember("obfs", rapidjson::StringRef(x.OBFS.c_str()), allocator);
2356+
}
2357+
2358+
if (!x.AuthStr.empty())
2359+
{
2360+
proxy.AddMember("auth_str", rapidjson::StringRef(x.AuthStr.c_str()), allocator);
2361+
rapidjson::Value auth_str;
2362+
auth_str.SetString(base64Encode(x.AuthStr).c_str(), allocator);
2363+
proxy.AddMember("auth", auth_str, allocator);
2364+
}
2365+
if (x.RecvWindowConn)
2366+
proxy.AddMember("recv_window_conn", x.RecvWindowConn, allocator);
2367+
if (x.RecvWindow)
2368+
proxy.AddMember("recv_window", x.RecvWindow, allocator);
2369+
if (!x.DisableMtuDiscovery.is_undef())
2370+
proxy.AddMember("disable_mtu_discovery", x.DisableMtuDiscovery.get(), allocator);
2371+
2372+
rapidjson::Value tls(rapidjson::kObjectType);
2373+
tls.AddMember("enabled", true, allocator);
2374+
if (!scv.is_undef())
2375+
tls.AddMember("insecure", scv.get(), allocator);
2376+
if (!x.Alpn.empty())
2377+
{
2378+
rapidjson::Value alpn(rapidjson::kArrayType);
2379+
alpn.PushBack(rapidjson::StringRef(x.Alpn[0].c_str()), allocator);
2380+
tls.AddMember("alpn", alpn, allocator);
2381+
}
2382+
if (!x.Ca.empty())
2383+
{
2384+
rapidjson::Value ca_str;
2385+
ca_str.SetString(x.Ca.c_str(), allocator);
2386+
tls.AddMember("certificate", ca_str, allocator);
2387+
}
2388+
if (!x.CaStr.empty())
2389+
tls.AddMember("certificate", rapidjson::StringRef(x.CaStr.c_str()), allocator);
2390+
proxy.AddMember("tls", tls, allocator);
2391+
break;
2392+
}
2393+
case ProxyType::Hysteria2:
2394+
{
2395+
addSingBoxCommonMembers(proxy, x, "hysteria2", allocator);
2396+
if (!x.Up.empty())
2397+
proxy.AddMember("up_mbps", x.UpSpeed, allocator);
2398+
if (!x.Down.empty())
2399+
proxy.AddMember("down_mbps", x.DownSpeed, allocator);
2400+
if (!x.OBFS.empty())
2401+
{
2402+
rapidjson::Value obfs(rapidjson::kObjectType);
2403+
obfs.AddMember("type", rapidjson::StringRef(x.OBFS.c_str()), allocator);
2404+
if (!x.OBFSParam.empty())
2405+
obfs.AddMember("password", rapidjson::StringRef(x.OBFSParam.c_str()), allocator);
2406+
proxy.AddMember("obfs", obfs, allocator);
2407+
}
2408+
if (!x.Password.empty())
2409+
proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);
2410+
2411+
rapidjson::Value tls(rapidjson::kObjectType);
2412+
tls.AddMember("enabled", true, allocator);
2413+
if (!scv.is_undef())
2414+
tls.AddMember("insecure", scv.get(), allocator);
2415+
if (!x.Alpn.empty())
2416+
{
2417+
rapidjson::Value alpn(rapidjson::kArrayType);
2418+
alpn.PushBack(rapidjson::StringRef(x.Alpn[0].c_str()), allocator);
2419+
tls.AddMember("alpn", alpn, allocator);
2420+
}
2421+
if (!x.Ca.empty())
2422+
{
2423+
rapidjson::Value ca_str(rapidjson::kStringType);
2424+
ca_str.SetString(x.Ca.c_str(), allocator);
2425+
tls.AddMember("certificate", ca_str, allocator);
2426+
}
2427+
if (!x.CaStr.empty())
2428+
tls.AddMember("certificate", rapidjson::StringRef(x.CaStr.c_str()), allocator);
2429+
proxy.AddMember("tls", tls, allocator);
2430+
break;
2431+
}
22582432
case ProxyType::HTTP:
22592433
case ProxyType::HTTPS:
22602434
{

src/parser/config/proxy.h

+29-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ enum class ProxyType
2020
HTTP,
2121
HTTPS,
2222
SOCKS5,
23-
WireGuard
23+
WireGuard,
24+
Hysteria,
25+
Hysteria2
2426
};
2527

2628
inline String getProxyTypeName(ProxyType type)
@@ -43,6 +45,12 @@ inline String getProxyTypeName(ProxyType type)
4345
return "HTTPS";
4446
case ProxyType::SOCKS5:
4547
return "SOCKS5";
48+
case ProxyType::WireGuard:
49+
return "WireGuard";
50+
case ProxyType::Hysteria:
51+
return "Hysteria";
52+
case ProxyType::Hysteria2:
53+
return "Hysteria2";
4654
default:
4755
return "Unknown";
4856
}
@@ -101,6 +109,24 @@ struct Proxy
101109
uint16_t KeepAlive = 0;
102110
String TestUrl;
103111
String ClientId;
112+
113+
String Ports;
114+
String Up;
115+
uint32_t UpSpeed;
116+
String Down;
117+
uint32_t DownSpeed;
118+
String AuthStr;
119+
String SNI;
120+
String Fingerprint;
121+
String Ca;
122+
String CaStr;
123+
uint32_t RecvWindowConn;
124+
uint32_t RecvWindow;
125+
tribool DisableMtuDiscovery;
126+
uint32_t HopInterval;
127+
StringArray Alpn;
128+
129+
uint32_t CWND = 0;
104130
};
105131

106132
#define SS_DEFAULT_GROUP "SSProvider"
@@ -111,5 +137,7 @@ struct Proxy
111137
#define TROJAN_DEFAULT_GROUP "TrojanProvider"
112138
#define SNELL_DEFAULT_GROUP "SnellProvider"
113139
#define WG_DEFAULT_GROUP "WireGuardProvider"
140+
#define HYSTERIA_DEFAULT_GROUP "HysteriaProvider"
141+
#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider"
114142

115143
#endif // PROXY_H_INCLUDED

0 commit comments

Comments
 (0)