diff options
author | Nick Mathewson <nickm@torproject.org> | 2006-09-21 21:48:22 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2006-09-21 21:48:22 +0000 |
commit | e4a9b4de4ec0573721b5e0e0969c9ea2f9e70baf (patch) | |
tree | 7c58d803ea7de0ca2f4dd2806b20b259036c25a6 /src/or/dns.c | |
parent | 04bec6757494a7ac3a798bde068abf151c8a8242 (diff) | |
download | tor-e4a9b4de4ec0573721b5e0e0969c9ea2f9e70baf.tar.gz tor-e4a9b4de4ec0573721b5e0e0969c9ea2f9e70baf.zip |
r8875@Kushana: nickm | 2006-09-21 16:46:28 -0400
Resolve bug 330: detect ISPs that want to hijack failing DNS requests and basically domain-squat the entire internet.
svn:r8440
Diffstat (limited to 'src/or/dns.c')
-rw-r--r-- | src/or/dns.c | 110 |
1 files changed, 107 insertions, 3 deletions
diff --git a/src/or/dns.c b/src/or/dns.c index 29255ad822..52cbb3daf0 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -122,6 +122,7 @@ static int spawn_dnsworker(void); static int spawn_enough_dnsworkers(void); #else static int configure_nameservers(int force); +static int answer_is_wildcarded(const char *ip); #endif #ifdef DEBUG_DNS_CACHE static void _assert_cache_ok(void); @@ -1330,6 +1331,11 @@ spawn_enough_dnsworkers(void) return 0; } + +void +dns_launch_wildcard_checks(void) +{ +} #else /* !USE_EVENTDNS */ /** Eventdns helper: return true iff the eventdns result <b>err</b> is @@ -1470,9 +1476,19 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses, status = DNS_RESOLVE_SUCCEEDED; tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); escaped_address = esc_for_log(string_address); - log_debug(LD_EXIT, "eventdns said that %s resolves to %s", - safe_str(escaped_address), - escaped_safe_str(answer_buf)); + + if (answer_is_wildcarded(answer_buf)) { + log_debug(LD_EXIT, "eventdns said that %s resolves to ISP-hijacked " + "address %s; treating as a failure.", + safe_str(escaped_address), + escaped_safe_str(answer_buf)); + addr = 0; + status = DNS_RESOLVE_FAILED_PERMANENT; + } else { + log_debug(LD_EXIT, "eventdns said that %s resolves to %s", + safe_str(escaped_address), + escaped_safe_str(answer_buf)); + } tor_free(escaped_address); } else if (type == DNS_PTR && count) { char *escaped_address; @@ -1546,6 +1562,94 @@ launch_resolve(edge_connection_t *exitconn) } return r ? -1 : 0; } + +/** If present, a list of dotted-quad IP addresses that our nameserver + * apparently wants to return in response to requests for nonexistent domains. + */ +static smartlist_t *dns_wildcard_list = NULL; + +/** Callback function when we get an answer (possibly failing) for a request + * for a (hopefully) nonexistent domain. */ +static void +eventdns_wildcard_check_callback(int result, char type, int count, int ttl, + void *addresses, void *arg) +{ + static int notice_given = 0; + if (result == DNS_ERR_NONE && type == DNS_IPv4_A && count) { + uint32_t *addrs = addresses; + int i; + char *string_address = arg; + if (!dns_wildcard_list) dns_wildcard_list = smartlist_create(); + for (i = 0; i < count; ++i) { + char answer_buf[INET_NTOA_BUF_LEN+1]; + struct in_addr in; + in.s_addr = addrs[i]; + tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); + if (!smartlist_string_isin(dns_wildcard_list, answer_buf)) + smartlist_add(dns_wildcard_list, tor_strdup(answer_buf)); + } + log(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 bad " + "addresses so far.", string_address, smartlist_len(dns_wildcard_list)); + notice_given = 1; + } + tor_free(arg); +} + +/** Launch a single request for a nonexistent hostname consisting of + * <b>len</b> random (plausible) characters followed by <b>suffix</b> */ +static void +launch_wildcard_check(int len, const char *suffix) +{ + char random_bytes[16], name[64], *addr; + size_t n = (len+1)/2; + int r; + + tor_assert(n <= sizeof(random_bytes)); + + if (crypto_rand(random_bytes, n) < 0) + return; + base32_encode(name, sizeof(name), random_bytes, n); + name[len] = '\0'; + strlcat(name, suffix, sizeof(name)); + + addr = tor_strdup(name); + r = eventdns_resolve_ipv4(name, DNS_QUERY_NO_SEARCH, + eventdns_wildcard_check_callback, addr); + if (r) + tor_free(addr); +} + +#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 +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) { + /* RFC2606 reserves these */ + launch_wildcard_check(8, ".invalid"); + launch_wildcard_check(8, ".test"); + } +} + +/** Return true iff we have noticed that the dotted-quad <b>ip</b> has been + * returned in response to a request for a nonexistent hostname. */ +static int +answer_is_wildcarded(const char *ip) +{ + return dns_wildcard_list && smartlist_string_isin(dns_wildcard_list, ip); +} #endif /* USE_EVENTDNS */ /** Exit with an assertion if <b>resolve</b> is corrupt. */ |