diff options
Diffstat (limited to 'src/or/dns.c')
-rw-r--r-- | src/or/dns.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/src/or/dns.c b/src/or/dns.c index 6c0a8a8ac7..4194a29a6b 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2016, The Tor Project, Inc. */ + * Copyright (c) 2007-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -102,7 +102,7 @@ static void assert_cache_ok_(void); #define assert_cache_ok() assert_cache_ok_() #else #define assert_cache_ok() STMT_NIL -#endif +#endif /* defined(DEBUG_DNS_CACHE) */ static void assert_resolve_ok(cached_resolve_t *resolve); /** Hash table of cached_resolve objects. */ @@ -160,8 +160,9 @@ evdns_log_cb(int warn, const char *msg) } if (!strcmpstart(msg, "Nameserver ") && (cp=strstr(msg, " has failed: "))) { char *ns = tor_strndup(msg+11, cp-(msg+11)); - const char *err = strchr(cp, ':')+2; - tor_assert(err); + const char *colon = strchr(cp, ':'); + tor_assert(colon); + const char *err = colon+2; /* Don't warn about a single failed nameserver; we'll warn with 'all * nameservers have failed' if we're completely out of nameservers; * otherwise, the situation is tolerable. */ @@ -181,6 +182,18 @@ evdns_log_cb(int warn, const char *msg) } else if (!strcmp(msg, "All nameservers have failed")) { control_event_server_status(LOG_WARN, "NAMESERVER_ALL_DOWN"); all_down = 1; + } else if (!strcmpstart(msg, "Address mismatch on received DNS")) { + static ratelim_t mismatch_limit = RATELIM_INIT(3600); + const char *src = strstr(msg, " Apparent source"); + if (!src || get_options()->SafeLogging) { + src = ""; + } + log_fn_ratelim(&mismatch_limit, severity, LD_EXIT, + "eventdns: Received a DNS packet from " + "an IP address to which we did not send a request. This " + "could be a DNS spoofing attempt, or some kind of " + "misconfiguration.%s", src); + return; } tor_log(severity, LD_EXIT, "eventdns: %s", msg); } @@ -365,7 +378,7 @@ set_expiry(cached_resolve_t *resolve, time_t expires) resolve->expire = expires; smartlist_pqueue_add(cached_resolve_pqueue, compare_cached_resolves_by_expiry_, - STRUCT_OFFSET(cached_resolve_t, minheap_idx), + offsetof(cached_resolve_t, minheap_idx), resolve); } @@ -412,7 +425,7 @@ purge_expired_resolves(time_t now) break; smartlist_pqueue_pop(cached_resolve_pqueue, compare_cached_resolves_by_expiry_, - STRUCT_OFFSET(cached_resolve_t, minheap_idx)); + offsetof(cached_resolve_t, minheap_idx)); if (resolve->state == CACHE_STATE_PENDING) { log_debug(LD_EXIT, @@ -948,14 +961,14 @@ assert_connection_edge_not_dns_pending(edge_connection_t *conn) for (pend = resolve->pending_connections; pend; pend = pend->next) { tor_assert(pend->conn != conn); } -#else +#else /* !(1) */ cached_resolve_t **resolve; HT_FOREACH(resolve, cache_map, &cache_root) { for (pend = (*resolve)->pending_connections; pend; pend = pend->next) { tor_assert(pend->conn != conn); } } -#endif +#endif /* 1 */ } /** Log an error and abort if any connection waiting for a DNS resolve is @@ -1383,7 +1396,7 @@ configure_nameservers(int force) evdns_base_load_hosts(the_evdns_base, sandbox_intern_string("/etc/hosts")); } -#endif +#endif /* defined(DNS_OPTION_HOSTSFILE) && defined(USE_LIBSECCOMP) */ log_info(LD_EXIT, "Parsing resolver configuration in '%s'", conf_fname); if ((r = evdns_base_resolv_conf_parse(the_evdns_base, flags, sandbox_intern_string(conf_fname)))) { @@ -1421,18 +1434,35 @@ configure_nameservers(int force) tor_free(resolv_conf_fname); resolv_conf_mtime = 0; } -#endif +#endif /* defined(_WIN32) */ #define SET(k,v) evdns_base_set_option(the_evdns_base, (k), (v)) + // If we only have one nameserver, it does not make sense to back off + // from it for a timeout. Unfortunately, the value for max-timeouts is + // currently clamped by libevent to 255, but it does not hurt to set + // it higher in case libevent gets a patch for this. + // Reducing attempts in the case of just one name server too, because + // it is very likely to be a local one where a network connectivity + // issue should not cause an attempt to fail. if (evdns_base_count_nameservers(the_evdns_base) == 1) { - SET("max-timeouts:", "16"); - SET("timeout:", "10"); + SET("max-timeouts:", "1000000"); + SET("attempts:", "1"); } else { SET("max-timeouts:", "3"); - SET("timeout:", "5"); } + // Elongate the queue of maximum inflight dns requests, so if a bunch + // time out at the resolver (happens commonly with unbound) we won't + // stall every other DNS request. This potentially means some wasted + // CPU as there's a walk over a linear queue involved, but this is a + // much better tradeoff compared to just failing DNS requests because + // of a full queue. + SET("max-inflight:", "8192"); + + // Time out after 5 seconds if no reply. + SET("timeout:", "5"); + if (options->ServerDNSRandomizeCase) SET("randomize-case:", "1"); else @@ -1927,7 +1957,7 @@ dns_launch_wildcard_checks(void) launch_wildcard_check(8, 16, ipv6, ".com"); launch_wildcard_check(8, 16, ipv6, ".org"); launch_wildcard_check(8, 16, ipv6, ".net"); - } + } } } @@ -2020,7 +2050,7 @@ assert_resolve_ok(cached_resolve_t *resolve) tor_assert(!resolve->hostname); else tor_assert(!resolve->result_ipv4.addr_ipv4); -#endif +#endif /* 0 */ /*XXXXX ADD MORE */ } } @@ -2070,7 +2100,7 @@ assert_cache_ok_(void) smartlist_pqueue_assert_ok(cached_resolve_pqueue, compare_cached_resolves_by_expiry_, - STRUCT_OFFSET(cached_resolve_t, minheap_idx)); + offsetof(cached_resolve_t, minheap_idx)); SMARTLIST_FOREACH(cached_resolve_pqueue, cached_resolve_t *, res, { @@ -2084,10 +2114,10 @@ assert_cache_ok_(void) }); } -#endif +#endif /* defined(DEBUG_DNS_CACHE) */ -cached_resolve_t -*dns_get_cache_entry(cached_resolve_t *query) +cached_resolve_t * +dns_get_cache_entry(cached_resolve_t *query) { return HT_FIND(cache_map, &cache_root, query); } |