mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
Merge remote-tracking branch 'public/bug19769_19025_029' into maint-0.2.9
This commit is contained in:
commit
58e1c6dd86
4
changes/bug19025
Normal file
4
changes/bug19025
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
o Major bugfixes (DNS):
|
||||||
|
- Fix a bug that prevented exit nodes from caching DNS records for more
|
||||||
|
than 60 seconds.
|
||||||
|
Fixes bug 19025; bugfix on 0.2.4.7-alpha.
|
7
changes/ticket19769
Normal file
7
changes/ticket19769
Normal file
@ -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.
|
33
src/or/dns.c
33
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
|
/** 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
|
uint32_t
|
||||||
dns_clip_ttl(uint32_t ttl)
|
dns_clip_ttl(uint32_t ttl)
|
||||||
{
|
{
|
||||||
if (ttl < MIN_DNS_TTL)
|
/* This logic is a defense against "DefectTor" DNS-based traffic
|
||||||
return MIN_DNS_TTL;
|
* confirmation attacks, as in https://nymity.ch/tor-dns/tor-dns.pdf .
|
||||||
else if (ttl > MAX_DNS_TTL)
|
* We only give two values: a "low" value and a "high" value.
|
||||||
return MAX_DNS_TTL;
|
*/
|
||||||
|
if (ttl < MIN_DNS_TTL_AT_EXIT)
|
||||||
|
return MIN_DNS_TTL_AT_EXIT;
|
||||||
else
|
else
|
||||||
return ttl;
|
return MAX_DNS_TTL_AT_EXIT;
|
||||||
}
|
|
||||||
|
|
||||||
/** 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;
|
|
||||||
else
|
|
||||||
return ttl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper: free storage held by an entry in the DNS cache. */
|
/** Helper: free storage held by an entry in the DNS cache. */
|
||||||
@ -336,7 +326,7 @@ cached_resolve_add_answer(cached_resolve_t *resolve,
|
|||||||
resolve->result_ipv4.err_ipv4 = dns_result;
|
resolve->result_ipv4.err_ipv4 = dns_result;
|
||||||
resolve->res_status_ipv4 = RES_STATUS_DONE_ERR;
|
resolve->res_status_ipv4 = RES_STATUS_DONE_ERR;
|
||||||
}
|
}
|
||||||
|
resolve->ttl_ipv4 = ttl;
|
||||||
} else if (query_type == DNS_IPv6_AAAA) {
|
} else if (query_type == DNS_IPv6_AAAA) {
|
||||||
if (resolve->res_status_ipv6 != RES_STATUS_INFLIGHT)
|
if (resolve->res_status_ipv6 != RES_STATUS_INFLIGHT)
|
||||||
return;
|
return;
|
||||||
@ -351,6 +341,7 @@ cached_resolve_add_answer(cached_resolve_t *resolve,
|
|||||||
resolve->result_ipv6.err_ipv6 = dns_result;
|
resolve->result_ipv6.err_ipv6 = dns_result;
|
||||||
resolve->res_status_ipv6 = RES_STATUS_DONE_ERR;
|
resolve->res_status_ipv6 = RES_STATUS_DONE_ERR;
|
||||||
}
|
}
|
||||||
|
resolve->ttl_ipv6 = ttl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1317,7 +1308,7 @@ make_pending_resolve_cached(cached_resolve_t *resolve)
|
|||||||
resolve->ttl_hostname < ttl)
|
resolve->ttl_hostname < ttl)
|
||||||
ttl = resolve->ttl_hostname;
|
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();
|
assert_cache_ok();
|
||||||
|
14
src/or/dns.h
14
src/or/dns.h
@ -12,6 +12,18 @@
|
|||||||
#ifndef TOR_DNS_H
|
#ifndef TOR_DNS_H
|
||||||
#define 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 dns_init(void);
|
||||||
int has_dns_init_failed(void);
|
int has_dns_init_failed(void);
|
||||||
void dns_free_all(void);
|
void dns_free_all(void);
|
||||||
@ -31,8 +43,6 @@ void dump_dns_mem_usage(int severity);
|
|||||||
#ifdef DNS_PRIVATE
|
#ifdef DNS_PRIVATE
|
||||||
#include "dns_structs.h"
|
#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,
|
MOCK_DECL(STATIC int,dns_resolve_impl,(edge_connection_t *exitconn,
|
||||||
int is_resolve,or_circuit_t *oncirc, char **hostname_out,
|
int is_resolve,or_circuit_t *oncirc, char **hostname_out,
|
||||||
int *made_connection_pending_out, cached_resolve_t **resolve_out));
|
int *made_connection_pending_out, cached_resolve_t **resolve_out));
|
||||||
|
12
src/or/or.h
12
src/or/or.h
@ -143,18 +143,6 @@
|
|||||||
/** Maximum size of a single extrainfo document, as above. */
|
/** Maximum size of a single extrainfo document, as above. */
|
||||||
#define MAX_EXTRAINFO_UPLOAD_SIZE 50000
|
#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? */
|
/** How often do we rotate onion keys? */
|
||||||
#define MIN_ONION_KEY_LIFETIME (7*24*60*60)
|
#define MIN_ONION_KEY_LIFETIME (7*24*60*60)
|
||||||
/** How often do we rotate TLS contexts? */
|
/** How often do we rotate TLS contexts? */
|
||||||
|
@ -345,9 +345,9 @@ test_cfmt_connected_cells(void *arg)
|
|||||||
memset(&cell, 0, sizeof(cell));
|
memset(&cell, 0, sizeof(cell));
|
||||||
tor_addr_parse(&addr, "30.40.50.60");
|
tor_addr_parse(&addr, "30.40.50.60");
|
||||||
rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
|
rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
|
||||||
&addr, 128);
|
&addr, 1024);
|
||||||
tt_int_op(rh.length, OP_EQ, 8);
|
tt_int_op(rh.length, OP_EQ, 8);
|
||||||
test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000080");
|
test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000e10");
|
||||||
|
|
||||||
/* Try parsing it. */
|
/* Try parsing it. */
|
||||||
tor_addr_make_unspec(&addr);
|
tor_addr_make_unspec(&addr);
|
||||||
@ -355,7 +355,7 @@ test_cfmt_connected_cells(void *arg)
|
|||||||
tt_int_op(r, OP_EQ, 0);
|
tt_int_op(r, OP_EQ, 0);
|
||||||
tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET);
|
tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET);
|
||||||
tt_str_op(fmt_addr(&addr), OP_EQ, "30.40.50.60");
|
tt_str_op(fmt_addr(&addr), OP_EQ, "30.40.50.60");
|
||||||
tt_int_op(ttl, OP_EQ, 128);
|
tt_int_op(ttl, OP_EQ, 3600); /* not 1024, since we clipped to 3600 */
|
||||||
|
|
||||||
/* Try an IPv6 address */
|
/* Try an IPv6 address */
|
||||||
memset(&rh, 0, sizeof(rh));
|
memset(&rh, 0, sizeof(rh));
|
||||||
|
@ -16,30 +16,11 @@ NS(test_main)(void *arg)
|
|||||||
{
|
{
|
||||||
(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(MIN_DNS_TTL_AT_EXIT - 1),==,MIN_DNS_TTL_AT_EXIT);
|
||||||
tt_int_op(dns_clip_ttl(ttl_mid),==,ttl_mid);
|
tt_int_op(dns_clip_ttl(ttl_mid),==,MAX_DNS_TTL_AT_EXIT);
|
||||||
tt_int_op(dns_clip_ttl(MAX_DNS_TTL + 1),==,MAX_DNS_TTL);
|
tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),==,MAX_DNS_TTL_AT_EXIT);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return;
|
return;
|
||||||
@ -749,7 +730,6 @@ NS(test_main)(void *arg)
|
|||||||
|
|
||||||
struct testcase_t dns_tests[] = {
|
struct testcase_t dns_tests[] = {
|
||||||
TEST_CASE(clip_ttl),
|
TEST_CASE(clip_ttl),
|
||||||
TEST_CASE(expiry_ttl),
|
|
||||||
TEST_CASE(resolve),
|
TEST_CASE(resolve),
|
||||||
TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
|
TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
|
||||||
TEST_CASE_ASPECT(resolve_impl, non_exit),
|
TEST_CASE_ASPECT(resolve_impl, non_exit),
|
||||||
|
Loading…
Reference in New Issue
Block a user