mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 17:34:04 +01:00
setup_dns_blocker.sh turns this PC into a DNS server that serves the identical /etc/hosts blocklist to the whole LAN with no per-device app, by feeding generate_hosts_file.sh output into dnsmasq via addn-hosts (same StevenBlack variant + custom entries + unblocks). Adds status/ refresh subcommands, a daily refresh timer, Restart=always, and logging to /var/log/dns-blocker/. Because the ISP router cannot advertise a custom DNS server, a dhcp/ dhcp-off mode makes the PC the LAN DHCP server (static IP via nmcli with a gateway-ping self-check and safe, always-online rollback), handing out itself as the DNS server so every device is blocked automatically. setup_wireguard_ssh.sh gains an allow-dns subcommand that opens DNS (53, LAN saddr) and DHCP (67) in the single-owner nftables ruleset. The DHCP accept rule is placed before 'ct state invalid drop' because the 0.0.0.0->255.255.255.255 DHCP broadcast is classified INVALID and was otherwise dropped. Firewall detection now reads the actual loaded ruleset (a ruleset can be loaded while nftables.service reads inactive) and avoids a grep -q/pipefail SIGPIPE false-negative. Verified end-to-end: Pixel-6a leased 192.168.1.82 with DNS 192.168.1.43; youtube.com blocked, legit sites resolve. Regression tests added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018pqSnrLt8QoWup7n2Ymk77
44 lines
3.7 KiB
JSON
44 lines
3.7 KiB
JSON
{
|
|
"intent": "Give every device on the LAN the same domain blocking as the PC's /etc/hosts, with no app installed on the device, by running the PC as a Pi-hole-like DNS (and, for this router, DHCP) server.",
|
|
"scope": [
|
|
"linux_configuration/scripts/single_use/features/setup_dns_blocker.sh (new: dnsmasq-based LAN DNS blocker + optional DHCP-server mode)",
|
|
"linux_configuration/scripts/single_use/features/setup_wireguard_ssh.sh (new allow-dns subcommand: opens DNS 53 + DHCP 67 for the LAN in the single-owner nftables ruleset)",
|
|
"linux_configuration/tests/test_setup_dns_blocker.sh (new regression tests)",
|
|
"Non-goals: no Pi-hole/web dashboard, no per-query analytics, no DoH enforcement on clients (a voluntary-DNS design cannot force off-path traffic)."
|
|
],
|
|
"changes": [
|
|
"dnsmasq serves the identical blocklist as /etc/hosts via addn-hosts pointed at generate_hosts_file.sh output (same StevenBlack variant + custom entries + unblocks); no-hosts + no-resolv keep it deterministic; bound to the LAN interface only so the systemd-resolved stub stays free.",
|
|
"Daily systemd timer rebuilds the feed and SIGHUPs dnsmasq; Restart=always drop-in; logs to /var/log/dns-blocker/.",
|
|
"dhcp/dhcp-off subcommands: because the ISP router cannot advertise a custom DNS, the PC becomes the LAN DHCP server (static IP via nmcli with a gateway-ping self-check + auto-revert; hands out itself as DNS). Rollback keeps the PC online on its static IP.",
|
|
"Firewall: allow-dns opens udp/tcp 53 (LAN saddr) and udp 67 for DHCP. The DHCP accept rule is placed BEFORE 'ct state invalid drop' because the 0.0.0.0->255.255.255.255 broadcast is classified INVALID and was being dropped.",
|
|
"Fixed firewall detection to read the actual loaded nftables ruleset (a ruleset can be loaded while nftables.service reads inactive), avoiding a grep -q/pipefail SIGPIPE false-negative."
|
|
],
|
|
"verification": [
|
|
{
|
|
"command": "sudo setup_dns_blocker.sh setup && sudo setup_dns_blocker.sh dhcp && setup_dns_blocker.sh status",
|
|
"result": "pass",
|
|
"evidence": "status all green: dnsmasq active/enabled, listening 192.168.1.43:53, firewall DNS/DHCP open for LAN, DHCP mode ON. Pixel-6a leased 192.168.1.82 with option6 dns-server=192.168.1.43 (DHCPDISCOVER->OFFER->REQUEST->ACK). dig @192.168.1.43 youtube.com -> 0.0.0.0 (blocked); example.com/wikipedia.org -> real IP."
|
|
},
|
|
{
|
|
"command": "on-device manual test (Pixel 6a)",
|
|
"result": "pass",
|
|
"evidence": "User confirmed: legit websites load, youtube.com is blocked."
|
|
},
|
|
{
|
|
"command": "bash linux_configuration/tests/test_setup_dns_blocker.sh",
|
|
"result": "pass",
|
|
"evidence": "PASS: dispatch (help lists all subcommands, unknown cmd exits non-zero) + firewall_is_loaded regression (drop->LOADED, accept->NOT_LOADED under set -o pipefail with large nft output)."
|
|
}
|
|
],
|
|
"risks": [
|
|
"Voluntary DNS: a device using DoH / Android Private DNS / a VPN / a manual DNS bypasses blocking; the PC is not the gateway so it cannot force traffic. Phone Private DNS must be Off.",
|
|
"PC is now the LAN DHCP server: if it is down, new devices get no lease (existing leases persist ~12h). Fail-closed by design.",
|
|
"Static IP pinned on enp6s0; a wrong gateway would break connectivity (mitigated by an immediate ping self-check that auto-reverts)."
|
|
],
|
|
"rollback": [
|
|
"DHCP: sudo setup_dns_blocker.sh dhcp-off (stops serving DHCP, KEEPS the PC on its static IP so it stays online), then re-tick the router's DHCP.",
|
|
"DNS blocker: systemctl disable --now dnsmasq dns-blocklist-refresh.timer; rm /etc/dnsmasq.d/lan-blocker.conf /etc/dnsmasq.d/lan-dhcp.conf.",
|
|
"Validate after rollback: devices get leases from the router again and normal DNS resolves."
|
|
]
|
|
}
|