feat(routing): add traffic type / protocol filtering and exclusion per section

This commit is contained in:
Dushnilin
2026-07-28 21:46:18 +03:00
parent a3e9981d13
commit 53e3f1f041
5 changed files with 97 additions and 0 deletions
+3
View File
@@ -254,7 +254,10 @@ export namespace Tachyon {
rule_set_with_subnets?: string[];
domain_ip_lists?: string[];
ports?: string[];
protocol?: string[];
excluded_protocol?: string[];
update_interval?: string;
proxy_string?: string;
nfqws_opt?: string;
nfqws2_opt?: string;
@@ -9074,7 +9074,47 @@ function createSectionContent(section) {
});
dependsOnRoutingAction(dscpOption);
const excludedProtocolOption = section.taboption(
"conditions",
form.MultiValue,
"excluded_protocol",
_("Exclude traffic types"),
_("Traffic of specified protocols (e.g. BitTorrent, QUIC, STUN) will bypass this section."),
);
excludedProtocolOption.value("bittorrent", _("BitTorrent / P2P"));
excludedProtocolOption.value("quic", _("QUIC (HTTP/3)"));
excludedProtocolOption.value("stun", _("STUN (P2P Calls)"));
excludedProtocolOption.value("dns", _("DNS"));
excludedProtocolOption.value("http", _("HTTP"));
excludedProtocolOption.value("tls", _("TLS / HTTPS"));
excludedProtocolOption.value("ssh", _("SSH"));
excludedProtocolOption.value("rdp", _("RDP"));
excludedProtocolOption.modalonly = true;
excludedProtocolOption.rmempty = true;
dependsOnRoutingAction(excludedProtocolOption);
const protocolOption = section.taboption(
"conditions",
form.MultiValue,
"protocol",
_("Traffic type filter"),
_("Apply rules of this section only to selected protocols."),
);
protocolOption.value("bittorrent", _("BitTorrent / P2P"));
protocolOption.value("quic", _("QUIC (HTTP/3)"));
protocolOption.value("stun", _("STUN (P2P Calls)"));
protocolOption.value("dns", _("DNS"));
protocolOption.value("http", _("HTTP"));
protocolOption.value("tls", _("TLS / HTTPS"));
protocolOption.value("ssh", _("SSH"));
protocolOption.value("rdp", _("RDP"));
protocolOption.modalonly = true;
protocolOption.rmempty = true;
dependsOnRoutingAction(protocolOption);
addDashboardServerFilterOptions(section);
}
function loadSectionTableOptions(sectionRef) {
+23
View File
@@ -3115,3 +3115,26 @@ msgstr "Хеши"
msgid "Init headers"
msgstr "Заголовки Init"
msgid "Exclude traffic types"
msgstr "Исключить типы трафика"
msgid "Traffic of specified protocols (e.g. BitTorrent, QUIC, STUN) will bypass this section."
msgstr "Трафик указанных протоколов (например, BitTorrent, QUIC, STUN) будет идти в обход этой секции."
msgid "Traffic type filter"
msgstr "Фильтр по типам трафика"
msgid "Apply rules of this section only to selected protocols."
msgstr "Применять правила этой секции только к выбранным протоколам."
msgid "BitTorrent / P2P"
msgstr "BitTorrent / P2P Торренты"
msgid "QUIC (HTTP/3)"
msgstr "QUIC (HTTP/3)"
msgid "STUN (P2P Calls)"
msgstr "STUN (P2P Звонки)"
+6
View File
@@ -906,7 +906,10 @@ function nft_runtime_signature_body(settings, sections) {
body = signature_add_value(body, "rule." + name + ".ports", section_rule_ports_csv(section));
body = signature_add_value(body, "rule." + name + ".fully_routed_ips", option(section, "fully_routed_ips", ""));
body = signature_add_value(body, "rule." + name + ".excluded_ips", option(section, "excluded_ips", ""));
body = signature_add_value(body, "rule." + name + ".excluded_protocol", option(section, "excluded_protocol", ""));
body = signature_add_value(body, "rule." + name + ".protocol", option(section, "protocol", ""));
body = signature_add_value(body, "rule." + name + ".community_subnet_lists", rule_config.filter_community_subnet_lists_value(connections.community_lists_value(section)));
body = signature_add_value(body, "rule." + name + ".remote_subnet_lists", option(section, "remote_subnet_lists", ""));
body = signature_add_value(body, "rule." + name + ".rule_set_with_subnets", connections.rule_sets_with_subnets_value(section));
body = signature_add_value(body, "rule." + name + ".domain_ip_lists", option(section, "domain_ip_lists", ""));
@@ -1295,7 +1298,10 @@ function append_sing_box_rule_signature_body(body, section, sections) {
body = signature_add_value(body, prefix + ".ports", section_rule_ports_csv(section));
body = signature_add_value(body, prefix + ".fully_routed_ips", option(section, "fully_routed_ips", ""));
body = signature_add_value(body, prefix + ".excluded_ips", option(section, "excluded_ips", ""));
body = signature_add_value(body, prefix + ".excluded_protocol", option(section, "excluded_protocol", ""));
body = signature_add_value(body, prefix + ".protocol", option(section, "protocol", ""));
}
body = signature_add_value(body, prefix + ".community_lists", connections.community_lists_value(section));
body = signature_add_value(body, prefix + ".rule_set", connections.rule_sets_value(section));
if (action != "dns")
@@ -1126,6 +1126,27 @@ function add_excluded_ips_rule(config, section) {
push(config.route.rules, route_rule);
}
function add_excluded_protocol_rule(config, section) {
let excluded = list_option(section, "excluded_protocol");
if (length(excluded) == 0)
return;
let route_rule = {
action: "route",
inbound: tproxy_inbound_matcher(),
outbound: runtime_constants.DIRECT_OUTBOUND_TAG,
protocol: single_or_array(excluded)
};
push(config.route.rules, route_rule);
}
function add_protocol_matchers(rule, section) {
let protocols = list_option(section, "protocol");
if (length(protocols) > 0)
rule.protocol = single_or_array(protocols);
}
function load_community_subnet_cidrs(community) {
let paths = [
"/tmp/sing-box/rulesets/community-subnets-" + as_string(community) + ".lst",
@@ -1161,8 +1182,10 @@ function add_combined_route_for_section(config, section) {
let section_name = section[".name"];
add_excluded_ips_rule(config, section);
add_excluded_protocol_rule(config, section);
add_fully_routed_ips_rule(config, section);
for (let community in connections.community_lists(section)) {
let ensured = ensure_community_ruleset(config, section_name, as_string(community));
push(rule_set_tags, ensured.tag);
@@ -1210,6 +1233,8 @@ function add_combined_route_for_section(config, section) {
route_rule.source_ip_cidr = source_ip_cidr;
add_port_matchers(route_rule, section);
add_dscp_matchers(route_rule, section);
add_protocol_matchers(route_rule, section);
if (length(rule_set_tags) > 0)
route_rule.rule_set = single_or_array(rule_set_tags);