summaryrefslogtreecommitdiff
path: root/src/or/dns.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-09-21 21:48:22 +0000
committerNick Mathewson <nickm@torproject.org>2006-09-21 21:48:22 +0000
commite4a9b4de4ec0573721b5e0e0969c9ea2f9e70baf (patch)
tree7c58d803ea7de0ca2f4dd2806b20b259036c25a6 /src/or/dns.c
parent04bec6757494a7ac3a798bde068abf151c8a8242 (diff)
downloadtor-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.c110
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. */