summaryrefslogtreecommitdiff
path: root/bootstrap-unbound.sh
blob: bed5ff1c091a14a1687068d19c60fe0199dc9e6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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."