
On a Lighter Note ! To summon it Up in single image !
Customized Panel To manage DNS Configuration via WEBMIN ! (SJZ)
Unbound is a secure DNS resolver. It can be a caching resolver, a recursive resolver, and both, suitable for offices/ISP’s. It is designed to be fast and lean and incorporates modern features based on open standards..
Installation of UNBOUND dns server for local network is fairly simple but I encountered some hurdles setting it up with Ubuntu 18 therefore I took notes on how I resolved it in this post for reference purposes. I am more comfrotable setting it up on Ubuntu 16!
After fresh installation of Ubuntu, It’s a good idea to keep your system TIME with any NTP source.
1 2 3 4 | apt-get -y install ntp ntpdate# Change timezone as per your localcp /usr/share/zoneinfo/Asia/Karachi /etc/localtimesudo /etc/init.d/ntp restart |
Install UNBOUND DNS Server on Ubuntu
Step #1
1 | apt-get install -y unbound |
If you are using Ubuntu 18 or later, you may read this ,else skip this section#2
Step # 2
#Additional notes for Ubuntu 18 version only
The problem with Ubuntu 18.04 is the systemd-resolved service which is listening on port 53 and therefore conflicts with unbound service
Edit the file /etc/systemd/resolved.conf
1 | nano /etc/systemd/resolved.conf |
& modify this
1 | DNSStubListener=no |
Now reboot
1 | shutdown -r now |
You can now confirm if 53 port is now free up
1 | netstat -tulpn | grep :53 |
Some housekeeping stuff for Ubuntu 18 & +
1 2 3 4 | sudo service systemd-resolved stopsudo rm -f /etc/resolv.confsudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.confsudo service systemd-resolved start |
Step#4
Edit the existing UNBOUND configuration file for customization…
1 | nano /etc/unbound/unbound.conf |
Example of unbound.conf
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 | # Unbound configuration file for Debian.server:# Use the root servers key for DNSSEC#auto-trust-anchor-file: "/var/lib/unbound/root.key"# Enable logschroot: ""#verbosity (log level from 0 to 4, 4 is debug)#verbosity: 1#logfile: /var/log/unbound/unbound.log#log-queries: yes#use-syslog: (do not write logs in syslog file in ubuntu /var/log/syslog -zaib)use-syslog: no#interface (interfaces on which Unbound will be launched and requests will be listened to)# Respond to DNS requests on all interfacesinterface: 0.0.0.0# DNS request port, IP and protocolport: 53do-ip4: yesdo-ip6: nodo-udp: yesdo-tcp: yes# Authorized IPs to access the DNS Server / access-control (determines whose requests are allowed to be processed)# if you want to allow all ip pools, uncomment following (make sure you have good firewall for it)# access-control: 0.0.0.0/0 allowaccess-control: 127.0.0.0/8 allowaccess-control: 10.0.0.0/8 allowaccess-control: 172.16.0.0/16 allowaccess-control: 192.168.0.0/16 allowaccess-control: 101.0.0.0/8 allow# Root servers information (To download here: ftp://ftp.internic.net/domain/named.cache)#root-hints: "/var/lib/unbound/root.hints"# Hide DNS Server infohide-identity: yeshide-version: yes# Improve the security of your DNS Server (Limit DNS Fraud and use DNSSEC)harden-glue: yesharden-dnssec-stripped: yes# Rewrite URLs written in CAPSuse-caps-for-id: yes# PERFORMANCE RELATED TUNING - USE IT WITH CARE - TTL Min (Seconds, I set it to 7 days)cache-min-ttl: 604800# PERFORMANCE RELATED TUNING - USE IT WITH CARE - TTL Max (Seconds, I set it to 14 days)cache-max-ttl: 1209600# Enable the prefetchprefetch: yes# Number of maximum threads CORES to use / zaib# Set num-threads equal to the number of CPU cores on the system.# Try NOT to use all available cores, example if you have 6 cores, try starting with 3/4num-threads: 4### Tweaks and optimizations# Number of slabs to use (Must be a multiple of num-threads (cpu cores) value)# Set below *-slabs options, value of num-threads x 2. Example 4 cpu x 2 = 8msg-cache-slabs: 8rrset-cache-slabs: 8infra-cache-slabs: 8key-cache-slabs: 8# Cache and buffer size (in mb)#Increase the memory size of the cache. Use roughly twice as much rrset cache memory as #you use msg cache memory. For example, rrset-cache-size: 100m / msg-cache-size: 50m#Due to malloc overhead, the total memory usage is likely to rise to double (or 2.5x) the total cache memory that is entered into the config.rrset-cache-size: 100mmsg-cache-size: 50mso-rcvbuf: 10m# Make sure your DNS Server treat your local network requests#private-address: 101.0.0.0/8# Add an unwanted reply threshold to clean the cache and avoid when possible a DNS Poisoningunwanted-reply-threshold: 10000# Authorize or not the localhost requestsdo-not-query-localhost: no# Use the root.key file for DNSSEC#auto-trust-anchor-file: "/var/lib/unbound/root.key"val-clean-additional: yes# Older version of unbound doesnt support *.conf, use specific filename instead. [zaib]# This line caused me much issue therefore I hardcoded file name instead of *.confinclude: "/etc/unbound/unbound.conf.d/*.conf" |
Example of /etc/unbound/myrecords.conf
You can use this file to add your custom DNS records
Create new file at (Make sure to include it in unbound.conf file (include: paramter)
1 | nano /etc/unbound/unbound.conf.d/myrecords.conf |
Now adding an ‘A’ Record
Assuming we want to add an A record for ‘zaib.com’ which has an IP of 1.2.3.4
1 | local-data: "zaib.com A 1.2.3.4" |
Adding a PTR Record
A PTR record (sometimes known as a reverse DNS record) allows you to request the hostname used by an IP (i.e. rather than running a DNS query for zaib.com, you’re asking for the hostname of the machine at 1.2.3.4)
local-data-ptr: "1.2.3.4 zaib.com"
Every time you make any changes to Unbound Config, make sure to restart or reload the configuration
1 | unbound-control reload |
Test if UNBOUND service is started successfully.
1 | unbound-control status |
OR
1 | service unbound status |
Result:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | â unbound.service - Unbound DNS serverLoaded: loaded (/lib/systemd/system/unbound.service; enabled; vendor preset: enabled)Active: active (running) since Tue 2019-12-10 12:28:59 PKT; 2s agoDocs: man:unbound(8)Process: 1588 ExecStartPre=/usr/lib/unbound/package-helper root_trust_anchor_update (code=exited, status=0/SUCCESS)Process: 1576 ExecStartPre=/usr/lib/unbound/package-helper chroot_setup (code=exited, status=0/SUCCESS)Main PID: 1610 (unbound)Tasks: 4 (limit: 2290)CGroup: /system.slice/unbound.serviceââ1610 /usr/sbin/unbound -dDec 10 12:28:58 u18 systemd[1]: Starting Unbound DNS server...Dec 10 12:28:59 u18 package-helper[1588]: /var/lib/unbound/root.key has contentDec 10 12:28:59 u18 package-helper[1588]: success: the anchor is okDec 10 12:28:59 u18 unbound[1610]: [1575962939] unbound[1610:0] warning: so-rcvbuf 1048576 was not granted. Got 425984. To fix: start with root permissions(linux) or sysctl bigger net.core.rmem_maxDec 10 12:28:59 u18 unbound[1610]: [1575962939] unbound[1610:0] notice: init module 0: subnetDec 10 12:28:59 u18 unbound[1610]: [1575962939] unbound[1610:0] notice: init module 1: validatorDec 10 12:28:59 u18 unbound[1610]: [1575962939] unbound[1610:0] notice: init module 2: iteratorDec 10 12:28:59 u18 unbound[1610]: [1575962939] unbound[1610:0] info: start of service (unbound 1.6.7).Dec 10 12:28:59 u18 systemd[1]: Started Unbound DNS server. |
Testing DNS service
Test if DNS server is responding to DNS queries
1 | dig @127.0.0.1 bbc.com |
1st Result: [check the Query time]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ; DiG 9.11.3-1ubuntu1.11-Ubuntu @127.0.0.1 bbc.com; (1 server found);; global options: +cmd;; Got answer:;; HEADE;- opcode: QUERY, status: NOERROR, id: 16313;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 4096;; QUESTION SECTION:;bbc.com. IN A;; ANSWER SECTION:bbc.com. 86400 IN A 151.101.192.81bbc.com. 86400 IN A 151.101.128.81bbc.com. 86400 IN A 151.101.0.81bbc.com. 86400 IN A 151.101.64.81;; Query time: 971 msec;; SERVER: 127.0.0.1#53(127.0.0.1);; WHEN: Tue Dec 10 07:04:21 UTC 2019;; MSG SIZE rcvd: 100 |
2nd Result: [check the Query time, it will be much less or zero because it will be added in the unbound dns cache]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | root@u18:/etc/unbound/unbound.conf.d# dig @127.0.0.1 bbc.com; DiG 9.11.3-1ubuntu1.11-Ubuntu @127.0.0.1 bbc.com; (1 server found);; global options: +cmd;; Got answer:;; HEADER&- opcode: QUERY, status: NOERROR, id: 14171;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 4096;; QUESTION SECTION:;bbc.com. IN A;; ANSWER SECTION:bbc.com. 86398 IN A 151.101.192.81bbc.com. 86398 IN A 151.101.128.81bbc.com. 86398 IN A 151.101.0.81bbc.com. 86398 IN A 151.101.64.81;; Query time: 0 msec;; SERVER: 127.0.0.1#53(127.0.0.1);; WHEN: Tue Dec 10 07:04:23 UTC 2019;; MSG SIZE rcvd: 100 |
See the difference between 1st & second response which shows that cache is working
Enabling LOG File [*recommended for troubleshoot purposes only*]
Create a Log file and assign rights to write logs:
1 2 3 | mkdir /var/log/unboundtouch /var/log/unbound/unbound.logchmod -R 777 /var/log/unbound/ |
Now enable it in the unbound config file & reload/restart UNBOUND service . I have commented it in the configuration file.
An example of viewing logs:
1 2 | sudo tail -f /var/log/unbound/unbound.logsudo tail -f /var/log/syslog |
UNBOUND.LOG
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | [1575963664] unbound[1962:3] info: 101.11.11.161 bbc.com.agp1. A IN[1575963664] unbound[1962:3] info: resolving bbc.com.agp1. A IN[1575963664] unbound[1962:3] info: response for bbc.com.agp1. A IN[1575963664] unbound[1962:3] info: reply from 193.0.14.129#53[1575963664] unbound[1962:3] info: query response was NXDOMAIN ANSWER[1575963664] unbound[1962:3] info: validate(nxdomain): sec_status_secure[1575963664] unbound[1962:3] info: validation success bbc.com.agp1. A IN[1575963664] unbound[1962:3] info: 101.11.11.161 bbc.com.agp1. AAAA IN[1575963664] unbound[1962:3] info: resolving bbc.com.agp1. AAAA IN[1575963664] unbound[1962:3] info: response for bbc.com.agp1. AAAA IN[1575963664] unbound[1962:3] info: reply from 199.7.83.42#53[1575963664] unbound[1962:3] info: query response was NXDOMAIN ANSWER[1575963664] unbound[1962:3] info: validate(nxdomain): sec_status_secure[1575963664] unbound[1962:3] info: validation success bbc.com.agp1. AAAA IN[1575963664] unbound[1962:1] info: 101.11.11.161 bbc.com. A IN[1575963664] unbound[1962:1] info: resolving bbc.com. A IN[1575963664] unbound[1962:1] info: resolving bbc.com. DS IN[1575963664] unbound[1962:1] info: NSEC3s for the referral proved no DS.[1575963664] unbound[1962:1] info: Verified that unsigned response is INSECURE[1575963672] unbound[1962:0] info: 101.11.11.161 bbc.com. AAAA IN |
# Example of cache export and import:
1 2 | unbound-control dump_cache > backupunbound-control load_cache > backup |
# Clear one site from cache
1 | unbound-control flush_zone google.com |
# View cached DNS contents or count
[sourceocde]unbound-control stats[/sourceocde]
# Count Cache entries
1 | unbound-control dump_cache | wc -l |
# Clear DNS Cache
1 | unbound-control flush_zone . |
Start UNBOUND in DEBUG mode
1 | unbound -d -vvvv |
Query Different DNS server for particular domains
If we want to query particular DNS servers for particular domains, use the forwarders as per below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Query bbc.com from 1.1.1.1 dns serverforward-zone:name: "bbc.com"forward-addr: 1.1.1.1# Query google.com from 8.8.4.4 dns serverforward-zone:name: "google.com"forward-addr: 8.8.4.4# Forward all other domains queries to 8.8.8.8forward-zone:name: "."forward-addr: 8.8.8.8 |
Reload unbound Config
1 | service unbound reload |
Check UNBOUND service every minute & restart service if required
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 | #!/bin/bash# Linux BASH Script to check UNBOUND DNS SRV Status, if service not running, it will start it# Syed Jahanzaib / 14-SEP-2022#set -xHOSTNAME=`hostname`ROLE="DNS"COMPANY="ZABBO"DATE=`date`TMP=tempROLE="Unbound-DNS-Service"SRVNAME="unbound"# Temporary file holder for host statusLOG="/var/log/dns.log"SRV_STATUS_HOLDER="/$TMP/$SRVNAME.srv.status.temp.holder.txt"touch $LOGtouch $TMPif [ ! -d "/$TMP" ]; thenechoechoecho "/$TMP folder not found, Creating it so all ping results should be saved there . . ."mkdir /$TMPfi# Run the scriptunbound-control status > $SRV_STATUS_HOLDERcount=`cat $SRV_STATUS_HOLDER | grep "stopped" | wc -l`if [ $count -eq 1 ]; thenservice unbound stopservice unbound startecho "$DATE - $HOSTNAME - $SRVNAME ($ROLE) found stopped. Script have started it manually."echo "$DATE - $HOSTNAME - $SRVNAME ($ROLE) found stopped. Script have started it manually." >> $LOGelseecho "$DATE - $HOSTNAME - $SRVNAME ($ROLE) is running OK."fi |
Schedule it to run every minute by editing crontab -e
1 | */1 * * * * /temp/chksrv.sh >/dev/null 2>&1 |
Securing DNS by Firewall
It is a good idea to allow only related ports to your unbound box from trusted/local sources only, and deny all other traffic.
1 2 3 4 | mkdir /temptouch /temp/fw.shchmod +x /temp/fw.shnano /temp/fw.sh |
& paste following
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 | #!/bin/sh# ------------------------------------# Syed Jahanzaib / aacable@hotmail.com# Created: January, 2011# Last Modified: 7th Jan, 2017# Last Modified: 19th-SEP-2021 [for GT/KH]# ------------------------------------# MODIFY THIS NAME IF REQUIREDALLOWED_IP_LIST=/temp/allowed_ip_list.txt############################################################################################################ donot modify below this line ########################################################################### Setting default filter policy, Use it with CARE / zaib# Clear old firewallclearecho "1- Clearing existing firewall rules, and allow all traffic for the time being ..."iptables -P INPUT ACCEPTiptables -P FORWARD ACCEPTiptables -P OUTPUT ACCEPTiptables -t nat -Fiptables -t nat -Xiptables -t mangle -Fiptables -t mangle -Xiptables -Fiptables -X# LOG everything, not recommended as it can put load on storage, make sure to do proper log rotation if its required#iptables -A INPUT -j LOGiptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT#Allow ICMPecho "2- Allowing ICMP packet rules ..."iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPTiptables -A OUTPUT -p icmp --icmp-type 0 -s 0/0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT## Unlimited access to loop backiptables -A INPUT -i lo -j ACCEPTiptables -A OUTPUT -o lo -j ACCEPTecho "3- Enforcing Firewalling, allowing only particular ports 22,53 to below specific IP pool only ..."echo "TCP/UDP PORTS 53,22.ALLOWED IP POOL ... "cat $ALLOWED_IP_LISTecho "..."for x in $(cat $ALLOWED_IP_LIST)do# Allow ip range to allow port range access on all interfaces , duplicate this rule as needediptables -A INPUT -s $x -p tcp --match multiport --dports 22,53 -j ACCEPTiptables -A OUTPUT -s $x -p tcp --match multiport --dports 22,53 -j ACCEPTiptables -A INPUT -s $x -p udp --match multiport --dports 22,53 -j ACCEPTiptables -A OUTPUT -s $x -p udp --match multiport --dports 22,53 -j ACCEPT# Allow single IP Address to access port 53# iptables -A INPUT --src 1.2.3.4 -p tcp --dport 53 -j ACCEPTdone##################################### Drop Everything else, use it at your own.###################################iptables -A INPUT -j DROP# script ends hereecho "Done" |
Save & Exit.
Now create a IP pool file in which you will add trusted/local lan/wan ip’s
1 2 | touch /temp/allowed_ip_list.txtnano /temp/allowed_ip_list.txt |
& add the lan ip’s
1 2 3 | 10.0.0.0/8172.16.0.0/16192.168.0.0/16 |
Save & Exit. & reload the UNBOUND service
1 2 3 4 | unbound-control reload unbound-control status#service unbound restart#service unbound status |
Don’t forget to add the fw.sh it in /etc/rc.local (before exit 0) line so that it can start on every system reboot.
Clearing Firewall
To clear firewall you can use following CMD or make a bash file for convenience.
1 2 3 4 | mkdir /temptouch /temp/clear_fw.shchmod +x /temp/clear_fw.shnano /temp/clear_fw.sh |
& paste following
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/sh# ------------------------------------# Syed Jahanzaib / aacable@hotmail.com# Created: January, 2011# Last Modified: 7th Jan, 2017# Last Modified: 27th-Aug-2021 [for galaxy tech khi/pk]# ------------------------------------## Setting default filter policy, Use it with CARE / zaib# Clear old firewalliptables -P INPUT ACCEPTiptables -P FORWARD ACCEPTiptables -P OUTPUT ACCEPTiptables -t nat -Fiptables -t nat -Xiptables -t mangle -Fiptables -t mangle -Xiptables -Fiptables -X |

