mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 20:44:38 +03:00
refactor config builder
This commit is contained in:
@@ -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,26 +821,24 @@ 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{
|
||||||
{"enabled", true},
|
{"enabled", true},
|
||||||
{"outbounds", QJsonArray{tagProxy, "bypass"}},
|
{"outbounds", QJsonArray{tagProxy, "bypass"}},
|
||||||
}}}},
|
}}}},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WriteVPNSingBoxConfig() {
|
QString WriteVPNSingBoxConfig() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user