This is an old revision of the document!
Unbound Howto
Base setup
server:
verbosity: 1
log-queries: no
port: 53
# ----------------------
# optimizations https://nlnetlabs.nl/documentation/unbound/howto-optimise/
# ----------------------
num-threads: 2
msg-cache-slabs: 2
rrset-cache-slabs: 2
infra-cache-slabs: 2
key-cache-slabs: 2
so-reuseport: yes
key-cache-size: 8m # default 4m
neg-cache-size: 2m # default 1m
rrset-cache-size: 100m # rrset=msg*2 # default 4m
msg-cache-size: 50m # default 4m
# depends on number of cores: 1024/cores - 50
outgoing-range: 462
num-queries-per-thread: 231 # outgoing-range/2
so-rcvbuf: 4m
so-sndbuf: 4m
outgoing-num-tcp: 100 #default 10
incoming-num-tcp: 100 #default 10
stream-wait-size: 8m #default 4m
# ----------------------
statistics-interval: 1200
# ----------------------
port: 53
interface: 0.0.0.0
interface: ::0
#
# tls setup get ssl keys from letsencrypt
#
interface: 0.0.0.0@853
interface: ::0@853
tls-service-key: /etc/unbound/privkey.pem
tls-service-pem: /etc/unbound/fullchain.pem
#
use-syslog: yes
# first start
# drill . ns @161.97.219.84 > named.cache.opennic
# dig -t DNSKEY . @161.97.219.84 | dnssec-dsfromkey -1 -f - . > opennic.dnskey
# dig -t DNSKEY . @161.97.219.84 | dnssec-dsfromkey -2 -f - . > opennic.dnskey
root-hints: "/etc/unbound/named.cache.opennic"
trust-anchor-file: "/etc/unbound/opennic.dnskey"
# dnssec not working at the moment for all domains
harden-dnssec-stripped: no
harden-glue: no
aggressive-nsec: no
do-not-query-localhost: no
access-control: 0.0.0.0/0 allow
access-control: ::0/0 allow
#
hide-identity: yes
identity: "pope.vatican.va"
hide-version: yes
version: "0.0"
tls-system-cert: yes
#ip-ratelimit-factor: 10
#ip-ratelimit: 60
ratelimit: 100
include: /etc/unbound/opennic_server.conf
local-zone: "168.192.in-addr.arpa." transparent
local-zone: "10.in-addr.arpa." transparent
local-zone: "16.172.in-addr.arpa." transparent
local-zone: "17.172.in-addr.arpa." transparent
local-zone: "18.172.in-addr.arpa." transparent
local-zone: "19.172.in-addr.arpa." transparent
local-zone: "20.172.in-addr.arpa." transparent
local-zone: "21.172.in-addr.arpa." transparent
local-zone: "22.172.in-addr.arpa." transparent
local-zone: "23.172.in-addr.arpa." transparent
local-zone: "24.172.in-addr.arpa." transparent
local-zone: "25.172.in-addr.arpa." transparent
local-zone: "26.172.in-addr.arpa." transparent
local-zone: "27.172.in-addr.arpa." transparent
local-zone: "28.172.in-addr.arpa." transparent
local-zone: "29.172.in-addr.arpa." transparent
local-zone: "30.172.in-addr.arpa." transparent
local-zone: "31.172.in-addr.arpa." transparent
local-zone: "0.in-addr.arpa." transparent
local-zone: "127.in-addr.arpa." transparent
local-zone: "254.169.in-addr.arpa." transparent
local-zone: "2.0.192.in-addr.arpa." transparent
local-zone: "100.51.198.in-addr.arpa." transparent
local-zone: "113.0.203.in-addr.arpa." transparent
local-zone: "255.255.255.255.in-addr.arpa." transparent
local-zone: "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." transparent
local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." transparent
local-zone: "d.f.ip6.arpa." transparent
local-zone: "8.e.f.ip6.arpa." transparent
local-zone: "9.e.f.ip6.arpa." transparent
local-zone: "a.e.f.ip6.arpa." transparent
local-zone: "b.e.f.ip6.arpa." transparent
local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." transparent
local-zone: "onion." always_null
# test local
# just an example
#local-zone: "porno." static
#local-data: 'porno. IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800'
#local-data: 'rechner.porno. IN A 127.0.0.1'
remote-control:
control-enable: yes
Refresh script
#!/usr/bin/perl
use strict;
use warnings;
use XML::Parser;
use Data::Dumper;
my @bla = `wget --no-check-certificate -q -O - https://servers.opennic.org?tier=1`;
my $done=0;
my $res="";
while ( @bla ) {
my $l = shift @bla;
unless ($done) {
if ( $l =~ /opennic\.glue/ ) {
$done++;
$res = $l;
}
}
}
$res =~ s/\<p\>//g;
$res =~ s/\<\/p\>//g;
$res =~ s/\<span\>//g;
$res =~ s/\<\/span\>//g;
$res =~ s/\<span\sclass=\'host\'[^\>]+\>//g;
$res =~ s/\<a.+\>(.+)\<\/a\>//;
$res =~ s/\<wbr\>/:/g;
if ( $res =~ /\>(\d+\.\d+\.\d+\.\d+)\</ ) {
print $1 . "\n";
}
if ( $res =~ /\>([0-9A-Fa-f]+:\S+)\</ ) {
print $1 . "\n";
}
#!/bin/bash
# arch linux packets needed:
# - ldns
# - unbound
# - gawk
# - coreutils
# - grep
AWK=/usr/bin/awk
CUT=/usr/bin/cut
DIG="/usr/bin/drill -t -r /etc/unbound/named.cache.opennic"
GREP=/bin/grep
PRINTF=/usr/bin/printf
SED=/bin/sed
KF=opennic.dnskey
CF=named.cache.opennic
SF=opennic_server.conf
DF=opennic_domains.conf
#MYIP='<please set me>'
MYIP=94.16.119.109
if [ "$MYIP" = "<please set me>" ] ; then
echo "set varieble MYIP in this script"
exit 1
fi
cd `dirname $0`
# Make sure only one copy runs at a time
LOCK="refresh_base.lock"
r=$($PRINTF %05d $RANDOM)
sleep ${r:0:1}.${r:1:5}
if [ -f $LOCK ]; then
last_serial=$(cat $LOCK)
dt=$((`date +%s` - `date -r $LOCK +%s`))
if [ $dt -lt 600 ]; then
echo "Last run ${dt}s < 600s left"
exit 0;
else
echo "Last run ${dt}s"
fi
fi
touch $LOCK
# first get any tier1 server to start
NS=( $(./getroot_opennic.pl) )
echo -n "Opennic tier1 Server: "
for ns in "${NS[@]}"; do
echo -n "$ns "
soa=$($DIG -Q SOA . @$ns)
if [ "$soa" ]; then NS0=$(echo $soa | awk '{print $1}') ; break ; fi
done
if [ ! "$NS0" ]; then
echo "No Opennic tier1 server could not be reached -- aborting!" >&2
exit 1
fi
echo
# get master server
NS0=$(echo $NS0 | awk '{print $1}')
echo -n "Master openic server: $NS0 ("
# get ip from master server
NS=( $(drill -Q @$ns ns0.opennic.glue.) )
for ns in "${NS[@]}"; do
if [ "$soa" ]; then NS0=$ns ; break ; fi
done
if [ ! "$NS0" ]; then
echo "could not be reached -- aborting!" >&2
exit 1
fi
echo "$NS0)"
soa=$($DIG -Q SOA . @$NS0)
serial=$(echo $soa | awk '{ print $3}')
refresh=$(echo $soa | awk '{ print $4}')
echo "Serial: $serial"
echo "Refresh: $refresh"
echo $serial > $LOCK
if [ -z "$last_serial" ] ; then
last_serial=0
fi
if [ $last_serial == $serial ]; then
echo "No Update needed serial not changed"
exit 0
fi
dig . ns @${NS0} > $CF
echo "Updated $CF"
dig -t DNSKEY . @${NS0} | dnssec-dsfromkey -1 -f - . > $KF
dig -t DNSKEY . @${NS0} | dnssec-dsfromkey -2 -f - . >> $KF
cp $KF /etc/trusted-key.key
echo "Updated $KF and /etc/trusted-key.key"
# Start printing the new file
ifs=$IFS
# Collect list of TLDs
TXT=(dns.opennic.glue $($DIG -Q @$NS0 TXT tlds.opennic.glue | tr -d '"'))
IFS=$'\n' TLDS=($(sort <<<${TXT[*]}))
IFS=$ifs
if [ "${TLDS[*]}" == "dns.opennic.glue" ]; then
echo "Failed to obtain list of TLDs" >&2
rm -f $LOCK
exit 1
else
echo "TLDS: ${TLDS[*]}" >&2
fi
echo "#" > $DF
echo "# OpenNIC zone config - file created by $HOSTNAME" >> $DF
echo "# Generated on `date '+%A, %d %b %Y at %T'`" >> $DF
echo "#" >> $DF
echo "#" > $SF
echo "# OpenNIC server config for opennic - file created by $HOSTNAME" >> $SF
echo "# Generated on `date '+%A, %d %b %Y at %T'`" >> $SF
echo "#" >> $SF
for TLD in "${TLDS[@]}" ; do
if [ $TLD != '.' ]; then
echo -n 'domain-insecure: "' >> $SF
echo -n $TLD >> $SF
echo '"' >> $SF
fi
# Check if this zone is mastered by this server
zone="$TLD.opennic.glue"
if [ "$TLD" == "." ]; then
zone="" ;
fi
master=($($DIG -Q TXT $zone. @$NS0 | sed 's/"//g' | $GREP ^ns) ns0.opennic.glue.)
echo "TLD $TLD master = ${master[*]}"
# Begin printing the zone config
echo >> $DF
echo "auth-zone:" >> $DF
echo " name: $TLD" >> $DF
if [ $TLD == '.' ]; then
echo " zonefile: sec/root.zone" >> $DF
else
echo " zonefile: sec/${TLD}.zone" >> $DF
fi
echo " for-downstream: no" >> $DF
# Collect a list of master nameservers for the zone
for mm in "${master[@]}" ; do
mm=$(echo $mm | $SED 's/\.$//')
ns=$(echo $mm | $CUT -d. -f1 | $SED 's/ns//')
AT="@$myDNS"
if [ "$ns" == "0" ]; then AT="@$NS0"; fi
if [ "$AT" == "@" ]; then AT=""; fi
# If this is an unknown NS, query its IPs
if [ ! "${RES[$ns]}" ]; then
A4=$($DIG -Q A $mm $AT)
A6=$($DIG -Q AAAA $mm $AT)
RES[$ns]="${A4[@]} ${A6[@]}"
fi
read -a IP <<< ${RES[$ns]}
# Print all IPs for all nameservers
for addr in "${IP[@]}" ; do
echo " master: $addr" >> $DF
done
done
echo >> $DF
done
echo "Updated $DF $SF"
unbound-control reload_keep_cache
echo "Restarted unbound"
sleep 10
wget -q --no-check-certificate -O test.txt 'https://report.opennicproject.org/t2log/t1.php?ip_addr=94.16.119.109'
if [ $(cat test.txt | perl -n -e 'if ( $p == 1 ) { /Passed/ && print "OK\n" ; $p = 0; } else { if ( /Test results:/ ) { $p=1; } }') != 'OK' ] ; then
echo "Opennic Tier1 TEST FAILED"
rm -f test.txt
exit 1
else
echo "Opennic Tier1 TEST OK"
rm -f test.txt
fi
sleep 10
wget -q --no-check-certificate -O test.txt 'https://servers.opennicproject.org/srvtest3/test.php?ip=94.16.119.109&ns=94.16.119.109'
if [ $(cat test.txt | perl -n -e '/Server\sstatus(.*)$/ && print $1;' | perl -n -e '/\[(.+)\]/ && print $1;') != '100%' ] ; then
echo "Opennic Tier2 TEST FAILED"
rm -f test.txt
exit 1
else
echo "Opennic Tier2 TEST OK"
rm -f test.txt
fi
if [ -z "$($DIG -TD . soa | grep '^\[T\]' | grep SOA)" ] ; then
echo "DNSSEC Test FAILED"
exit 1
else
echo "DNSSEC Test OK"
fi
git commit -am "Serial: $serial"