diff options
author | Nick Mathewson <nickm@torproject.org> | 2006-12-28 21:29:11 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2006-12-28 21:29:11 +0000 |
commit | e5f5b96ca6bc35d22478840600c2dfdf2778950f (patch) | |
tree | 1c6d406bffc1d2691ff125894146d191fe17ebd2 /src/or/dns.c | |
parent | 4cd302a1ebd44eafe5ac57062288436ab41b1220 (diff) | |
download | tor-e5f5b96ca6bc35d22478840600c2dfdf2778950f.tar.gz tor-e5f5b96ca6bc35d22478840600c2dfdf2778950f.zip |
r11723@Kushana: nickm | 2006-12-28 13:52:48 -0500
Fix bug 364: check for whether popular hostnames (curently google, yahoo, mit, and slashdot) are getting wildcarded. If they are, we are probably behind a DNS server that is useless: change our exit policy to reject *:*.
svn:r9199
Diffstat (limited to 'src/or/dns.c')
-rw-r--r-- | src/or/dns.c | 135 |
1 files changed, 117 insertions, 18 deletions
diff --git a/src/or/dns.c b/src/or/dns.c index 1369c7da1a..a85b5ee212 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -122,6 +122,7 @@ static void dnsworker_main(void *data); static int spawn_dnsworker(void); static int spawn_enough_dnsworkers(void); #else +static void add_wildcarded_test_address(const char *address); static int configure_nameservers(int force); static int answer_is_wildcarded(const char *ip); #endif @@ -902,8 +903,12 @@ dns_found_answer(const char *address, int is_reverse, uint32_t addr, resolve = HT_FIND(cache_map, &cache_root, &search); if (!resolve) { - log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.", - escaped_safe_str(address)); + or_options_t *options = get_options(); + int is_test_address = options->ServerDNSTestAddresses && + smartlist_string_isin_case(options->ServerDNSTestAddresses, address); + if (!is_test_address) + log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.", + escaped_safe_str(address)); add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl); return; } @@ -1385,9 +1390,15 @@ spawn_enough_dnsworkers(void) } void -dns_launch_wildcard_checks(void) +dns_launch_correctness_checks(void) { } + +int +dns_seems_to_be_broken(void) +{ + return 0; +} #else /* !USE_EVENTDNS */ /** Eventdns helper: return true iff the eventdns result <b>err</b> is @@ -1512,13 +1523,14 @@ configure_nameservers(int force) */ static void evdns_callback(int result, char type, int count, int ttl, void *addresses, - void *arg) + void *arg) { char *string_address = arg; int is_reverse = 0; int status = DNS_RESOLVE_FAILED_PERMANENT; uint32_t addr = 0; const char *hostname = NULL; + int was_wildcarded = 0; if (result == DNS_ERR_NONE) { if (type == DNS_IPv4_A && count) { @@ -1537,6 +1549,7 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, "address %s; treating as a failure.", safe_str(escaped_address), escaped_safe_str(answer_buf)); + was_wildcarded = 1; addr = 0; status = DNS_RESOLVE_FAILED_PERMANENT; } else { @@ -1566,6 +1579,17 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, if (evdns_err_is_transient(result)) status = DNS_RESOLVE_FAILED_TRANSIENT; } + if (was_wildcarded) { + or_options_t *options = get_options(); + int is_test_address = options->ServerDNSTestAddresses && + smartlist_string_isin_case(options->ServerDNSTestAddresses, hostname); + + if (is_test_address) { + /* Ick. We're getting redirected on known-good addresses. Our DNS + * server must really hate us. */ + add_wildcarded_test_address(hostname); + } + } if (result != DNS_ERR_SHUTDOWN) dns_found_answer(string_address, is_reverse, addr, hostname, status, ttl); tor_free(string_address); @@ -1634,6 +1658,13 @@ static strmap_t *dns_wildcard_response_count = NULL; * nameserver wants to return in response to requests for nonexistent domains. */ static smartlist_t *dns_wildcard_list = NULL; +static int dns_wildcard_one_notice_given = 0; +static int dns_wildcard_notice_given = 0; + +/** DOCDOC */ +static smartlist_t *dns_wildcarded_test_address_list = NULL; +static int dns_wildcarded_test_address_notice_given = 0; +static int dns_is_completely_invalid = 0; /** Called when we see <b>id</b> (a dotted quad) in response to a request for * a hopefully bogus address. */ @@ -1641,7 +1672,6 @@ static void wildcard_increment_answer(const char *id) { int *ip; - static int notice_given = 0; if (!dns_wildcard_response_count) dns_wildcard_response_count = strmap_new(); @@ -1655,14 +1685,40 @@ wildcard_increment_answer(const char *id) if (*ip > 5 && n_wildcard_requests > 10) { if (!dns_wildcard_list) dns_wildcard_list = smartlist_create(); if (!smartlist_string_isin(dns_wildcard_list, id)) { - log(notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, + log(dns_wildcard_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, "Your DNS provider has given \"%s\" as an answer for %d different " "invalid addresses. Apparently they are hijacking DNS failures. " "I'll try to correct for this by treating future occurrences of " "\"%s\" as 'not found'.", id, *ip, id); smartlist_add(dns_wildcard_list, tor_strdup(id)); } - notice_given = 1; + dns_wildcard_notice_given = 1; + } +} + +static void +add_wildcarded_test_address(const char *address) +{ + int n; + if (!dns_wildcarded_test_address_list) + dns_wildcarded_test_address_list = smartlist_create(); + + if (smartlist_string_isin_case(dns_wildcarded_test_address_list, address)) + return; + + smartlist_add(dns_wildcarded_test_address_list, tor_strdup(address)); + n = smartlist_len(dns_wildcarded_test_address_list); + if (n > smartlist_len(get_options()->ServerDNSTestAddresses)/2) { + log(dns_wildcarded_test_address_notice_given ? LOG_INFO : LOG_NOTICE, + LD_EXIT, "Your DNS provider tried to redirect \"%s\" to a junk " + "address. It has done this with %d test addresses so far. I'm " + "going to stop being an exit node for now, since our DNS seems so " + "broken.", address, n); + if (!dns_is_completely_invalid) { + dns_is_completely_invalid = 1; + mark_my_descriptor_dirty(); + } + dns_wildcarded_test_address_notice_given = 1; } } @@ -1670,9 +1726,8 @@ wildcard_increment_answer(const char *id) * for a (hopefully) nonexistent domain. */ static void evdns_wildcard_check_callback(int result, char type, int count, int ttl, - void *addresses, void *arg) + void *addresses, void *arg) { - static int notice_given = 0; (void)ttl; ++n_wildcard_requests; if (result == DNS_ERR_NONE && type == DNS_IPv4_A && count) { @@ -1686,13 +1741,13 @@ evdns_wildcard_check_callback(int result, char type, int count, int ttl, tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); wildcard_increment_answer(answer_buf); } - log(notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, + log(dns_wildcard_one_notice_given ? LOG_INFO : LOG_NOTICE, LD_EXIT, "Your DNS provider gave an answer for \"%s\", which " "is not supposed to exist. Apparently they are hijacking " "DNS failures. Trying to correct for this. We've noticed %d possibly " "bad addresses so far.", string_address, strmap_size(dns_wildcard_response_count)); - notice_given = 1; + dns_wildcard_one_notice_given = 1; } tor_free(arg); } @@ -1721,18 +1776,38 @@ launch_wildcard_check(int min_len, int max_len, const char *suffix) tor_free(addr); } +static void +launch_test_addresses(int fd, short event, void *args) +{ + or_options_t *options = get_options(); + (void)fd; + (void)event; + (void)args; + + log_info(LD_EXIT, "Launching checks to see whether our nameservers like to " + "hijack *everything*."); + /* This situation is worse than the failure-hijacking situation. When this + * happens, we're no good for DNS requests at all, and we shouldn't really + * be an exit server.*/ + if (!options->ServerDNSTestAddresses) + return; + SMARTLIST_FOREACH(options->ServerDNSTestAddresses, const char *, address, + { + evdns_resolve_ipv4(address, DNS_QUERY_NO_SEARCH, evdns_callback, + tor_strdup(address)); + }); +} + #define N_WILDCARD_CHECKS 2 -/** Launch DNS requests for a few nonexistent hostnames, and see if we can - * catch our nameserver trying to hijack them and map them to a stupid "I - * couldn't find ggoogle.com but maybe you'd like to buy these lovely - * encyclopedias" page. */ -void +/** Launch DNS requests for a few nonexistent hostnames and a few well-known + * hostnames, and see if we can catch our nameserver trying to hijack them and + * map them to a stupid "I couldn't find ggoogle.com but maybe you'd like to + * buy these lovely encyclopedias" page. */ +static void dns_launch_wildcard_checks(void) { int i; - if (!get_options()->ServerDNSDetectHijacking) - return; log_info(LD_EXIT, "Launching checks to see whether our nameservers like " "to hijack DNS failures."); for (i = 0; i < N_WILDCARD_CHECKS; ++i) { @@ -1756,6 +1831,30 @@ dns_launch_wildcard_checks(void) } } +/* DOCDOC */ +void +dns_launch_correctness_checks(void) +{ + static struct event launch_event; + struct timeval timeout; + if (!get_options()->ServerDNSDetectHijacking) + return; + dns_launch_wildcard_checks(); + + /* Wait a while before launching requests for test addresses, so we can + * get the results from checking for wildcarding. */ + evtimer_set(&launch_event, launch_test_addresses, NULL); + timeout.tv_sec = 30; + timeout.tv_usec = 0; + evtimer_add(&launch_event, &timeout); +} + +int +dns_seems_to_be_broken(void) +{ + return dns_is_completely_invalid; +} + /** Return true iff we have noticed that the dotted-quad <b>ip</b> has been * returned in response to requests for nonexistent hostnames. */ static int |