Fix implementation of v2ray-plugin in Quantumult X subscriptions

Add example for using Clash proxy-provider.
Optimize codes.
This commit is contained in:
Tindy X committed 2020-07-10 17:48:34 +08:00
1 parent c4ef7ed9eb
commit dc4eae34b1
5 files changed
+142 -25

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
mixed-port: 7890
allow-lan: true
mode: Rule
log-level: info
external-controller: 127.0.0.1:9090
proxy-providers:
HK:
type: http
path: proxy-providers/HK.yaml
url: {{ getLink("/sub?target=clash&list=true&include=HK&url=https%3A%2F%2Fexample.com%2Fsubscription") }}
interval: 86400
health-check:
enable: true
url: http://www.gstatic.com/generate_204
interval: 300
rule-providers: ~
rules: ~
+19 -1
View File
@@ -162,7 +162,7 @@ public:
template <typename T> tribool(const T &value) { set(value); } template <typename T> tribool(const T &value) { set(value); }
explicit tribool(const tribool &value) { *this = value; } tribool(const tribool &value) { *this = value; }
~tribool() = default; ~tribool() = default;
@@ -194,6 +194,12 @@ public:
return *this; return *this;
} }
tribool reverse()
{
_M_VALUE = _M_VALUE == -1 ? -1 : (_M_VALUE == 0 ? 1 : 0);
return *this;
}
bool get(const bool &def_value = false) bool get(const bool &def_value = false)
{ {
if(_M_VALUE == -1) if(_M_VALUE == -1)
@@ -201,6 +207,18 @@ public:
return _M_VALUE; return _M_VALUE;
} }
std::string get_str()
{
switch(_M_VALUE)
{
case 0:
return "false";
case 1:
return "true";
}
return "undef";
}
template <typename T> bool set(const T &value) template <typename T> bool set(const T &value)
{ {
_M_VALUE = value; _M_VALUE = value;
+39 -8
View File
@@ -903,7 +903,7 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, const std::s
if(group.empty()) if(group.empty())
group = HTTP_DEFAULT_GROUP; group = HTTP_DEFAULT_GROUP;
node.group = group; node.group = group;
node.proxyStr = httpConstruct(group, remark, address, port, username, password, type == "HTTPS", scv); node.proxyStr = httpConstruct(group, remark, address, port, username, password, type == "HTTPS", tfo, scv);
break; break;
case "Trojan"_hash: case "Trojan"_hash:
host = GetMember(json, "Host"); host = GetMember(json, "Host");
@@ -1081,7 +1081,7 @@ void explodeClash(Node yamlnode, const std::string &custom_port, std::vector<nod
singleproxy["tls"] >>= tls; singleproxy["tls"] >>= tls;
node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP; node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP;
node.proxyStr = httpConstruct(group, ps, server, port, user, password, tls == "true", scv); node.proxyStr = httpConstruct(group, ps, server, port, user, password, tls == "true", tfo, scv);
break; break;
case "trojan"_hash: case "trojan"_hash:
group = TROJAN_DEFAULT_GROUP; group = TROJAN_DEFAULT_GROUP;
@@ -1242,7 +1242,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
for(auto &x : proxies) for(auto &x : proxies)
{ {
std::string remarks, server, port, method, username, password; //common std::string remarks, server, port, method, username, password; //common
std::string plugin, pluginopts, pluginopts_mode, pluginopts_host = "cloudfront.net", mod_url, mod_md5; //ss std::string plugin, pluginopts, pluginopts_mode, pluginopts_host, mod_url, mod_md5; //ss
std::string id, net, tls, host, edge, path; //v2 std::string id, net, tls, host, edge, path; //v2
std::string protocol, protoparam; //ssr std::string protocol, protoparam; //ssr
std::string itemName, itemVal, config; std::string itemName, itemVal, config;
@@ -1458,7 +1458,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
default: continue; default: continue;
} }
} }
node.proxyStr = httpConstruct(node.group, remarks, server, port, username, password, false, scv); node.proxyStr = httpConstruct(node.group, remarks, server, port, username, password, false, tfo, scv);
break; break;
case "trojan"_hash: // surge 4 style trojan proxy case "trojan"_hash: // surge 4 style trojan proxy
node.linkType = SPEEDTEST_MESSAGE_FOUNDTROJAN; node.linkType = SPEEDTEST_MESSAGE_FOUNDTROJAN;
@@ -1546,10 +1546,28 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
case "ssr-protocol"_hash: protocol = itemVal; break; case "ssr-protocol"_hash: protocol = itemVal; break;
case "ssr-protocol-param"_hash: protoparam = itemVal; break; case "ssr-protocol-param"_hash: protoparam = itemVal; break;
case "obfs"_hash: case "obfs"_hash:
plugin = "simple-obfs"; {
pluginopts_mode = itemVal; switch(hash_(itemVal))
{
case "http"_hash:
case "tls"_hash:
plugin = "simple-obfs";
pluginopts_mode = itemVal;
break;
case "wss"_hash:
tls = "tls";
[[fallthrough]];
case "ws"_hash:
pluginopts_mode = "websocket";
plugin = "v2ray-plugin";
break;
default:
pluginopts_mode = itemVal;
}
break; break;
}
case "obfs-host"_hash: pluginopts_host = itemVal; break; case "obfs-host"_hash: pluginopts_host = itemVal; break;
case "obfs-uri"_hash: path = itemVal; break;
case "udp-relay"_hash: udp = itemVal; break; case "udp-relay"_hash: udp = itemVal; break;
case "fast-open"_hash: tfo = itemVal; break; case "fast-open"_hash: tfo = itemVal; break;
case "tls13"_hash: tls13 = itemVal; break; case "tls13"_hash: tls13 = itemVal; break;
@@ -1558,11 +1576,23 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
} }
if(remarks.empty()) if(remarks.empty())
remarks = server + ":" + port; remarks = server + ":" + port;
if(plugin.size()) switch(hash_(plugin))
{ {
case "simple-obfs"_hash:
pluginopts = "obfs=" + pluginopts_mode; pluginopts = "obfs=" + pluginopts_mode;
if(pluginopts_host.size()) if(pluginopts_host.size())
pluginopts += ";obfs-host=" + pluginopts_host; pluginopts += ";obfs-host=" + pluginopts_host;
break;
case "v2ray-plugin"_hash:
if(pluginopts_host.empty() && !isIPv4(server) && !isIPv6(server))
pluginopts_host = server;
pluginopts = "mode=" + pluginopts_mode;
if(pluginopts_host.size())
pluginopts += ";host=" + pluginopts_host;
if(path.size())
pluginopts += ";path=" + path;
pluginopts += ";" + tls;
break;
} }
if(protocol.size()) if(protocol.size())
@@ -1681,6 +1711,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
case "over-tls"_hash: tls = itemVal; break; case "over-tls"_hash: tls = itemVal; break;
case "tls-verification"_hash: scv = itemVal == "false"; break; case "tls-verification"_hash: scv = itemVal == "false"; break;
case "tls13"_hash: tls13 = itemVal; break; case "tls13"_hash: tls13 = itemVal; break;
case "fast-open"_hash: tfo = itemVal; break;
default: continue; default: continue;
} }
} }
@@ -1697,7 +1728,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector
node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP; node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP;
node.group = HTTP_DEFAULT_GROUP; node.group = HTTP_DEFAULT_GROUP;
node.proxyStr = httpConstruct(node.group, remarks, server, port, username, password, tls == "true", scv, tls13); node.proxyStr = httpConstruct(node.group, remarks, server, port, username, password, tls == "true", tfo, scv, tls13);
break; break;
default: default:
continue; continue;
+1 -1
View File
@@ -11,7 +11,7 @@ std::string vmessConstruct(const std::string &group, const std::string &remarks,
std::string ssrConstruct(const std::string &group, const std::string &remarks, const std::string &remarks_base64, 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, bool libev, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); std::string ssrConstruct(const std::string &group, const std::string &remarks, const std::string &remarks_base64, 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, bool libev, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
std::string ssConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &method, const std::string &plugin, const std::string &pluginopts, bool libev, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); std::string ssConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &method, const std::string &plugin, const std::string &pluginopts, bool libev, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
std::string socksConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); std::string socksConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
std::string httpConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool scv = tribool(), tribool tls13 = tribool()); std::string httpConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
std::string trojanConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &host, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool()); std::string trojanConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &host, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
std::string snellConstruct(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, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool()); std::string snellConstruct(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, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
void explodeVmess(std::string vmess, const std::string &custom_port, nodeInfo &node); void explodeVmess(std::string vmess, const std::string &custom_port, nodeInfo &node);
+66 -15
View File
@@ -273,7 +273,7 @@ std::string socksConstruct(const std::string &group, const std::string &remarks,
return sb.GetString(); return sb.GetString();
} }
std::string httpConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool scv, tribool tls13) std::string httpConstruct(const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool tfo, tribool scv, tribool tls13)
{ {
rapidjson::StringBuffer sb; rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb); rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
@@ -292,6 +292,13 @@ std::string httpConstruct(const std::string &group, const std::string &remarks,
writer.String(username.data()); writer.String(username.data());
writer.Key("Password"); writer.Key("Password");
writer.String(password.data()); writer.String(password.data());
writer.Key("TLSSecure");
writer.Bool(tls);
if(!tfo.is_undef())
{
writer.Key("EnableTFO");
writer.Bool(tfo);
}
if(!scv.is_undef()) if(!scv.is_undef())
{ {
writer.Key("AllowInsecure"); writer.Key("AllowInsecure");
@@ -1540,8 +1547,18 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, const std::string &base_c
{ {
proxy = "custom, " + hostname + ", " + port + ", " + method + ", " + password + ", https://github.com/ConnersHua/SSEncrypt/raw/master/SSEncrypt.module"; proxy = "custom, " + hostname + ", " + port + ", " + method + ", " + password + ", https://github.com/ConnersHua/SSEncrypt/raw/master/SSEncrypt.module";
} }
if(plugin.size() && pluginopts.size()) if(plugin.size())
proxy += "," + replace_all_distinct(pluginopts, ";", ","); {
switch(hash_(plugin))
{
case "simple-obfs"_hash:
if(pluginopts.size())
proxy += "," + replace_all_distinct(pluginopts, ";", ",");
break;
default:
continue;
}
}
break; break;
case SPEEDTEST_MESSAGE_FOUNDVMESS: case SPEEDTEST_MESSAGE_FOUNDVMESS:
if(surge_ver < 4 && surge_ver != -3) if(surge_ver < 4 && surge_ver != -3)
@@ -1638,10 +1655,10 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, const std::string &base_c
continue; continue;
} }
if(tfo) if(!tfo.is_undef())
proxy += ", tfo=true"; proxy += ", tfo=" + tfo.get_str();
if(udp) if(!udp.is_undef())
proxy += ", udp-relay=true"; proxy += ", udp-relay=" + udp.get_str();
if(ext.nodelist) if(ext.nodelist)
output_nodelist += remark + " = " + proxy + "\n"; output_nodelist += remark + " = " + proxy + "\n";
@@ -2278,8 +2295,36 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
plugin = GetMember(json, "Plugin"); plugin = GetMember(json, "Plugin");
pluginopts = GetMember(json, "PluginOption"); pluginopts = GetMember(json, "PluginOption");
proxyStr = "shadowsocks = " + hostname + ":" + port + ", method=" + method + ", password=" + password; proxyStr = "shadowsocks = " + hostname + ":" + port + ", method=" + method + ", password=" + password;
if(plugin.size() && pluginopts.size()) if(plugin.size())
proxyStr += ", " + replace_all_distinct(pluginopts, ";", ", "); {
switch(hash_(plugin))
{
case "simple-obfs"_hash:
if(pluginopts.size())
proxyStr += ", " + replace_all_distinct(pluginopts, ";", ", ");
break;
case "v2ray-plugin"_hash:
pluginopts = replace_all_distinct(pluginopts, ";", "&");
plugin = getUrlArg(pluginopts, "mode") == "websocket" ? "ws" : "";
host = getUrlArg(pluginopts, "host");
path = getUrlArg(pluginopts, "path");
tlssecure = pluginopts.find("tls") != pluginopts.npos;
if(tlssecure && plugin == "ws")
{
plugin += 's';
if(!tls13.is_undef())
proxyStr += ", tls13=" + std::string(tls13 ? "true" : "false");
}
proxyStr += ", obfs=" + plugin;
if(host.size())
proxyStr += ", obfs-host=" + host;
if(path.size())
proxyStr += ", obfs-uri=" + path;
break;
default: continue;
}
}
break; break;
case SPEEDTEST_MESSAGE_FOUNDSSR: case SPEEDTEST_MESSAGE_FOUNDSSR:
password = GetMember(json, "Password"); password = GetMember(json, "Password");
@@ -2301,7 +2346,11 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
proxyStr = "http = " + hostname + ":" + port + ", username=" + (id.size() ? id : "none") + ", password=" + (password.size() ? password : "none"); proxyStr = "http = " + hostname + ":" + port + ", username=" + (id.size() ? id : "none") + ", password=" + (password.size() ? password : "none");
if(tlssecure) if(tlssecure)
{
proxyStr += ", over-tls=true"; proxyStr += ", over-tls=true";
if(!tls13.is_undef())
proxyStr += ", tls13=" + std::string(tls13 ? "true" : "false");
}
break; break;
case SPEEDTEST_MESSAGE_FOUNDTROJAN: case SPEEDTEST_MESSAGE_FOUNDTROJAN:
password = GetMember(json, "Password"); password = GetMember(json, "Password");
@@ -2312,17 +2361,19 @@ void netchToQuanX(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rule
if(tlssecure) if(tlssecure)
{ {
proxyStr += ", over-tls=true, tls-host=" + host; proxyStr += ", over-tls=true, tls-host=" + host;
if(!tls13.is_undef())
proxyStr += ", tls13=" + std::string(tls13 ? "true" : "false");
} }
break; break;
default: default:
continue; continue;
} }
if(tfo) if(!tfo.is_undef())
proxyStr += ", fast-open=true"; proxyStr += ", fast-open=" + tfo.get_str();
if(udp) if(!udp.is_undef())
proxyStr += ", udp-relay=true"; proxyStr += ", udp-relay=" + tfo.get_str();
if(scv && (x.linkType == SPEEDTEST_MESSAGE_FOUNDHTTP || x.linkType == SPEEDTEST_MESSAGE_FOUNDTROJAN)) if(!scv.is_undef() && (x.linkType == SPEEDTEST_MESSAGE_FOUNDHTTP || x.linkType == SPEEDTEST_MESSAGE_FOUNDTROJAN))
proxyStr += ", tls-verification=false"; proxyStr += ", tls-verification=" + scv.reverse().get_str();
proxyStr += ", tag=" + remark; proxyStr += ", tag=" + remark;
ini.Set("{NONAME}", proxyStr); ini.Set("{NONAME}", proxyStr);