On 11/30/2023 6:13 AM, Simon Kelley wrote:
As you've surmised, making more than one dnsmasq/DHCP instance on a
server work is tricky.

It can be done, but only in a very specific way.

Each dnsmasq instance must be configured to serve exactly one interface,
using the --interface config option.

Under these circumstances, dnsmasq will log

DHCP, sockets bound exclusively to interface <interface>

at startup.

Your example will not work, because your instance A is binding to more
than one interface. To fix this you need to start separate dnsmasq
instances for eth0 and eth1, or you need to bridge eth0 and eth1 to
single bridge interface and configure dnsmasq to listen on that.


The reason behind this is that the dnsmasq DHCP subsystem uses one
socket, which listens on the wildcard address (so that broadcasts to
255.255.255.255 arrive, amongst other reasons.) In the "exactly one
interface" state, dnsmasq can also bind that socket to a physical
interface, using the SO_BINDTODEVICE socket option, which allows the
multiple-server setup to work. SO_BINDTODEVICE only allows one device,
hence the one interface limitation.

I performed some practical tests in case anyone is interested. I created one dnsmasq instance with:

interface=enp0s8
interface=enp0s10
bind-interfaces
listen-address=192.168.204.1

and another with

interface=enp0s9
bind-interfaces
except-interface=lo

Both instances were able to start up without any issues, presumably because of SO_REUSEADDR /SO_REUSEPORT being used on the socket.

NOTE: If I don't specify "bind-interfaces" in the second case, then it errors out with "failed to bind DHCP server socket: Address already in use".

From another host I then ran "dhclient -d enp0s9" to emit a broadcast packet, or "dhclient  -d enp0s9 -s <addrss>" to emit a unicast packet.

If the incoming DHCP packets on enp0s9 are broadcast packets, everything is fine because both instances of dnsmasq receive the packet (due to SO_REUSEADDR /SO_REUSEPORT).  The first instance just ignores it, the second instance replies to it.

If the incoming DHCP packets on enp0s9 are unicast packets (like a DHCPREQUEST to the IP address of enp0s9), it's non-deterministic which instance of dnsmasq receives the packet.  If it's the first, the packet is ignored and the client gets no response.  If it's the second, it works as expected.

Following the instructions above to ensure that each instance binds to a single interface with SO_BINDTODEVICE would avoid the issue with the unicast packets by ensuring that all the incoming packets are processed by the dnsmasq instance which actually cares about them.

Chris Friesen


_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to