The 2.86 domain matching rewrite failed to take into account the possibilty that
server=/example.com/#
could be combined with, for example
address=/example.com/1.2.3.4
resulting in the struct server datastructure for the former getting passed
to forward_query(), rapidly followed by a SEGV.
This fix makes server=/example.com/# a fully fledged member of the
priority list, which is now IPv6 addr, IPv4 addr, all zero return,
resolvconf servers, upstream servers, no-data return
Thanks to dl6er@dl6er.de for finding and characterising the bug.
This patch also changes the method of calling querystr() such that
it is only called when logging is enabled, to eliminate any
possible performance problems from searching the larger table.
Domain patterns in --address, --server and --local have, for many years,
matched complete labels only, so
--server=/google.com/1.2.3.4
will apply to google.com and www.google.com but NOT supergoogle.com
This commit introduces an optional '*' at the LHS of the domain string which
changes this behaviour so as to include substring matches _within_ labels. So,
--server=/*google.com/1.2.3.4
applies to google.com, www.google.com AND supergoogle.com.
This extends query filtering support beyond what is currently possible
with the `--ipset` configuration option, by adding support for:
1) Specifying allowlists on a per-client basis, based on their
associated Linux connection track mark.
2) Dynamic configuration of allowlists via Ubus.
3) Reporting when a DNS query resolves or is rejected via Ubus.
4) DNS name patterns containing wildcards.
Disallowed queries are not forwarded; they are rejected
with a REFUSED error code.
Signed-off-by: Etan Kissling <etan_kissling@apple.com>
(addressed reviewer feedback)
Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
The sharing point for DNSSEC RR data used to be when it entered the
cache, having been validated. After that queries requiring the KEY or
DS records would share the cached values. There is a common case in
dual-stack hosts that queries for A and AAAA records for the same
domain are made simultaneously. If required keys were not in the
cache, this would result in two requests being sent upstream for the
same key data (and all the subsequent chain-of-trust queries.) Now we
combine these requests and elide the duplicates, resulting in fewer
queries upstream and better performance. To keep a better handle on
what's going on, the "extra" logging mode has been modified to
associate queries and answers for DNSSEC queries in the same way as
ordinary queries. The requesting address and port have been removed
from DNSSEC logging lines, since this is no longer strictly defined.
This used to have a global limit, but that has a problem when using
different servers for different upstream domains. Queries which are
routed by domain to an upstream server which is not responding will
build up and trigger the limit, which breaks DNS service for all other
domains which could be handled by other servers. The change is to make
the limit per server-group, where a server group is the set of servers
configured for a particular domain. In the common case, where only
default servers are declared, there is no effective change.
This should be largely transparent, but it drastically
improves performance and reduces memory foot-print when
configuring large numbers domains of the form
local=/adserver.com/
or
local=/adserver.com/#
Lookup times now grow as log-to-base-2 of the number of domains,
rather than greater than linearly, as before.
The change makes multiple addresses associated with a domain work
address=/example.com/1.2.3.4
address=/example.com/5.6.7.8
It also handles multiple upstream servers for a domain better; using
the same try/retry alogrithms as non domain-specific servers. This
also applies to DNSSEC-generated queries.
Finally, some of the oldest and gnarliest code in dnsmasq has had
a significant clean-up. It's far from perfect, but it _is_ better.
CVE-2021-3448 applies.
It's possible to specify the source address or interface to be
used when contacting upstream nameservers: server=8.8.8.8@1.2.3.4
or server=8.8.8.8@1.2.3.4#66 or server=8.8.8.8@eth0, and all of
these have, until now, used a single socket, bound to a fixed
port. This was originally done to allow an error (non-existent
interface, or non-local address) to be detected at start-up. This
means that any upstream servers specified in such a way don't use
random source ports, and are more susceptible to cache-poisoning
attacks.
We now use random ports where possible, even when the
source is specified, so server=8.8.8.8@1.2.3.4 or
server=8.8.8.8@eth0 will use random source
ports. server=8.8.8.8@1.2.3.4#66 or any use of --query-port will
use the explicitly configured port, and should only be done with
understanding of the security implications.
Note that this change changes non-existing interface, or non-local
source address errors from fatal to run-time. The error will be
logged and communiction with the server not possible.
Previously we were always using <sys/poll.h> since
HAVE_POLL_H is never set. This looks like an autoconfism
that has crept in, but we don't use autoconf.
poll.h is the correct header file, as far as I can tell.
If identical queries from IPv4 and IPv6 sources are combined by the
new code added in 15b60ddf93 then replies
can end up being sent via the wrong family of socket. The ->fd
should be per query, not per-question.
In bind-interfaces mode, this could also result in replies being sent
via the wrong socket even when IPv4/IPV6 issues are not in play.
Unlike COPTS=-DHAVE_DNSSEC, allow usage of just sha256 function from
nettle, but keep DNSSEC disabled at build time. Skips use of internal
hash implementation without support for validation built-in.
If we add the EDNS client subnet option, or the client's
MAC address, then the reply we get back may very depending on
that. Since the cache is ignorant of such things, it's not safe to
cache such replies. This patch determines when a dangerous EDNS
option is being added and disables caching.
Note that for much the same reason, we can't combine multiple
queries for the same question when dangerous EDNS options are
being added, and the code now handles that in the same way. This
query combining is required for security against cache poisoning,
so disabling the cache has a security function as well as a
correctness one.
Previously, such queries would all be forwarded
independently. This is, in theory, inefficent but in practise
not a problem, _except_ that is means that an answer for any
of the forwarded queries will be accepted and cached.
An attacker can send a query multiple times, and for each repeat,
another {port, ID} becomes capable of accepting the answer he is
sending in the blind, to random IDs and ports. The chance of a
succesful attack is therefore multiplied by the number of repeats
of the query. The new behaviour detects repeated queries and
merely stores the clients sending repeats so that when the
first query completes, the answer can be sent to all the
clients who asked. Refer: CERT VU#434904.
Use the SHA-256 hash function to verify that DNS answers
received are for the questions originally asked. This replaces
the slightly insecure SHA-1 (when compiled with DNSSEC) or
the very insecure CRC32 (otherwise). Refer: CERT VU#434904.
From 606d638918edb0e0ec07fe27eb68d06fb5ebd981 Mon Sep 17 00:00:00 2001
From: Miao Wang <shankerwangmiao@gmail.com>
Date: Fri, 4 Dec 2020 09:59:37 +0800
Subject: [PATCH v2] pxe: support pxe clients with custom vendor-class
According to UEFI[1] and PXE[2] specs, PXE clients are required to have
`PXEClient` identfier in the vendor-class field of DHCP requests, and
PXE servers should also include that identifier in their responses.
However, the firmware of servers from a few vendors[3] are customized to
include a different identifier. This patch adds an option named
`dhcp-pxe-vendor` to provide a list of such identifiers. The identifier
used in responses sent from dnsmasq is identical to that in the coresponding
request.
[1]: https://uefi.org/sites/default/files/resources/UEFI%20Spec%202.8B%20May%202020.pdf
[2]: http://www.pix.net/software/pxeboot/archive/pxespec.pdf
[3]: For instance, TaiShan servers from Huawei, which are Arm64-based,
send `HW-Client` in PXE requests up to now.
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
Save listening address into listener. Use it to find existing listeners
before creating new one. If it exist, increase just used counter.
Release only listeners not already used.
Duplicates family in listener.
We call this, which avoids POLLERR returns from netlink on a loaded system,
if the kernel is new enough to support it. Sadly, qemu-user doesn't support
the socket option, so if it fails despite the kernel being new enough to
support it, we just emit a warning, rather than failing hard.
A call to get_new_frec() for a DNSSEC query could manage to
free the original frec that we're doing the DNSSEC query to validate.
Bad things then happen.
This requires that the original frec is old, so it doesn't happen
in practice. I found it when running under gdb, and there have been
reports of SEGV associated with large system-clock warps which are
probably the same thing.
Same as for the dbus, allow specifying ubus service name (namespace) on
the command line as an optional argument to --enable-ubus option.
Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
When dhcp-host options can have many IPv6 addresses, we need
to deal with one of them being declined by a client. The other
addresses are still valid.
It seems that this logic never worked, even with only one address, since
the DECLINED flag was never tested.