Different packages are available on RHEL 7 to configure a caching-only DNS server. We are going to configure unbound and bind today.
We use a RHEL 7.0 virtual machine in this article. Please be advised that only one package should be deployed on a DNS server, either unbound or bind.
Catching-only Name Server with Unbound
Install the unbound package, enable the service on boot and configure firewall:
# yum install -y unbound # systemctl enable unbound # firewall-cmd --permanent --add-service=dns # firewall-cmd --reload
Prevent getting errors about server-keys that do not exist:
# unbound-control-setup
Open the file /etc/unbound/unbound.conf
for editing, and add the following lines, where access control is set to our lab LAN:
interface: 0.0.0.0 access-control: 10.8.8.0/24 allow
Now, if we have some other DNS server already configured which contains some local zones (f.e. rhce.local), then we want to forward all requests for that zone to such DNS server so that they can be resolved. Since we have a FreeIPA server in place with the “rhce.local” zone, we want to add it to out unbound configuration:
forward-zone: name: "rhce.local" forward-addr: 10.8.8.70
Forward address is the IP address of our FreeIPA server. To forward all requests to another DNS server, we need to configure a forward zone for the root (.) domain.
Now, if we tried to restore the local zone, it would give us a validation failure. By default, unbound requires DNSSEC validation on all DNS responses it receives. For internal DNS domains that have not been configured with DNSSEC, we may want to bypass this.
Include the domain-insecure parameter, followed by the name of the DNS domain we don’t want to do DNSSEC validation for:
domain-insecure: "rhce.local"
Verify configuration:
# unbound-checkconf
Start the unbound service:
# systemctl start unbound
Configure the nameservers, in our particular case:
# nmcli c mod mybond0 ipv4.dns 127.0.0.1
Verify:
# cat /etc/resolv.conf # Generated by NetworkManager nameserver 127.0.0.1
Unbound Version Disclosure
Unbound version is returned by default:
# dig localhost version.bind chaos txt +noall +answer|tail -n1 version.bind. 0 CH TXT "unbound 1.4.20"
The unbound version number can be hidden by adding “hide-version: no” to the file unbound.conf
.
Catching-only Name Server with Bind
Install the bind package, enable the service on boot and configure firewall:
# yum install -y bind # systemctl enable named # firewall-cmd --permanent --add-service=dns # firewall-cmd --reload
Open the file /etc/named.conf
for editing. Create the following access control list (acl) statement:
acl "trusted" { 127.0.0.0/8; 10.8.8.0/24; };
This allows us to define groups of hosts, so that they can be permitted access to the nameserver.
Tell Bind to listen on any IPv4 address, and allow queries and transfers from the “trusted” clients.
listen-on port 53 { any; }; allow-query { "trusted"; }; allow-transfer { "trusted"; }; dnssec-validation no;
Now the same thing as with the unbound configuration, if we have some other DNS server already configured which contains some local zones, then we want to forward all requests for that zone to such DNS server so that they can be resolved.
Add a per-domain forwarding:
zone "rhce.local" IN { type forward; forwarders { 10.8.8.70; }; };
Check for syntax errors:
# named-checkconf
Start the service:
# systemctl enable named
Configure the nameservers, in our particular case:
# nmcli c mod mybond0 ipv4.dns 127.0.0.1
Verify:
# cat /etc/resolv.conf # Generated by NetworkManager nameserver 127.0.0.1
Bind Version Disclosure
Bind version is returned by default:
# dig localhost version.bind chaos txt +noall +answer|tail -n1 version.bind. 0 CH TXT "9.9.4-RedHat-9.9.4-14.el7"
In case there is a need to hide the version number, this can be achieved by adding a “version none” to the file named.conf
.
SELinux
It doesn’t hurt to mention that depending on Bind configuration, some SELinux changes may be required.
For example, if we wanted to determine whether Bind can bind tcp socket to http ports, we would need turn on the named_tcp_bind_http_port boolean. It’s disabled by default.
# setsebool -P named_tcp_bind_http_port=1
If we wanted to determine whether Bind can write to master zone files, what is generally used for dynamic DNS or zone transfers, we would need to turn on the named_write_master_zones boolean (disabled by default):
# setsebool -P named_write_master_zones=1
Troubleshooting DNS Issues
Journal
Check journal for any obvious errors:
# journalctl -xlf
Dig
Check if DNS resolution was successful:
# dig rhce.local | grep status
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14297
The status of NXDOMAIN means that the DNS information that was requested was not found:
# dig rhce2.local | grep status
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 23674
Check what name servers are defined for the zone of interest:
# dig NS rhce.local +noall +answer ; < <>> DiG 9.9.4-RedHat-9.9.4-14.el7 < <>> NS rhce.local +noall +answer ;; global options: +cmd rhce.local. 86392 IN NS ipa.rhce.local.
Find out the IPs of the name servers for the zone of interest, and check if they are available:
# dig A ipa.rhce.local +noall +answer ; < <>> DiG 9.9.4-RedHat-9.9.4-14.el7 < <>> A ipa.rhce.local +noall +answer ;; global options: +cmd ipa.rhce.local. 443 IN A 10.8.8.70
Check if DNS server is catching queries:
# dig A google.com +noall +stats
; < <>> DiG 9.9.4-RedHat-9.9.4-14.el7 < <>> A google.com +noall +stats
;; global options: +cmd
;; Query time: 67 msec
;; SERVER: 10.8.8.71#53(10.8.8.71)
;; WHEN: Tue May 31 11:44:15 BST 2016
;; MSG SIZE rcvd: 55
# dig A google.com +noall +stats
; < <>> DiG 9.9.4-RedHat-9.9.4-14.el7 < <>> A google.com +noall +stats
;; global options: +cmd
;; Query time: 0 msec
;; SERVER: 10.8.8.71#53(10.8.8.71)
;; WHEN: Tue May 31 11:44:21 BST 2016
;; MSG SIZE rcvd: 55
It sometimes may be the case that some invalid records are cached.
Unbound
Print cache to stdout:
# unbound-control dump_cache
In case some invalid records are cached, it may be required to flush everything:
# unbound-control flush_zone . ok removed 19 rrsets, 8 messages and 3 key entries
Hello.
When I configure unbound to use 8.8.8.8 as forward -addr it is OK and I can ping or dig to Internet addresses from any another server. But when I set up forward-addr as my router’s IP I have an issue. I can ping and dig without any errors from server where unbound is installed but I can’t ping or dig to the Internet’s addresses from another servers and get SERVFAIL status.
Could you assist?
Thanks.
Your unbound server needs to allow queries from clients.
Great article, thanks
just one minor thing, I think:
The unbound version number can be hidden by adding “hide-version: no” to the file unbound.conf.
should say:
The unbound version number can be hidden by adding “hide-version: yes” to the file unbound.conf.
and
dig localhost version.bind chaos txt +noall +answer|tail -n1
didn’t work for me so I used:
dig localhost version.bind chaos txt +noall +answer|grep version
Thanks for your feedback!
Thank you for these great guides – they are invaluable
You’re welcome!
Does linux documentation provides ready made examples for both the packages to set up cache dns ?
like we see in smtp.
Bind features a range of installed documentation covering many different topics, check under
/usr/share/doc/bind-VERSION_NUMBER/
to see if there is anything that you’re looking for.So I have to share issue that I faced with unbound package on RHEL 7.0
In my environment every package was installed from ftp repository configured in yum repositories, packages are copied from original ISO file provided by RedHat(their website).
I have installed unbound and out of the box if I execute systemctl start unbound, it fails without any message in journal – seriously completely without any sign – just says process failed, exited.
How I managed to overcome this, install unbound, run unbound-control-setup, configured /etc/unbound/unbound.conf, after that started service with unbound-control start, after that enabled it with systemctl enable unbound and rebooted the server, after that it works. I am glad that this is fixed in later RHEL versions, but anyhow, it would be the shame to fail on the exam because of this stupid issue.
Thanks for your feedback. This is helpful.
In real life, what’s the interest of a caching-only DNS server ? It’s maybe too obvious for me to see any use case. Please help.
CentOS (and probably other Linux) does not cache DNS queries unless you have something like dnsmasq installed.
Now, if you use a 3-Tier infrastructure, then your load balancer has to talk to the application, and the application has to talk to the backend. If you use DNS, then for each request there is a DNS lookup performed. It may not sound like a big issue, but imagine a scenario where you have say 500 requests coming in every second. That’s 500 DNS lookups per second. It can quickly add up to a noticeable delay. I worked on a project where this was a real thing.
Using a cacthing-only DNS server can help to solve the problem (but it’s not the only solution, obviously). You should get the idea.
Thanks Tomas. Now I remember that 10 years ago we were using NSCD, but it had its own problems. I don’t know what became this software, and I don’t remember if it was installed by default (on CentOS 5 for example).