Remi Gacogne [Fri, 17 Oct 2025 14:35:34 +0000 (16:35 +0200)]
dnsdist: Fix query rules bypass after tagging from a dynblock
In 2.0.0 we introduced the ability to set a tag when a dynamic
block matches, making it possible to combine dynamic blocks with
existing rules. Unfortunately the implementation turned out to
bypass query rules after setting a tag, so the mechanism could
only be used with the remaining rules chains (cache hit, cache-miss,
cache inserted, self-answered and regular response rules).
This commit fixes that to ensure that we can use tags with query
rules as well.
Remi Gacogne [Fri, 17 Oct 2025 10:33:21 +0000 (12:33 +0200)]
dnsdist: Make inserting to the in-memory rings a bit faster
This commit moves the allocation and copy of the DNS name before
taking the lock, reducing contention. In completely unrealistic
benchmarks this makes the insertion ~10% faster.
Ideally I would rather move the existing `DNSName` instead of allocating
a new one, as we are usually done with it by the point we insert
into the rings, but this involves a lot of changes so let's start
with this.
Remi Gacogne [Mon, 13 Oct 2025 14:13:03 +0000 (16:13 +0200)]
ComboAddress: Fix "unspecified address" test when the port is set
This fixes the QUIC issue reported on FreeBSD: the frontend
was not considered to be bound to an `ANY`/unspecified address
because the port was set, causing the address selection address
to fail.
Remi Gacogne [Fri, 10 Oct 2025 09:45:25 +0000 (11:45 +0200)]
dnsdist: Set up the dns header for timeout response rules
Response actions expect that there is a DNS payload containing at
least a DNS header, as an incoming packet smaller than a DNS header
would have been discarded early in the processing path.
Unfortunately this is not true for timeout response rules, where we
no longer have the DNS payload from the query and obviously don't
have a response either. This commit restores a DNS header from the
information we have (query ID, flags) so that most actions can
proceed normally.
Remi Gacogne [Tue, 7 Oct 2025 11:34:49 +0000 (13:34 +0200)]
dnsdist: Fix handling of large XSK frames
There was a bug in the way we were computing the remaining capacity
of a XSK frame, because we forgot to account for the network headers.
This caused some XSK responses to be discarded by the kernel (`tx_invalid_descs`)
because there was not enough space left in the frame (less than
`XDP_PACKET_HEADROOM`).
Thanks to `ednaq` for reporting this via ou YesWeHack program.
Remi Gacogne [Fri, 10 Oct 2025 08:18:40 +0000 (10:18 +0200)]
dnsdist: Make the round-robin LB policy internal counter atomic
Otherwise TSAN is rightfully complaining that there is a data race
because several threads are updating at the same time. While the
impact of this counter being corrupted is almost zero, and there is
an actual overhead to making it atomic, I believe this is the only
correct way to ensure the expected behaviour of this policy.
dnsdist: Fix release builds by updating the locked Rust lib version
Since we are now dynamically setting the version of our internal Rust library
when generating the release tarball, `cargo` needs to update the `Cargo.lock`
file to reflect the new version, which is not possible if we are passing `--locked`:
```
error: the lock file /pdns/dnsdist-2.1.0-alpha0.870.master.gc64b979bc/dnsdist-rust-lib/rust/Cargo.lock needs to be updated but --locked was passed to prevent this
If you want to try to generate the lock file without accessing the network, remove the --locked flag and use --offline instead.
```
This commit fixes that also updating the `Cargo.lock` file when generating the
release tarball so that `cargo` no longer needs to update the `Cargo.lock`.
dnsdist: Fix setting meta keys on response, pass them from question to response
This commit fixes setting Protocol Buffer meta keys on DNS response via Lua FFI:
the existing code was assuming it was possible to use the question methods on a
response object which is not true and would likely have ended in a crash at some
point.
It also propates meta keys set on a DNS question to the corresponding DNS response.
Before this commit the values were not passed along to the response which was quite
unexpected, especially for self-answered responses.
dnsdist: Fix access to frontends while in client mode
Since 2.0 we return `nil` instead of an object containing a `NULL`
pointer when the requested object does not exist, to make it possible
to check the validity of the returned object from `Lua`. It makes
sense in all contexts except when we are in client mode, because
then accessing the object in the remaining parts of the configuration
will trigger an error. Our DNS over HTTPS documentation itself contains
such a Lua configuration snippet, which is now broken.
This commit reverts back to sending an object containg a `NULL`
pointer when accessing the frontends in the client mode case.
Remi Gacogne [Fri, 27 Jun 2025 14:09:18 +0000 (16:09 +0200)]
dnsdist-resolver: Fix a bug when we get new IPs for a server
The `dnsdist-resolver` script regularly checks the IPs corresponding
to a backend `hostname`, and updates our backend accordingly:
- if an IP we previously received vanishes, it removes the backend
corresponding to that IP
- if a new IP shows up, it adds a new backend
The existing code tries to avoid some work by keeping track of the
number of IPs associated to a given server, skipping the comparisons
of recently received IPs to existing ones if the number did not change.
This unfortunately does not work well if we get the same number of IPs
but with different IPs in the set.
This caused some backends to never get removed and stay along as ghosts,
as well as some new IPs to never be picked up.
Remi Gacogne [Fri, 22 Aug 2025 07:57:57 +0000 (09:57 +0200)]
dnsdist: Fix a memory access violation in the nghttp2 unit tests
Calling `nghttp2_session_send` from a callback does not work well
when ``nghttp2_session_send`` ends up closing the current stream,
triggering a use-after-free.
It's not clear from the API documentation, but it is mentioned in
the programmers' guide's remarks:
> Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send2()`,
`nghttp2_session_recv()` or `nghttp2_session_mem_recv2()` from the
nghttp2 callback functions directly or indirectly. It will lead to the
crash. You can submit requests or frames in the callbacks then call
these functions outside the callbacks.
dnsdist: Explicitly update the configuration thread-local copy
This commits ensures that all DNSdist threads are regularly checking
if there is a new version of the runtime-modifiable configuration and
update their local copy if necessary. Regular accesses to the copy
are now fully read-only, meaning they do not invalidate the current copy.
It prevents the case where a function is invalidating the copy that the
caller is holding, and makes accessing the configuration cheaper.
dnsdist: Stop reading on incoming DoH sockets if we are done
If the underlying library doesn't want to read, we have nothing
to send at the moment, but we are still waiting for responses,
there is no need to keep polling the socket.
The way the nghttp2 library works means that we can get notified
that a stream has been closed while we are still in the function
sending the actual response. This is not a "killed" stream, but
just a regular closure.
Remi Gacogne [Thu, 19 Jun 2025 09:18:27 +0000 (11:18 +0200)]
dnsdist: Enforce concurrent streams count for pending queries
The gist of the `MadeYouRest` attack is that streams can be reset
by the client, and thus no longer count towards the maximum number
of a streams as far as the library is concerned, while the server
is still processing the query and doing actual work.
This pull request introduces a counter for "killed but still being
processed streams" to prevent it.