Merge branch 'extract_relay_dns'

This commit is contained in:
Nick Mathewson 2020-02-19 13:58:53 -05:00
commit a65efa7e83
9 changed files with 90 additions and 67 deletions

3
changes/ticket33366 Normal file
View File

@ -0,0 +1,3 @@
o Minor features (compilation size):
- Most Server-side DNS code is now disabled when building without
support for relay mode. Closes ticket 33366.

View File

@ -966,7 +966,6 @@ conn_close_if_marked(int i)
return 0; /* nothing to see here, move along */ return 0; /* nothing to see here, move along */
now = time(NULL); now = time(NULL);
assert_connection_ok(conn, now); assert_connection_ok(conn, now);
/* assert_all_pending_dns_resolves_ok(); */
log_debug(LD_NET,"Cleaning up connection (fd "TOR_SOCKET_T_FORMAT").", log_debug(LD_NET,"Cleaning up connection (fd "TOR_SOCKET_T_FORMAT").",
conn->s); conn->s);

View File

@ -432,6 +432,21 @@ warn_if_hs_unreachable(const edge_connection_t *conn, uint8_t reason)
} }
} }
/** Given a TTL (in seconds) from a DNS response or from a relay, determine
* what TTL clients and relays should actually use for caching it. */
uint32_t
clip_dns_ttl(uint32_t ttl)
{
/* 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)
return MIN_DNS_TTL;
else
return MAX_DNS_TTL;
}
/** Send a relay end cell from stream <b>conn</b> down conn's circuit, and /** Send a relay end cell from stream <b>conn</b> down conn's circuit, and
* remember that we've done so. If this is not a client connection, set the * remember that we've done so. If this is not a client connection, set the
* relay end cell's reason for closing as <b>reason</b>. * relay end cell's reason for closing as <b>reason</b>.
@ -480,7 +495,7 @@ connection_edge_end(edge_connection_t *conn, uint8_t reason)
memcpy(payload+1, tor_addr_to_in6_addr8(&conn->base_.addr), 16); memcpy(payload+1, tor_addr_to_in6_addr8(&conn->base_.addr), 16);
addrlen = 16; addrlen = 16;
} }
set_uint32(payload+1+addrlen, htonl(dns_clip_ttl(conn->address_ttl))); set_uint32(payload+1+addrlen, htonl(clip_dns_ttl(conn->address_ttl)));
payload_len += 4+addrlen; payload_len += 4+addrlen;
} }
@ -845,7 +860,7 @@ connected_cell_format_payload(uint8_t *payload_out,
return -1; return -1;
} }
set_uint32(payload_out + connected_payload_len, htonl(dns_clip_ttl(ttl))); set_uint32(payload_out + connected_payload_len, htonl(clip_dns_ttl(ttl)));
connected_payload_len += 4; connected_payload_len += 4;
tor_assert(connected_payload_len <= MAX_CONNECTED_CELL_PAYLOAD_LEN); tor_assert(connected_payload_len <= MAX_CONNECTED_CELL_PAYLOAD_LEN);

View File

@ -182,6 +182,21 @@ void connection_ap_warn_and_unmark_if_pending_circ(
entry_connection_t *entry_conn, entry_connection_t *entry_conn,
const char *where); const char *where);
/** Lowest value for DNS ttl that a server should give or a client should
* believe. */
#define MIN_DNS_TTL (5*60)
/** Highest value for DNS ttl that a server should give or a client should
* believe. */
#define MAX_DNS_TTL (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)
uint32_t clip_dns_ttl(uint32_t ttl);
int connection_half_edge_is_valid_data(const smartlist_t *half_conns, int connection_half_edge_is_valid_data(const smartlist_t *half_conns,
streamid_t stream_id); streamid_t stream_id);
int connection_half_edge_is_valid_sendme(const smartlist_t *half_conns, int connection_half_edge_is_valid_sendme(const smartlist_t *half_conns,

View File

@ -23,7 +23,6 @@
#include "app/config/config.h" #include "app/config/config.h"
#include "core/or/connection_edge.h" #include "core/or/connection_edge.h"
#include "feature/control/control_events.h" #include "feature/control/control_events.h"
#include "feature/relay/dns.h"
#include "feature/nodelist/nodelist.h" #include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerset.h" #include "feature/nodelist/routerset.h"
@ -689,7 +688,7 @@ client_dns_set_addressmap_impl(entry_connection_t *for_conn,
if (ttl<0) if (ttl<0)
ttl = DEFAULT_DNS_TTL; ttl = DEFAULT_DNS_TTL;
else else
ttl = dns_clip_ttl(ttl); ttl = clip_dns_ttl(ttl);
if (exitname) { if (exitname) {
/* XXXX fails to ever get attempts to get an exit address of /* XXXX fails to ever get attempts to get an exit address of

View File

@ -268,22 +268,6 @@ has_dns_init_failed(void)
return nameserver_config_failed; return nameserver_config_failed;
} }
/** Helper: Given a TTL from a DNS response, determine what TTL to give the
* OP that asked us to resolve it, and how long to cache that record
* ourselves. */
uint32_t
dns_clip_ttl(uint32_t ttl)
{
/* 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 MAX_DNS_TTL_AT_EXIT;
}
/** Helper: free storage held by an entry in the DNS cache. */ /** Helper: free storage held by an entry in the DNS cache. */
static void static void
free_cached_resolve_(cached_resolve_t *r) free_cached_resolve_(cached_resolve_t *r)
@ -521,7 +505,7 @@ send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type,
uint32_t ttl; uint32_t ttl;
buf[0] = answer_type; buf[0] = answer_type;
ttl = dns_clip_ttl(conn->address_ttl); ttl = clip_dns_ttl(conn->address_ttl);
switch (answer_type) switch (answer_type)
{ {
@ -593,7 +577,7 @@ send_resolved_hostname_cell,(edge_connection_t *conn,
size_t namelen = strlen(hostname); size_t namelen = strlen(hostname);
tor_assert(namelen < 256); tor_assert(namelen < 256);
ttl = dns_clip_ttl(conn->address_ttl); ttl = clip_dns_ttl(conn->address_ttl);
buf[0] = RESOLVED_TYPE_HOSTNAME; buf[0] = RESOLVED_TYPE_HOSTNAME;
buf[1] = (uint8_t)namelen; buf[1] = (uint8_t)namelen;
@ -987,25 +971,6 @@ assert_connection_edge_not_dns_pending(edge_connection_t *conn)
#endif /* 1 */ #endif /* 1 */
} }
/** Log an error and abort if any connection waiting for a DNS resolve is
* corrupted. */
void
assert_all_pending_dns_resolves_ok(void)
{
pending_connection_t *pend;
cached_resolve_t **resolve;
HT_FOREACH(resolve, cache_map, &cache_root) {
for (pend = (*resolve)->pending_connections;
pend;
pend = pend->next) {
assert_connection_ok(TO_CONN(pend->conn), 0);
tor_assert(!SOCKET_OK(pend->conn->base_.s));
tor_assert(!connection_in_array(TO_CONN(pend->conn)));
}
}
}
/** Remove <b>conn</b> from the list of connections waiting for conn-\>address. /** Remove <b>conn</b> from the list of connections waiting for conn-\>address.
*/ */
void void
@ -1063,7 +1028,7 @@ connection_dns_remove(edge_connection_t *conn)
* the resolve for <b>address</b> itself, and remove any cached results for * the resolve for <b>address</b> itself, and remove any cached results for
* <b>address</b> from the cache. * <b>address</b> from the cache.
*/ */
MOCK_IMPL(void, MOCK_IMPL(STATIC void,
dns_cancel_pending_resolve,(const char *address)) dns_cancel_pending_resolve,(const char *address))
{ {
pending_connection_t *pend; pending_connection_t *pend;
@ -1338,7 +1303,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_clip_ttl(ttl)); set_expiry(new_resolve, time(NULL) + clip_dns_ttl(ttl));
} }
assert_cache_ok(); assert_cache_ok();
@ -2188,7 +2153,7 @@ dns_cache_handle_oom(time_t now, size_t min_remove_bytes)
total_bytes_removed += bytes_removed; total_bytes_removed += bytes_removed;
/* Increase time_inc by a reasonable fraction. */ /* Increase time_inc by a reasonable fraction. */
time_inc += (MAX_DNS_TTL_AT_EXIT / 4); time_inc += (MAX_DNS_TTL / 4);
} while (total_bytes_removed < min_remove_bytes); } while (total_bytes_removed < min_remove_bytes);
return total_bytes_removed; return total_bytes_removed;

View File

@ -12,29 +12,14 @@
#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. */ #ifdef HAVE_MODULE_RELAY
#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);
uint32_t dns_clip_ttl(uint32_t ttl);
int dns_reset(void); int dns_reset(void);
void connection_dns_remove(edge_connection_t *conn); void connection_dns_remove(edge_connection_t *conn);
void assert_connection_edge_not_dns_pending(edge_connection_t *conn); void assert_connection_edge_not_dns_pending(edge_connection_t *conn);
void assert_all_pending_dns_resolves_ok(void);
MOCK_DECL(void,dns_cancel_pending_resolve,(const char *question));
int dns_resolve(edge_connection_t *exitconn); int dns_resolve(edge_connection_t *exitconn);
void dns_launch_correctness_checks(void);
int dns_seems_to_be_broken(void); int dns_seems_to_be_broken(void);
int dns_seems_to_be_broken_for_ipv6(void); int dns_seems_to_be_broken_for_ipv6(void);
void dns_reset_correctness_checks(void); void dns_reset_correctness_checks(void);
@ -42,6 +27,48 @@ size_t dns_cache_total_allocation(void);
void dump_dns_mem_usage(int severity); void dump_dns_mem_usage(int severity);
size_t dns_cache_handle_oom(time_t now, size_t min_remove_bytes); size_t dns_cache_handle_oom(time_t now, size_t min_remove_bytes);
/* These functions are only used within the feature/relay module, and don't
* need stubs. */
void dns_free_all(void);
void dns_launch_correctness_checks(void);
#else /* !defined(HAVE_MODULE_RELAY) */
#define dns_init() (0)
#define dns_seems_to_be_broken() (0)
#define has_dns_init_failed() (0)
#define dns_cache_total_allocation() (0)
#define dns_reset_correctness_checks() STMT_NIL
#define assert_connection_edge_not_dns_pending(conn) \
((void)(conn))
#define dump_dns_mem_usage(severity)\
((void)(severity))
#define dns_cache_handle_oom(now, bytes) \
((void)(now), (void)(bytes), 0)
#define connection_dns_remove(conn) \
STMT_BEGIN \
(void)(conn); \
tor_assert_nonfatal_unreached(); \
STMT_END
static inline int
dns_reset(void)
{
return 0;
}
static inline int
dns_resolve(edge_connection_t *exitconn)
{
(void)exitconn;
tor_assert_nonfatal_unreached();
return -1;
}
#endif /* defined(HAVE_MODULE_RELAY) */
#ifdef DNS_PRIVATE #ifdef DNS_PRIVATE
#include "feature/relay/dns_structs.h" #include "feature/relay/dns_structs.h"
@ -50,6 +77,7 @@ size_t number_of_configured_nameservers(void);
tor_addr_t *configured_nameserver_address(const size_t idx); tor_addr_t *configured_nameserver_address(const size_t idx);
#endif #endif
MOCK_DECL(STATIC void,dns_cancel_pending_resolve,(const char *question));
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));
@ -74,4 +102,3 @@ launch_resolve,(cached_resolve_t *resolve));
#endif /* defined(DNS_PRIVATE) */ #endif /* defined(DNS_PRIVATE) */
#endif /* !defined(TOR_DNS_H) */ #endif /* !defined(TOR_DNS_H) */

View File

@ -1,7 +1,6 @@
# Legacy shared relay code: migrate to the relay module over time # Legacy shared relay code: migrate to the relay module over time
LIBTOR_APP_A_SOURCES += \ LIBTOR_APP_A_SOURCES += \
src/feature/relay/dns.c \
src/feature/relay/onion_queue.c \ src/feature/relay/onion_queue.c \
src/feature/relay/router.c \ src/feature/relay/router.c \
src/feature/relay/routerkeys.c src/feature/relay/routerkeys.c
@ -10,6 +9,7 @@ LIBTOR_APP_A_SOURCES += \
# ADD_C_FILE: INSERT SOURCES HERE. # ADD_C_FILE: INSERT SOURCES HERE.
MODULE_RELAY_SOURCES = \ MODULE_RELAY_SOURCES = \
src/feature/relay/dns.c \
src/feature/relay/ext_orport.c \ src/feature/relay/ext_orport.c \
src/feature/relay/routermode.c \ src/feature/relay/routermode.c \
src/feature/relay/relay_config.c \ src/feature/relay/relay_config.c \

View File

@ -80,11 +80,11 @@ test_dns_clip_ttl(void *arg)
{ {
(void)arg; (void)arg;
uint32_t ttl_mid = MIN_DNS_TTL_AT_EXIT / 2 + MAX_DNS_TTL_AT_EXIT / 2; uint32_t ttl_mid = MIN_DNS_TTL / 2 + MAX_DNS_TTL / 2;
tt_int_op(dns_clip_ttl(MIN_DNS_TTL_AT_EXIT - 1),OP_EQ,MIN_DNS_TTL_AT_EXIT); tt_int_op(clip_dns_ttl(MIN_DNS_TTL - 1),OP_EQ,MIN_DNS_TTL);
tt_int_op(dns_clip_ttl(ttl_mid),OP_EQ,MAX_DNS_TTL_AT_EXIT); tt_int_op(clip_dns_ttl(ttl_mid),OP_EQ,MAX_DNS_TTL);
tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),OP_EQ,MAX_DNS_TTL_AT_EXIT); tt_int_op(clip_dns_ttl(MAX_DNS_TTL + 1),OP_EQ,MAX_DNS_TTL);
done: done:
return; return;