Re: [Dnsmasq-discuss] Does the --interface option to dnsmasq also apply to incoming broadcast DHCP requests?
On 30.11.23 00:09, Chris Friesen via Dnsmasq-discuss wrote: I was just wondering whether the --interface and --except-interface options to dnsmasq would also apply to messages like DHCPDISCOVER and DHCPREQUEST Yes. You may also want to further tune usage via '--no-dhcp-interface' (or maybe '--no-dhcpv4-interface' and '--no-dhcpv6-interface' in a future release, see https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/msg16828.html ). However, I wonder whether tagging requests for the interfaces and setting up corresponding dhcp options for those tags wouldn't already match your requirements with only one instance of dnsmasq running. Kind regards, Buck ___ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
Re: [Dnsmasq-discuss] Does the --interface option to dnsmasq also apply to incoming broadcast DHCP requests?
On 29/11/2023 23:09, Chris Friesen via Dnsmasq-discuss wrote: Hi, I was just wondering whether the --interface and --except-interface options to dnsmasq would also apply to messages like DHCPDISCOVER and DHCPREQUEST which are broadcast to 255.255.255.255. In my particular case I have an existing dnsmasq instance that is running, and I want to add a second dnsmasq instance to handle DHCP requests coming from a specific subset of interfaces. I don't want the primary dnsmasq instance to see the requests coming in on those interfaces, and I don't want the second dnsmasq instance to see requests coming in on the other interfaces. As a concrete example, suppose I have network interfaces eth0/eth1/eth2 and I have instance A of dnsmasq which is run as "dnsmasq --except-interface eth2", and instance B of dnsmasq which is run as "dnsmasq --interface eth2 --except-interface lo". If a broadcast DHCPDISCOVER or DHCPREQUEST comes in on eth0/eth1 which dnsmasq instance(s) will see it? If a broadcast DHCPDISCOVER or DHCPREQUEST comes in on eth2 which dnsmasq instance(s) will see it? If a broadcast DHCPDISCOVER or DHCPREQUEST is emitted by an entity on the local host which dnsmasq instance(s) will see it? Thanks, Chris Friesen 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 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. Cheers, Simon. ___ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
Re: [Dnsmasq-discuss] Does the --interface option to dnsmasq also apply to incoming broadcast DHCP requests?
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. Perfect, thanks. Chris ___ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss
Re: [Dnsmasq-discuss] [PATCH] Add number of forks for TCP to metrics and dump
Looks good. Patch applied. Cheers, Simon. On 24/11/2023 11:13, Damian Sawicki via Dnsmasq-discuss wrote: Hello dnsmasq experts, Following up on the recent addition of the flag --max-tcp-connections, I'd like to propose a patch with monitoring of the number of TCP connections. This way, a user can actually estimate their usage and adjust --max-tcp-connections accordingly to prevent overload. The patch adds the relevant information to the metrics and to the output of dump_cache() (which is called when dnsmasq receives SIGUSR1). Hence, users not collecting metrics will still be able to troubleshoot with SIGUSR1. In addition to the current usage, dump_cache() contains the information on the highest usage since it was last called. Please kindly let me know what you think. Best regards, Damian Sawicki * Add to the metrics and dump_cache() the info on the utilisation of the limit on concurrent TCP connections (the variable daemon->max_procs, customisable via --max-tcp-connections). --- man/dnsmasq.8 | 2 +- src/cache.c | 5 + src/dnsmasq.c | 11 ++- src/dnsmasq.h | 1 + src/metrics.c | 1 + src/metrics.h | 1 + src/option.c | 1 + 7 files changed, 20 insertions(+), 2 deletions(-) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 6d37360..1b5ebda 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -2303,7 +2303,7 @@ they expired in order to make room for new names and the total number of names that have been inserted into the cache. The number of cache hits and misses and the number of authoritative queries answered are also given. For each upstream server it gives the number of queries sent, and the number which -resulted in an error. In +resulted in an error. It also gives information on the number of forks for TCP connections. In .B --no-daemon mode or when full logging is enabled (\fB--log-queries\fP), a complete dump of the contents of the cache is made. diff --git a/src/cache.c b/src/cache.c index 5342ce2..b95e3c7 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1895,6 +1895,11 @@ void dump_cache(time_t now) #endif blockdata_report(); + my_syslog(LOG_INFO, _("child processes for TCP requests: in use %zu, highest since last SIGUSR1 %zu, max %zu."), + daemon->metrics[METRIC_TCP_CONNECTIONS], + daemon->max_procs_used, + daemon->max_procs); + daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS]; /* sum counts from different records for same server */ for (serv = daemon->servers; serv; serv = serv->next) diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 65ba334..39aaf19 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -1534,7 +1534,11 @@ static void async_event(int pipe, time_t now) else if (daemon->port != 0) for (i = 0 ; i < daemon->max_procs; i++) if (daemon->tcp_pids[i] == p) - daemon->tcp_pids[i] = 0; +{ + daemon->tcp_pids[i] = 0; + if (daemon->tcp_pipes[i] == -1) +daemon->metrics[METRIC_TCP_CONNECTIONS]--; +} break; #if defined(HAVE_SCRIPT) @@ -1844,6 +1848,8 @@ static void check_dns_listeners(time_t now) { close(daemon->tcp_pipes[i]); daemon->tcp_pipes[i] = -1; +if (daemon->tcp_pids[i] == 0) + daemon->metrics[METRIC_TCP_CONNECTIONS]--; } for (listener = daemon->listeners; listener; listener = listener->next) @@ -1972,6 +1978,9 @@ static void check_dns_listeners(time_t now) /* i holds index of free slot */ daemon->tcp_pids[i] = p; daemon->tcp_pipes[i] = pipefd[0]; + daemon->metrics[METRIC_TCP_CONNECTIONS]++; + if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used) +daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS]; } close(confd); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 67c083b..3d85b73 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1314,6 +1314,7 @@ extern struct daemon { int dumpfd; #endif int max_procs; + uint max_procs_used; } *daemon; struct server_details { diff --git a/src/metrics.c b/src/metrics.c index 050ccb3..1a9a4d3 100644 --- a/src/metrics.c +++ b/src/metrics.c @@ -39,6 +39,7 @@ const char * metric_names[] = { "leases_pruned_4", "leases_allocated_6", "leases_pruned_6", +"tcp_connections", }; const char* get_metric_name(int i) { diff --git a/src/metrics.h b/src/metrics.h index 22e9e48..e1cdd87 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -38,6 +38,7 @@ enum { METRIC_LEASES_PRUNED_4, METRIC_LEASES_ALLOCATED_6, METRIC_LEASES_PRUNED_6, + METRIC_TCP_CONNECTIONS, __METRIC_MAX, }; diff --git a/src/option.c b/src/option.c index 9423582..3eeda18 100644 --- a/src/option.c +++ b/src/option.c @@ -5855,6 +5855,7 @@ void read_opts(int argc, char **argv, char *compile_opts) daemon->randport_limit =
[Dnsmasq-discuss] [PATCH] Introduce local-service=host specialization
Hello! I have sent similar proposal already in year 2021 [1]. But I have reworked that a bit to reuse existing --local-service option and just add new parameter to it. If --local-service=host is used, dnsmasq will bind to addresses on lo interface only. It will not even open port on other interfaces, preventing possible scanning of running service from outside. It roughly becomes similar default like other resolvers without configuration use. BIND9 or unbound will listen also on localhost only. To avoid regressions, it still becomes inactive when any --interface, --listen-address or similar is specified at least once. Then you have to explicitly use --interface=lo to listen *also* on localhost. The change is related to Fedora bug #1852373 [2], also newly re-opened CVE-2020-14312 issue for RHEL8 [3]. Having explicitly specified bind-interfaces & interface=lo in dnsmasq default configuration has resulted in multiple regressions across different packages, which did not rewrite distribution provided configuration. I think it could be useful also for others. What do you think? Looking for any feedback! Regards, Petr 1. https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q4/015749.html 2. https://bugzilla.redhat.com/show_bug.cgi?id=1852373 3. https://issues.redhat.com/browse/RHEL-9516 -- Petr Menšík Software Engineer, RHEL Red Hat, https://www.redhat.com/ PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB From fa6c187cb12d275b6cffc0d7659ed6dd9ae06b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= Date: Tue, 5 Oct 2021 13:46:51 +0200 Subject: [PATCH] Introduce new --local-service=host parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to local-service, but more strict. Listen only on localhost unless other interface is specified. Has no effect when interface is provided explicitly. I had multiple bugs fillen on Fedora, because I have changed default configuration to: interface=lo bind-interfaces People just adding configuration parts to /etc/dnsmasq.d or appending to existing configuration often fail to see some defaults are already there. Give them auto-ignored configuration as smart default. Signed-off-by: Petr Menšík Do not add a new parameter on command line. Instead add just parameter for behaviour modification of existing local-service option. Now it accepts two optional values: - net: exactly the same as before - host: bind only to lo interface, do not listen on any other addresses than loopback. --- man/dnsmasq.8 | 8 +--- src/dnsmasq.c | 2 ++ src/dnsmasq.h | 3 ++- src/option.c | 44 +--- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 6d37360..0f0f0c8 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -270,14 +270,16 @@ the address dnsmasq is listening on. When an interface is specified, it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6 addresses associated with the interface. Since any defined authoritative zones are also available as part of the normal recusive DNS service supplied by dnsmasq, it can make sense to have an --auth-server declaration with no interfaces or address, but simply specifying the primary external nameserver. .TP -.B --local-service +.B --local-service[=net|host] +Without parameter or with net parameter, restricts service to connected network. Accept DNS queries only from hosts whose address is on a local subnet, -ie a subnet for which an interface exists on the server. This option +ie a subnet for which an interface exists on the server. With host parameter, listens +only on lo interface and accepts queries from localhost only. This option only has effect if there are no \fB--interface\fP, \fB--except-interface\fP, \fB--listen-address\fP or \fB--auth-server\fP options. It is intended to be set as a default on installation, to allow unconfigured installations to be useful but also safe from being used for DNS amplification attacks. -.TP +.TP .B \-2, --no-dhcp-interface= Do not provide DHCP, TFTP or router advertisement on the specified interface, but do provide DNS service. .TP diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 65ba334..83174cf 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -861,6 +861,8 @@ int main (int argc, char **argv) if (option_bool(OPT_LOCAL_SERVICE)) my_syslog(LOG_INFO, _("DNS service limited to local subnets")); + else if (option_bool(OPT_LOCALHOST_SERVICE)) + my_syslog(LOG_INFO, _("DNS service limited to localhost")); } my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 67c083b..d6985b6 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -281,7 +281,8 @@ struct event_desc { #define OPT_NORR 69 #define OPT_NO_IDENT 70 #define OPT_CACHE_RR 71 -#define OPT_LAST 72 +#define OPT_LOC
Re: [Dnsmasq-discuss] Does the --interface option to dnsmasq also apply to incoming broadcast DHCP requests?
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 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 " 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