refactor config builder

This commit is contained in:
arm64v8a
2022-12-08 12:04:38 +09:00
parent 8d348e02c5
commit 0307758ff6
3 changed files with 133 additions and 119 deletions

View File

@@ -13,12 +13,19 @@ namespace NekoRay {
// Common // Common
QSharedPointer<BuildConfigResult> BuildConfig(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) { QSharedPointer<BuildConfigResult> BuildConfig(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) {
QSharedPointer<BuildConfigResult> result; auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
status->ent = ent;
status->result = result;
status->forTest = forTest;
status->forExport = forExport;
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
result = BuildConfigSingBox(ent, forTest, forExport); BuildConfigSingBox(status);
} else { } else {
result = BuildConfigV2Ray(ent, forTest, forExport); BuildConfigV2Ray(status);
} }
// hook.js // hook.js
if (result->error.isEmpty()) { if (result->error.isEmpty()) {
auto source = qjs::ReadHookJS(); auto source = qjs::ReadHookJS();
@@ -47,11 +54,11 @@ namespace NekoRay {
for (auto id: list) { for (auto id: list) {
ents += profileManager->GetProfile(id); ents += profileManager->GetProfile(id);
if (ents.last() == nullptr) { if (ents.last() == nullptr) {
result->error = QString("chain missing ent: %1").arg(id); status->result->error = QString("chain missing ent: %1").arg(id);
return {}; return {};
} }
if (ents.last()->type == "chain") { if (ents.last()->type == "chain") {
result->error = QString("chain in chain is not allowed: %1").arg(id); status->result->error = QString("chain in chain is not allowed: %1").arg(id);
return {}; return {};
} }
} }
@@ -125,15 +132,10 @@ namespace NekoRay {
// V2Ray // V2Ray
QSharedPointer<BuildConfigResult> BuildConfigV2Ray(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) { void BuildConfigV2Ray(const QSharedPointer<BuildConfigStatus> &status) {
auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
status->ent = ent;
status->result = result;
// Log // Log
auto logObj = QJsonObject{{"loglevel", dataStore->log_level}}; auto logObj = QJsonObject{{"loglevel", dataStore->log_level}};
result->coreConfig.insert("log", logObj); status->result->coreConfig.insert("log", logObj);
// Inbounds // Inbounds
QJsonObject sniffing{ QJsonObject sniffing{
@@ -145,7 +147,7 @@ namespace NekoRay {
}; };
// socks-in // socks-in
if (InRange(dataStore->inbound_socks_port, 0, 65535) && !forTest) { if (InRange(dataStore->inbound_socks_port, 0, 65535) && !status->forTest) {
QJsonObject socksInbound; QJsonObject socksInbound;
socksInbound["tag"] = "socks-in"; socksInbound["tag"] = "socks-in";
socksInbound["protocol"] = "socks"; socksInbound["protocol"] = "socks";
@@ -161,7 +163,7 @@ namespace NekoRay {
status->inbounds += socksInbound; status->inbounds += socksInbound;
} }
// http-in // http-in
if (InRange(dataStore->inbound_http_port, 0, 65535) && !forTest) { if (InRange(dataStore->inbound_http_port, 0, 65535) && !status->forTest) {
QJsonObject socksInbound; QJsonObject socksInbound;
socksInbound["tag"] = "http-in"; socksInbound["tag"] = "http-in";
socksInbound["protocol"] = "http"; socksInbound["protocol"] = "http";
@@ -175,7 +177,7 @@ namespace NekoRay {
// Outbounds // Outbounds
auto tagProxy = BuildChain(0, status); auto tagProxy = BuildChain(0, status);
if (!result->error.isEmpty()) return result; if (!status->result->error.isEmpty()) return;
// direct & bypass & block // direct & bypass & block
status->outbounds += QJsonObject{ status->outbounds += QJsonObject{
@@ -192,7 +194,7 @@ namespace NekoRay {
}; };
// block for tun // block for tun
if (!forTest) { if (!status->forTest) {
status->routingRules += QJsonObject{ status->routingRules += QJsonObject{
{"type", "field"}, {"type", "field"},
{ {
@@ -212,7 +214,7 @@ namespace NekoRay {
} }
// DNS Routing (tun2socks 用到,防污染) // DNS Routing (tun2socks 用到,防污染)
if (dataStore->dns_routing && !forTest) { if (dataStore->dns_routing && !status->forTest) {
QJsonObject dnsOut; QJsonObject dnsOut;
dnsOut["protocol"] = "dns"; dnsOut["protocol"] = "dns";
dnsOut["tag"] = "dns-out"; dnsOut["tag"] = "dns-out";
@@ -240,13 +242,13 @@ namespace NekoRay {
} }
// custom inbound // custom inbound
QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray()) if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray())
result->coreConfig.insert("inbounds", status->inbounds); status->result->coreConfig.insert("inbounds", status->inbounds);
result->coreConfig.insert("outbounds", status->outbounds); status->result->coreConfig.insert("outbounds", status->outbounds);
// user rule // user rule
if (!forTest) { if (!status->forTest) {
DOMAIN_USER_RULE DOMAIN_USER_RULE
IP_USER_RULE IP_USER_RULE
} }
@@ -258,8 +260,8 @@ namespace NekoRay {
// Remote or FakeDNS // Remote or FakeDNS
QJsonObject dnsServerRemote; QJsonObject dnsServerRemote;
dnsServerRemote["address"] = dataStore->fake_dns ? "fakedns" : dataStore->remote_dns; dnsServerRemote["address"] = dataStore->fake_dns ? "fakedns" : dataStore->remote_dns;
dnsServerRemote["domains"] = status->domainListDNSRemote; dnsServerRemote["domains"] = QList2QJsonArray<QString>(status->domainListDNSRemote);
if (!forTest) dnsServers += dnsServerRemote; if (!status->forTest) dnsServers += dnsServerRemote;
// Direct // Direct
auto directDnsAddress = dataStore->direct_dns; auto directDnsAddress = dataStore->direct_dns;
@@ -287,19 +289,20 @@ namespace NekoRay {
} }
dnsServers += QJsonObject{ dnsServers += QJsonObject{
{"address", directDnsAddress}, {"address", directDnsAddress},
{"domains", status->domainListDNSDirect}, {"domains", QList2QJsonArray<QString>(status->domainListDNSDirect)},
{"skipFallback", true}, {"skipFallback", true},
}; };
dns["disableFallbackIfMatch"] = true; dns["disableFallbackIfMatch"] = true;
dns["servers"] = dnsServers; dns["servers"] = dnsServers;
dns["tag"] = "dns"; dns["tag"] = "dns";
result->coreConfig.insert("dns", dns); status->result->coreConfig.insert("dns", dns);
// Routing // Routing
QJsonObject routing; QJsonObject routing;
routing["domainStrategy"] = dataStore->domain_strategy; routing["domainStrategy"] = dataStore->domain_strategy;
routing["domainMatcher"] = dataStore->domain_matcher == DomainMatcher::MPH ? "mph" : "linear"; routing["domainMatcher"] = dataStore->domain_matcher == DomainMatcher::MPH ? "mph" : "linear";
if (status->forTest) routing["domainStrategy"] = "AsIs";
// final add block route // final add block route
QJsonObject routingRule_tmp; QJsonObject routingRule_tmp;
@@ -307,12 +310,12 @@ namespace NekoRay {
routingRule_tmp["outboundTag"] = "block"; routingRule_tmp["outboundTag"] = "block";
if (!status->ipListBlock.isEmpty()) { if (!status->ipListBlock.isEmpty()) {
auto tmp = routingRule_tmp; auto tmp = routingRule_tmp;
tmp["ip"] = status->ipListBlock; tmp["ip"] = QList2QJsonArray<QString>(status->ipListBlock);
status->routingRules += tmp; status->routingRules += tmp;
} }
if (!status->domainListBlock.isEmpty()) { if (!status->domainListBlock.isEmpty()) {
auto tmp = routingRule_tmp; auto tmp = routingRule_tmp;
tmp["domain"] = status->domainListBlock; tmp["domain"] = QList2QJsonArray<QString>(status->domainListBlock);
status->routingRules += tmp; status->routingRules += tmp;
} }
@@ -320,12 +323,12 @@ namespace NekoRay {
routingRule_tmp["outboundTag"] = "proxy"; routingRule_tmp["outboundTag"] = "proxy";
if (!status->ipListRemote.isEmpty()) { if (!status->ipListRemote.isEmpty()) {
auto tmp = routingRule_tmp; auto tmp = routingRule_tmp;
tmp["ip"] = status->ipListRemote; tmp["ip"] = QList2QJsonArray<QString>(status->ipListRemote);
status->routingRules += tmp; status->routingRules += tmp;
} }
if (!status->domainListRemote.isEmpty()) { if (!status->domainListRemote.isEmpty()) {
auto tmp = routingRule_tmp; auto tmp = routingRule_tmp;
tmp["domain"] = status->domainListRemote; tmp["domain"] = QList2QJsonArray<QString>(status->domainListRemote);
status->routingRules += tmp; status->routingRules += tmp;
} }
@@ -333,22 +336,23 @@ namespace NekoRay {
routingRule_tmp["outboundTag"] = "bypass"; routingRule_tmp["outboundTag"] = "bypass";
if (!status->ipListDirect.isEmpty()) { if (!status->ipListDirect.isEmpty()) {
auto tmp = routingRule_tmp; auto tmp = routingRule_tmp;
tmp["ip"] = status->ipListDirect; tmp["ip"] = QList2QJsonArray<QString>(status->ipListDirect);
status->routingRules += tmp; status->routingRules += tmp;
} }
if (!status->domainListDirect.isEmpty()) { if (!status->domainListDirect.isEmpty()) {
auto tmp = routingRule_tmp; auto tmp = routingRule_tmp;
tmp["domain"] = status->domainListDirect; tmp["domain"] = QList2QJsonArray<QString>(status->domainListDirect);
status->routingRules += tmp; status->routingRules += tmp;
} }
// final add routing rule // final add routing rule
// custom routing rule // custom routing rule
auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray(); auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray();
QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray()) if (status->forTest) routingRules = {};
if (!status->forTest) QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray())
QJSONARRAY_ADD(routingRules, status->routingRules) QJSONARRAY_ADD(routingRules, status->routingRules)
routing["rules"] = routingRules; routing["rules"] = routingRules;
result->coreConfig.insert("routing", routing); status->result->coreConfig.insert("routing", routing);
// Policy & stats // Policy & stats
QJsonObject policy; QJsonObject policy;
@@ -362,10 +366,8 @@ namespace NekoRay {
policySystem["statsOutboundDownlink"] = true; policySystem["statsOutboundDownlink"] = true;
policySystem["statsOutboundUplink"] = true; policySystem["statsOutboundUplink"] = true;
policy["system"] = policySystem; policy["system"] = policySystem;
result->coreConfig.insert("policy", policy); status->result->coreConfig.insert("policy", policy);
result->coreConfig.insert("stats", QJsonObject()); status->result->coreConfig.insert("stats", QJsonObject());
return result;
} }
QString BuildChainInternal(int chainId, const QList<QSharedPointer<ProxyEntity>> &ents, QString BuildChainInternal(int chainId, const QList<QSharedPointer<ProxyEntity>> &ents,
@@ -555,9 +557,10 @@ namespace NekoRay {
status->result->outboundStats += ent->traffic_data; status->result->outboundStats += ent->traffic_data;
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
// TODO no such field?
auto ds = dataStore->outbound_domain_strategy; auto ds = dataStore->outbound_domain_strategy;
if (ds == "UseIPv4") { if (status->forTest) {
ds = "";
} else if (ds == "UseIPv4") {
ds = "ipv4_only"; ds = "ipv4_only";
} else if (ds == "UseIPv6") { } else if (ds == "UseIPv6") {
ds = "ipv6_only"; ds = "ipv6_only";
@@ -571,7 +574,7 @@ namespace NekoRay {
outbound["domain_strategy"] = ds; outbound["domain_strategy"] = ds;
// TODO apply mux // TODO apply mux
} else { } else {
outbound["domainStrategy"] = dataStore->outbound_domain_strategy; if (!status->forTest) outbound["domainStrategy"] = dataStore->outbound_domain_strategy;
// apply mux // apply mux
if (dataStore->mux_cool > 0 && !muxApplied) { if (dataStore->mux_cool > 0 && !muxApplied) {
// TODO refactor mux settings // TODO refactor mux settings
@@ -616,19 +619,14 @@ namespace NekoRay {
// SingBox // SingBox
QSharedPointer<BuildConfigResult> BuildConfigSingBox(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport) { void BuildConfigSingBox(const QSharedPointer<BuildConfigStatus> &status) {
auto result = QSharedPointer<BuildConfigResult>(new BuildConfigResult);
auto status = QSharedPointer<BuildConfigStatus>(new BuildConfigStatus);
status->ent = ent;
status->result = result;
// Log // Log
result->coreConfig["log"] = QJsonObject{{"level", dataStore->log_level}}; status->result->coreConfig["log"] = QJsonObject{{"level", dataStore->log_level}};
// Inbounds // Inbounds
// mixed-in // mixed-in
if (InRange(dataStore->inbound_socks_port, 0, 65535) && !forTest) { if (InRange(dataStore->inbound_socks_port, 0, 65535) && !status->forTest) {
QJsonObject socksInbound; QJsonObject socksInbound;
socksInbound["tag"] = "mixed-in"; socksInbound["tag"] = "mixed-in";
socksInbound["type"] = "mixed"; socksInbound["type"] = "mixed";
@@ -643,7 +641,7 @@ namespace NekoRay {
// Outbounds // Outbounds
auto tagProxy = BuildChain(0, status); auto tagProxy = BuildChain(0, status);
if (!result->error.isEmpty()) return result; if (!status->result->error.isEmpty()) return;
// direct & bypass & block // direct & bypass & block
status->outbounds += QJsonObject{ status->outbounds += QJsonObject{
@@ -658,7 +656,7 @@ namespace NekoRay {
{"type", "block"}, {"type", "block"},
{"tag", "block"}, {"tag", "block"},
}; };
if (!forTest) { if (!status->forTest) {
status->outbounds += QJsonObject{ status->outbounds += QJsonObject{
{"type", "dns"}, {"type", "dns"},
{"tag", "dns-out"}, {"tag", "dns-out"},
@@ -666,59 +664,60 @@ namespace NekoRay {
} }
// custom inbound // custom inbound
QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray()) if (!status->forTest) QJSONARRAY_ADD(status->inbounds, QString2QJsonObject(dataStore->custom_inbound)["inbounds"].toArray())
result->coreConfig.insert("inbounds", status->inbounds); status->result->coreConfig.insert("inbounds", status->inbounds);
result->coreConfig.insert("outbounds", status->outbounds); status->result->coreConfig.insert("outbounds", status->outbounds);
// user rule // user rule
if (!forTest) { if (!status->forTest) {
DOMAIN_USER_RULE DOMAIN_USER_RULE
IP_USER_RULE IP_USER_RULE
} }
// sing-box common rule object // sing-box common rule object
auto make_rule = [&](const QJsonArray &arr, bool isIP = false) { auto make_rule = [&](const QStringList &list, bool isIP = false) {
QJsonObject rule; QJsonObject rule;
QJsonArray ips; //
QJsonArray geoips; QJsonArray ip_cidr;
QJsonArray geoip;
//
QJsonArray domain_keyword; QJsonArray domain_keyword;
QJsonArray domain_subdomain; QJsonArray domain_subdomain;
QJsonArray domain_full; QJsonArray domain_full;
QJsonArray domain_suffix; QJsonArray domain_suffix;
QJsonArray geosites; QJsonArray geosite;
for (const auto &domain_: arr) { for (auto item: list) {
auto domain = domain_.toString();
if (isIP) { if (isIP) {
if (domain.startsWith("geoip:")) { if (item.startsWith("geoip:")) {
geoips += domain.replace("geoip:", ""); geoip += item.replace("geoip:", "");
} else { } else {
ips += domain; ip_cidr += item;
} }
} else { } else {
if (domain.startsWith("geosite:")) { if (item.startsWith("geosite:")) {
geosites += domain.replace("geosite:", ""); geosite += item.replace("geosite:", "");
} else if (domain.startsWith("full:")) { } else if (item.startsWith("full:")) {
domain_full += domain.replace("full:", ""); domain_full += item.replace("full:", "");
} else if (domain.startsWith("domain:")) { } else if (item.startsWith("domain:")) {
domain_suffix += domain.replace("domain:", ""); domain_suffix += item.replace("domain:", "");
} else { } else {
domain_keyword += domain; domain_keyword += item;
} }
} }
} }
if (isIP) { if (isIP) {
if (ips.isEmpty() && geoips.isEmpty()) return rule; if (ip_cidr.isEmpty() && geoip.isEmpty()) return rule;
rule["ip_cidr"] = ips; rule["ip_cidr"] = ip_cidr;
rule["geoip"] = geoips; rule["geoip"] = geoip;
} else { } else {
if (domain_keyword.isEmpty() && domain_subdomain.isEmpty() && domain_full.isEmpty() && geosites.isEmpty()) { if (domain_keyword.isEmpty() && domain_subdomain.isEmpty() && domain_full.isEmpty() && geosite.isEmpty()) {
return rule; return rule;
} }
rule["domain"] = domain_full; rule["domain"] = domain_full;
rule["domain_suffix"] = domain_suffix; rule["domain_suffix"] = domain_suffix;
rule["domain_keyword"] = domain_keyword; rule["domain_keyword"] = domain_keyword;
rule["geosite"] = geosites; rule["geosite"] = geosite;
} }
return rule; return rule;
}; };
@@ -729,7 +728,7 @@ namespace NekoRay {
QJsonArray dnsRules; QJsonArray dnsRules;
// Remote // Remote
if (!forTest) if (!status->forTest)
dnsServers += QJsonObject{ dnsServers += QJsonObject{
{"tag", "dns-remote"}, {"tag", "dns-remote"},
{"address_resolver", "dns-underlying"}, {"address_resolver", "dns-underlying"},
@@ -738,12 +737,12 @@ namespace NekoRay {
}; };
// neko only // neko only
auto underlyingStr = forExport ? "local" : "underlying://0.0.0.0"; auto underlyingStr = status->forExport ? "local" : "underlying://0.0.0.0";
// Direct // Direct
auto directDNSAddress = dataStore->direct_dns; auto directDNSAddress = dataStore->direct_dns;
if (directDNSAddress == "localhost") directDNSAddress = underlyingStr; if (directDNSAddress == "localhost") directDNSAddress = underlyingStr;
if (!forTest) if (!status->forTest)
dnsServers += QJsonObject{ dnsServers += QJsonObject{
{"tag", "dns-direct"}, {"tag", "dns-direct"},
{"address_resolver", "dns-underlying"}, {"address_resolver", "dns-underlying"},
@@ -759,8 +758,8 @@ namespace NekoRay {
}; };
// sing-box dns rule object // sing-box dns rule object
auto add_rule_dns = [&](const QJsonArray &arr, const QString &server) { auto add_rule_dns = [&](const QStringList &list, const QString &server) {
auto rule = make_rule(arr, false); auto rule = make_rule(list, false);
if (rule.isEmpty()) return; if (rule.isEmpty()) return;
rule["server"] = server; rule["server"] = server;
dnsRules += rule; dnsRules += rule;
@@ -771,19 +770,20 @@ namespace NekoRay {
dns["servers"] = dnsServers; dns["servers"] = dnsServers;
dns["rules"] = dnsRules; dns["rules"] = dnsRules;
result->coreConfig.insert("dns", dns); status->result->coreConfig.insert("dns", dns);
// Routing // Routing
// custom routing rule (top) // custom routing rule (top)
auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray(); auto routingRules = QString2QJsonObject(dataStore->routing->custom)["rules"].toArray();
if (status->forTest) routingRules = {};
// dns hijack // dns hijack
if (!forTest) routingRules += QJsonObject{{"protocol", "dns"}, {"outbound", "dns-out"}}; if (!status->forTest) routingRules += QJsonObject{{"protocol", "dns"}, {"outbound", "dns-out"}};
// sing-box routing rule object // sing-box routing rule object
auto add_rule_route = [&](const QJsonArray &arr, bool isIP, const QString &out) { auto add_rule_route = [&](const QStringList &list, bool isIP, const QString &out) {
auto rule = make_rule(arr, isIP); auto rule = make_rule(list, isIP);
if (rule.isEmpty()) return; if (rule.isEmpty()) return;
rule["outbound"] = out; rule["outbound"] = out;
routingRules += rule; routingRules += rule;
@@ -800,11 +800,11 @@ namespace NekoRay {
// geopath // geopath
auto geoip = FindCoreAsset("geoip.db"); auto geoip = FindCoreAsset("geoip.db");
auto geosite = FindCoreAsset("geosite.db"); auto geosite = FindCoreAsset("geosite.db");
if (geoip.isEmpty()) result->error = +"geoip.db not found"; if (geoip.isEmpty()) status->result->error = +"geoip.db not found";
if (geosite.isEmpty()) result->error = +"geosite.db not found"; if (geosite.isEmpty()) status->result->error = +"geosite.db not found";
// final add routing rule // final add routing rule
QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray()) if (!status->forTest) QJSONARRAY_ADD(routingRules, QString2QJsonObject(dataStore->custom_route_global)["rules"].toArray())
QJSONARRAY_ADD(routingRules, status->routingRules) QJSONARRAY_ADD(routingRules, status->routingRules)
auto routeObj = QJsonObject{ auto routeObj = QJsonObject{
{"rules", routingRules}, {"rules", routingRules},
@@ -821,16 +821,16 @@ namespace NekoRay {
{"path", geosite}, {"path", geosite},
}, },
}}; }};
if (forExport) { if (status->forExport) {
routeObj.remove("geoip"); routeObj.remove("geoip");
routeObj.remove("geosite"); routeObj.remove("geosite");
routeObj.remove("auto_detect_interface"); routeObj.remove("auto_detect_interface");
} }
result->coreConfig.insert("route", routeObj); status->result->coreConfig.insert("route", routeObj);
// api // api
if (!forTest && !forExport && dataStore->traffic_loop_interval > 0) { if (!status->forTest && !status->forExport && dataStore->traffic_loop_interval > 0) {
result->coreConfig.insert("experimental", QJsonObject{ status->result->coreConfig.insert("experimental", QJsonObject{
{"v2ray_api", QJsonObject{ {"v2ray_api", QJsonObject{
{"listen", "127.0.0.1:" + Int2String(dataStore->inbound_socks_port + 10)}, {"listen", "127.0.0.1:" + Int2String(dataStore->inbound_socks_port + 10)},
{"stats", QJsonObject{ {"stats", QJsonObject{
@@ -839,8 +839,6 @@ namespace NekoRay {
}}}}, }}}},
}); });
} }
return result;
} }
QString WriteVPNSingBoxConfig() { QString WriteVPNSingBoxConfig() {

View File

@@ -19,21 +19,24 @@ namespace NekoRay {
class BuildConfigStatus { class BuildConfigStatus {
public: public:
QList<int> globalProfiles;
QSharedPointer<BuildConfigResult> result; QSharedPointer<BuildConfigResult> result;
QSharedPointer<ProxyEntity> ent; QSharedPointer<ProxyEntity> ent;
bool forTest;
bool forExport;
// priv
QList<int> globalProfiles;
// xxList is V2Ray format string list // xxList is V2Ray format string list
QJsonArray domainListDNSRemote; QStringList domainListDNSRemote;
QJsonArray domainListDNSDirect; QStringList domainListDNSDirect;
QJsonArray domainListRemote; QStringList domainListRemote;
QJsonArray domainListDirect; QStringList domainListDirect;
QJsonArray ipListRemote; QStringList ipListRemote;
QJsonArray ipListDirect; QStringList ipListDirect;
QJsonArray domainListBlock; QStringList domainListBlock;
QJsonArray ipListBlock; QStringList ipListBlock;
// config format // config format
@@ -42,14 +45,11 @@ namespace NekoRay {
QJsonArray outbounds; QJsonArray outbounds;
}; };
QSharedPointer<BuildConfigResult> BuildConfig(const QSharedPointer<ProxyEntity> &ent, QSharedPointer<BuildConfigResult> BuildConfig(const QSharedPointer<ProxyEntity> &ent, bool forTest, bool forExport);
bool forTest, bool forExport);
QSharedPointer<BuildConfigResult> BuildConfigV2Ray(const QSharedPointer<ProxyEntity> &ent, void BuildConfigV2Ray(const QSharedPointer<BuildConfigStatus> &status);
bool forTest, bool forExport);
QSharedPointer<BuildConfigResult> BuildConfigSingBox(const QSharedPointer<ProxyEntity> &ent, void BuildConfigSingBox(const QSharedPointer<BuildConfigStatus> &status);
bool forTest, bool forExport);
QString BuildChain(int chainId, const QSharedPointer<BuildConfigStatus> &status); QString BuildChain(int chainId, const QSharedPointer<BuildConfigStatus> &status);

View File

@@ -228,10 +228,26 @@ namespace NekoRay::sub {
auto plugin_n = proxy["plugin"]; auto plugin_n = proxy["plugin"];
auto pluginOpts_n = proxy["plugin-opts"]; auto pluginOpts_n = proxy["plugin-opts"];
if (plugin_n.IsDefined() && pluginOpts_n.IsDefined()) { if (plugin_n.IsDefined() && pluginOpts_n.IsDefined()) {
if (Node2QString(plugin_n) == "obfs") { QStringList ssPlugin;
bean->plugin = "obfs-local;obfs=" + Node2QString(pluginOpts_n["mode"]) + ";obfs-host=" + auto plugin = Node2QString(plugin_n);
Node2QString(pluginOpts_n["host"]); if (plugin == "obfs") {
ssPlugin << "obfs-local";
ssPlugin << "obfs=" + Node2QString(pluginOpts_n["mode"]);
ssPlugin << "obfs-host=" + Node2QString(pluginOpts_n["host"]);
} else if (plugin == "v2ray-plugin") {
auto mode = Node2QString(pluginOpts_n["mode"]);
auto host = Node2QString(pluginOpts_n["host"]);
auto path = Node2QString(pluginOpts_n["path"]);
ssPlugin << "v2ray-plugin";
if (!mode.isEmpty() && mode != "websocket") ssPlugin << "mode=" + mode;
if (Node2Bool(pluginOpts_n["tls"])) ssPlugin << "tls";
if (!host.isEmpty()) ssPlugin << "host=" + host;
if (!path.isEmpty()) ssPlugin << "path=" + path;
// clash only: skip-cert-verify
// clash only: headers
// clash: mux=?
} }
bean->plugin = ssPlugin.join(";");
} }
auto protocol_n = proxy["protocol"]; auto protocol_n = proxy["protocol"];
if (protocol_n.IsDefined()) { if (protocol_n.IsDefined()) {