Commit Graph

376 Commits

Author SHA1 Message Date
Simon Kelley
0b6144583b Log failed TCP DNS connections upstream when --log-debug active. 2025-02-05 17:15:52 +00:00
Simon Kelley
5226b712a3 Add --no-0x20-encode config option.
The "bit 0x20 encoding" implemented in 995a16ca0c
can interact badly with (hopefully) rare broken upstream servers. Provide
an option to turn it off and a log message to give a clue as to why DNS service
is non-functional.
2025-02-03 21:02:12 +00:00
Simon Kelley
0762732647 belt-and-braces extra call to check_log_writer() in tcp_request() 2025-02-01 15:24:24 +00:00
Simon Kelley
6e6a45a7d9 Bump copyrights to 2025. 2025-01-23 17:08:39 +00:00
Simon Kelley
199e65c4d9 Remove misleading comment. 2025-01-20 15:55:42 +00:00
Simon Kelley
995a16ca0c Implement "DNS-0x20 encoding".
This provides extra protection against reply-spoof attacks.

Since DNS queries are case-insensitive, it's possible to randomly flip
the case of letters in a query and still get the correct answer back.
This adds an extra dimension for a cache-poisoning attacker to guess
when sending replies in-the-blind since it's expected that the
legitimate answer will have the same pattern of upper and lower case
as the query, so any replies which don't can be ignored as
malicious.

The amount of extra entropy clearly depends on the number
of a-z and A-Z characters in the query, and this implementation puts a
hard limit of 32 bits to make rescource allocation easy. This about
doubles entropy over the standard random ID and random port
combination.
2025-01-19 21:54:58 +00:00
Simon Kelley
65f9c1aca1 Case-sensitive matching of questions and answers.
When checking that an answer is the answer to the question that
we asked, compare the name in a case-sensitive manner.

Clients can set the letters in a query to a random pattern of
uppercase and lowercase to add more randomness as protection against
cache-poisoning attacks, and we don't want to nullify that.

This actually restores the status quo before
commit ed6d29a784
since matching questions and answers using a checksum
can't help but be case sensitive.

This patch is a preparation for introducing DNS-0x20
in the dnsmasq query path.
2025-01-19 00:08:36 +00:00
Simon Kelley
8ce27433f8 Handle DS queries to auth zones.
When dnsmasq is configured to act as an authoritative server and has
an authoritative zone configured, and recieves a query for
that zone _as_forwarder_ it answers the query directly rather
than forwarding it. This doesn't affect the answer, but it
saves dnsmasq forwarding the query to the recusor upstream,
whch then bounces it back to dnsmasq in auth mode. The
exception should be when the query is for the root of zone, for a DS
RR. The answer to that has to come from the parent, via the
recursor, and will typically be a proof-of-nonexistence since
dnsmasq doesn't support signed zones. This patch suppresses
local answers and forces forwarding to the upstream recursor
for such queries. It stops breakage when a DNSSEC validating
client makes queries to dnsmasq acting as forwarder for a zone
for which it is authoritative.
2025-01-18 08:57:14 +00:00
Simon Kelley
71766c0c35 Tweak handling of duplicate DNS answers via UDP.
If we get a duplicate answer for a query via UDP which we have
either already received and started DNSSEC validation, or was
truncated and we've passed to TCP, then just ignore it.

The code was already in place, but had evolved wonky and
only worked for error replies which would otherwise prompt
a retransmit.
2025-01-13 20:30:37 +00:00
Simon Kelley
da58455508 Tweak 7d915a0bb9
A downstream query may have gone to TCP, not just DNSSEC queries.
2025-01-13 11:03:30 +00:00
Simon Kelley
7d915a0bb9 Don't do retries over UDP when we've sent the query by TCP. 2025-01-12 22:02:05 +00:00
Simon Kelley
51343bd9a2 Treat replies with CD flag set the same for UDP and TCP code paths. 2025-01-12 16:25:07 +00:00
Simon Kelley
b58276a73c Return EDE OTHER error when DNSSEC validation abandoned.
This distinguishes the case where we found a message was bogus
from cases where the process failed.
2025-01-12 16:00:09 +00:00
Simon Kelley
0003db15cb Fix crash introduced in 6656790f24 2025-01-07 23:08:35 +00:00
Simon Kelley
6656790f24 Handle queries with EDNS client subnet fields better.
If dnsmasq is configured to add an EDNS client subnet to a query,
it is careful to suppress use of the cache, since a cached answer may
not be valid for a query with a different client subnet.
Extend this behaviour to queries which arrive a dnsmasq
already carrying an EDNS client subnet.

