Skip to content

Instantly share code, notes, and snippets.

@iptoux
Last active February 6, 2023 22:15
Show Gist options
  • Save iptoux/25fcc418c0b426ff990283e1f33675e7 to your computer and use it in GitHub Desktop.
Save iptoux/25fcc418c0b426ff990283e1f33675e7 to your computer and use it in GitHub Desktop.
Unbound automatic bash install script for proxmox
#!/bin/bash
n='([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
m='([0-9]|[12][0-9]|3[012])'
echo -n "Updating repos: "
apt -q update &> /dev/null
echo "done"
echo -n "Updating system: "
apt -q -y upgrade &> /dev/null
echo "done"
echo -e "Installing unbound: (1/2)"
apt -q -y install unbound &> /dev/null
echo -e "\rInstalling unbound: (2/2)"
apt -q -y install apparmor &> /dev/null
echo -e "\rInstalling unbound: done"
echo -n "Getting DNS ROOT Servers: "
wget https://www.internic.net/domain/named.root -qO- | tee /var/lib/unbound/root.hints &> /dev/null
echo "done"
echo -e "\nUser variables:\n "
read -p "Enter listen ip (def: 127.0.0.1):> " DNS_IP
if ! [[ $DNS_IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
read -p "False, listen ip (def: 127.0.0.1):> " DNS_IP
fi
read -p "Enter listen port (default: 5335):> " DNS_PORT
if ! [[ $DNS_PORT =~ ^[0-9]+$ ]]
then
read -p "False, please enter only numbers:> " DNS_PORT
elif [[ ${#DNS_PORT} -gt 5 ]]
then
read -p "False, please enter an max lenght of 5:> " DNS_PORT
fi
read -p "Enter private ip (CIDR/range):> " DNS_PRIV
if ! [[ $DNS_PRIV =~ ^$n(\.$n){3}/$m$ ]]; then
read -p "False, enter in CIDR/range:> " DNS_PRIV
fi
read -p "Enable logging? (y/N):> " DNS_LOG
if [ $DNS_LOG == "y" ] || [ $DNS_LOG == "Y" ]; then
echo "Please enter path+name for logfile (leave empty for default)"
read -rp "Default? /var/log/unbound/unbound.log:> " DNS_LOG_DEF
if [[ ${#DNS_LOG_DEF} -lt 1 ]]; then
DNS_LOG_FILE="/var/log/unbound/unbound.log"
else
DNS_LOG_FILE=$DNS_LOG_DEF
fi
read -rp "Enter Loglevel (1-5):> " DNS_LOG_LVL
if [[ ${DNS_LOG_LVL} -gt 5 ]] || [[ ${DNS_LOG_LVL} -lt 1 ]]; then
read -rp "False, valid between 1 and 5:> " DNS_LOG_LVL
fi
else
DNS_LOG_STAT="# logfile:"
DNS_LOG_FILE="/var/log/unbound/unbound.log"
DNS_LOG_LVL=0
fi
echo -n "Checking for log directory: "
DNS_LOG_STAT="logfile:"
DNS_LOG_PATH="$(dirname ${DNS_LOG_FILE})"
if [ -d ${DNS_LOG_PATH} ]; then
if ! [ -f ${DNS_LOG_FILE} ]; then
touch ${DNS_LOG_FILE}
echo "Logfile created."
else
echo "Logfile exists."
fi
else
mkdir -p ${DNS_LOG_PATH}
touch ${DNS_LOG_FILE}
echo "Logfile and directory created."
fi
echo -n "Chowning logfile: "
chown unbound:unbound ${DNS_LOG_FILE} &> /dev/null
echo "done"
PICONF="/etc/unbound/unbound.conf.d/pi-hole.conf"
echo -n "Generate config file: "
cat <<EOF >${PICONF}
server:
# If no logfile is specified, syslog is used
${DNS_LOG_STAT} "$DNS_LOG_FILE"
# Level 0 means no verbosity, only errors
# Level 1 gives operational information
# Level 2 gives detailed operational information
# Level 3 gives query level information
# Level 4 gives algorithm level information
# Level 5 logs client identification for cache misses
verbosity: ${DNS_LOG_LVL}
# Answer queries from
# The local machine
interface: 127.0.0.1
interface: ::1
# The local machine on the network
interface: ${DNS_IP}
# Default DNS port
port: ${DNS_PORT}
# Save in cache for an hour to a day
cache-min-ttl: 3600
cache-max-ttl: 86400
# Enable IPv4, IPv6, UDP and TCP requests
do-ip4: yes
do-ip6: no # May be set to yes if you have IPv6 connectivity
do-udp: yes
do-tcp: yes
# You want to leave this to no unless you have *native* IPv6. With 6to4 and
# Terredo tunnels your web browser should favor IPv4 for the same reasons
prefer-ip6: no
# Use this only when you downloaded the list of primary root servers!
# If you use the default dns-root-data package, unbound will find it automatically
root-hints: "/var/lib/unbound/root.hints"
# Trust glue only if it is within the server's authority
harden-glue: yes
# Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS
harden-dnssec-stripped: yes
# Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes
# see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details
use-caps-for-id: no
# Reduce EDNS reassembly buffer size.
# IP fragmentation is unreliable on the Internet today, and can cause
# transmission failures when large DNS messages are sent via UDP. Even
# when fragmentation does work, it may not be secure; it is theoretically
# possible to spoof parts of a fragmented DNS message, without easy
# detection at the receiving end. Recently, there was an excellent study
# >>> Defragmenting DNS - Determining the optimal maximum UDP response size for DNS <<<
# by Axel Koolhaas, and Tjeerd Slokker (https://indico.dns-oarc.net/event/36/contributions/776/)
# in collaboration with NLnet Labs explored DNS using real world data from the
# the RIPE Atlas probes and the researchers suggested different values for
# IPv4 and IPv6 and in different scenarios. They advise that servers should
# be configured to limit DNS messages sent over UDP to a size that will not
# trigger fragmentation on typical network links. DNS servers can switch
# from UDP to TCP when a DNS response is too big to fit in this limited
# buffer size. This value has also been suggested in DNS Flag Day 2020.
edns-buffer-size: 1232
# Perform prefetching of close to expired message cache entries
# This only applies to domains that have been frequently queried
prefetch: yes
# One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads above 1.
num-threads: 1
# Ensure kernel buffer is large enough to not lose messages in traffic spikes
so-rcvbuf: 1m
# Privacy
# Hide identity and version
hide-identity: yes
hide-version: yes
# Ensure privacy of local IP ranges
# Localhost
private-address: 127.0.0.1
private-address: ::1
# Windows
# private-address: 169.254.0.0/16
# private-address: 172.16.0.0/12
# Network
private-address: ${DNS_PRIV}
# private-address: 2001:db8::/108
# Vpn
# private-address: 10.0.0.0/8
# private-address: fd00::/8
# Prevent from resolving network IPs
do-not-query-address: ${DNS_PRIV}
do-not-query-localhost: yes
# Launch in a deamon (temporarily disabled)
# do-daemonize: yes
# Access control
# Deny all the Internet (temporarily refuse)
access-control: 0.0.0.0/0 refuse
access-control: ::0/0 refuse
# Allow localhost
access-control: 127.0.0.1 allow
access-control: ::1 allow
# Allow from network CIDR
access-control: ${DNS_PRIV} allow_snoop
# Prefetch old-cached DNS responses
prefetch: yes
EOF
echo "done"
echo ""
echo -n "Restarting unbound service: "
service unbound restart
echo "done"
echo -n "Testing configuration: "
TESTENV="$(dig pi-hole.net @${DNS_IP} -p ${DNS_PORT} | grep status | cut -d ':' -f3 | cut -d ',' -f1)"
if [[ "${TESTENV}" -eq "NOERROR" ]]; then
echo "success"
else
echo "failed! Please recheck configuration."
fi
echo -n "Checking for piHole on local server: "
if ! command -v pihole &> /dev/null
then
echo "not found."
echo ""
echo "Please add \"edns-packet-max=1232\" into \"/etc/dnsmasq.d/99-edns.conf\" on your piHole server."
echo ""
else
echo "found."
echo -n "Inform piHole(FTL/dnsmasq): "
touch /etc/dnsmasq.d/99-edns.conf
echo "edns-packet-max=1232" > "/etc/dnsmasq.d/99-edns.conf"
echo "done"
fi
echo -n "Disable openresolver: "
systemctl disable unbound-resolvconf.service &> /dev/null
systemctl stop unbound-resolvconf.service &> /dev/null
echo "done"
echo -n "Apply appamor settings: "
echo "/var/log/unbound/unbound.log rw," >> "/etc/apparmor.d/local/usr.sbin.unbound"
apparmor_parser -r /etc/apparmor.d/usr.sbin.unbound &> /dev/null
echo "done"
echo -n "Restarting unbound: "
service unbound stop &> /dev/null
sleep 1
service unbound start &> /dev/null
echo "done"
echo ""
echo -e "Finally, configure Pi-hole to use your recursive DNS server\nby specifying 127.0.0.1#5335 as the Custom DNS (IPv4):\n"
echo ">>> https://docs.pi-hole.net/images/RecursiveResolver.png"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment