diff --git a/base/base/clash_provider_test.yml b/base/base/clash_provider_test.yml new file mode 100644 index 000000000..8e0611e8d --- /dev/null +++ b/base/base/clash_provider_test.yml @@ -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: ~ diff --git a/src/misc.h b/src/misc.h index 3c2bf8434..a7239329c 100644 --- a/src/misc.h +++ b/src/misc.h @@ -162,7 +162,7 @@ class tribool template tribool(const T &value) { set(value); } - explicit tribool(const tribool &value) { *this = value; } + tribool(const tribool &value) { *this = value; } ~tribool() = default; @@ -194,6 +194,12 @@ class tribool return *this; } + tribool reverse() + { + _M_VALUE = _M_VALUE == -1 ? -1 : (_M_VALUE == 0 ? 1 : 0); + return *this; + } + bool get(const bool &def_value = false) { if(_M_VALUE == -1) @@ -201,6 +207,18 @@ class tribool return _M_VALUE; } + std::string get_str() + { + switch(_M_VALUE) + { + case 0: + return "false"; + case 1: + return "true"; + } + return "undef"; + } + template bool set(const T &value) { _M_VALUE = value; diff --git a/src/speedtestutil.cpp b/src/speedtestutil.cpp index 6440d52f8..3bebf4790 100644 --- a/src/speedtestutil.cpp +++ b/src/speedtestutil.cpp @@ -903,7 +903,7 @@ void explodeNetch(std::string netch, bool ss_libev, bool ssr_libev, const std::s if(group.empty()) group = HTTP_DEFAULT_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; case "Trojan"_hash: host = GetMember(json, "Host"); @@ -1081,7 +1081,7 @@ void explodeClash(Node yamlnode, const std::string &custom_port, std::vector>= tls; 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; case "trojan"_hash: group = TROJAN_DEFAULT_GROUP; @@ -1242,7 +1242,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector for(auto &x : proxies) { 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 protocol, protoparam; //ssr std::string itemName, itemVal, config; @@ -1458,7 +1458,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector 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; case "trojan"_hash: // surge 4 style trojan proxy 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-param"_hash: protoparam = itemVal; break; 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; + } case "obfs-host"_hash: pluginopts_host = itemVal; break; + case "obfs-uri"_hash: path = itemVal; break; case "udp-relay"_hash: udp = itemVal; break; case "fast-open"_hash: tfo = 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()) remarks = server + ":" + port; - if(plugin.size()) + switch(hash_(plugin)) { + case "simple-obfs"_hash: pluginopts = "obfs=" + pluginopts_mode; if(pluginopts_host.size()) 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()) @@ -1681,6 +1711,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector case "over-tls"_hash: tls = itemVal; break; case "tls-verification"_hash: scv = itemVal == "false"; break; case "tls13"_hash: tls13 = itemVal; break; + case "fast-open"_hash: tfo = itemVal; break; default: continue; } } @@ -1697,7 +1728,7 @@ bool explodeSurge(std::string surge, const std::string &custom_port, std::vector node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP; 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; default: continue; diff --git a/src/speedtestutil.h b/src/speedtestutil.h index abfc000c2..29b5c125d 100644 --- a/src/speedtestutil.h +++ b/src/speedtestutil.h @@ -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 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 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 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); diff --git a/src/subexport.cpp b/src/subexport.cpp index d8db974aa..c9a375da1 100644 --- a/src/subexport.cpp +++ b/src/subexport.cpp @@ -273,7 +273,7 @@ std::string socksConstruct(const std::string &group, const std::string &remarks, 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::Writer writer(sb); @@ -292,6 +292,13 @@ std::string httpConstruct(const std::string &group, const std::string &remarks, writer.String(username.data()); writer.Key("Password"); writer.String(password.data()); + writer.Key("TLSSecure"); + writer.Bool(tls); + if(!tfo.is_undef()) + { + writer.Key("EnableTFO"); + writer.Bool(tfo); + } if(!scv.is_undef()) { writer.Key("AllowInsecure"); @@ -1540,8 +1547,18 @@ std::string netchToSurge(std::vector &nodes, const std::string &base_c { proxy = "custom, " + hostname + ", " + port + ", " + method + ", " + password + ", https://github.com/ConnersHua/SSEncrypt/raw/master/SSEncrypt.module"; } - if(plugin.size() && pluginopts.size()) - proxy += "," + replace_all_distinct(pluginopts, ";", ","); + if(plugin.size()) + { + switch(hash_(plugin)) + { + case "simple-obfs"_hash: + if(pluginopts.size()) + proxy += "," + replace_all_distinct(pluginopts, ";", ","); + break; + default: + continue; + } + } break; case SPEEDTEST_MESSAGE_FOUNDVMESS: if(surge_ver < 4 && surge_ver != -3) @@ -1638,10 +1655,10 @@ std::string netchToSurge(std::vector &nodes, const std::string &base_c continue; } - if(tfo) - proxy += ", tfo=true"; - if(udp) - proxy += ", udp-relay=true"; + if(!tfo.is_undef()) + proxy += ", tfo=" + tfo.get_str(); + if(!udp.is_undef()) + proxy += ", udp-relay=" + udp.get_str(); if(ext.nodelist) output_nodelist += remark + " = " + proxy + "\n"; @@ -2278,8 +2295,36 @@ void netchToQuanX(std::vector &nodes, INIReader &ini, std::vector &nodes, INIReader &ini, std::vector &nodes, INIReader &ini, std::vector