Miod Vallat [Thu, 20 Mar 2025 13:35:00 +0000 (14:35 +0100)]
Add an API-specific lookup method to DNSBackend.
This method, APILookup(), behaves similarly to lookup() but allows
disabled records to be returned to the caller. Backends with no support
for disabled records (bind, geoip, ldap, lua2, pipe, tinydns) implement
it as a by-default wrapper over lookup(). Other backends override with
their own processing.
SQL-style backends use distinct queries, api-id-query and
api-any-id-query, so as not to penalize non-API workloads.
def checkForwards(self, expected):
attempts = 0
tries = 10
ex = None
while attempts < tries:
try:
with open('configs/' + self._confdir + '/catzone.forward.catz.') as file:
reality = yaml.safe_load(file);
if expected == reality:
return
except Exception as e:
ex = e
attempts = attempts + 1
> sleep(0.1)
E NameError: name 'sleep' is not defined
```
dnsdist: Add support for switching certificates based on SNI w/ OpenSSL
We already supported this with GnuTLS, but OpenSSL does not make it
easy: we need to keep a different `SSL_CTX` object for each certificate/key
and change the `SSL_CTX` associated with an incoming connection to
the correct one based on the Server Name Indication from the servername
callback (actually OpenSSL devs advise to use the ClientHello callback
instead when using a recent enough version of OpenSSL, but the
SNI hostname is not available is not available at this point so we
would have to parse it ourselves, which is a terrible idea, and the
drawbacks are not clear. `nginx` has been getting away with it, so
hopefully we will as well).
One additional issue is that we still need to load certificates
for the same name but different key types (RSA vs ECDSA, for example)
in the same `SSL_CTX` context, which makes the code a bit convoluted.
This is currently equivalent to DNSName and is intended to be used for,
well, zone names. This will allow specific processing later, and
currently make the areas where such names are used more visible.
This commit is mostly mechanical and introduces type changes in various
API and data fields.
Otto Moerbeek [Tue, 8 Apr 2025 14:40:20 +0000 (16:40 +0200)]
rec regr tests: allow to set moduledir using an env var
This makes picking the right modulerdir explicit instead of hard-coded.
With meson the location varies, and also I would like to use packaged
modules even when I happen to have backend .so's in the default place.
Generate a valid packet for timeout response rules so that other
actions that requires packet buffer would be happy. Fix a few
clang-tidy issues, address a few PR comments, i.e. revert changes
that fixed in other commit.
Remi Gacogne [Mon, 3 Mar 2025 10:57:54 +0000 (11:57 +0100)]
dnsdist: Share tickets key between identical frontends created via YAML
Using the same Session Ticket Encryption Key on identical frontends
allow TLS sessions to be resumed in a much more efficient way, reducing
the latency and CPU usage. While it was already possible to do so by
manually managing the STEK, the default behaviour was to create and use
a different STEK for each frontend, because our Lua configuration makes
it almost impossible to ensure that two frontends are identical.
This is not an issue with the new YAML configuration format, so let's
share the STEK automatically in this case.
Remi Gacogne [Fri, 28 Mar 2025 14:52:08 +0000 (15:52 +0100)]
dnsdist: Add mitigations against misbehaving TCP/TLS clients
This commit adds several mitigations against misbehaving TCP/TLS clients:
- when a client is near the limit of concurrent TCP connections it is
allowed to have, the number of DNS queries over a single TCP connection
is restricted to 1 and the idle timout is reduced to 500 ms
- the same restrictions are applied to all connections if the frontend
is near the limit of concurrent TCP connections
- a limit of 50 read I/O events per query is enforced on incoming TCP
connections, to prevent a connection from continuously sending very small
packets to keep the worker busy. Clients exceeding this limit can
be prevented from opening new TCP connections for a configurable
amount of time
- three new configurable rates are introduced: new TCP connections
per second per client, new TLS sessions per second per client,
resumed TLS sessions per secondper client. Clients exceeding these
rates can be prevented from opening new TCP connections for a
configurable amount of time
Remi Gacogne [Mon, 31 Mar 2025 09:10:34 +0000 (11:10 +0200)]
dnsdist: Fix a TOCTOU in the Async regression tests
The existing code was catching all exceptions based on `OSError`
raised by a call to `os.unlink()` , and re-throwing if the file
actually existed, in an attempt to only ignore the case where
the file did not exist and still fail if the process did not
have enough rights to remove it, for example.
Unfortunately this construct introduced a TOCTOU issue, where the
initial exception might have been raised because the file did not
exist at the time of the call, resulting in a `FileNotFoundError`
exception being raised, but had been created before the existence
check, resulting in a puzzling message:
```
ready: 8/8 workersException in thread Asynchronous Responder:
Traceback (most recent call last):
File "/usr/lib/python3.13/threading.py", line 992, in run
self._target(*self._args, **self._kwargs)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/pdns/regression-tests.dnsdist/test_Async.py", line 17, in AsyncResponder
os.unlink(listenPath)
~~~~~~~~~^^^^^^^^^^^^
8 workers [816 items]
```
The new code only catches `FileNotFoundError` instead, so that
other errors are still causing a failure without needing a second
check.