mirror of
https://github.com/MetaCubeX/subconverter.git
synced 2025-11-04 18:19:42 +08:00
Add AnyTLS support
This commit is contained in:
parent
28a569c9de
commit
8b6a1ccb8b
@ -128,7 +128,8 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const Proxy &
|
|||||||
{ProxyType::WireGuard, "WIREGUARD"},
|
{ProxyType::WireGuard, "WIREGUARD"},
|
||||||
{ProxyType::Hysteria, "HYSTERIA"},
|
{ProxyType::Hysteria, "HYSTERIA"},
|
||||||
{ProxyType::Hysteria2, "HYSTERIA2"},
|
{ProxyType::Hysteria2, "HYSTERIA2"},
|
||||||
{ProxyType::TUIC, "TUIC"}
|
{ProxyType::TUIC, "TUIC"},
|
||||||
|
{ProxyType::AnyTLS, "ANYTLS"}
|
||||||
};
|
};
|
||||||
if(startsWith(rule, "!!GROUP="))
|
if(startsWith(rule, "!!GROUP="))
|
||||||
{
|
{
|
||||||
@ -589,7 +590,25 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
|
|||||||
if (!scv.is_undef())
|
if (!scv.is_undef())
|
||||||
singleproxy["skip-cert-verify"] = scv.get();
|
singleproxy["skip-cert-verify"] = scv.get();
|
||||||
break;
|
break;
|
||||||
|
case ProxyType::AnyTLS:
|
||||||
|
singleproxy["type"] = "anytls";
|
||||||
|
if (!x.Password.empty())
|
||||||
|
singleproxy["password"] = x.Password;
|
||||||
|
if (!x.SNI.empty())
|
||||||
|
singleproxy["sni"] = x.SNI;
|
||||||
|
if (!x.Alpn.empty())
|
||||||
|
singleproxy["alpn"] = x.Alpn;
|
||||||
|
if (!x.Fingerprint.empty())
|
||||||
|
singleproxy["fingerprint"] = x.Fingerprint;
|
||||||
|
if (x.IdleSessionCheckInterval != 0)
|
||||||
|
singleproxy["idle-session-check-interval"] = x.IdleSessionCheckInterval;
|
||||||
|
if (x.IdleSessionTimeout != 0)
|
||||||
|
singleproxy["idle-session-timeout"] = x.IdleSessionTimeout;
|
||||||
|
if (x.MinIdleSession != 0)
|
||||||
|
singleproxy["min-idle-session"] = x.MinIdleSession;
|
||||||
|
if (!scv.is_undef())
|
||||||
|
singleproxy["skip-cert-verify"] = scv.get();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2536,6 +2555,41 @@ void proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::v
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ProxyType::AnyTLS:
|
||||||
|
{
|
||||||
|
addSingBoxCommonMembers(proxy, x, "anytls", allocator);
|
||||||
|
|
||||||
|
if (!x.Password.empty())
|
||||||
|
proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);
|
||||||
|
|
||||||
|
if (!x.SNI.empty())
|
||||||
|
proxy.AddMember("sni", rapidjson::StringRef(x.SNI.c_str()), allocator);
|
||||||
|
|
||||||
|
if (x.IdleSessionCheckInterval)
|
||||||
|
proxy.AddMember("idle_session_check_interval", rapidjson::Value(formatSingBoxInterval(x.IdleSessionCheckInterval).c_str(), allocator), allocator);
|
||||||
|
if (x.IdleSessionTimeout)
|
||||||
|
proxy.AddMember("idle_session_timeout", rapidjson::Value(formatSingBoxInterval(x.IdleSessionTimeout).c_str(), allocator), allocator);
|
||||||
|
if (x.MinIdleSession)
|
||||||
|
proxy.AddMember("min_idle_session", rapidjson::Value(formatSingBoxInterval(x.MinIdleSession).c_str(), allocator), allocator);
|
||||||
|
// TLS 配置
|
||||||
|
rapidjson::Value tls(rapidjson::kObjectType);
|
||||||
|
tls.AddMember("enabled", true, allocator);
|
||||||
|
|
||||||
|
if (!scv.is_undef())
|
||||||
|
tls.AddMember("insecure", scv.get(), allocator);
|
||||||
|
if (!x.Fingerprint.empty())
|
||||||
|
tls.AddMember("insecure", true, allocator);
|
||||||
|
if (!x.Alpn.empty()) {
|
||||||
|
rapidjson::Value alpn(rapidjson::kArrayType);
|
||||||
|
for (const auto& item : x.Alpn)
|
||||||
|
alpn.PushBack(rapidjson::StringRef(item.c_str()), allocator);
|
||||||
|
tls.AddMember("alpn", alpn, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.AddMember("tls", tls, allocator);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ProxyType::HTTP:
|
case ProxyType::HTTP:
|
||||||
case ProxyType::HTTPS:
|
case ProxyType::HTTPS:
|
||||||
{
|
{
|
||||||
|
|||||||
@ -23,7 +23,8 @@ enum class ProxyType
|
|||||||
WireGuard,
|
WireGuard,
|
||||||
Hysteria,
|
Hysteria,
|
||||||
Hysteria2,
|
Hysteria2,
|
||||||
TUIC
|
TUIC,
|
||||||
|
AnyTLS
|
||||||
};
|
};
|
||||||
|
|
||||||
inline String getProxyTypeName(ProxyType type)
|
inline String getProxyTypeName(ProxyType type)
|
||||||
@ -54,6 +55,8 @@ inline String getProxyTypeName(ProxyType type)
|
|||||||
return "Hysteria2";
|
return "Hysteria2";
|
||||||
case ProxyType::TUIC:
|
case ProxyType::TUIC:
|
||||||
return "TUIC";
|
return "TUIC";
|
||||||
|
case ProxyType::AnyTLS:
|
||||||
|
return "AnyTLS";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
@ -142,6 +145,10 @@ struct Proxy
|
|||||||
uint32_t MaxUdpRelayPacketSize;
|
uint32_t MaxUdpRelayPacketSize;
|
||||||
tribool FastOpen;
|
tribool FastOpen;
|
||||||
uint32_t MaxOpenStreams;
|
uint32_t MaxOpenStreams;
|
||||||
|
|
||||||
|
uint32_t IdleSessionCheckInterval;
|
||||||
|
uint32_t IdleSessionTimeout;
|
||||||
|
uint32_t MinIdleSession;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SS_DEFAULT_GROUP "SSProvider"
|
#define SS_DEFAULT_GROUP "SSProvider"
|
||||||
@ -155,5 +162,6 @@ struct Proxy
|
|||||||
#define HYSTERIA_DEFAULT_GROUP "HysteriaProvider"
|
#define HYSTERIA_DEFAULT_GROUP "HysteriaProvider"
|
||||||
#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider"
|
#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider"
|
||||||
#define TUIC_DEFAULT_GROUP "TUICProvider"
|
#define TUIC_DEFAULT_GROUP "TUICProvider"
|
||||||
|
#define ANYTLS_DEFAULT_GROUP "AnyTLSProvider"
|
||||||
|
|
||||||
#endif // PROXY_H_INCLUDED
|
#endif // PROXY_H_INCLUDED
|
||||||
|
|||||||
@ -294,6 +294,35 @@ void tuicConstruct(
|
|||||||
node.FastOpen = tribool(fast_open);
|
node.FastOpen = tribool(fast_open);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void anytlsConstruct(
|
||||||
|
Proxy &node,
|
||||||
|
const std::string &group,
|
||||||
|
const std::string &remarks,
|
||||||
|
const std::string &server,
|
||||||
|
const std::string &port,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &sni,
|
||||||
|
const std::string &alpn,
|
||||||
|
const std::string &fingerprint,
|
||||||
|
const std::string &idle_session_check_interval,
|
||||||
|
const std::string &idle_session_timeout,
|
||||||
|
const std::string &min_idle_session,
|
||||||
|
tribool tfo,
|
||||||
|
tribool scv,
|
||||||
|
const std::string &underlying_proxy
|
||||||
|
) {
|
||||||
|
commonConstruct(node, ProxyType::AnyTLS, group, remarks, server, port, tribool(), tfo, scv, tribool(), underlying_proxy);
|
||||||
|
node.Password = password;
|
||||||
|
node.SNI = sni;
|
||||||
|
if (!alpn.empty()) {
|
||||||
|
node.Alpn = StringArray{alpn};
|
||||||
|
}
|
||||||
|
node.Fingerprint = fingerprint;
|
||||||
|
node.IdleSessionCheckInterval = to_int(idle_session_check_interval);
|
||||||
|
node.IdleSessionTimeout = to_int(idle_session_timeout);
|
||||||
|
node.MinIdleSession = to_int(min_idle_session);
|
||||||
|
}
|
||||||
|
|
||||||
void explodeVmess(std::string vmess, Proxy &node)
|
void explodeVmess(std::string vmess, Proxy &node)
|
||||||
{
|
{
|
||||||
std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni;
|
std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni;
|
||||||
@ -1146,6 +1175,8 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
|
|||||||
std::string ports, obfs_protocol, up, up_speed, down, down_speed, auth, auth_str,/* obfs, sni,*/ fingerprint, ca, ca_str, recv_window_conn, recv_window, disable_mtu_discovery, hop_interval, alpn; //hysteria
|
std::string ports, obfs_protocol, up, up_speed, down, down_speed, auth, auth_str,/* obfs, sni,*/ fingerprint, ca, ca_str, recv_window_conn, recv_window, disable_mtu_discovery, hop_interval, alpn; //hysteria
|
||||||
std::string obfs_password, cwnd; //hysteria2
|
std::string obfs_password, cwnd; //hysteria2
|
||||||
std::string uuid,/*ip , password*/ heartbeat_interval, disable_sni, reduce_rtt, request_timeout, udp_relay_mode, congestion_controller, max_udp_relay_packet_size, max_open_streams, fast_open; //TUIC
|
std::string uuid,/*ip , password*/ heartbeat_interval, disable_sni, reduce_rtt, request_timeout, udp_relay_mode, congestion_controller, max_udp_relay_packet_size, max_open_streams, fast_open; //TUIC
|
||||||
|
std::string idle_session_check_interval, idle_session_timeout, min_idle_session;
|
||||||
|
|
||||||
string_array dns_server;
|
string_array dns_server;
|
||||||
tribool udp, tfo, scv;
|
tribool udp, tfo, scv;
|
||||||
Node singleproxy;
|
Node singleproxy;
|
||||||
@ -1432,6 +1463,19 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
|
|||||||
singleproxy["max-open-streams"] >>= max_open_streams;
|
singleproxy["max-open-streams"] >>= max_open_streams;
|
||||||
singleproxy["fast-open"] >>= fast_open;
|
singleproxy["fast-open"] >>= fast_open;
|
||||||
tuicConstruct(node, group, ps, server, port, uuid, password, ip, heartbeat_interval, alpn, disable_sni, reduce_rtt, request_timeout, udp_relay_mode, congestion_controller, max_udp_relay_packet_size, max_open_streams, sni, fast_open, tfo, scv, underlying_proxy);
|
tuicConstruct(node, group, ps, server, port, uuid, password, ip, heartbeat_interval, alpn, disable_sni, reduce_rtt, request_timeout, udp_relay_mode, congestion_controller, max_udp_relay_packet_size, max_open_streams, sni, fast_open, tfo, scv, underlying_proxy);
|
||||||
|
break;
|
||||||
|
case "anytls"_hash: {
|
||||||
|
group = ANYTLS_DEFAULT_GROUP;
|
||||||
|
singleproxy["password"] >>= password;
|
||||||
|
singleproxy["sni"] >>= sni;
|
||||||
|
if (singleproxy["alpn"].IsSequence())
|
||||||
|
singleproxy["alpn"][0] >>= alpn;
|
||||||
|
else
|
||||||
|
singleproxy["alpn"] >>= alpn;
|
||||||
|
singleproxy["fingerprint"] >>= fingerprint;
|
||||||
|
anytlsConstruct(node, group, ps, server, port, password, sni, alpn, fingerprint, idle_session_check_interval, idle_session_timeout, min_idle_session, tfo, scv, underlying_proxy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1664,7 +1708,7 @@ void explodeStdTuic(std::string tuic, Proxy &node) {
|
|||||||
if (!strFind(tuic, ":"))
|
if (!strFind(tuic, ":"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (regGetMatch(tuic, R"(^(.*?):(\d+)$)", 3, 0, &ip, &port))
|
if (regGetMatch(tuic, R"(^(.*?):(\d+)$)", 3, 0, &add, &port))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1702,6 +1746,61 @@ void explodeTUIC(std::string tuic, Proxy &node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void explodeStdAnyTLS(std::string anytls, Proxy &node) {
|
||||||
|
std::string add, port, password, sni, alpn, fingerprint, remarks, addition,idle_session_check_interval,idle_session_timeout,min_idle_session;
|
||||||
|
tribool tfo, scv;
|
||||||
|
|
||||||
|
anytls = anytls.substr(9); // 去除 anytls://
|
||||||
|
string_size pos;
|
||||||
|
|
||||||
|
pos = anytls.rfind("#");
|
||||||
|
if (pos != anytls.npos) {
|
||||||
|
remarks = urlDecode(anytls.substr(pos + 1));
|
||||||
|
anytls.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = anytls.rfind("?");
|
||||||
|
if (pos != anytls.npos) {
|
||||||
|
addition = anytls.substr(pos + 1);
|
||||||
|
anytls.erase(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持 user:pass@host:port
|
||||||
|
if (strFind(anytls, "@")) {
|
||||||
|
if (regGetMatch(anytls, R"(^(.*?)@(.*?):(\d+)$)", 4, 0, &password, &add, &port))
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
password = getUrlArg(addition, "password");
|
||||||
|
if (password.empty()) return;
|
||||||
|
|
||||||
|
if (!strFind(anytls, ":")) return;
|
||||||
|
if (regGetMatch(anytls, R"(^(.*?):(\d+)$)", 3, 0, &add, &port)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他参数
|
||||||
|
sni = getUrlArg(addition, "peer");
|
||||||
|
alpn = getUrlArg(addition, "alpn");
|
||||||
|
fingerprint = getUrlArg(addition, "hpkp");
|
||||||
|
tfo = tribool(getUrlArg(addition, "tfo"));
|
||||||
|
scv = tribool(getUrlArg(addition, "insecure"));
|
||||||
|
|
||||||
|
if (remarks.empty())
|
||||||
|
remarks = add + ":" + port;
|
||||||
|
|
||||||
|
anytlsConstruct(node, "AnyTLS", remarks, add, port, password, sni, alpn, fingerprint, idle_session_check_interval, idle_session_timeout, min_idle_session,tfo, scv, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void explodeAnyTLS(std::string anytls, Proxy &node) {
|
||||||
|
anytls = regReplace(anytls, "(anytls)://", "anytls://");
|
||||||
|
|
||||||
|
// replace /? with ?
|
||||||
|
anytls = regReplace(anytls, "/\\?", "?", true, false);
|
||||||
|
if (regMatch(anytls, "anytls://(.*?)[:](.*)")) {
|
||||||
|
explodeStdAnyTLS(anytls, node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// peer = (public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, allowed-ips = "0.0.0.0/0, ::/0", endpoint = engage.cloudflareclient.com:2408, client-id = 139/184/125),(public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, endpoint = engage.cloudflareclient.com:2408)
|
// peer = (public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, allowed-ips = "0.0.0.0/0, ::/0", endpoint = engage.cloudflareclient.com:2408, client-id = 139/184/125),(public-key = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=, endpoint = engage.cloudflareclient.com:2408)
|
||||||
void parsePeers(Proxy &node, const std::string &data)
|
void parsePeers(Proxy &node, const std::string &data)
|
||||||
{
|
{
|
||||||
@ -2601,6 +2700,8 @@ void explode(const std::string &link, Proxy &node)
|
|||||||
explodeHysteria2(link, node);
|
explodeHysteria2(link, node);
|
||||||
else if (strFind(link, "tuic://") || strFind(link, "tuic://"))
|
else if (strFind(link, "tuic://") || strFind(link, "tuic://"))
|
||||||
explodeTUIC(link, node);
|
explodeTUIC(link, node);
|
||||||
|
else if (strFind(link, "anytls://") || strFind(link, "anytls://"))
|
||||||
|
explodeAnyTLS(link, node);
|
||||||
else if(isLink(link))
|
else if(isLink(link))
|
||||||
explodeHTTPSub(link, node);
|
explodeHTTPSub(link, node);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,24 @@ void tuicConstruct(
|
|||||||
const std::string &underlying_proxy = ""
|
const std::string &underlying_proxy = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void anytlsConstruct(
|
||||||
|
Proxy &node,
|
||||||
|
const std::string &group,
|
||||||
|
const std::string &remarks,
|
||||||
|
const std::string &server,
|
||||||
|
const std::string &port,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &sni,
|
||||||
|
const std::string &alpn,
|
||||||
|
const std::string &fingerprint,
|
||||||
|
const std::string &idle_session_check_interval,
|
||||||
|
const std::string &idle_session_timeout,
|
||||||
|
const std::string &min_idle_session,
|
||||||
|
tribool tfo,
|
||||||
|
tribool scv,
|
||||||
|
const std::string &underlying_proxy = ""
|
||||||
|
);
|
||||||
|
|
||||||
void explodeVmess(std::string vmess, Proxy &node);
|
void explodeVmess(std::string vmess, Proxy &node);
|
||||||
void explodeSSR(std::string ssr, Proxy &node);
|
void explodeSSR(std::string ssr, Proxy &node);
|
||||||
void explodeSS(std::string ss, Proxy &node);
|
void explodeSS(std::string ss, Proxy &node);
|
||||||
@ -118,6 +136,7 @@ void explodeShadowrocket(std::string kit, Proxy &node);
|
|||||||
void explodeKitsunebi(std::string kit, Proxy &node);
|
void explodeKitsunebi(std::string kit, Proxy &node);
|
||||||
void explodeHysteria2(std::string hysteria2, Proxy &node);
|
void explodeHysteria2(std::string hysteria2, Proxy &node);
|
||||||
void explodeTUIC(std::string tuic, Proxy &node);
|
void explodeTUIC(std::string tuic, Proxy &node);
|
||||||
|
void explodeAnyTLS(std::string anytls, Proxy &node);
|
||||||
|
|
||||||
/// Parse a link
|
/// Parse a link
|
||||||
void explode(const std::string &link, Proxy &node);
|
void explode(const std::string &link, Proxy &node);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user