Discussion:
[Dnsmasq-discuss] Is dnsmasq supposed to listen on UDP port 0.0.0.0:67 when listen-address is specified?
Parke
2017-12-20 22:31:39 UTC
Permalink
Hi,

Is dnsmasq supposed to listen on UDP port 0.0.0.0:67 when
listen-address is specified?

DNS service is bound to the specified IP address (on port 53, both TCP and UDP).

But dnsmasq's DHCP server is still binding to UDP 0.0.0.0:67.

I am running version 2.76-5+rpt1+deb9u1 on Raspbian 9 (Stretch).

Thanks,

Parke
Kurt H Maier
2017-12-20 23:37:40 UTC
Permalink
Post by Parke
Hi,
Is dnsmasq supposed to listen on UDP port 0.0.0.0:67 when
listen-address is specified?
From the manpage:

-z, --bind-interfaces
On systems which support it, dnsmasq binds the wildcard address,
even when it is listening on only some interfaces. It then discards
requests that it shouldn't reply to. This has the advantage of working
even when interfaces come and go and change address. This option forces
dnsmasq to really bind only the interfaces it is listening on. About the
only time when this is useful is when running another nameserver (or
another instance of dnsmasq) on the same machine. Setting this option
also enables multiple instances of dnsmasq which provide DHCP service to
run in the same machine.

khm
Parke
2017-12-21 02:40:10 UTC
Permalink
Hi,

Here is a minimal, three line test.conf file:

listen-address=192.168.0.22
bind-interfaces
dhcp-range=192.168.0.80,192.168.0.99,12h

When I run it, I get:

# sudo dnsmasq -C test.conf -d
dnsmasq: started, version 2.76 cachesize 150
dnsmasq: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP
DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify
dnsmasq-dhcp: DHCP, IP range 192.168.0.80 -- 192.168.0.99, lease time 12h
dnsmasq: reading /etc/resolv.conf
dnsmasq: ignoring nameserver 192.168.0.22 - local interface
dnsmasq: read /etc/hosts - 5 addresses

And:

# sudo netstat -lnp | grep dnsmasq
tcp 0 0 192.168.0.22:53 0.0.0.0:*
LISTEN 7094/dnsmasq
udp 0 0 192.168.0.22:53 0.0.0.0:*
7094/dnsmasq
udp 0 0 0.0.0.0:67 0.0.0.0:*
7094/dnsmasq
----

Is it possible to bind port 67 to the listen-address? If so, how?

Thanks!

-Parke
Kurt H Maier
2017-12-21 03:47:15 UTC
Permalink
Hi,
If I understand this right, I think I can replicate it with e.g.

dnsmasq --interface=eth0 \
--dhcp-range=192.168.0.50,192.168.0.100,12h \
--bind-interfaces \
--listen-address=192.168.1.50

