voxpupuli / puppet-unbound

Puppet module for deploying the swiss-army of DNS, Unbound
https://forge.puppet.com/puppet/unbound
Apache License 2.0
28 stars 71 forks source link

Default interfaces on multi-homed servers #12

Closed nicwaller closed 9 years ago

nicwaller commented 11 years ago

I ran into a strange problem today with Unbound while using this module. I'm not sure whether this is a configuration problem or a bug, so I'm reporting it here first.

On a server with two IP addresses, I had to explicitly list both IP addresses in unbound.conf before Unbound would answer queries on the second address. This ran counter to my expectation that I could set interface: 0.0.0.0 to listen on all IP addresses.

One possible solution is changing this module to explicitly list all IP addresses as listening interfaces in unbound.conf.

Before making that change, it would be prudent to:

The full story

My server had Unbound installed and configured to listen on "0.0.0.0" interface. It was successfully responding to DNS queries for other hosts as defined by the access-control directive, even on different subnets.

Then I added a second IP address to the server as a virtual interface (eth0:0). Strangely, Unbound refused to answer DNS queries on this second IP address, even after restarting the service. Running netstat -tapn confirmed that Unbound was listening on 0.0.0.0:53.

Then I explicitly listed each local IP address in unbound.conf and restarted Unbound. At that point, the server successfully responded to DNS queries as expected.

interface: 192.168.0.20
interface: 192.168.0.30

I'm using Scientific Linux 6.4, and the version of Unbound is 1.4.19 from EPEL.

nicwaller commented 11 years ago

Aha, I figured out what is happening. Unbound is replying from the wrong interface.

When Unbound is configured to listen on any interface (0.0.0.0), then it uses the wildcard source address (0.0.0.0) for the reply packet and allows the kernel to choose the source interface. Since DNS over UDP is connectionless, the kernel just chooses the first available interface and the client sees a reply from a different address than it queried. Any well-behaved client will reject that answer.

This is referenced in a question on the Unbound mailing list from September 2011: http://www.nlnetlabs.nl/pipermail/unbound-users/2011-September/002061.html

The recommended solution is to explicitly list each interface. Then Unbound will reply using the same interface that it received the request on, instead of using the wildcard (0.0.0.0) interface.

Also note that the option interface-automatic technically does solve the problem as well, however it is NOT recommended because it is experimental, and it requires the availability of IPv6.

Going based on my own experience, the expected behavior is that Unbound should work on all interfaces unless otherwise specified. (Principle of least astonishment) Here are the options as I see them.

  1. This module could be modified to create an interface line for each active IP address.
  2. Or, more simply, set the default interface to ${ipaddress} so that any admin perusing the config file will quickly understand why it isn't working. Consider also adding a comment in the config file and an entry in the param documentation explaining why it's configured that way. Of course, the end user is still free to customize interfaces using the class parameter.
igalic commented 10 years ago

Most Linux distributions support a dual IP stack, with IPv6 as the default.

zachfi commented 9 years ago

I believe this issue has been addressed by the inclusion of the interface param in params.pp.