commit 71a1e5dfa4b495cba3e3e5a26b06a5a42ae93ba9
parent eddf5725fc790fd08a131331be96500e43e3019b
Author: David Goulet <dgoulet@torproject.org>
Date: Mon, 19 Jan 2026 13:07:12 -0500
dns: Clip all TTL to 60 returned in RESOLVED
Mitigate an exit DNS cache oracle which could leak to an attacker that a
certain domain was cached or not.
Fixes #40979
Signed-off-by: David Goulet <dgoulet@torproject.org>
Diffstat:
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/changes/ticket40979 b/changes/ticket40979
@@ -0,0 +1,4 @@
+ o Minor bugfixes (DNS, exit):
+ - Clip every returned DNS TTL to 60 (RESOLVED) in order to mitigate an exit
+ DNS cache oracle. Fixes bug 40979; bugfix on 0.3.5.1-alpha.
+
diff --git a/src/feature/relay/dns.c b/src/feature/relay/dns.c
@@ -86,6 +86,13 @@
* that the resolver is wedged? */
#define RESOLVE_MAX_TIMEOUT 300
+/** The clipped TTL sent back in the RESOLVED cell for every DNS queries.
+ *
+ * See https://gitlab.torproject.org/tpo/core/tor/-/issues/40979 for a thorough
+ * explanation but this is first and foremost a security fix in order to avoid
+ * an exit DNS cache oracle. */
+#define RESOLVED_CLIPPED_TTL (60)
+
/** Our evdns_base; this structure handles all our name lookups. */
static struct evdns_base *the_evdns_base = NULL;
@@ -512,10 +519,9 @@ send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type,
// generate a too-big message.)
char buf[RELAY_PAYLOAD_SIZE_MIN], *cp = buf;
size_t buflen = 0;
- uint32_t ttl;
+ uint32_t ttl = RESOLVED_CLIPPED_TTL;
buf[0] = answer_type;
- ttl = conn->address_ttl;
switch (answer_type)
{
@@ -585,7 +591,7 @@ send_resolved_hostname_cell,(edge_connection_t *conn,
{
char buf[RELAY_PAYLOAD_SIZE_MAX];
size_t buflen;
- uint32_t ttl;
+ uint32_t ttl = RESOLVED_CLIPPED_TTL;
if (BUG(!hostname))
return;
@@ -595,7 +601,6 @@ send_resolved_hostname_cell,(edge_connection_t *conn,
if (BUG(namelen >= 256)) {
return;
}
- ttl = conn->address_ttl;
buf[0] = RESOLVED_TYPE_HOSTNAME;
buf[1] = (uint8_t)namelen;