Unbound DNS server behind a VIP - solving reply from unexpected source

Written by - 5 comments

Published on - Listed in Linux


In my previous post I wrote about getting Unbound to work without Internet connection (Get Unbound DNS lookups working in Ubuntu 16.04 Xenial, understand SERVFAIL). For the blog post I simplified the setup, but in reality the DNS architecture was built on a "cluster" on two Xenial hosts running KeepAliveD and sharing a virtual IP address (VIP).

After a couple of tests, I stumbled across the following problem:

$ dig -t A www.claudiokuenzler.com @192.168.10.10
;; reply from unexpected source: 192.168.10.11#53, expected 192.168.10.10#53
;; reply from unexpected source: 192.168.10.11#53, expected 192.168.10.10#53
;; reply from unexpected source: 192.168.10.11#53, expected 192.168.10.10#53

You've guessed it right. 192.168.10.10 is the VIP on which I tried to run the DNS lookup. But the DNS response came back from the active server's primary IP address 192.168.10.11. Dig correctly says "dude, something's not right" and doesn't accept the answer.

I already thought I had to set up some weird masquerading NAT to always respond with the VIP but that would cause problems on the second host, the VRRP BACKUP host. And also it would prevent local lookups to work (by default, if I wouldn't add yet another masquerading hack for localhost). Already by trying to write down my ideas of potential masquerading rules you can guess that this would be nothing else than a hack to make something work - which should be simple and work out of the box.

Luckily I read through the manpage of unbound.conf again and I found something very interesting:

       interface-automatic:
              Detect source interface on UDP queries and copy them to replies.  This feature is experimental, and needs support in your OS for particular
              socket options.  Default value is no.

The description sounds pretty much what I need, so I gave it a shot and added "interface-automatic: yes" into the config:

server:
        interface: 0.0.0.0
        interface-automatic: yes
        access-control: 10.0.0.0/16 allow
        access-control: 127.0.0.0/8 allow
        access-control: 172.16.0.0/12 allow
        access-control: 192.168.0.0/16 allow
        verbosity: 1
        domain-insecure: *
        root-hints: /var/lib/unbound/root.hints

After a restart of Unbound I tried it again - with success:

$ dig -t A www.claudiokuenzler.com @192.168.10.10

; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> -t A www.claudiokuenzler.com @192.168.10.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32099
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.claudiokuenzler.com.       IN      A

;; ANSWER SECTION:
www.claudiokuenzler.com. 28636  IN      A       144.76.83.23

;; Query time: 4 msec
;; SERVER: 192.168.10.10#53(192.168.10.10)
;; WHEN: Fri Feb 17 11:14:33 CET 2017
;; MSG SIZE  rcvd: 68

And it still works on the primary IP of the cluster hosts, too:

$ dig -t A www.claudiokuenzler.com @192.168.10.11

; <<>> DiG 9.9.5-3ubuntu0.11-Ubuntu <<>> -t A www.claudiokuenzler.com @192.168.10.11
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62942
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.claudiokuenzler.com.       IN      A

;; ANSWER SECTION:
www.claudiokuenzler.com. 28493  IN      A       144.76.83.23

;; Query time: 0 msec
;; SERVER: 192.168.10.11#53(192.168.10.11)
;; WHEN: Fri Feb 17 11:16:54 CET 2017
;; MSG SIZE  rcvd: 68

Well done, Unbound! I'm positively surprised that this config option is available!

PS: I also tried to set the Unbound listener to the VIP by setting "interface" to the virtual ip address in unbound.conf (instead of using all interfaces 0.0.0.0). But as the VIP is only assigned once Unbound runs correctly (I added specific DNS checks in keepalived.conf), Unbound was not able to start and failed with:

unbound[32235]: [1487320777] unbound[32535:0] error: can't bind socket: Cannot assign requested address for 192.168.10.10
unbound[32235]: [1487320777] unbound[32535:0] fatal error: could not open ports
unbound[32235]:    ...fail!


Add a comment

Show form to leave a comment

Comments (newest first)

kante from wrote on Feb 14th, 2023:

Thank you!!


Dan from San Francisco wrote on Apr 12th, 2022:

THANK YOU! That
interface-automatic: yes

Was all I needed to get ubound up and running after an hour of poking and prodding!

Fantastic!


Arjun from wrote on Nov 9th, 2020:

Thanks!!. This helped me.


Martin Herren from wrote on Jan 24th, 2020:

Thanks ! Solved my issue in running an unbound server in a docker that has to serve both, as a DNS server for the LAN and as a DNS server for the other docker services.


root from wrote on Sep 1st, 2017:

Thanks for this post. I experienced this error in my DNS cluster. Now the problem is solved.


RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Observability   Office   OpenSearch   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder