feat(toolbox): move Tor egress DNSPort 5353→9053 (avahi conflict) + Unbound .onion forward-zone

This commit is contained in:
CyberMind-FR 2026-07-09 07:37:14 +02:00
parent f2ed362015
commit f686d8811b
5 changed files with 34 additions and 3 deletions

View File

@ -0,0 +1,7 @@
# SecuBox: resolve .onion via the toolbox Tor egress DNSPort (automap).
# Installed by secubox-toolbox-tor-reconcile only while egress is armed.
server:
do-not-query-localhost: no
forward-zone:
name: "onion."
forward-addr: 127.0.0.1@9053

View File

@ -30,7 +30,7 @@ table inet toolbox_tor {
oifname "lo" return
# DNS always via Tor (no leak), even to local resolvers — before the
# tor_exempt return so own-subnet resolvers don't bypass it.
ip daddr != 127.0.0.0/8 meta skuid "secubox-toolbox" meta l4proto { tcp, udp } th dport 53 redirect to :5353
ip daddr != 127.0.0.0/8 meta skuid "secubox-toolbox" meta l4proto { tcp, udp } th dport 53 redirect to :9053
# Own services / LAN / loopback → DIRECT (never torified).
ip daddr @tor_exempt return
# Everything else from the worker uid → Tor TransPort.

View File

@ -8,7 +8,7 @@
SocksPort 127.0.0.1:9050
TransPort 127.0.0.1:9040
DNSPort 127.0.0.1:5353
DNSPort 127.0.0.1:9053
AutomapHostsOnResolve 1
VirtualAddrNetworkIPv4 10.192.0.0/10

View File

@ -28,6 +28,8 @@ NFT_DROPIN=/etc/nftables.d/zz-secubox-toolbox-tor.nft
TORRC_DROPIN_SRC=/usr/lib/secubox/toolbox/conf/torrc-toolbox-egress.conf
TORRC_DROPIN=/etc/tor/torrc.d/10-secubox-toolbox-egress.conf
TORRC_MAIN=/etc/tor/torrc
UNBOUND_ONION_SRC=/usr/lib/secubox/toolbox/conf/48-secubox-onion.conf
UNBOUND_ONION_DST=/etc/unbound/unbound.conf.d/48-secubox-onion.conf
log() { logger -t "secubox-${MODULE}" -- "$*" 2>/dev/null || true; echo "[$MODULE] $*"; }
@ -39,7 +41,7 @@ want_from_flag() {
}
arm() {
log "arming kbin Tor egress (TransPort 9040 / DNSPort 5353)"
log "arming kbin Tor egress (TransPort 9040 / DNSPort 9053)"
mkdir -p /etc/tor/torrc.d
install -m 0644 "$TORRC_DROPIN_SRC" "$TORRC_DROPIN"
# Debian's torrc does not %include torrc.d by default — add it idempotently.
@ -54,6 +56,13 @@ arm() {
populate_exempt
systemctl restart tor 2>/dev/null || systemctl start tor 2>/dev/null || \
log "WARN tor failed to (re)start — egress fail-closed until it does"
# Resolve .onion via the egress DNSPort (automap). Fail-safe: never abort
# arm() on a rejected drop-in — just remove it and keep going.
if [ -f "$UNBOUND_ONION_SRC" ] && [ -d /etc/unbound/unbound.conf.d ]; then
install -m 0644 "$UNBOUND_ONION_SRC" "$UNBOUND_ONION_DST"
unbound-checkconf >/dev/null 2>&1 && systemctl reload unbound 2>/dev/null || \
{ rm -f "$UNBOUND_ONION_DST"; log "WARN unbound .onion forward-zone rejected — removed"; }
fi
log "ARMED"
}
@ -92,6 +101,7 @@ disarm() {
rm -f "$NFT_DROPIN"
if table_present; then nft delete table inet toolbox_tor 2>/dev/null || true; fi
rm -f "$TORRC_DROPIN"
if [ -f "$UNBOUND_ONION_DST" ]; then rm -f "$UNBOUND_ONION_DST"; systemctl reload unbound 2>/dev/null || true; fi
# Stop tor to minimise attack surface when not in use (no hidden services
# are owned by this drop-in; secubox-tor manages those separately).
systemctl stop tor 2>/dev/null || true

View File

@ -0,0 +1,14 @@
from pathlib import Path
CONF = Path(__file__).resolve().parents[1] / "conf"
def test_dnsport_moved_off_avahi_5353():
torrc = (CONF / "torrc-toolbox-egress.conf").read_text()
assert "DNSPort 127.0.0.1:9053" in torrc
assert "5353" not in torrc # avahi owns 5353
def test_nft_redirect_targets_9053():
nft = (CONF / "nft-toolbox-tor.nft").read_text()
assert "redirect to :9053" in nft
assert ":5353" not in nft
def test_unbound_onion_forward_zone_valid():
conf = (CONF / "48-secubox-onion.conf").read_text()
assert 'name: "onion."' in conf
assert "forward-addr: 127.0.0.1@9053" in conf