This change is rather more involved than may seem necessary at first sight,
since the existing code relies on all queries being decorated by dnsmasq
and therefore not cached, so there is no chance that an incoming query
might hit the cache and cache lookup don't need to be suppressed, just
cache insertion. When downstream queries may be a mix of client-subnet
bearing and plain vanilla, it can't be assumed that the answers are never
in the cache, and queries with subnets must not do lookups.
2025-01-07 20:46:33 +00:00
Simon Kelley
e24c341068 Fix wrong packet size when dumpong packets to file. 2025-01-01 17:03:50 +00:00
Matthias Andree
d578da0665 Fix FTBFS when using -pedantic compiler flag.
I am attaching an incremental git-am ready patch to go on top your Git HEAD,
to fix all sorts of issues and make this conforming C99 with default
options set,
and fix another load of warnings you receive when setting the compiler
to pick the nits,
-pedantic-errors -std=c99 (or c11, c18, c2x).
It changes many void * to uint8_t * to make the "increment by bytes"
explicit.
You can't do:

void *foo;
// ...
foo += 2.
2024-12-24 11:18:42 +00:00
Simon Kelley
0f437b3b5e Banish compiler warnings. 2024-12-20 21:57:21 +00:00
Simon Kelley
742af6e4b9 Refactor receive_query() to removed duplicated code. 2024-12-20 20:02:01 +00:00
Simon Kelley
3eb008c36d Further refactoring of the TCP DNS codepath.
It's not t a thing of beauty, but it's less ugly than it was.
Any bugs, I blame on what I started from....
2024-12-19 16:38:47 +00:00
Simon Kelley
32248ebd5b Fix thinko in 3b74df4f55 2024-12-19 12:33:54 +00:00
Simon Kelley
ab177cb153 Improve handling of non-QUERY DNS requests.
We can't answer and shouldn't forward non-QUERY DNS requests.

This patch fixes handling such requests from TCP connections; before
the connection would be closed without reply.

It also changes the RCODE in the answer from REFUSED to NOTIMP and
provides clearer logging.
2024-12-13 23:00:21 +00:00
Simon Kelley
3b74df4f55 Fix erroneous "DNSSEC validated" state with non-DNSSEC upstream servers.
When DNSEC validation is enabled, but a query is not validated
because it gets forwarded to a non-DNSEC-capable upstream
server, the rr_status array is not correctly cleared, with
the effect that the answer may be maked as DNSSEC validated
if the immediately preceding query was DNS signed and validated.
2024-12-10 15:01:59 +00:00
Simon Kelley
c6bc22adc7 Add missing dump_packet_udp() call. 2024-11-27 00:19:32 +00:00
Simon Kelley
32a8f3e009 Finesse TCP timeouts for upstream connections.
Timeouts for TCP connections to non-responive servers are very long.
This in not appropriate for DNS connections.

Set timeouts for connection setup, sending data and recieving data.
The timeouts for connection setup and sending data are set at 5 seconds.
For recieving the reply this is doubled, to take into account the
time for usptream to actually get the answer.

Thanks to Petr Menšík for pointing out this problem, and finding a better
and more portable solution than the one in place heretofore.
2024-11-25 23:18:07 +00:00
Simon Kelley
481ff0ed10 Logging tweaks. 2024-11-25 10:17:50 +00:00
Simon Kelley
f04cf8506a Simplify EDNS0 packet size handling.
In the post 2020 flag-day world, we limit UDP packets to 1232 bytes
which can go anywhere, so the dodgy code to try and determine the
functional maxmimum packet size on the path from upstream servers
is obsolete.
2024-11-24 23:06:22 +00:00
Simon Kelley
04d7693d86 Tweak logging for truncated replies. 2024-11-24 22:13:44 +00:00
Simon Kelley
d2790914df More edns0 rationalisation. 2024-11-24 00:37:40 +00:00
Simon Kelley
334e144c36 Don't empty reply packets received from upstream marked as truncated.
It's concievable that upstream, has provided a useful minimal reply.

After a patch from Rahul Thakur.
2024-11-23 23:38:31 +00:00
Simon Kelley
8bd54efceb Typo fix. 2024-11-23 22:53:34 +00:00
Simon Kelley
e5e8c14d87 Large refactor of EDNS0 UDP packet size handling.
This was kinda strange before, with a lot of cargo-cult copied code,
and no clear strategy.

Now it works like this:

When talking upstream we always add a pseudoheader, and set the
UDP packet size to --edns-packet-max unless we've had problems
talking to a server, when it's reduced to 1280 if that fixes things.

