[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r8440: Resolve bug 330: detect ISPs that want to hijack failing DNS (in tor/trunk: . doc src/or)



Author: nickm
Date: 2006-09-21 17:48:22 -0400 (Thu, 21 Sep 2006)
New Revision: 8440

Modified:
   tor/trunk/
   tor/trunk/ChangeLog
   tor/trunk/doc/TODO
   tor/trunk/doc/tor.1.in
   tor/trunk/src/or/config.c
   tor/trunk/src/or/dns.c
   tor/trunk/src/or/main.c
   tor/trunk/src/or/or.h
Log:
 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.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/branches/eventdns [r8875] on c95137ef-5f19-0410-b913-86e773d04f59

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/ChangeLog	2006-09-21 21:48:22 UTC (rev 8440)
@@ -1,6 +1,5 @@
 Changes in version 0.1.2.2-alpha - 2006-??-??
   o Major features:
-
     - Add server-side support for "reverse" DNS lookups (using PTR
       records so clients can determine the canonical hostname for a given
       IPv4 address).  This has been specified for a long time, but was
@@ -8,6 +7,11 @@
       servers now announce in their descriptors whether they support
       eventdns.
 
+  o Minor features:
+    - Check for name servers (like Earthlink's) that hijack failing DNS
+      requests and replace the 'no such server' answer with a "helpful"
+      redirect to an advertising-driven search portal.  [Resolves bug 330.]
+
   o Security Fixes, minor
     - If a client asked for a server by name, and we didn't have a
       descriptor for a named server with that name, we might return an old

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/doc/TODO	2006-09-21 21:48:22 UTC (rev 8440)
@@ -87,9 +87,9 @@
         - Write-limit directory responses (need to research)
 
 N - DNS improvements
-    - Option to deal with broken DNS of the "ggoogle.com? Ah, you meant
+    o Option to deal with broken DNS of the "ggoogle.com? Ah, you meant
       ads.me.com!" variety.
-d     - Autodetect whether DNS is broken in this way.
+      o Autodetect whether DNS is broken in this way.
     - Don't ask reject *:* nodes for DNS unless client wants you to.
     . Asynchronous DNS
       o Document and rename SearchDomains, ResolvConf options

Modified: tor/trunk/doc/tor.1.in
===================================================================
--- tor/trunk/doc/tor.1.in	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/doc/tor.1.in	2006-09-21 21:48:22 UTC (rev 8440)
@@ -647,6 +647,15 @@
 connected to "www.example.com".
 This option only effects name lookup for addresses requested by clients.
 (Defaults to "0".)
+.LP
+.TP
+\fBServerDNSDetectHijacking \fR\fB0\fR|\fB1\fR\fP
+When this option is set to 1, we will test periodically to determine whether
+our local nameservers have been configured to hijack failing DNS requests
+(usually to an advertising site).  If they are, we will attempt to correct
+this.  This option only effects name lookup for addresses requested by
+clients; and only takes effect if Tor was built with eventdns support.
+(Defaults to "1".)
 
 .SH DIRECTORY SERVER OPTIONS
 .PP

Modified: tor/trunk/src/or/config.c
===================================================================
--- tor/trunk/src/or/config.c	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/src/or/config.c	2006-09-21 21:48:22 UTC (rev 8440)
@@ -222,6 +222,7 @@
   VAR("RunTesting",          BOOL,     RunTesting,           "0"),
   VAR("SafeLogging",         BOOL,     SafeLogging,          "1"),
   VAR("SafeSocks",           BOOL,     SafeSocks,            "0"),
+  VAR("ServerDNSDetectHijacking",BOOL,   ServerDNSDetectHijacking,"1"),
   VAR("ServerDNSResolvConfFile", STRING, ServerDNSResolvConfFile, NULL),
   VAR("ServerDNSSearchDomains",  BOOL,   ServerDNSSearchDomains,  "0"),
   VAR("ShutdownWaitLength",  INTERVAL, ShutdownWaitLength,   "30 seconds"),

Modified: tor/trunk/src/or/dns.c
===================================================================
--- tor/trunk/src/or/dns.c	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/src/or/dns.c	2006-09-21 21:48:22 UTC (rev 8440)
@@ -122,6 +122,7 @@
 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 @@
 
   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 @@
       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 @@
   }
   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. */

Modified: tor/trunk/src/or/main.c
===================================================================
--- tor/trunk/src/or/main.c	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/src/or/main.c	2006-09-21 21:48:22 UTC (rev 8440)
@@ -722,6 +722,7 @@
   static time_t time_to_try_getting_descriptors = 0;
   static time_t time_to_reset_descriptor_failures = 0;
   static time_t time_to_add_entropy = 0;
+  static time_t time_to_check_for_wildcarded_dns = 0;
   or_options_t *options = get_options();
   int i;
   int have_dir_info;
@@ -923,6 +924,20 @@
    * we'll pass it to poll/select and bad things will happen.
    */
   close_closeable_connections();
+
+  /** 9. and if we're a server, check whether our DNS is telling stories to
+   * us. */
+  if (server_mode(options) && time_to_check_for_wildcarded_dns < now) {
+    if (!time_to_check_for_wildcarded_dns) {
+      time_to_check_for_wildcarded_dns = now + 60 + crypto_rand_int(120);
+    } else {
+      dns_launch_wildcard_checks();
+      time_to_check_for_wildcarded_dns = now + 12*3600 +
+        crypto_rand_int(12*3600);
+    }
+  }
+
+
 }
 
 static struct event *timeout_event = NULL;

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2006-09-21 21:48:16 UTC (rev 8439)
+++ tor/trunk/src/or/or.h	2006-09-21 21:48:22 UTC (rev 8440)
@@ -1574,6 +1574,8 @@
   int ServerDNSSearchDomains; /**< Boolean: If set, we don't force exit
                       * addresses to be FQDNs, but rather search for them in
                       * the local domains. */
+  int ServerDNSDetectHijacking; /**< Boolean: If true, check for DNS failure
+                                 * hijacking */
   char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
                      * resolver from the file here rather than from
                      * /etc/resolv.conf (unix) or the registry (windows) */
@@ -2158,6 +2160,7 @@
 void assert_all_pending_dns_resolves_ok(void);
 void dns_cancel_pending_resolve(const char *question);
 int dns_resolve(edge_connection_t *exitconn);
+void dns_launch_wildcard_checks(void);
 
 /********************************* hibernate.c **********************/