mirror of
https://github.com/MetaCubeX/subconverter.git
synced 2025-11-04 18:19:42 +08:00
Add TUIC support
This commit is contained in:
parent
d3e2211f9e
commit
d17e3835d4
@ -127,7 +127,8 @@ bool applyMatcher(const std::string &rule, std::string &real_rule, const Proxy &
|
||||
{ProxyType::SOCKS5, "SOCKS5"},
|
||||
{ProxyType::WireGuard, "WIREGUARD"},
|
||||
{ProxyType::Hysteria, "HYSTERIA"},
|
||||
{ProxyType::Hysteria2, "HYSTERIA2"}
|
||||
{ProxyType::Hysteria2, "HYSTERIA2"},
|
||||
{ProxyType::TUIC, "TUIC"}
|
||||
};
|
||||
if(startsWith(rule, "!!GROUP="))
|
||||
{
|
||||
@ -557,6 +558,38 @@ void proxyToClash(std::vector<Proxy> &nodes, YAML::Node &yamlnode, const ProxyGr
|
||||
if (x.HopInterval)
|
||||
singleproxy["hop-interval"] = x.HopInterval;
|
||||
break;
|
||||
case ProxyType::TUIC:
|
||||
singleproxy["type"] = "tuic";
|
||||
if (!x.UUID.empty())
|
||||
singleproxy["uuid"] = x.UUID;
|
||||
if (!x.Password.empty())
|
||||
singleproxy["password"] = x.Password;
|
||||
if (!x.HeartbeatInterval.empty())
|
||||
singleproxy["heartbeat-interval"] = x.HeartbeatInterval;
|
||||
if (!x.Alpn.empty())
|
||||
singleproxy["alpn"] = x.Alpn;
|
||||
if (!x.FastOpen.is_undef())
|
||||
singleproxy["fast-open"] = x.FastOpen.get();
|
||||
if (!x.UdpRelayMode.empty())
|
||||
singleproxy["udp-relay-mode"] = x.UdpRelayMode;
|
||||
if (!x.CongestionController.empty())
|
||||
singleproxy["congestion-controller"] = x.CongestionController;
|
||||
if (!x.SNI.empty())
|
||||
singleproxy["sni"] = x.SNI;
|
||||
if (!x.DisableSNI.is_undef())
|
||||
singleproxy["disable-sni"] = x.DisableSNI.get();
|
||||
if (!x.ReduceRTT.is_undef())
|
||||
singleproxy["reduce-rtt"] = x.ReduceRTT.get();
|
||||
if (x.RequestTimeout != 0)
|
||||
singleproxy["request-timeout"] = x.RequestTimeout;
|
||||
if (x.MaxUdpRelayPacketSize != 0)
|
||||
singleproxy["max-udp-relay-packet-size"] = x.MaxUdpRelayPacketSize;
|
||||
if (x.MaxOpenStreams != 0)
|
||||
singleproxy["max-open-streams"] = x.MaxOpenStreams;
|
||||
if (!scv.is_undef())
|
||||
singleproxy["skip-cert-verify"] = scv.get();
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -947,7 +980,6 @@ std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf
|
||||
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())
|
||||
@ -955,6 +987,15 @@ std::string proxyToSurge(std::vector<Proxy> &nodes, const std::string &base_conf
|
||||
if(!x.SNI.empty())
|
||||
proxy += ",sni=" + x.SNI;
|
||||
break;
|
||||
case ProxyType::TUIC:
|
||||
if(surge_ver < 4)
|
||||
continue;
|
||||
proxy = "tuic-v5, " + hostname + ", " + port + ", password=" + password;
|
||||
if(!x.UUID.empty())
|
||||
proxy += ",uuid=" + x.UUID;
|
||||
if(!x.SNI.empty())
|
||||
proxy += ",sni=" + x.SNI;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -2452,6 +2493,49 @@ void proxyToSingBox(std::vector<Proxy> &nodes, rapidjson::Document &json, std::v
|
||||
proxy.AddMember("tls", tls, allocator);
|
||||
break;
|
||||
}
|
||||
case ProxyType::TUIC:
|
||||
{
|
||||
addSingBoxCommonMembers(proxy, x, "tuic", allocator);
|
||||
|
||||
if (!x.UUID.empty())
|
||||
proxy.AddMember("uuid", rapidjson::StringRef(x.UUID.c_str()), allocator);
|
||||
|
||||
if (!x.Password.empty())
|
||||
proxy.AddMember("password", rapidjson::StringRef(x.Password.c_str()), allocator);
|
||||
|
||||
if (!x.HeartbeatInterval.empty())
|
||||
proxy.AddMember("heartbeat", rapidjson::StringRef(x.HeartbeatInterval.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.UdpRelayMode.empty())
|
||||
proxy.AddMember("udp_relay_mode", rapidjson::StringRef(x.UdpRelayMode.c_str()), allocator);
|
||||
|
||||
if (!x.CongestionController.empty())
|
||||
proxy.AddMember("congestion_controller", rapidjson::StringRef(x.CongestionController.c_str()), allocator);
|
||||
|
||||
if (!x.SNI.empty())
|
||||
proxy.AddMember("sni", rapidjson::StringRef(x.SNI.c_str()), allocator);
|
||||
|
||||
if (!scv.is_undef())
|
||||
{
|
||||
rapidjson::Value tls(rapidjson::kObjectType);
|
||||
tls.AddMember("enabled", true, allocator);
|
||||
tls.AddMember("insecure", scv.get(), allocator);
|
||||
proxy.AddMember("tls", tls, allocator);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ProxyType::HTTP:
|
||||
case ProxyType::HTTPS:
|
||||
{
|
||||
|
||||
@ -22,7 +22,8 @@ enum class ProxyType
|
||||
SOCKS5,
|
||||
WireGuard,
|
||||
Hysteria,
|
||||
Hysteria2
|
||||
Hysteria2,
|
||||
TUIC
|
||||
};
|
||||
|
||||
inline String getProxyTypeName(ProxyType type)
|
||||
@ -51,6 +52,8 @@ inline String getProxyTypeName(ProxyType type)
|
||||
return "Hysteria";
|
||||
case ProxyType::Hysteria2:
|
||||
return "Hysteria2";
|
||||
case ProxyType::TUIC:
|
||||
return "TUIC";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@ -127,6 +130,18 @@ struct Proxy
|
||||
StringArray Alpn;
|
||||
|
||||
uint32_t CWND = 0;
|
||||
|
||||
String UUID;
|
||||
String IP;
|
||||
String HeartbeatInterval;
|
||||
tribool DisableSNI;
|
||||
tribool ReduceRTT;
|
||||
uint32_t RequestTimeout;
|
||||
String UdpRelayMode;
|
||||
String CongestionController;
|
||||
uint32_t MaxUdpRelayPacketSize;
|
||||
tribool FastOpen;
|
||||
uint32_t MaxOpenStreams;
|
||||
};
|
||||
|
||||
#define SS_DEFAULT_GROUP "SSProvider"
|
||||
@ -139,5 +154,6 @@ struct Proxy
|
||||
#define WG_DEFAULT_GROUP "WireGuardProvider"
|
||||
#define HYSTERIA_DEFAULT_GROUP "HysteriaProvider"
|
||||
#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider"
|
||||
#define TUIC_DEFAULT_GROUP "TUICProvider"
|
||||
|
||||
#endif // PROXY_H_INCLUDED
|
||||
|
||||
@ -224,7 +224,7 @@ void hysteria2Construct(
|
||||
const std::string &fingerprint,
|
||||
const std::string &alpn,
|
||||
const std::string &ca,
|
||||
const std::string &caStr,
|
||||
const std::string &ca_str,
|
||||
const std::string &cwnd,
|
||||
const std::string &hop_interval,
|
||||
tribool tfo,
|
||||
@ -245,11 +245,55 @@ void hysteria2Construct(
|
||||
node.Alpn = StringArray {alpn};
|
||||
}
|
||||
node.Ca = ca;
|
||||
node.CaStr = caStr;
|
||||
node.CaStr = ca_str;
|
||||
node.CWND = to_int(cwnd);
|
||||
node.HopInterval = to_int(hop_interval);
|
||||
}
|
||||
|
||||
void tuicConstruct(
|
||||
Proxy &node,
|
||||
const std::string &group,
|
||||
const std::string &remarks,
|
||||
const std::string &server,
|
||||
const std::string &port,
|
||||
const std::string &uuid,
|
||||
const std::string &password,
|
||||
const std::string &ip,
|
||||
const std::string &heartbeat_interval,
|
||||
const std::string &alpn,
|
||||
const std::string &disable_sni,
|
||||
const std::string &reduce_rtt,
|
||||
const std::string &request_timeout,
|
||||
const std::string &udp_relay_mode,
|
||||
const std::string &congestion_controller,
|
||||
const std::string &max_udp_relay_packet_size,
|
||||
const std::string &max_open_streams,
|
||||
const std::string &sni,
|
||||
const std::string &fast_open,
|
||||
tribool tfo,
|
||||
tribool scv,
|
||||
const std::string &underlying_proxy
|
||||
){
|
||||
commonConstruct(node, ProxyType::TUIC, group, remarks, server, port, tribool(), tfo, scv, tribool(), underlying_proxy);
|
||||
node.Password = password;
|
||||
node.UUID = uuid;
|
||||
node.IP = ip;
|
||||
node.HeartbeatInterval = heartbeat_interval;
|
||||
if (!alpn.empty())
|
||||
{
|
||||
node.Alpn = StringArray {alpn};
|
||||
}
|
||||
node.DisableSNI= disable_sni;
|
||||
node.ReduceRTT = reduce_rtt;
|
||||
node.RequestTimeout = to_int(request_timeout);
|
||||
node.UdpRelayMode = udp_relay_mode;
|
||||
node.CongestionController = congestion_controller;
|
||||
node.MaxUdpRelayPacketSize = to_int(max_udp_relay_packet_size);
|
||||
node.MaxOpenStreams = to_int(max_open_streams);
|
||||
node.SNI = sni;
|
||||
node.FastOpen = tribool(fast_open);
|
||||
}
|
||||
|
||||
void explodeVmess(std::string vmess, Proxy &node)
|
||||
{
|
||||
std::string version, ps, add, port, type, id, aid, net, path, host, tls, sni;
|
||||
@ -1101,6 +1145,7 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
|
||||
std::string ip, ipv6, private_key, public_key, mtu; //wireguard
|
||||
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 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
|
||||
string_array dns_server;
|
||||
tribool udp, tfo, scv;
|
||||
Node singleproxy;
|
||||
@ -1366,9 +1411,27 @@ void explodeClash(Node yamlnode, std::vector<Proxy> &nodes)
|
||||
singleproxy["cwnd"] >>= cwnd;
|
||||
singleproxy["hop-interval"] >>= hop_interval;
|
||||
|
||||
hysteria2Construct(node, group, ps, server, port, ports, up, down, password, obfs, obfs_password, sni, fingerprint, ca, ca_str, cwnd, alpn, hop_interval, tfo, scv, underlying_proxy);
|
||||
hysteria2Construct(node, group, ps, server, port, ports, up, down, password, obfs, obfs_password, sni, fingerprint, alpn, ca, ca_str, cwnd, hop_interval, tfo, scv, underlying_proxy);
|
||||
break;
|
||||
|
||||
case "tuic"_hash:
|
||||
group = TUIC_DEFAULT_GROUP;
|
||||
singleproxy["uuid"] >>= uuid;
|
||||
singleproxy["ip"] >>= ip;
|
||||
singleproxy["password"] >>= password;
|
||||
singleproxy["heartbeat_interval"] >>= heartbeat_interval;
|
||||
if (singleproxy["alpn"].IsSequence())
|
||||
singleproxy["alpn"][0] >>= alpn;
|
||||
else
|
||||
singleproxy["alpn"] >>= alpn;
|
||||
singleproxy["disable-sni"] >>= disable_sni;
|
||||
singleproxy["reduce-rtt"] >>= reduce_rtt;
|
||||
singleproxy["request-timeout"] >>= request_timeout;
|
||||
singleproxy["udp-relay-mode"] >>= udp_relay_mode;
|
||||
singleproxy["congestion-controller"] >>= congestion_controller;
|
||||
singleproxy["max-udp-relay-packet-size"] >>= max_udp_relay_packet_size;
|
||||
singleproxy["max-open-streams"] >>= max_open_streams;
|
||||
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);
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -1547,6 +1610,7 @@ void explodeStdHysteria2(std::string hysteria2, Proxy &node) {
|
||||
obfs = getUrlArg(addition, "obfs");
|
||||
obfs_password = getUrlArg(addition, "obfs-password");
|
||||
sni = getUrlArg(addition, "sni");
|
||||
|
||||
fingerprint = getUrlArg(addition, "pinSHA256");
|
||||
if (remarks.empty())
|
||||
remarks = add + ":" + port;
|
||||
@ -1566,6 +1630,78 @@ void explodeHysteria2(std::string hysteria2, Proxy &node) {
|
||||
}
|
||||
}
|
||||
|
||||
void explodeStdTuic(std::string tuic, Proxy &node) {
|
||||
std::string add, port,uuid, ip, password, token, heartbeat_interval, disable_sni, reduce_rtt, request_timeout;
|
||||
std::string udp_relay_mode, congestion_controller, max_udp_relay_packet_size, max_open_streams;
|
||||
std::string alpn, sni, fast_open, remarks, addition;
|
||||
tribool tfo, scv;
|
||||
|
||||
tuic = tuic.substr(7); // 去除 tuic://
|
||||
string_size pos;
|
||||
|
||||
pos = tuic.rfind("#");
|
||||
if (pos != tuic.npos) {
|
||||
remarks = urlDecode(tuic.substr(pos + 1));
|
||||
tuic.erase(pos);
|
||||
}
|
||||
|
||||
pos = tuic.rfind("?");
|
||||
if (pos != tuic.npos) {
|
||||
addition = tuic.substr(pos + 1);
|
||||
tuic.erase(pos);
|
||||
}
|
||||
|
||||
// 支持 user:pass@host:port
|
||||
if (strFind(tuic, "@")) {
|
||||
if (regGetMatch(tuic, R"(^(.*?):(.*?)@(.*?):(\d+)$)", 5, 0, &uuid, &password, &add, &port))
|
||||
return;
|
||||
} else {
|
||||
uuid = getUrlArg(addition, "uuid");
|
||||
password = getUrlArg(addition, "password");
|
||||
if (uuid.empty() || password.empty())
|
||||
return;
|
||||
|
||||
if (!strFind(tuic, ":"))
|
||||
return;
|
||||
|
||||
if (regGetMatch(tuic, R"(^(.*?):(\d+)$)", 3, 0, &ip, &port))
|
||||
return;
|
||||
}
|
||||
|
||||
// 其他参数
|
||||
token = getUrlArg(addition, "token");
|
||||
heartbeat_interval = getUrlArg(addition, "heartbeat_interval");
|
||||
disable_sni = getUrlArg(addition, "disable_sni");
|
||||
reduce_rtt = getUrlArg(addition, "reduce_rtt");
|
||||
request_timeout = getUrlArg(addition, "request_timeout");
|
||||
udp_relay_mode = getUrlArg(addition, "udp_relay_mode");
|
||||
congestion_controller = getUrlArg(addition, "congestion_control");
|
||||
max_udp_relay_packet_size = getUrlArg(addition, "max_udp_relay_packet_size");
|
||||
max_open_streams = getUrlArg(addition, "max_open_streams");
|
||||
alpn = getUrlArg(addition, "alpn");
|
||||
sni = getUrlArg(addition, "sni");
|
||||
fast_open = getUrlArg(addition, "fast_open");
|
||||
scv = getUrlArg(addition, "insecure");
|
||||
|
||||
if (remarks.empty())
|
||||
remarks = add + ":" + port;
|
||||
|
||||
tuicConstruct(node, TUIC_DEFAULT_GROUP, remarks, add, 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, "");
|
||||
}
|
||||
|
||||
void explodeTUIC(std::string tuic, Proxy &node) {
|
||||
tuic = regReplace(tuic, "(tuic)://", "tuic://");
|
||||
|
||||
// replace /? with ?
|
||||
tuic = regReplace(tuic, "/\\?", "?", true, false);
|
||||
if (regMatch(tuic, "tuic://(.*?)[:](.*)")) {
|
||||
explodeStdTuic(tuic, 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)
|
||||
void parsePeers(Proxy &node, const std::string &data)
|
||||
{
|
||||
@ -2463,6 +2599,8 @@ void explode(const std::string &link, Proxy &node)
|
||||
explodeTrojan(link, node);
|
||||
else if (strFind(link, "hysteria2://") || strFind(link, "hy2://"))
|
||||
explodeHysteria2(link, node);
|
||||
else if (strFind(link, "tuic://") || strFind(link, "tuic://"))
|
||||
explodeTUIC(link, node);
|
||||
else if(isLink(link))
|
||||
explodeHTTPSub(link, node);
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ void httpConstruct(Proxy &node, const std::string &group, const std::string &rem
|
||||
void trojanConstruct(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 &network, const std::string &host, const std::string &path, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool(), const std::string &underlying_proxy = "");
|
||||
void snellConstruct(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 &obfs, const std::string &host, uint16_t version = 0, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), const std::string &underlying_proxy = "");
|
||||
|
||||
|
||||
void hysteriaConstruct(
|
||||
Proxy &node,
|
||||
const std::string &group,
|
||||
@ -52,8 +53,8 @@ void hysteriaConstruct(
|
||||
const std::string &recv_window,
|
||||
const std::string &disable_mtu_discovery,
|
||||
const std::string &hop_interval,
|
||||
const std::string &alpn,
|
||||
tribool tfo,
|
||||
const std::string &alpn,
|
||||
tribool tfo,
|
||||
tribool scv,
|
||||
const std::string &underlying_proxy = ""
|
||||
);
|
||||
@ -82,6 +83,31 @@ void hysteria2Construct(
|
||||
const std::string &underlying_proxy = ""
|
||||
);
|
||||
|
||||
void tuicConstruct(
|
||||
Proxy &node,
|
||||
const std::string &group,
|
||||
const std::string &remarks,
|
||||
const std::string &server,
|
||||
const std::string &port,
|
||||
const std::string &uuid,
|
||||
const std::string &password,
|
||||
const std::string &ip,
|
||||
const std::string &heartbeat_interval,
|
||||
const std::string &alpn,
|
||||
const std::string &disable_sni,
|
||||
const std::string &reduce_rtt,
|
||||
const std::string &request_timeout,
|
||||
const std::string &udp_relay_mode,
|
||||
const std::string &congestion_controller,
|
||||
const std::string &max_udp_relay_packet_size,
|
||||
const std::string &max_open_streams,
|
||||
const std::string &sni,
|
||||
const std::string &fast_open,
|
||||
tribool tfo,
|
||||
tribool scv,
|
||||
const std::string &underlying_proxy = ""
|
||||
);
|
||||
|
||||
void explodeVmess(std::string vmess, Proxy &node);
|
||||
void explodeSSR(std::string ssr, Proxy &node);
|
||||
void explodeSS(std::string ss, Proxy &node);
|
||||
@ -91,6 +117,7 @@ void explodeStdVMess(std::string vmess, Proxy &node);
|
||||
void explodeShadowrocket(std::string kit, Proxy &node);
|
||||
void explodeKitsunebi(std::string kit, Proxy &node);
|
||||
void explodeHysteria2(std::string hysteria2, Proxy &node);
|
||||
void explodeTUIC(std::string tuic, Proxy &node);
|
||||
|
||||
/// Parse a link
|
||||
void explode(const std::string &link, Proxy &node);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user