mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2025-12-19 13:50:12 +08:00
prepare routting rules for SB 1.11
This commit is contained in:
parent
26efd64821
commit
4b39687871
@ -8,4 +8,6 @@ namespace Preset::SingBox {
|
||||
inline QStringList V2RAYTransports = {"http", "grpc", "quic", "httpupgrade", "ws", "tcp"};
|
||||
inline QStringList Flows = {"xtls-rprx-vision"};
|
||||
inline QStringList SniffProtocols = {"http", "tls", "quic", "stun", "dns", "bittorrent", "dtls", "ssh", "rdp"};
|
||||
inline QStringList ActionTypes = {"route", "reject", "hijack-dns", "route-options", "sniff", "resolve"};
|
||||
inline QStringList rejectMethods = {"default", "drop"};
|
||||
} // namespace Preset::SingBox
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <include/configs/proxy/Preset.hpp>
|
||||
|
||||
#include "include/global/NekoGui.hpp"
|
||||
|
||||
namespace NekoGui {
|
||||
@ -36,15 +38,37 @@ namespace NekoGui {
|
||||
QList<QString> rule_set;
|
||||
bool invert = false;
|
||||
int outboundID = -2; // -1 is proxy -2 is direct -3 is block -4 is dns_out
|
||||
// since sing-box 1.11.0
|
||||
QString actionType = "route";
|
||||
|
||||
[[nodiscard]] QJsonObject get_rule_json(bool forView = false, const QString& outboundTag = "") const;
|
||||
// reject options
|
||||
QString rejectMethod;
|
||||
bool no_drop = false;
|
||||
|
||||
// route options
|
||||
QString override_address;
|
||||
QString override_port;
|
||||
// TODO maybe add some of dial fields?
|
||||
|
||||
// sniff options
|
||||
QStringList sniffers;
|
||||
bool sniffOverrideDest = false;
|
||||
|
||||
// resolve options
|
||||
QString strategy;
|
||||
|
||||
[[nodiscard]] QJsonObject get_rule_json(bool forView = false, const QString& outboundTag = "");
|
||||
static QStringList get_attributes();
|
||||
static QStringList get_route_options();
|
||||
static QStringList get_reject_options();
|
||||
static QStringList get_sniff_options();
|
||||
static QStringList get_resolve_options();
|
||||
static inputType get_input_type(const QString& fieldName);
|
||||
static QStringList get_values_for_field(const QString& fieldName);
|
||||
QStringList get_current_value_string(const QString& fieldName);
|
||||
[[nodiscard]] QString get_current_value_bool(const QString& fieldName) const;
|
||||
void set_field_value(const QString& fieldName, const QStringList& value);
|
||||
[[nodiscard]] bool isEmpty() const;
|
||||
[[nodiscard]] bool isEmpty();
|
||||
};
|
||||
|
||||
class RoutingChain : public JsonStore {
|
||||
|
||||
@ -46,6 +46,14 @@ namespace NekoGui {
|
||||
rule_set << other.rule_set;
|
||||
invert = other.invert;
|
||||
outboundID = other.outboundID;
|
||||
actionType = other.actionType;
|
||||
rejectMethod = other.rejectMethod;
|
||||
no_drop = other.no_drop;
|
||||
override_address = other.override_address;
|
||||
override_port = other.override_port;
|
||||
sniffers << other.sniffers;
|
||||
sniffOverrideDest = other.sniffOverrideDest;
|
||||
strategy = other.strategy;
|
||||
|
||||
_add(new configItem("name", &name, itemType::string));
|
||||
_add(new configItem("ip_version", &ip_version, itemType::string));
|
||||
@ -70,9 +78,17 @@ namespace NekoGui {
|
||||
_add(new configItem("rule_set", &rule_set, itemType::stringList));
|
||||
_add(new configItem("invert", &invert, itemType::boolean));
|
||||
_add(new configItem("outboundID", &outboundID, itemType::integer));
|
||||
_add(new configItem("actionType", &actionType, itemType::string));
|
||||
_add(new configItem("rejectMethod", &rejectMethod, itemType::string));
|
||||
_add(new configItem("noDrop", &no_drop, itemType::boolean));
|
||||
_add(new configItem("override_address", &override_address, itemType::string));
|
||||
_add(new configItem("override_port", &override_port, itemType::integer));
|
||||
_add(new configItem("sniffers", &sniffers, itemType::stringList));
|
||||
_add(new configItem("sniffOverrideDest", &sniffOverrideDest, itemType::boolean));
|
||||
_add(new configItem("strategy", &strategy, itemType::string));
|
||||
}
|
||||
|
||||
QJsonObject RouteRule::get_rule_json(bool forView, const QString& outboundTag) const {
|
||||
QJsonObject RouteRule::get_rule_json(bool forView, const QString& outboundTag) {
|
||||
QJsonObject obj;
|
||||
|
||||
if (!ip_version.isEmpty()) obj["ip_version"] = ip_version.toInt();
|
||||
@ -96,32 +112,56 @@ namespace NekoGui {
|
||||
if (isValidStrArray(process_path_regex)) obj["process_path_regex"] = get_as_array(process_path_regex);
|
||||
if (isValidStrArray(rule_set)) obj["rule_set"] = get_as_array(rule_set);
|
||||
if (invert) obj["invert"] = invert;
|
||||
// fix action type
|
||||
if (actionType == "route")
|
||||
{
|
||||
if (outboundID == -3) actionType = "reject";
|
||||
if (outboundID == -4) actionType = "resolve";
|
||||
}
|
||||
obj["action_type"] = actionType;
|
||||
|
||||
if (forView) {
|
||||
switch (outboundID) { // TODO use constants
|
||||
case -1:
|
||||
obj["outbound"] = "proxy";
|
||||
break;
|
||||
case -2:
|
||||
obj["outbound"] = "direct";
|
||||
break;
|
||||
case -3:
|
||||
obj["outbound"] = "block";
|
||||
break;
|
||||
case -4:
|
||||
obj["outbound"] = "dns-out";
|
||||
break;
|
||||
default:
|
||||
auto prof = NekoGui::profileManager->GetProfile(outboundID);
|
||||
if (prof == nullptr) {
|
||||
MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted");
|
||||
return {};
|
||||
if (actionType == "reject")
|
||||
{
|
||||
if (!rejectMethod.isEmpty()) obj["reject_method"] = rejectMethod;
|
||||
if (no_drop) obj["no_drop"] = no_drop;
|
||||
}
|
||||
if (actionType == "route" || actionType == "route-options")
|
||||
{
|
||||
if (!override_address.isEmpty()) obj["override_address"] = override_address;
|
||||
if (override_port.toInt() > 0) obj["override_port"] = override_port.toInt();
|
||||
|
||||
if (actionType == "route")
|
||||
{
|
||||
if (forView) {
|
||||
switch (outboundID) { // TODO use constants
|
||||
case -1:
|
||||
obj["outbound"] = "proxy";
|
||||
break;
|
||||
case -2:
|
||||
obj["outbound"] = "direct";
|
||||
break;
|
||||
default:
|
||||
auto prof = NekoGui::profileManager->GetProfile(outboundID);
|
||||
if (prof == nullptr) {
|
||||
MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted");
|
||||
return {};
|
||||
}
|
||||
obj["outbound"] = prof->bean->DisplayName();
|
||||
}
|
||||
obj["outbound"] = prof->bean->DisplayName();
|
||||
} else {
|
||||
if (!outboundTag.isEmpty()) obj["outbound"] = outboundTag;
|
||||
else obj["outbound"] = outboundID;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!outboundTag.isEmpty()) obj["outbound"] = outboundTag;
|
||||
else obj["outbound"] = outboundID;
|
||||
}
|
||||
if (actionType == "sniff")
|
||||
{
|
||||
if (isValidStrArray(sniffers)) obj["sniffers"] = get_as_array(sniffers);
|
||||
if (sniffOverrideDest) obj["override_destination"] = sniffOverrideDest;
|
||||
}
|
||||
if (actionType == "resolve")
|
||||
{
|
||||
if (!strategy.isEmpty()) obj["strategy"] = strategy;
|
||||
}
|
||||
|
||||
return obj;
|
||||
@ -151,17 +191,51 @@ namespace NekoGui {
|
||||
"process_path_regex",
|
||||
"rule_set",
|
||||
"invert",
|
||||
"action_type",
|
||||
};
|
||||
}
|
||||
|
||||
QStringList RouteRule::get_route_options()
|
||||
{
|
||||
QStringList options;
|
||||
options << "override_address" << "override_port";
|
||||
return options;
|
||||
}
|
||||
|
||||
QStringList RouteRule::get_reject_options()
|
||||
{
|
||||
QStringList options;
|
||||
options << "method" << "no_drop";
|
||||
return options;
|
||||
}
|
||||
|
||||
QStringList RouteRule::get_resolve_options()
|
||||
{
|
||||
QStringList options;
|
||||
options << "strategy";
|
||||
return options;
|
||||
}
|
||||
|
||||
QStringList RouteRule::get_sniff_options()
|
||||
{
|
||||
QStringList options;
|
||||
options << "override_destination";
|
||||
return options;
|
||||
}
|
||||
|
||||
inputType RouteRule::get_input_type(const QString& fieldName) {
|
||||
if (fieldName == "invert" ||
|
||||
fieldName == "source_ip_is_private" ||
|
||||
fieldName == "ip_is_private") return trufalse;
|
||||
fieldName == "ip_is_private" ||
|
||||
fieldName == "no_drop" ||
|
||||
fieldName == "override_destination") return trufalse;
|
||||
|
||||
if (fieldName == "ip_version" ||
|
||||
fieldName == "network" ||
|
||||
fieldName == "protocol") return select;
|
||||
fieldName == "protocol" ||
|
||||
fieldName == "action_type" ||
|
||||
fieldName == "method" ||
|
||||
fieldName == "strategy") return select;
|
||||
|
||||
return text;
|
||||
}
|
||||
@ -178,6 +252,22 @@ namespace NekoGui {
|
||||
resp.prepend("");
|
||||
return resp;
|
||||
}
|
||||
if (fieldName == "action_type")
|
||||
{
|
||||
return Preset::SingBox::ActionTypes;
|
||||
}
|
||||
if (fieldName == "method")
|
||||
{
|
||||
auto resp = Preset::SingBox::rejectMethods;
|
||||
resp.prepend("");
|
||||
return resp;
|
||||
}
|
||||
if (fieldName == "strategy")
|
||||
{
|
||||
auto resp = Preset::SingBox::DomainStrategy;
|
||||
resp.prepend("");
|
||||
return resp;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -191,6 +281,26 @@ namespace NekoGui {
|
||||
if (fieldName == "protocol") {
|
||||
return {protocol};
|
||||
}
|
||||
if (fieldName == "action_type")
|
||||
{
|
||||
return {actionType};
|
||||
}
|
||||
if (fieldName == "method")
|
||||
{
|
||||
return {rejectMethod};
|
||||
}
|
||||
if (fieldName == "strategy")
|
||||
{
|
||||
return {strategy};
|
||||
}
|
||||
if (fieldName == "override_address")
|
||||
{
|
||||
return {override_address};
|
||||
}
|
||||
if (fieldName == "override_port")
|
||||
{
|
||||
return {override_port};
|
||||
}
|
||||
if (fieldName == "inbound") return inbound;
|
||||
if (fieldName == "domain") return domain;
|
||||
if (fieldName == "domain_suffix") return domain_suffix;
|
||||
@ -219,6 +329,14 @@ namespace NekoGui {
|
||||
if (fieldName == "invert") {
|
||||
return invert? "true":"false";
|
||||
}
|
||||
if (fieldName == "no_drop")
|
||||
{
|
||||
return no_drop? "true":"false";
|
||||
}
|
||||
if (fieldName == "override_destination")
|
||||
{
|
||||
return sniffOverrideDest? "true":"false";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -295,9 +413,37 @@ namespace NekoGui {
|
||||
if (fieldName == "invert") {
|
||||
invert = value[0]=="true";
|
||||
}
|
||||
if (fieldName == "action_type")
|
||||
{
|
||||
actionType = value[0];
|
||||
}
|
||||
if (fieldName == "method")
|
||||
{
|
||||
rejectMethod = value[0];
|
||||
}
|
||||
if (fieldName == "no_drop")
|
||||
{
|
||||
no_drop = value[0]=="true";
|
||||
}
|
||||
if (fieldName == "override_address")
|
||||
{
|
||||
override_address = value[0];
|
||||
}
|
||||
if (fieldName == "override_port")
|
||||
{
|
||||
override_port = value[0];
|
||||
}
|
||||
if (fieldName == "override_destination")
|
||||
{
|
||||
sniffOverrideDest = value[0]=="true";
|
||||
}
|
||||
if (fieldName == "strategy")
|
||||
{
|
||||
strategy = value[0];
|
||||
}
|
||||
}
|
||||
|
||||
bool RouteRule::isEmpty() const {
|
||||
bool RouteRule::isEmpty() {
|
||||
return get_rule_json().keys().length() == 1;
|
||||
}
|
||||
|
||||
@ -307,10 +453,6 @@ namespace NekoGui {
|
||||
return true;
|
||||
case -2:
|
||||
return true;
|
||||
case -3:
|
||||
return true;
|
||||
case -4:
|
||||
return true;
|
||||
default:
|
||||
return profileManager->profiles.count(id) > 0;
|
||||
}
|
||||
@ -319,8 +461,6 @@ namespace NekoGui {
|
||||
int getOutboundID(const QString& name) {
|
||||
if (name == "proxy") return -1;
|
||||
if (name == "direct") return -2;
|
||||
if (name == "block") return -3;
|
||||
if (name == "dns-out" || name == "dns_out") return -4;
|
||||
for (const auto& item: profileManager->profiles) {
|
||||
if (item.second->bean->name == name) return item.first;
|
||||
}
|
||||
@ -411,8 +551,7 @@ namespace NekoGui {
|
||||
defaultChain->name = "Default";
|
||||
auto defaultRule = std::make_shared<RouteRule>();
|
||||
defaultRule->name = "Route DNS";
|
||||
defaultRule->protocol = "dns";
|
||||
defaultRule->outboundID = -4;
|
||||
defaultRule->actionType = "hijack-dns";
|
||||
defaultChain->Rules << defaultRule;
|
||||
return defaultChain;
|
||||
}
|
||||
@ -425,8 +564,7 @@ namespace NekoGui {
|
||||
|
||||
auto rule0 = std::make_shared<RouteRule>();
|
||||
rule0->name = "Route DNS";
|
||||
rule0->protocol = "dns";
|
||||
rule0->outboundID = -4;
|
||||
rule0->actionType = "hijack-dns";
|
||||
chain->Rules << rule0;
|
||||
|
||||
auto rule1 = std::make_shared<RouteRule>();
|
||||
@ -452,8 +590,7 @@ namespace NekoGui {
|
||||
|
||||
auto rule0 = std::make_shared<RouteRule>();
|
||||
rule0->name = "Route DNS";
|
||||
rule0->protocol = "dns";
|
||||
rule0->outboundID = -4;
|
||||
rule0->actionType = "hijack-dns";
|
||||
chain->Rules << rule0;
|
||||
|
||||
auto rule1 = std::make_shared<RouteRule>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user