Answering queries from downstream, we get the answer (either from
upstream or local data) If local data won't fit the advertised size
(or 512 if there's not pseudoheader) return truncated. If upstream
returns truncated, do likewise. If upstream is OK, but the answer is
too big for downstream, truncate the answer.
2024-11-23 22:38:41 +00:00
Simon Kelley
4cf2f757ec Rationalise reties.
The saved query includes all the modifications, made on first
forwarding, which simplifies retries.
2024-11-22 22:23:36 +00:00
Simon Kelley
b5ac983bf6 Fix wrong transaction ID when retrying DNSSEC queries. 2024-11-21 15:09:14 +00:00
Simon Kelley
498794ad85 Extralog tweaks to get log-id right in a couple of odd cases. 2024-11-03 23:40:43 +00:00
Simon Kelley
467fbd1086 Fix argument-order thinko on call to new lookup_frec() 2024-11-03 23:07:54 +00:00
Simon Kelley
7b7aef903e Handle error return from blockdata_alloc in all cases. 2024-11-02 22:37:51 +00:00
Simon Kelley
09a1839272 Don't send suspect answer as query to next server in DNS TCP codepath. 2024-11-02 22:18:56 +00:00
Simon Kelley
959d991d10 Replace query hashing in TCP code path. 2024-11-02 21:09:17 +00:00
Simon Kelley
ed6d29a784 Remove query hashing in UDP DNS code path.
Now we're always saving the query, this is no longer necessary,
and allows the removal of a lot of quite hairy code.

Much more code removal to come, once the TCP code path is also purged.
2024-11-02 15:33:37 +00:00
Simon Kelley
5d6399b71c DOn't churn a query though the blockdata store twice when forwarding it. 2024-11-01 16:50:15 +00:00
Simon Kelley
3b6df06fb8 Always save forwarded query locally.
We do this in many cases anyway (DNSSEC, fast-retry) and doing
it unconditionally allows much simplification of knarly code, to follow.
2024-11-01 16:06:58 +00:00
Simon Kelley
a9d46d42cb Tweak packet-reduction code going from TCP->UDP. 2024-10-13 23:09:48 +01:00
Simon Kelley
0338aa4586 Don't log bogus source address when doing fast retry. 2024-10-13 00:09:26 +01:00
Simon Kelley
d15d371051 Handle truncated response UDP-to-TCP to downstream queries when validating.
A relatively common situation is that the reply to a downstream query
will fit in a UDP packet when no DNSSEC RRs are present, but overflows
when the RRSIGS, NSEC ect are added. This extends the automatic
move from UDP to TCP to downstream queries which get truncated replies,
in the hope that once stripped of the DNSSEC RRs, the reply can be returned
via UDP, nwithout making the downstream retry with TCP.

If the downstream sets the DO bit, (ie it wants the DNSSEC RRs, then
this path is not taken, since the downstream will have to get a truncated
repsonse and retry to get a correct answer.
2024-10-12 22:32:21 +01:00
Simon Kelley
1c26ec2876 UDP-to-TCP bugfix: wrong calls to extract_name and
suppress rapid (UDP) retry once we've switched to TCP.
2024-10-04 17:20:33 +01:00
Simon Kelley
e9a7cd0a50 Fix DNSSEC work counting when swapping from UDP to TCP 2024-10-04 17:20:33 +01:00
Simon Kelley
f5cdb007d8 Improve handling of truncated replies to DNSSEC queries.
Heretofore, when a validating the result of an external query triggers
a DNSKEY or DS query and the result of that query is truncated, dnsmasq
has forced the whole validation process to move to TCP by returning a
truncated reply to the original requestor. This forces the original
requestor to retry the query in TCP mode, and the DNSSEC subqueries
also get made via TCP and everything works.

Note that in general the actual answer being validated is not large
enough to trigger truncation, and there's no reason not to return that
answer via UDP if we can validate it successfully. It follows that
a substandard client which can't do TCP queries will still work if the
answer could be returned via UDP, but fails if it gets an artifically
truncated answer and cannot move to TCP.

This patch teaches dnsmasq to move to TCP for DNSSEC queries when
validating UDP answers. That makes the substandard clients mentioned
above work, and saves a round trip even for clients that can do TCP.
2024-10-04 17:20:33 +01:00
Simon Kelley
46288c7e90 Tidy up parameters to sendmsg() syscall.
The msg_controllen field passed to sendmsg is computed using the
CMSG_SPACE(), which is correct, but CMSG_SPACE() can include
padding bytes at the end of the passed structure if they are required
to align subsequent structures in the buffer. Make sure these
bytes are zeroed to avoid passing uninitiased memory to the kernel,
even though it will never touch these bytes.

Also tidy up the mashalling code in send_from to use pointers to
the structure being filled out, rather than a temporary copy which
then gets memcpy()'d into place. The DHCP sendmsg code has always
worked like this.

Thanks to  Dominik Derigs for running Memcheck as submitting the
initial patch.
2024-10-04 17:20:24 +01:00
Simon Kelley
1ed783b8d7 Fix spurious "resource limit exceeded" messages.
Replies from upstream with a REFUSED rcode can result in
log messages stating that a resource limit has been exceeded,
which is not the case.

Thanks to Dominik Derigs and the Pi-hole project for
spotting this.
2024-02-19 12:22:43 +00:00