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: add hysteria & hysteria 2 support 添加hysteria/ hysteria 2 支持 #731

Merged
merged 8 commits into from
Nov 28, 2024
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
2 changes: 1 addition & 1 deletion scripts/build.alpine.release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -xe
apk add gcc g++ build-base linux-headers cmake make autoconf automake libtool python2 python3
apk add mbedtls-dev mbedtls-static zlib-dev rapidjson-dev zlib-static pcre2-dev

git clone https://github.com/curl/curl --depth=1 --branch curl-8_4_0
git clone https://github.com/curl/curl --depth=1 --branch curl-8_6_0
cd curl
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
make install -j2 > /dev/null
Expand Down
2 changes: 1 addition & 1 deletion scripts/build.macos.release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ sudo install -d /usr/local/include/date/
sudo install -m644 libcron/externals/date/include/date/* /usr/local/include/date/
cd ..

git clone https://github.com/ToruNiina/toml11 --depth=1
git clone https://github.com/ToruNiina/toml11 --branch="v3.7.1" --depth=1
cd toml11
cmake -DCMAKE_CXX_STANDARD=11 .
sudo make install -j6 > /dev/null
Expand Down
4 changes: 2 additions & 2 deletions scripts/build.windows.release.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash
set -xe

git clone https://github.com/curl/curl --depth=1 --branch curl-8_4_0
git clone https://github.com/curl/curl --depth=1 --branch curl-8_6_0
cd curl
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 .
make install -j4
Expand Down Expand Up @@ -38,7 +38,7 @@ cmake -DRAPIDJSON_BUILD_DOC=OFF -DRAPIDJSON_BUILD_EXAMPLES=OFF -DRAPIDJSON_BUILD
make install -j4
cd ..

git clone https://github.com/ToruNiina/toml11 --depth=1
git clone https://github.com/ToruNiina/toml11 --branch v3.8.1 --depth=1
cd toml11
cmake -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" -DCMAKE_CXX_STANDARD=11 .
make install -j4
Expand Down
5 changes: 0 additions & 5 deletions scripts/rules_config.conf
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ match=Clash/config/**
dest=base/config/
keep_tree=false

[DivineEngine]
url=https://github.com/DivineEngine/Profiles
commit=f4d75f7d48a3f42129e030bef751d4d22bca02da
match=Surge/Ruleset/**

[NobyDa]
url=https://github.com/NobyDa/Script
branch=master
Expand Down
194 changes: 184 additions & 10 deletions src/generator/config/subexport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,19 @@ 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 std::map<ProxyType, const char *> types = {{ProxyType::Shadowsocks, "SS"},
{ProxyType::ShadowsocksR, "SSR"},
{ProxyType::VMess, "VMESS"},
{ProxyType::Trojan, "TROJAN"},
{ProxyType::Snell, "SNELL"},
{ProxyType::HTTP, "HTTP"},
{ProxyType::HTTPS, "HTTPS"},
{ProxyType::SOCKS5, "SOCKS5"},
{ProxyType::WireGuard, "WIREGUARD"}};
static const std::map<ProxyType, const char *> types = {
{ProxyType::Shadowsocks, "SS"},
{ProxyType::ShadowsocksR, "SSR"},
{ProxyType::VMess, "VMESS"},
{ProxyType::Trojan, "TROJAN"},
{ProxyType::Snell, "SNELL"},
{ProxyType::HTTP, "HTTP"},
{ProxyType::HTTPS, "HTTPS"},
{ProxyType::SOCKS5, "SOCKS5"},
{ProxyType::WireGuard, "WIREGUARD"},
{ProxyType::Hysteria, "HYSTERIA"},
{ProxyType::Hysteria2, "HYSTERIA2"}
};
if(startsWith(rule, "!!GROUP="))
{
regGetMatch(rule, group_regex, 3, 0, &target, &ret_real_rule);
Expand Down Expand Up @@ -478,6 +482,77 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
if(x.Mtu > 0)
singleproxy["mtu"] = x.Mtu;
break;
case ProxyType::Hysteria:
singleproxy["type"] = "hysteria";
if (!x.Ports.empty())
singleproxy["ports"] = x.Ports;
if (!x.Protocol.empty())
singleproxy["protocol"] = x.Protocol;
if (!x.OBFSParam.empty())
singleproxy["obfs-protocol"] = x.OBFSParam;
if (!x.Up.empty())
singleproxy["up"] = x.Up;
if (x.UpSpeed)
singleproxy["up-speed"] = x.UpSpeed;
if (!x.Down.empty())
singleproxy["down"] = x.Down;
if (x.DownSpeed)
singleproxy["down-speed"] = x.DownSpeed;
if (!x.AuthStr.empty())
{
singleproxy["auth-str"] = x.AuthStr;
singleproxy["auth"] = base64Encode(x.AuthStr);
}
if (!x.OBFS.empty())
singleproxy["obfs"] = x.OBFS;
if (!x.SNI.empty())
singleproxy["sni"] = x.SNI;
if (!scv.is_undef())
singleproxy["skip-cert-verify"] = scv.get();
if (!x.Fingerprint.empty())
singleproxy["fingerprint"] = x.Fingerprint;
if (!x.Alpn.empty())
singleproxy["alpn"] = x.Alpn;
if (!x.Ca.empty())
singleproxy["ca"] = x.Ca;
if (!x.CaStr.empty())
singleproxy["ca-str"] = x.CaStr;
if (x.RecvWindowConn)
singleproxy["recv-window-conn"] = x.RecvWindowConn;
if (x.RecvWindow)
singleproxy["recv-window"] = x.RecvWindow;
if (!x.DisableMtuDiscovery.is_undef())
singleproxy["disable-mtu-discovery"] = x.DisableMtuDiscovery.get();
if (!x.TCPFastOpen.is_undef())
singleproxy["fast-open"] = x.TCPFastOpen.get();
if (x.HopInterval)
singleproxy["hop-interval"] = x.HopInterval;
break;
case ProxyType::Hysteria2:
singleproxy["type"] = "hysteria2";
if (!x.Up.empty())
singleproxy["up"] = x.UpSpeed;
if (!x.Down.empty())
singleproxy["down"] = x.DownSpeed;
if (!x.Password.empty())
singleproxy["password"] = x.Password;
if (!x.OBFS.empty())
singleproxy["obfs"] = x.OBFS;
if (!x.OBFSParam.empty())
singleproxy["obfs-password"] = x.OBFSParam;
if (!x.SNI.empty())
singleproxy["sni"] = x.SNI;
if (!scv.is_undef())
singleproxy["skip-cert-verify"] = scv.get();
if (!x.Alpn.empty())
singleproxy["alpn"] = x.Alpn;
if (!x.Ca.empty())
singleproxy["ca"] = x.Ca;
if (!x.CaStr.empty())
singleproxy["ca-str"] = x.CaStr;
if (x.CWND)
singleproxy["cwnd"] = x.CWND;
break;
default:
continue;
}
Expand Down Expand Up @@ -860,6 +935,20 @@ std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf
ini.set(real_section, "keepalive", std::to_string(x.KeepAlive));
ini.set(real_section, "peer", "(" + generatePeer(x) + ")");
break;
case ProxyType::Hysteria2:
if(surge_ver < 4)
continue;
proxy = "hysteria, " + hostname + ", " + port + ", password=" + password;
if(x.DownSpeed)
proxy += ", download-bandwidth=" + x.DownSpeed;

if(!scv.is_undef())
proxy += ",skip-cert-verify=" + std::string(scv.get() ? "true" : "false");
if(!x.Fingerprint.empty())
proxy += ",server-cert-fingerprint-sha256=" + x.Fingerprint;
if(!x.SNI.empty())
proxy += ",sni=" + x.SNI;
break;
default:
continue;
}
Expand Down Expand Up @@ -2168,7 +2257,6 @@ void proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::v
udp.define(x.UDP);
tfo.define(x.TCPFastOpen);
scv.define(x.AllowInsecure);

rapidjson::Value proxy(rapidjson::kObjectType);
switch (x.Type)
{
Expand Down Expand Up @@ -2255,6 +2343,92 @@ void proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::v
proxy.AddMember("mtu", x.Mtu, allocator);
break;
}
case ProxyType::Hysteria:
{
addSingBoxCommonMembers(proxy, x, "hysteria", allocator);
if (!x.Up.empty())
proxy.AddMember("up_mbps", x.UpSpeed, allocator);
if (!x.Down.empty())
proxy.AddMember("down_mbps", x.DownSpeed, allocator);
if (!x.OBFS.empty())
{
proxy.AddMember("obfs", rapidjson::StringRef(x.OBFS.c_str()), allocator);
}

if (!x.AuthStr.empty())
{
proxy.AddMember("auth_str", rapidjson::StringRef(x.AuthStr.c_str()), allocator);
rapidjson::Value auth_str;
auth_str.SetString(base64Encode(x.AuthStr).c_str(), allocator);
proxy.AddMember("auth", auth_str, allocator);
}
if (x.RecvWindowConn)
proxy.AddMember("recv_window_conn", x.RecvWindowConn, allocator);
if (x.RecvWindow)
proxy.AddMember("recv_window", x.RecvWindow, allocator);
if (!x.DisableMtuDiscovery.is_undef())
proxy.AddMember("disable_mtu_discovery", x.DisableMtuDiscovery.get(), allocator);

rapidjson::Value tls(rapidjson::kObjectType);
tls.AddMember("enabled", true, allocator);
if (!scv.is_undef())
tls.AddMember("insecure", scv.get(), allocator);
if (!x.Alpn.empty())
{
rapidjson::Value alpn(rapidjson::kArrayType);
alpn.PushBack(rapidjson::StringRef(x.Alpn[0].c_str()), allocator);
tls.AddMember("alpn", alpn, allocator);
}
if (!x.Ca.empty())
{
rapidjson::Value ca_str;
ca_str.SetString(x.Ca.c_str(), allocator);
tls.AddMember("certificate", ca_str, allocator);
}
if (!x.CaStr.empty())
tls.AddMember("certificate", rapidjson::StringRef(x.CaStr.c_str()), allocator);
proxy.AddMember("tls", tls, allocator);
break;
}
case ProxyType::Hysteria2:
{
addSingBoxCommonMembers(proxy, x, "hysteria2", allocator);
if (!x.Up.empty())
proxy.AddMember("up_mbps", x.UpSpeed, allocator);
if (!x.Down.empty())
proxy.AddMember("down_mbps", x.DownSpeed, allocator);
if (!x.OBFS.empty())
{
rapidjson::Value obfs(rapidjson::kObjectType);
obfs.AddMember("type", rapidjson::StringRef(x.OBFS.c_str()), allocator);
if (!x.OBFSParam.empty())
obfs.AddMember("password", rapidjson::StringRef(x.OBFSParam.c_str()), allocator);
proxy.AddMember("obfs", obfs, allocator);
}
if (!x.Password.empty())
proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);

rapidjson::Value tls(rapidjson::kObjectType);
tls.AddMember("enabled", true, allocator);
if (!scv.is_undef())
tls.AddMember("insecure", scv.get(), allocator);
if (!x.Alpn.empty())
{
rapidjson::Value alpn(rapidjson::kArrayType);
alpn.PushBack(rapidjson::StringRef(x.Alpn[0].c_str()), allocator);
tls.AddMember("alpn", alpn, allocator);
}
if (!x.Ca.empty())
{
rapidjson::Value ca_str(rapidjson::kStringType);
ca_str.SetString(x.Ca.c_str(), allocator);
tls.AddMember("certificate", ca_str, allocator);
}
if (!x.CaStr.empty())
tls.AddMember("certificate", rapidjson::StringRef(x.CaStr.c_str()), allocator);
proxy.AddMember("tls", tls, allocator);
break;
}
case ProxyType::HTTP:
case ProxyType::HTTPS:
{
Expand Down
30 changes: 29 additions & 1 deletion src/parser/config/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ enum class ProxyType
HTTP,
HTTPS,
SOCKS5,
WireGuard
WireGuard,
Hysteria,
Hysteria2
};

inline String getProxyTypeName(ProxyType type)
Expand All @@ -43,6 +45,12 @@ inline String getProxyTypeName(ProxyType type)
return "HTTPS";
case ProxyType::SOCKS5:
return "SOCKS5";
case ProxyType::WireGuard:
return "WireGuard";
case ProxyType::Hysteria:
return "Hysteria";
case ProxyType::Hysteria2:
return "Hysteria2";
default:
return "Unknown";
}
Expand Down Expand Up @@ -101,6 +109,24 @@ struct Proxy
uint16_t KeepAlive = 0;
String TestUrl;
String ClientId;

String Ports;
String Up;
uint32_t UpSpeed;
String Down;
uint32_t DownSpeed;
String AuthStr;
String SNI;
String Fingerprint;
String Ca;
String CaStr;
uint32_t RecvWindowConn;
uint32_t RecvWindow;
tribool DisableMtuDiscovery;
uint32_t HopInterval;
StringArray Alpn;

uint32_t CWND = 0;
};

#define SS_DEFAULT_GROUP "SSProvider"
Expand All @@ -111,5 +137,7 @@ struct Proxy
#define TROJAN_DEFAULT_GROUP "TrojanProvider"
#define SNELL_DEFAULT_GROUP "SnellProvider"
#define WG_DEFAULT_GROUP "WireGuardProvider"
#define HYSTERIA_DEFAULT_GROUP "HysteriaProvider"
#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider"

#endif // PROXY_H_INCLUDED
Loading