fix: OpenWrt 25.12 compatibility fixes, startup speedup, and Telegram polling fix
- wget: remove -t flag incompatible with BusyBox 25.12+, add curl-first fallback in download_to_file() with wget as fallback - startup/reload speedup (5 improvements): - cut sing-box verification timeout from 45 iterations to 15 - remove redundant second stability wait for sing-box process - batch requirement check + runtime validation into single ucode fork - replace dnsmasq full restart with procd reload (config-conditional bounce) - move telegram and watchdog runtime start to background - telegram: fix "API failure" spam - empty result[] from getUpdates is now treated as a successful idle poll, not an error that triggers backoff - watchdog SmartDetect: extract domain from proxy and VPN URLs for DNS health check, use real domains (google.com/example.com) instead of provider-specific endpoints that trigger false alerts - tests: new invariants for wget -t prohibition, telegram empty-result handling, DNS apply reload-vs-restart, and combined validation mode ownership
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
WATCHDOG_UC="$ROOT_DIR/tachyon/files/usr/lib/service/watchdog.uc"
|
||||
TACHYON_LIB="$ROOT_DIR/tachyon/files/usr/lib"
|
||||
|
||||
ucode() {
|
||||
command ucode -L "$TACHYON_LIB" "$@"
|
||||
}
|
||||
|
||||
fail() {
|
||||
printf 'FAIL: %s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
extract() {
|
||||
ucode "$WATCHDOG_UC" smart-detect-extract-domain "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Asserts the line yields exactly the expected domain.
|
||||
assert_extracts() {
|
||||
local line="$1"
|
||||
local expected="$2"
|
||||
local label="$3"
|
||||
local actual
|
||||
actual="$(extract "$line")"
|
||||
[ "$actual" = "$expected" ] || fail "$label: expected '$expected', got '$actual'"
|
||||
}
|
||||
|
||||
# Asserts the line yields no domain (exit 1, empty stdout).
|
||||
assert_rejects() {
|
||||
local line="$1"
|
||||
local label="$2"
|
||||
local actual
|
||||
actual="$(extract "$line")"
|
||||
[ -z "$actual" ] || fail "$label: expected no domain, got '$actual'"
|
||||
}
|
||||
|
||||
# --- quoted-host form (primary sing-box log shape) ---
|
||||
assert_extracts 'outbound/direct: failed to connect to "example.com:443"' \
|
||||
example.com "quoted host with port"
|
||||
assert_extracts 'direct connection failed: "sub.domain.example.org"' \
|
||||
sub.domain.example.org "quoted host without port, multi-label"
|
||||
assert_extracts 'DIRECT timeout "xn--80ak6aa92e.com:443"' \
|
||||
xn--80ak6aa92e.com "punycode host"
|
||||
assert_extracts 'direct reset "a-b-c.example.co.uk:8443"' \
|
||||
a-b-c.example.co.uk "internal hyphens and multi-part TLD"
|
||||
|
||||
# --- target= form (fallback pattern) ---
|
||||
assert_extracts 'direct failed target=blocked.example.net' \
|
||||
blocked.example.net "target= form"
|
||||
assert_extracts 'direct failed target blocked2.example.net' \
|
||||
blocked2.example.net "target<space> form"
|
||||
|
||||
# --- rejections: nothing usable on the line ---
|
||||
assert_rejects 'direct failed to connect to 192.168.1.1:443' "bare IPv4 is not a domain"
|
||||
assert_rejects 'direct connection failed, no host in line' "no host present"
|
||||
assert_rejects 'direct failed "localhost"' "single-label host has no TLD"
|
||||
assert_rejects 'direct failed "a.co"' "below 5-char minimum"
|
||||
|
||||
# --- rejections: wildcards must never reach the probe ---
|
||||
assert_rejects 'direct failed "*.example.com"' "wildcard star rejected"
|
||||
assert_rejects 'direct failed "?.example.com"' "wildcard question mark rejected"
|
||||
|
||||
# --- rejections: malformed labels ---
|
||||
assert_rejects 'direct failed "example..com"' "consecutive dots rejected"
|
||||
assert_rejects 'direct failed "-example.com"' "leading hyphen rejected"
|
||||
|
||||
# --- shell metacharacters must be returned inert, never executed ---
|
||||
# The extractor is the boundary that keeps log text out of the probe command;
|
||||
# a hostile log line must either be rejected or come back as a plain string.
|
||||
SENTINEL="$ROOT_DIR/tmp_smart_detect_injection_sentinel"
|
||||
rm -f "$SENTINEL"
|
||||
for hostile in \
|
||||
'direct failed "example.com; touch '"$SENTINEL"'"' \
|
||||
'direct failed "example.com$(touch '"$SENTINEL"')"' \
|
||||
'direct failed "example.com`touch '"$SENTINEL"'`"' \
|
||||
'direct failed "example.com | touch '"$SENTINEL"'"'
|
||||
do
|
||||
out="$(extract "$hostile")"
|
||||
case "$out" in
|
||||
*';'*|*'$('*|*'`'*|*'|'*|*' '*)
|
||||
fail "injection: metacharacters survived extraction: '$out'"
|
||||
;;
|
||||
esac
|
||||
[ ! -e "$SENTINEL" ] || fail "injection: command executed during extraction of '$hostile'"
|
||||
done
|
||||
rm -f "$SENTINEL"
|
||||
|
||||
printf 'smart_detect_domain_extraction checks passed\n'
|
||||
Reference in New Issue
Block a user