feat(routing): route router's own traffic through designated section
This commit is contained in:
@@ -6742,3 +6742,15 @@ msgstr "Блокировать: "
|
||||
|
||||
msgid "Traffic from these IP addresses will never be routed through this section, even if other conditions match."
|
||||
msgstr "Трафик от этих IP-адресов никогда не будет маршрутизирован через эту секцию, даже если другие условия совпадают."
|
||||
|
||||
msgid "Route Router's Own Traffic"
|
||||
msgstr "Маршрутизировать собственный трафик роутера"
|
||||
|
||||
msgid "Route local traffic originating directly from the router (e.g. wget, curl, opkg, torrent clients on the router) through Tachyon."
|
||||
msgstr "Направлять локальный трафик, исходящий непосредственно с роутера (например, wget, curl, opkg, торрент-клиент на роутере), через Tachyon."
|
||||
|
||||
msgid "Router Traffic Target Section"
|
||||
msgstr "Секция для трафика роутера"
|
||||
|
||||
msgid "Select the section to route router's own traffic through."
|
||||
msgstr "Выберите секцию для маршрутизации трафика роутера."
|
||||
|
||||
@@ -1806,6 +1806,31 @@ function createSettingsContent(section, capabilities) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = section.taboption(
|
||||
"network",
|
||||
form.Flag,
|
||||
"route_router_traffic",
|
||||
_("Route Router's Own Traffic"),
|
||||
_(
|
||||
"Route local traffic originating directly from the router (e.g. wget, curl, opkg, torrent clients on the router) through Tachyon.",
|
||||
),
|
||||
);
|
||||
configureDownloadViaProxyFlag(o, "route_router_traffic_section");
|
||||
|
||||
o = section.taboption(
|
||||
"network",
|
||||
form.ListValue,
|
||||
"route_router_traffic_section",
|
||||
_("Router Traffic Target Section"),
|
||||
_("Select the section to route router's own traffic through."),
|
||||
);
|
||||
o.depends("route_router_traffic", "1");
|
||||
configureDownloadSectionOption(
|
||||
o,
|
||||
"route_router_traffic_section",
|
||||
capabilities,
|
||||
);
|
||||
|
||||
o = section.taboption(
|
||||
"services",
|
||||
form.Flag,
|
||||
|
||||
@@ -6742,3 +6742,15 @@ msgstr "Блокировать: "
|
||||
|
||||
msgid "Traffic from these IP addresses will never be routed through this section, even if other conditions match."
|
||||
msgstr "Трафик от этих IP-адресов никогда не будет маршрутизирован через эту секцию, даже если другие условия совпадают."
|
||||
|
||||
msgid "Route Router's Own Traffic"
|
||||
msgstr "Маршрутизировать собственный трафик роутера"
|
||||
|
||||
msgid "Route local traffic originating directly from the router (e.g. wget, curl, opkg, torrent clients on the router) through Tachyon."
|
||||
msgstr "Направлять локальный трафик, исходящий непосредственно с роутера (например, wget, curl, opkg, торрент-клиент на роутере), через Tachyon."
|
||||
|
||||
msgid "Router Traffic Target Section"
|
||||
msgstr "Секция для трафика роутера"
|
||||
|
||||
msgid "Select the section to route router's own traffic through."
|
||||
msgstr "Выберите секцию для маршрутизации трафика роутера."
|
||||
|
||||
@@ -2570,6 +2570,63 @@ function nft_guest_mode_signature_body(body, guest_mode) {
|
||||
return body;
|
||||
}
|
||||
|
||||
function router_output_intercept_enabled(settings) {
|
||||
if (type(settings) != "object")
|
||||
settings = uci_settings();
|
||||
return bool_option(settings, "route_router_traffic", false) &&
|
||||
option(settings, "route_router_traffic_section", "") != "";
|
||||
}
|
||||
|
||||
function nft_disable_router_output_intercept(table) {
|
||||
run_args_quiet([ "nft", "delete", "chain", "inet", as_string(table), "output_redirect" ]);
|
||||
return true;
|
||||
}
|
||||
|
||||
function nft_enable_router_output_intercept(table, localv4_set, outbound_mark, exclude_ntp) {
|
||||
table = as_string(table);
|
||||
localv4_set = as_string(localv4_set || "localv4");
|
||||
outbound_mark = as_string(outbound_mark || runtime_constants.OUTBOUND_MARK);
|
||||
let port = as_string(runtime_constants.REDIRECT_INBOUND_PORT);
|
||||
|
||||
if (!run_args_quiet([ "nft", "flush", "chain", "inet", table, "output_redirect" ])) {
|
||||
if (!nft_create_chain(table, "output_redirect", "{ type nat hook output priority -100; policy accept; }"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nft_add_rule(table, "output_redirect", [ "ct", "status", "dnat", "return" ]))
|
||||
return false;
|
||||
if (!nft_add_rule(table, "output_redirect", [ "meta", "l4proto", "icmp", "return" ]))
|
||||
return false;
|
||||
if (!nft_add_rule(table, "output_redirect", [ "ip", "daddr", "@" + localv4_set, "return" ]))
|
||||
return false;
|
||||
if (!nft_add_rule(table, "output_redirect", [ "tcp", "dport", "53", "return" ]))
|
||||
return false;
|
||||
if (!nft_add_rule(table, "output_redirect", [ "udp", "dport", "53", "return" ]))
|
||||
return false;
|
||||
if (arg_bool(exclude_ntp) && !nft_add_rule(table, "output_redirect", [ "udp", "dport", "123", "return" ]))
|
||||
return false;
|
||||
if (outbound_mark != "" && !nft_add_rule(table, "output_redirect", [ "meta", "mark", outbound_mark, "return" ]))
|
||||
return false;
|
||||
return nft_add_rule(table, "output_redirect", [
|
||||
"meta", "l4proto", "tcp", "counter", "redirect", "to", ":" + port
|
||||
]);
|
||||
}
|
||||
|
||||
function nft_sync_router_output_intercept(table, localv4_set, outbound_mark) {
|
||||
table = as_string(table || "tachyon");
|
||||
localv4_set = as_string(localv4_set || "localv4");
|
||||
outbound_mark = as_string(outbound_mark || runtime_constants.OUTBOUND_MARK);
|
||||
let settings = uci_settings();
|
||||
if (!router_output_intercept_enabled(settings))
|
||||
return nft_disable_router_output_intercept(table);
|
||||
return nft_enable_router_output_intercept(
|
||||
table,
|
||||
localv4_set,
|
||||
outbound_mark,
|
||||
option(settings, "exclude_ntp", "0")
|
||||
);
|
||||
}
|
||||
|
||||
function nft_runtime_signature_from_settings_and_sections(settings, sections, schedules, profiles, guest_modes) {
|
||||
let body = "";
|
||||
|
||||
@@ -2580,6 +2637,8 @@ function nft_runtime_signature_from_settings_and_sections(settings, sections, sc
|
||||
body = signature_add_value(body, "settings.game_console_ips", option(settings, "game_console_ips", ""));
|
||||
body = signature_add_value(body, "settings.excluded_clients", option(settings, "excluded_clients", ""));
|
||||
body = signature_add_value(body, "settings.excluded_ips", option(settings, "excluded_ips", ""));
|
||||
body = signature_add_value(body, "settings.route_router_traffic", bool_option(settings, "route_router_traffic", false) ? "1" : "0");
|
||||
body = signature_add_value(body, "settings.route_router_traffic_section", option(settings, "route_router_traffic_section", ""));
|
||||
|
||||
for (let section in sections)
|
||||
body = nft_rule_signature_body(body, object_or_empty(section));
|
||||
@@ -3248,6 +3307,12 @@ else if (mode == "tproxy-route-rule-present")
|
||||
exit(tproxy_route_rule_present(ARGV[1], ARGV[2]) ? 0 : 1);
|
||||
else if (mode == "ensure-bridge-netfilter-disabled")
|
||||
exit(ensure_bridge_netfilter_disabled() ? 0 : 1);
|
||||
else if (mode == "nft-enable-router-output-intercept")
|
||||
exit(nft_enable_router_output_intercept(ARGV[1], ARGV[2], ARGV[3], ARGV[4]) ? 0 : 1);
|
||||
else if (mode == "nft-disable-router-output-intercept")
|
||||
exit(nft_disable_router_output_intercept(ARGV[1]) ? 0 : 1);
|
||||
else if (mode == "nft-sync-router-output-intercept")
|
||||
exit(nft_sync_router_output_intercept(ARGV[1], ARGV[2], ARGV[3]) ? 0 : 1);
|
||||
else {
|
||||
warn("Usage: nft/apply.uc <operation> ...\n");
|
||||
exit(1);
|
||||
|
||||
@@ -28,6 +28,8 @@ let strings = {
|
||||
isolate_p2p: "Isolate P2P",
|
||||
log_level: "Log Level",
|
||||
exclude_ntp: "Exclude NTP",
|
||||
route_router_traffic: "Route Router Traffic",
|
||||
route_router_traffic_section: "Router Traffic Section",
|
||||
shutdown_correctly: "Clean Shutdown",
|
||||
smart_detect: "Smart Detect",
|
||||
smart_detect_sections: "Smart Detect Sections",
|
||||
@@ -582,6 +584,8 @@ let strings = {
|
||||
isolate_p2p: "Изолировать P2P",
|
||||
log_level: "Уровень логов",
|
||||
exclude_ntp: "Исключить NTP",
|
||||
route_router_traffic: "Маршрутизировать трафик роутера",
|
||||
route_router_traffic_section: "Секция трафика роутера",
|
||||
shutdown_correctly: "Корректное завершение",
|
||||
smart_detect: "Smart Detect",
|
||||
smart_detect_sections: "Секции Smart Detect",
|
||||
|
||||
@@ -926,6 +926,8 @@ function start_main() {
|
||||
return status;
|
||||
}
|
||||
|
||||
module_status(NFT_UC, [ "nft-sync-router-output-intercept", NFT_TABLE_NAME, NFT_LOCALV4_SET_NAME, NFT_OUTBOUND_MARK ]);
|
||||
|
||||
status = module_status(PRIORITY_UC, [ "start-runtime" ]);
|
||||
if (status != 0) {
|
||||
log_message("Failed to start Priority runtime. Aborted.", "fatal");
|
||||
@@ -1039,6 +1041,8 @@ function stop_main() {
|
||||
module_success(PARENTAL_QUOTA_UC, [ "remove-cron" ]);
|
||||
module_success(TELEGRAM_UC, [ "stop-runtime" ]);
|
||||
|
||||
module_success(NFT_UC, [ "nft-disable-router-output-intercept", NFT_TABLE_NAME ]);
|
||||
|
||||
if (command_success_from_args([ "nft", "list", "table", "inet", NFT_TABLE_NAME ])) {
|
||||
if (!command_success_from_args([ "nft", "delete", "table", "inet", NFT_TABLE_NAME ]))
|
||||
log_message("Failed to delete nft table " + NFT_TABLE_NAME, "warn");
|
||||
@@ -1539,6 +1543,8 @@ function reload(reason) {
|
||||
module_success(PARENTAL_QUOTA_UC, [ "install-cron" ]);
|
||||
module_success(PARENTAL_QUOTA_UC, [ "tick" ]);
|
||||
|
||||
module_status(NFT_UC, [ "nft-sync-router-output-intercept", NFT_TABLE_NAME, NFT_LOCALV4_SET_NAME, NFT_OUTBOUND_MARK ]);
|
||||
|
||||
if (plan.needs_dnsmasq_configure == 1) {
|
||||
status = dnsmasq_configure(true);
|
||||
if (status != 0)
|
||||
|
||||
@@ -999,6 +999,8 @@ function nft_runtime_signature_body(settings, sections, schedules, profiles, gue
|
||||
body = signature_add_value(body, "settings.game_console_ips", option(settings, "game_console_ips", ""));
|
||||
body = signature_add_value(body, "settings.excluded_clients", option(settings, "excluded_clients", ""));
|
||||
body = signature_add_value(body, "settings.excluded_ips", option(settings, "excluded_ips", ""));
|
||||
body = signature_add_value(body, "settings.route_router_traffic", bool_option(settings, "route_router_traffic", false) ? "1" : "0");
|
||||
body = signature_add_value(body, "settings.route_router_traffic_section", option(settings, "route_router_traffic_section", ""));
|
||||
|
||||
for (let section in sections) {
|
||||
section = object_or_empty(section);
|
||||
@@ -1662,6 +1664,8 @@ function sing_box_signature_body(settings, sections, servers, mwan3_active, sche
|
||||
body = signature_add_value(body, "settings.download_lists_via_proxy_section", option(settings, "download_lists_via_proxy_section", ""));
|
||||
if (download_via_proxy_enabled(settings, "components"))
|
||||
body = signature_add_value(body, "settings.download_components_via_proxy_section", option(settings, "download_components_via_proxy_section", ""));
|
||||
body = signature_add_value(body, "settings.route_router_traffic", bool_option_value(settings, "route_router_traffic", false));
|
||||
body = signature_add_value(body, "settings.route_router_traffic_section", option(settings, "route_router_traffic_section", ""));
|
||||
|
||||
for (let section in sections)
|
||||
body = append_sing_box_rule_signature_body(body, object_or_empty(section), sections);
|
||||
|
||||
@@ -611,6 +611,8 @@ let setting_schema = {
|
||||
isolate_p2p: "isolate_p2p",
|
||||
log_level: "log_level",
|
||||
exclude_ntp: "exclude_ntp",
|
||||
route_router_traffic: "route_router_traffic",
|
||||
route_router_traffic_section: "route_router_traffic_section",
|
||||
shutdown_correctly: "shutdown_correctly",
|
||||
smart_detect: "smart_detect",
|
||||
smart_detect_sections: "smart_detect_sections"
|
||||
@@ -671,7 +673,7 @@ function is_boolean_key(key) {
|
||||
"dns_detour_enabled", "enable_output_network_interface", "enable_badwan_interface_monitoring",
|
||||
"enable_yacd", "disable_quic", "block_doh", "list_update_enabled", "component_update_check_enabled",
|
||||
"download_lists_via_proxy", "download_components_via_proxy", "dont_touch_dhcp",
|
||||
"isolate_p2p", "exclude_ntp", "shutdown_correctly", "smart_detect",
|
||||
"isolate_p2p", "exclude_ntp", "route_router_traffic", "shutdown_correctly", "smart_detect",
|
||||
"notify_crash", "notify_restart", "notify_server_switch", "notify_subscription", "notify_cert", "notify_dns_leak",
|
||||
"daily_report_enabled", "quiet_hours_enabled"];
|
||||
for (let x in b) if (x == key) return true;
|
||||
|
||||
@@ -28,6 +28,9 @@ const DNS_SOURCE6_SET = "tachyon_dns_sources6";
|
||||
const SERVICE_MIXED_INBOUND_TAG = "service-mixed-in";
|
||||
const SERVICE_MIXED_INBOUND_ADDRESS = "127.0.0.1";
|
||||
const SERVICE_MIXED_INBOUND_PORT = 4534;
|
||||
const REDIRECT_INBOUND_TAG = "redirect-in";
|
||||
const REDIRECT_INBOUND_ADDRESS = "127.0.0.1";
|
||||
const REDIRECT_INBOUND_PORT = 1604;
|
||||
const DIRECT_BYPASS_INBOUND_TAG = "direct-bypass-in";
|
||||
const DIRECT_BYPASS_OUTBOUND_TAG = "direct-bypass-out";
|
||||
const DIRECT_BYPASS_DEFAULT_PORT = 2080;
|
||||
@@ -142,6 +145,9 @@ return {
|
||||
SERVICE_MIXED_INBOUND_TAG,
|
||||
SERVICE_MIXED_INBOUND_ADDRESS,
|
||||
SERVICE_MIXED_INBOUND_PORT,
|
||||
REDIRECT_INBOUND_TAG,
|
||||
REDIRECT_INBOUND_ADDRESS,
|
||||
REDIRECT_INBOUND_PORT,
|
||||
DIRECT_BYPASS_INBOUND_TAG,
|
||||
DIRECT_BYPASS_OUTBOUND_TAG,
|
||||
DIRECT_BYPASS_DEFAULT_PORT,
|
||||
|
||||
@@ -827,6 +827,42 @@ function add_service_mixed_proxy(config, settings, sections) {
|
||||
runtime_generate_unsupported("download components via proxy section is not set");
|
||||
}
|
||||
|
||||
function router_traffic_section(settings) {
|
||||
if (!bool_option(settings, "route_router_traffic", false))
|
||||
return "";
|
||||
return option(settings, "route_router_traffic_section", "");
|
||||
}
|
||||
|
||||
function add_router_traffic_redirect(config, settings) {
|
||||
let section_name = router_traffic_section(settings);
|
||||
if (section_name == "")
|
||||
return;
|
||||
|
||||
push(config.inbounds, {
|
||||
type: "redirect",
|
||||
tag: runtime_constants.REDIRECT_INBOUND_TAG,
|
||||
listen: runtime_constants.REDIRECT_INBOUND_ADDRESS,
|
||||
listen_port: runtime_constants.REDIRECT_INBOUND_PORT
|
||||
});
|
||||
|
||||
let sec_out = outbound_tag(section_name);
|
||||
if (sec_out != "") {
|
||||
let target_idx = 0;
|
||||
if (type(config.route) == "object" && type(config.route.rules) == "array") {
|
||||
for (let i = 0; i < length(config.route.rules); i++) {
|
||||
let r = config.route.rules[i];
|
||||
if (r.action == "sniff" || r.action == "hijack-dns")
|
||||
target_idx = i + 1;
|
||||
}
|
||||
splice(config.route.rules, target_idx, 0, {
|
||||
action: "route",
|
||||
inbound: [ runtime_constants.REDIRECT_INBOUND_TAG ],
|
||||
outbound: sec_out
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Content blocking (parental control domains) ─────────────────────────────
|
||||
// Each enabled `config schedule` with blocked_domains generates:
|
||||
// 1. DNS rules (on the dedicated dns-block-in inbound) that reject the
|
||||
@@ -1368,6 +1404,7 @@ function generate_config(output_path, service_address, mwan3_active, supports_xh
|
||||
add_service_mixed_proxy(config, settings, sections);
|
||||
for (let section in sections)
|
||||
add_mixed_proxy_for_section(config, section, service_address);
|
||||
add_router_traffic_redirect(config, settings);
|
||||
|
||||
add_content_blocking(config);
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@ function config(settings, runtime) {
|
||||
if (type(runtime) == "object" && type(runtime.dns_health_inbounds) == "array")
|
||||
for (let inbound in runtime.dns_health_inbounds)
|
||||
push(dns_hijack_inbounds, inbound);
|
||||
if (bool_option(settings, "route_router_traffic", false) && option(settings, "route_router_traffic_section", "") != "")
|
||||
push(sniff_inbounds, runtime_constants.REDIRECT_INBOUND_TAG);
|
||||
let rules = [
|
||||
{ action: "sniff", inbound: sniff_inbounds },
|
||||
{ action: "hijack-dns", inbound: dns_hijack_inbounds }
|
||||
|
||||
@@ -687,6 +687,10 @@ br-lan tun0
|
||||
|
||||
[settings.excluded_ips]
|
||||
|
||||
[settings.route_router_traffic]
|
||||
0
|
||||
[settings.route_router_traffic_section]
|
||||
|
||||
[rule.text_rule.action]
|
||||
bypass
|
||||
[rule.text_rule.ip_cidr]
|
||||
@@ -795,6 +799,10 @@ br-lan tun0
|
||||
|
||||
[settings.excluded_ips]
|
||||
|
||||
[settings.route_router_traffic]
|
||||
0
|
||||
[settings.route_router_traffic_section]
|
||||
|
||||
[rule.enabled.action]
|
||||
bypass
|
||||
[rule.enabled.ip_cidr]
|
||||
@@ -853,6 +861,10 @@ br-lan
|
||||
|
||||
[settings.excluded_ips]
|
||||
|
||||
[settings.route_router_traffic]
|
||||
0
|
||||
[settings.route_router_traffic_section]
|
||||
|
||||
EOF_EXPECTED
|
||||
expected_signature="$(md5sum "$WORK_DIR/signature-defaults-expected.txt" | awk '{print $1}')"
|
||||
assert_eq "$expected_signature" \
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib"
|
||||
NFT_RUNTIME="$ROOT_DIR/tachyon/files/usr/lib/nft/apply.uc"
|
||||
WORK_DIR="$(mktemp -d)"
|
||||
NFT_LOG="$WORK_DIR/nft.log"
|
||||
LOGGER_LOG="$WORK_DIR/logger.log"
|
||||
export NFT_LOG LOGGER_LOG
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$WORK_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
fail() {
|
||||
printf 'FAIL: %s\n' "$1" >&2
|
||||
printf 'nft log:\n' >&2
|
||||
cat "$NFT_LOG" >&2 2>/dev/null || true
|
||||
exit 1
|
||||
}
|
||||
|
||||
assert_contains() {
|
||||
local file="$1"
|
||||
local expected="$2"
|
||||
local label="$3"
|
||||
|
||||
grep -Fq "$expected" "$file" || fail "$label: expected '$expected'"
|
||||
}
|
||||
|
||||
mkdir -p "$WORK_DIR/bin"
|
||||
|
||||
cat >"$WORK_DIR/bin/nft" <<'NFT'
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
{
|
||||
printf 'nft'
|
||||
for arg in "$@"; do
|
||||
printf '\t%s' "$arg"
|
||||
done
|
||||
printf '\n'
|
||||
} >> "${NFT_LOG:?}"
|
||||
|
||||
if [ "$#" -ge 5 ] && [ "$1" = "flush" ] && [ "$2" = "chain" ]; then
|
||||
if [ ! -f "$WORK_DIR/chain_exists" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$#" -ge 5 ] && [ "$1" = "add" ] && [ "$2" = "chain" ]; then
|
||||
touch "$WORK_DIR/chain_exists"
|
||||
fi
|
||||
|
||||
if [ "$#" -ge 5 ] && [ "$1" = "delete" ] && [ "$2" = "chain" ]; then
|
||||
rm -f "$WORK_DIR/chain_exists"
|
||||
fi
|
||||
NFT
|
||||
chmod 0755 "$WORK_DIR/bin/nft"
|
||||
|
||||
cat >"$WORK_DIR/bin/logger" <<'LOGGER'
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
printf 'logger\t%s\n' "$*" >> "${LOGGER_LOG:?}"
|
||||
LOGGER
|
||||
chmod 0755 "$WORK_DIR/bin/logger"
|
||||
|
||||
export PATH="$WORK_DIR/bin:$PATH"
|
||||
|
||||
nft_ucode() {
|
||||
ucode -S -L "$TACHYON_LIB" "$NFT_RUNTIME" "$@"
|
||||
}
|
||||
|
||||
# Test 1: Direct enable call
|
||||
: > "$NFT_LOG"
|
||||
rm -f "$WORK_DIR/chain_exists"
|
||||
nft_ucode nft-enable-router-output-intercept TachyonTable localv4 0x00100000 1
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\tchain\tinet\tTachyonTable\toutput_redirect\t{ type nat hook output priority -100; policy accept; }' "enable: creates chain output_redirect"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tct\tstatus\tdnat\treturn' "enable: ct status dnat return"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tip\tdaddr\t@localv4\treturn' "enable: localv4 bypass"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\ttcp\tdport\t53\treturn' "enable: port 53 bypass"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tudp\tdport\t123\treturn' "enable: exclude_ntp bypass"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tmeta\tmark\t0x00100000\treturn' "enable: outbound_mark bypass"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tmeta\tl4proto\ttcp\tcounter\tredirect\tto\t:1604' "enable: tcp redirect to 1604"
|
||||
|
||||
# Test 2: Direct disable call
|
||||
: > "$NFT_LOG"
|
||||
nft_ucode nft-disable-router-output-intercept TachyonTable
|
||||
assert_contains "$NFT_LOG" $'nft\tdelete\tchain\tinet\tTachyonTable\toutput_redirect' "disable: deletes chain output_redirect"
|
||||
|
||||
# Test 3: Sync from UCI - when enabled
|
||||
STATE_ENABLED="$WORK_DIR/enabled.state"
|
||||
cat >"$STATE_ENABLED" <<'STATE'
|
||||
tachyon.settings=settings
|
||||
tachyon.settings.route_router_traffic=1
|
||||
tachyon.settings.route_router_traffic_section=proxy_sec
|
||||
tachyon.settings.exclude_ntp=1
|
||||
tachyon.proxy_sec=section
|
||||
tachyon.proxy_sec.enabled=1
|
||||
tachyon.proxy_sec.routing_mode=proxy
|
||||
tachyon.proxy_sec.mark=354
|
||||
tachyon.proxy_sec.tproxy_port=10080
|
||||
STATE
|
||||
|
||||
: > "$NFT_LOG"
|
||||
rm -f "$WORK_DIR/chain_exists"
|
||||
TACHYON_UCI_STATE_FILE="$STATE_ENABLED" nft_ucode nft-sync-router-output-intercept TachyonTable localv4 0x00100000
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\tchain\tinet\tTachyonTable\toutput_redirect\t{ type nat hook output priority -100; policy accept; }' "sync(enabled): creates chain"
|
||||
assert_contains "$NFT_LOG" $'nft\tadd\trule\tinet\tTachyonTable\toutput_redirect\tmeta\tl4proto\ttcp\tcounter\tredirect\tto\t:1604' "sync(enabled): redirects to port"
|
||||
|
||||
# Test 4: Sync from UCI - when disabled
|
||||
STATE_DISABLED="$WORK_DIR/disabled.state"
|
||||
cat >"$STATE_DISABLED" <<'STATE'
|
||||
tachyon.settings=settings
|
||||
tachyon.settings.route_router_traffic=0
|
||||
tachyon.settings.route_router_traffic_section=proxy_sec
|
||||
tachyon.proxy_sec=section
|
||||
tachyon.proxy_sec.enabled=1
|
||||
tachyon.proxy_sec.routing_mode=proxy
|
||||
tachyon.proxy_sec.mark=354
|
||||
STATE
|
||||
|
||||
: > "$NFT_LOG"
|
||||
TACHYON_UCI_STATE_FILE="$STATE_DISABLED" nft_ucode nft-sync-router-output-intercept TachyonTable localv4 0x00100000
|
||||
assert_contains "$NFT_LOG" $'nft\tdelete\tchain\tinet\tTachyonTable\toutput_redirect' "sync(disabled): deletes chain"
|
||||
|
||||
# Test 5: Verify UCI setting loads route_router_traffic
|
||||
CHECK_SETTINGS=$(TACHYON_UCI_STATE_FILE="$STATE_DISABLED" ucode -S -L "$TACHYON_LIB" -e '
|
||||
let uci = require("core.uci");
|
||||
let val = uci.get("tachyon.settings.route_router_traffic");
|
||||
print("val=" + val);
|
||||
')
|
||||
if [ "$CHECK_SETTINGS" != "val=0" ]; then
|
||||
fail "UCI route_router_traffic expected val=0, got '$CHECK_SETTINGS'"
|
||||
fi
|
||||
|
||||
printf 'ALL TESTS PASSED for route_router_traffic\n'
|
||||
@@ -591,6 +591,10 @@ secret
|
||||
0
|
||||
[settings.download_components_via_proxy]
|
||||
0
|
||||
[settings.route_router_traffic]
|
||||
0
|
||||
[settings.route_router_traffic_section]
|
||||
|
||||
[rule.proxy1.action]
|
||||
proxy
|
||||
[rule.proxy1.connection_urls]
|
||||
|
||||
Reference in New Issue
Block a user