mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 19:07:04 +01:00
Gateway mode routes LAN devices through the PC: forced DNS, DoH/DoT dropped. The work laptop still bypassed it through Cloudflare WARP, so the WARP ingress is dropped too. warp_window.sh opens it for the LAN only Mon/Fri 09:00-15:30 (nft set with a timeout to 15:30), asked for over a forced-command key by warp_home.sh, which keeps WARP off at home otherwise because WARP fails closed. Also: dnsmasq upstreams, AAAA filtering, DoH canary, and extracted_repo_dir resolving ~/src first (the nightly blocklist refresh had failed since 2026-09-11). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C8pdLR4MePsLocE1pWz7F
139 lines
4.9 KiB
Bash
Executable File
139 lines
4.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# dnsmasq config, drop-in, refresh timer and watchdog units.
|
|
#
|
|
# Sourced by setup_dns_blocker.sh; split out to keep it under the 250-line cap.
|
|
# Sourced rather than run, so it inherits the caller's strict mode.
|
|
|
|
# Upstream resolvers for every name not in the blocklist.
|
|
readonly UPSTREAMS=(1.1.1.1 9.9.9.9)
|
|
# Hostnames browsers use to reach DoH providers; answered 0.0.0.0 so a browser
|
|
# set to "secure DNS" falls back to this resolver instead of bypassing it.
|
|
readonly DOH_HOSTNAMES=(
|
|
dns.google cloudflare-dns.com one.one.one.one dns.quad9.net
|
|
dns.nextdns.io doh.opendns.com dns.adguard-dns.com doh.cleanbrowsing.org
|
|
dns.mullvad.net dns.controld.com freedns.controld.com doh.libredns.gr
|
|
)
|
|
|
|
write_dnsmasq_conf() {
|
|
ensure_dir "$(dirname "$DNSMASQ_CONF")" # /etc/dnsmasq.d may not exist yet
|
|
local server_lines doh_lines
|
|
server_lines="$(printf 'server=%s\n' "${UPSTREAMS[@]}")"
|
|
doh_lines="$(printf 'address=/%s/0.0.0.0\n' "${DOH_HOSTNAMES[@]}")"
|
|
log_info "Writing ${DNSMASQ_CONF} (listen on ${LAN_IFACE}/${LAN_IP}, upstream ${UPSTREAMS[*]})."
|
|
cat >"$DNSMASQ_CONF" <<EOF
|
|
# Managed by setup_dns_blocker.sh -- LAN DNS blocker.
|
|
# Serves the identical blocklist as /etc/hosts to LAN clients via addn-hosts.
|
|
# Do not edit by hand; re-run 'setup_dns_blocker.sh setup' instead.
|
|
|
|
# Listen only on the LAN interface (leaves 127.0.0.53 free for the
|
|
# systemd-resolved stub that the /etc/hosts installer enables).
|
|
# bind-dynamic, not bind-interfaces: at boot dnsmasq can start before
|
|
# ${LAN_IFACE} exists, and bind-interfaces then dies with "unknown interface".
|
|
# Its 5 s restart recovered, but stunnel-dot's start job had already failed on
|
|
# the dependency and was never retried, so DoT stayed down every boot.
|
|
# bind-dynamic binds the address whenever the interface appears.
|
|
interface=${LAN_IFACE}
|
|
bind-dynamic
|
|
|
|
# Do NOT read /etc/hosts (huge + immutable); the blocklist comes from the feed.
|
|
no-hosts
|
|
addn-hosts=${FEED}
|
|
|
|
# Forward everything not in the blocklist to the upstream resolvers ONLY.
|
|
# no-resolv: ignore /etc/resolv.conf so we never chain through the
|
|
# systemd-resolved stub (127.0.0.53) that the /etc/hosts installer enables.
|
|
# Not the Funbox: it drops ~20% of queries (measured 2026-09-18), which is
|
|
# every device's problem once gateway mode forces all LAN DNS through here.
|
|
no-resolv
|
|
${server_lines}
|
|
domain-needed
|
|
bogus-priv
|
|
|
|
cache-size=10000
|
|
|
|
# The feed only carries 0.0.0.0, so every AAAA query used to be forwarded and a
|
|
# "blocked" name resolved to its real IPv6 address. Strip AAAA everywhere: the
|
|
# LAN has no IPv6 from the Funbox anyway, and IPv6 would bypass gateway mode.
|
|
filter-AAAA
|
|
|
|
# DoH bypasses this resolver. Firefox turns its default DoH off only when the
|
|
# canary domain is NXDOMAIN; the bootstrap names stop browsers resolving the
|
|
# common DoH providers (gateway mode also drops their IPs).
|
|
local=/use-application-dns.net/
|
|
${doh_lines}
|
|
|
|
# Log dnsmasq's own messages (startup, upstream failures) -- "log failures".
|
|
log-facility=${LOG_FILE}
|
|
# log-queries # opt-in: full per-query log (verbose + privacy). Off by default.
|
|
EOF
|
|
}
|
|
|
|
install_restart_dropin() {
|
|
ensure_dir "$DNSMASQ_DROPIN_DIR"
|
|
cat >"$DNSMASQ_DROPIN" <<'EOF'
|
|
# Managed by setup_dns_blocker.sh -- keep the resolver up.
|
|
# No network-online ordering: the stock unit is Before=network-online.target,
|
|
# so After= here was an ordering cycle systemd broke by deleting a job at every
|
|
# boot. bind-dynamic (dnsmasq.conf) makes waiting for the NIC unnecessary.
|
|
[Service]
|
|
Restart=always
|
|
RestartSec=5
|
|
EOF
|
|
}
|
|
|
|
install_refresh_timer() {
|
|
cat >"$REFRESH_SERVICE" <<EOF
|
|
[Unit]
|
|
Description=Rebuild the LAN DNS blocklist and reload dnsmasq
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=${SELF} refresh
|
|
EOF
|
|
cat >"$REFRESH_TIMER" <<'EOF'
|
|
[Unit]
|
|
Description=Daily rebuild of the LAN DNS blocklist
|
|
|
|
[Timer]
|
|
OnCalendar=daily
|
|
Persistent=true
|
|
RandomizedDelaySec=15m
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOF
|
|
}
|
|
|
|
# The whole LAN's DHCP/DNS depends on this one process. Restart=always in the
|
|
# drop-in only catches an actual crash; an incident on 2026-07-23 found
|
|
# dnsmasq dead with ZERO error logged (no crash, no "Stopping"/"Stopped" line
|
|
# either -- consistent with something issuing a plain stop, not a failure) and
|
|
# it stayed down for hours, silently, until noticed by a phone unable to join
|
|
# WiFi. Mirrors the existing shutdown-timer-monitor-watchdog pattern used
|
|
# elsewhere in this repo: same 5-minute cadence, same is-active-or-start shape,
|
|
# plus a logger call so a future incident leaves a trace instead of none.
|
|
install_watchdog() {
|
|
cat >"$WATCHDOG_SERVICE" <<'EOF'
|
|
[Unit]
|
|
Description=Watchdog for dnsmasq (LAN DHCP/DNS)
|
|
After=multi-user.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/bin/bash -c 'systemctl is-active --quiet dnsmasq || { logger -t dnsmasq-watchdog "dnsmasq was down -- restarting"; systemctl restart dnsmasq; }'
|
|
EOF
|
|
cat >"$WATCHDOG_TIMER" <<'EOF'
|
|
[Unit]
|
|
Description=Watchdog Timer for dnsmasq
|
|
|
|
[Timer]
|
|
OnBootSec=60
|
|
OnUnitActiveSec=300
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOF
|
|
}
|