In this case, we can trace this to get:
setsockopt(4, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(67), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
...
setsockopt(4, SOL_SOCKET, SO_BINDTODEVICE, "eth0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0

So, while SO_REUSEPORT and SO_REUSEADDR are both successful, I'm not
able to create another socket to listen (dnsmasq fails with the address
already in use error).

khm
Parke
2017-12-21 05:45:47 UTC
Permalink
And there is the big question of: Will each incoming UDP packet be
sent to all receiving sockets? Or just to one out of a pool of
receiving sockets?
Looks like load balancing to me.

From man 7 socket on Linux:

SO_REUSEPORT (since Linux 3.9)

For UDP sockets, the use of this option can
provide better distribution of incoming
datagrams to multiple processes (or threads)
as compared to the traditional technique of
having multiple processes compete to receive
datagrams on the same socket.

Perhaps dnsmasq is hoping that each separate instance is bound to a
different device/interface via SO_BINDTODEVICE? (Of course, dnsmasq
lacks the ability to confirm that other instances are correctly
configured.)

And that device binding will give each incoming packet only a single
path to the single (and correct) instance of dnsmasq?

And the SO_REUSEADDR option is necessary to allow multiple bindings to
the same address (even though each binding is to a separate interface
via SO_BINDTODEVICE)?

And given that FreeBSD lacks SO_BINDTODEVICE, this code will not work
as intended on FreeBSD? (I.e. FreeBSD will get undesired load
balancing, rather than mirroring which would work?)

But it seems that all the above can be done with just SO_REUSEADDR,
and that SO_REUSEPORT is superfluous. At least on Linux. (As the
purpose of SO_REUSEPORT is to load balance across processes while
bypassing expensive inter-process contention for a single socket?)
Hmmm. Hopefully someone who understands it can decide if I am making
any sense.

-Parke
Ignat Korchagin
2017-12-21 10:56:35 UTC
Permalink
FYI a good overview of SO_REUSEPORT at least in Linux is here
https://blog.cloudflare.com/the-sad-state-of-linux-socket-balancing/
Post by Parke
And there is the big question of: Will each incoming UDP packet be
sent to all receiving sockets? Or just to one out of a pool of
receiving sockets?
Looks like load balancing to me.
SO_REUSEPORT (since Linux 3.9)
For UDP sockets, the use of this option can
provide better distribution of incoming
datagrams to multiple processes (or threads)
as compared to the traditional technique of
having multiple processes compete to receive
datagrams on the same socket.
Perhaps dnsmasq is hoping that each separate instance is bound to a
different device/interface via SO_BINDTODEVICE? (Of course, dnsmasq
lacks the ability to confirm that other instances are correctly
configured.)
And that device binding will give each incoming packet only a single
path to the single (and correct) instance of dnsmasq?
And the SO_REUSEADDR option is necessary to allow multiple bindings to
the same address (even though each binding is to a separate interface
via SO_BINDTODEVICE)?
And given that FreeBSD lacks SO_BINDTODEVICE, this code will not work
as intended on FreeBSD? (I.e. FreeBSD will get undesired load
balancing, rather than mirroring which would work?)
But it seems that all the above can be done with just SO_REUSEADDR,
and that SO_REUSEPORT is superfluous. At least on Linux. (As the
purpose of SO_REUSEPORT is to load balance across processes while
bypassing expensive inter-process contention for a single socket?)
Hmmm. Hopefully someone who understands it can decide if I am making
any sense.
-Parke
_______________________________________________
Dnsmasq-discuss mailing list
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
Parke
2017-12-22 02:46:28 UTC
Permalink
Post by Ignat Korchagin
FYI a good overview of SO_REUSEPORT at least in Linux is here
https://blog.cloudflare.com/the-sad-state-of-linux-socket-balancing/
Thanks. The article deals with accepting on a TCP socket, not
receiving on a UDP socket.

But if the principles are similar for UDP, then, as I expected, it
looks like SO_REUSEPORT provides load balancing.

Does anyone believe that dnsmasq is intending to create load balancing
when multiple instances bind to the same DHCP socket? (I don't. I
believe dnsmasq is expecting mirroring, but I could be wrong.)

Cheers,

Parke
Ignat Korchagin
2017-12-22 12:10:03 UTC
Permalink
I think so as well. It may create issues when someone runs 2 dnsmasq
processes with different configurations (for different interfaces for
example - 1 dnsmasq process per interface). Kernel may "balance" incoming
UDP packets to another dnsmasq instance (which AFAIR will just ignore it),
so there will be more retries in general for DHCP traffic.
Post by Parke
Post by Ignat Korchagin
FYI a good overview of SO_REUSEPORT at least in Linux is here
https://blog.cloudflare.com/the-sad-state-of-linux-socket-balancing/
Thanks. The article deals with accepting on a TCP socket, not
receiving on a UDP socket.
But if the principles are similar for UDP, then, as I expected, it
looks like SO_REUSEPORT provides load balancing.
Does anyone believe that dnsmasq is intending to create load balancing
when multiple instances bind to the same DHCP socket? (I don't. I
believe dnsmasq is expecting mirroring, but I could be wrong.)
Cheers,
Parke
_______________________________________________
Dnsmasq-discuss mailing list
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
Loading...