diff options
-rwxr-xr-x | bootstrap-unbound.sh | 91 | ||||
-rwxr-xr-x | convert.sh | 62 |
2 files changed, 153 insertions, 0 deletions
diff --git a/bootstrap-unbound.sh b/bootstrap-unbound.sh new file mode 100755 index 0000000..bed5ff1 --- /dev/null +++ b/bootstrap-unbound.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# bootstrap-unbound.sh +# One-shot installer / hardener for an Unbound recursive resolver +# Tested on Debian 11+/Ubuntu 22.04+ (systemd-based) + +set -euo pipefail +IFS=$'\n\t' + +######################### 1. Settings ################################ + +# Where youβll listen for queries (adjust subnet as needed!) +LISTEN_SUBNET="192.168.0.0/16" +THREADS="$(nproc)" +ROOT_HINTS="/var/lib/unbound/root.hints" +UNBOUND_CONF="/etc/unbound/unbound.conf" + +######################### 2. Install ################################# + +echo "π¦ Installing Unbound..." +apt-get update -qq +DEBIAN_FRONTEND=noninteractive apt-get install -y unbound curl jq dnsutils + +######################### 3. Root hints ############################## + +echo "π Fetching ICANN root hints..." +curl -sSL https://www.internic.net/domain/named.root -o "$ROOT_HINTS" + +######################### 4. Config file ############################# + +echo "π Writing $UNBOUND_CONF ..." +cat > "$UNBOUND_CONF" <<EOF +server: + interface: 0.0.0.0 + access-control: ${LISTEN_SUBNET} allow + access-control: 127.0.0.0/8 allow + + # Performance + num-threads: ${THREADS} + msg-cache-size: 128m + rrset-cache-size: 256m + prefetch: yes + prefetch-key: yes + + # DNSSEC + auto-trust-anchor-file: "/var/lib/unbound/root.key" + val-permissive-mode: no + + # Root servers + root-hints: "${ROOT_HINTS}" + + # Privacy + qname-minimisation: yes + minimal-responses: yes + + # Hardening + harden-dnssec-stripped: yes + harden-referral-path: yes + + # Logging (comment out if too chatty) + log-queries: no + log-replies: no + +remote-control: + control-enable: yes +EOF + +######################### 5. Control certs ########################### + +echo "π Generating control-channel certificates..." +unbound-control-setup + +######################### 6. Enable + start ########################## + +echo "π Enabling & starting Unbound..." +systemctl enable --now unbound + +######################### 7. Smoke tests ############################# + +echo -e "\nπ Quick DNSSEC validation tests:\n" + +GOOD_DOMAIN="cloudflare.com" +BAD_DOMAIN="dnssec-failed.org" +SERVER="127.0.0.1" + +good=$(dig +dnssec +adflag "$GOOD_DOMAIN" @"$SERVER" | grep -q "flags:.* ad" && echo "β
Validated" || echo "β FAILED") +bad=$(dig +dnssec +adflag "$BAD_DOMAIN" @"$SERVER" | grep -q "SERVFAIL" && echo "β
Blocked " || echo "β FAILED") + +printf " %-25s %s\n" "$GOOD_DOMAIN" "$good" +printf " %-25s %s\n" "$BAD_DOMAIN" "$bad" + +echo -e "\nπ All done. Point your LANβs DNS to this server and enjoy DNSSEC-validated recursion." diff --git a/convert.sh b/convert.sh new file mode 100755 index 0000000..f325d0c --- /dev/null +++ b/convert.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -e + +echo "π§Ή Stopping and disabling AdGuardHome..." +systemctl stop AdGuardHome || true +systemctl disable AdGuardHome || true +rm -f /etc/systemd/system/AdGuardHome.service +rm -rf /opt/AdGuardHome +rm -f /usr/bin/AdGuardHome + +echo "π¦ Installing Unbound..." +apt update +apt install -y unbound curl + +echo "π Fetching root hints..." +curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache + +echo "π Setting up hardened Unbound config..." +cat >/etc/unbound/unbound.conf <<EOF +server: + interface: 0.0.0.0 + access-control: 192.168.0.0/16 allow + access-control: 127.0.0.0/8 allow + + num-threads: $(nproc) + msg-cache-size: 128m + rrset-cache-size: 256m + prefetch: yes + prefetch-key: yes + + auto-trust-anchor-file: "/var/lib/unbound/root.key" + val-permissive-mode: no + + root-hints: "/var/lib/unbound/root.hints" + + qname-minimisation: yes + harden-dnssec-stripped: yes + harden-referral-path: yes + minimal-responses: yes + +remote-control: + control-enable: yes +EOF + +echo "π Disabling systemd-resolved stub listener if present..." +if [ -f /etc/systemd/resolved.conf ]; then + sed -i 's/^#*DNSStubListener=.*/DNSStubListener=no/' /etc/systemd/resolved.conf + systemctl restart systemd-resolved +fi + +echo "π¦ Restarting Unbound..." +systemctl enable unbound +systemctl restart unbound + +echo "β
Verifying Unbound is listening..." +ss -ulpn | grep :53 || echo "β οΈ Unbound might not be listening properly." + +echo "π§ͺ Test locally with:" +echo " dig +dnssec cloudflare.com @127.0.0.1" +echo " dig +dnssec dnssec-failed.org @127.0.0.1" + +echo "π Conversion complete. Box is now a recursive DNS resolver!" |