summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/ticket197697
-rw-r--r--src/or/dns.c30
-rw-r--r--src/or/dns.h14
-rw-r--r--src/or/or.h12
-rw-r--r--src/test/test_dns.c28
5 files changed, 33 insertions, 58 deletions
diff --git a/changes/ticket19769 b/changes/ticket19769
new file mode 100644
index 0000000000..9fc05c3e9e
--- /dev/null
+++ b/changes/ticket19769
@@ -0,0 +1,7 @@
+ o Major features (security):
+ - Change the algorithm used to decide DNS TTLs on client and server side,
+ to better resist DNS-based correlation attacks like the DefecTor attack
+ of Greschbach, Pulls, Roberts, Winter, and Feamster). Now
+ relays only return one of two possible DNS TTL values, and clients
+ are willing to believe DNS TTL values up to 3 hours long.
+ Closes ticket 19769.
diff --git a/src/or/dns.c b/src/or/dns.c
index 5f9813b912..41a6dfd0a4 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -243,29 +243,19 @@ has_dns_init_failed(void)
}
/** Helper: Given a TTL from a DNS response, determine what TTL to give the
- * OP that asked us to resolve it. */
+ * OP that asked us to resolve it, and how long to cache that record
+ * ourselves. */
uint32_t
dns_clip_ttl(uint32_t ttl)
{
- if (ttl < MIN_DNS_TTL)
- return MIN_DNS_TTL;
- else if (ttl > MAX_DNS_TTL)
- return MAX_DNS_TTL;
- else
- return ttl;
-}
-
-/** Helper: Given a TTL from a DNS response, determine how long to hold it in
- * our cache. */
-STATIC uint32_t
-dns_get_expiry_ttl(uint32_t ttl)
-{
- if (ttl < MIN_DNS_TTL)
- return MIN_DNS_TTL;
- else if (ttl > MAX_DNS_ENTRY_AGE)
- return MAX_DNS_ENTRY_AGE;
+ /* This logic is a defense against "DefectTor" DNS-based traffic
+ * confirmation attacks, as in https://nymity.ch/tor-dns/tor-dns.pdf .
+ * We only give two values: a "low" value and a "high" value.
+ */
+ if (ttl < MIN_DNS_TTL_AT_EXIT)
+ return MIN_DNS_TTL_AT_EXIT;
else
- return ttl;
+ return MAX_DNS_TTL_AT_EXIT;
}
/** Helper: free storage held by an entry in the DNS cache. */
@@ -1317,7 +1307,7 @@ make_pending_resolve_cached(cached_resolve_t *resolve)
resolve->ttl_hostname < ttl)
ttl = resolve->ttl_hostname;
- set_expiry(new_resolve, time(NULL) + dns_get_expiry_ttl(ttl));
+ set_expiry(new_resolve, time(NULL) + dns_clip_ttl(ttl));
}
assert_cache_ok();
diff --git a/src/or/dns.h b/src/or/dns.h
index b14f7dd29c..951a2a3467 100644
--- a/src/or/dns.h
+++ b/src/or/dns.h
@@ -12,6 +12,18 @@
#ifndef TOR_DNS_H
#define TOR_DNS_H
+/** Lowest value for DNS ttl that a server will give. */
+#define MIN_DNS_TTL_AT_EXIT (5*60)
+/** Highest value for DNS ttl that a server will give. */
+#define MAX_DNS_TTL_AT_EXIT (60*60)
+
+/** How long do we keep DNS cache entries before purging them (regardless of
+ * their TTL)? */
+#define MAX_DNS_ENTRY_AGE (3*60*60)
+/** How long do we cache/tell clients to cache DNS records when no TTL is
+ * known? */
+#define DEFAULT_DNS_TTL (30*60)
+
int dns_init(void);
int has_dns_init_failed(void);
void dns_free_all(void);
@@ -31,8 +43,6 @@ void dump_dns_mem_usage(int severity);
#ifdef DNS_PRIVATE
#include "dns_structs.h"
-STATIC uint32_t dns_get_expiry_ttl(uint32_t ttl);
-
MOCK_DECL(STATIC int,dns_resolve_impl,(edge_connection_t *exitconn,
int is_resolve,or_circuit_t *oncirc, char **hostname_out,
int *made_connection_pending_out, cached_resolve_t **resolve_out));
diff --git a/src/or/or.h b/src/or/or.h
index 66717792b4..e48cd92f03 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -143,18 +143,6 @@
/** Maximum size of a single extrainfo document, as above. */
#define MAX_EXTRAINFO_UPLOAD_SIZE 50000
-/** How long do we keep DNS cache entries before purging them (regardless of
- * their TTL)? */
-#define MAX_DNS_ENTRY_AGE (30*60)
-/** How long do we cache/tell clients to cache DNS records when no TTL is
- * known? */
-#define DEFAULT_DNS_TTL (30*60)
-/** How long can a TTL be before we stop believing it? */
-#define MAX_DNS_TTL (3*60*60)
-/** How small can a TTL be before we stop believing it? Provides rudimentary
- * pinning. */
-#define MIN_DNS_TTL 60
-
/** How often do we rotate onion keys? */
#define MIN_ONION_KEY_LIFETIME (7*24*60*60)
/** How often do we rotate TLS contexts? */
diff --git a/src/test/test_dns.c b/src/test/test_dns.c
index 8346c0a33f..6a8e92cb47 100644
--- a/src/test/test_dns.c
+++ b/src/test/test_dns.c
@@ -16,30 +16,11 @@ NS(test_main)(void *arg)
{
(void)arg;
- uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_TTL / 2;
+ uint32_t ttl_mid = MIN_DNS_TTL_AT_EXIT / 2 + MAX_DNS_TTL_AT_EXIT / 2;
- tt_int_op(dns_clip_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL);
- tt_int_op(dns_clip_ttl(ttl_mid),==,ttl_mid);
- tt_int_op(dns_clip_ttl(MAX_DNS_TTL + 1),==,MAX_DNS_TTL);
-
- done:
- return;
-}
-
-#undef NS_SUBMODULE
-
-#define NS_SUBMODULE expiry_ttl
-
-static void
-NS(test_main)(void *arg)
-{
- (void)arg;
-
- uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_ENTRY_AGE / 2;
-
- tt_int_op(dns_get_expiry_ttl(MIN_DNS_TTL - 1),==,MIN_DNS_TTL);
- tt_int_op(dns_get_expiry_ttl(ttl_mid),==,ttl_mid);
- tt_int_op(dns_get_expiry_ttl(MAX_DNS_ENTRY_AGE + 1),==,MAX_DNS_ENTRY_AGE);
+ tt_int_op(dns_clip_ttl(MIN_DNS_TTL_AT_EXIT - 1),==,MIN_DNS_TTL_AT_EXIT);
+ tt_int_op(dns_clip_ttl(ttl_mid),==,MAX_DNS_TTL_AT_EXIT);
+ tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),==,MAX_DNS_TTL_AT_EXIT);
done:
return;
@@ -749,7 +730,6 @@ NS(test_main)(void *arg)
struct testcase_t dns_tests[] = {
TEST_CASE(clip_ttl),
- TEST_CASE(expiry_ttl),
TEST_CASE(resolve),
TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
TEST_CASE_ASPECT(resolve_impl, non_exit),