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

[or-cvs] r9199: Fix bug 364: check for whether popular hostnames (curently g (in tor/trunk: . doc src/or)



Author: nickm
Date: 2006-12-28 16:29:11 -0500 (Thu, 28 Dec 2006)
New Revision: 9199

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
   tor/trunk/src/or/router.c
Log:
 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 *:*.



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

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/ChangeLog	2006-12-28 21:29:11 UTC (rev 9199)
@@ -67,6 +67,9 @@
       never believe reported remote addresses when they're internal.
     - Add client-side caching for reverse DNS lookups.
     - Add support to tor-resolve for reverse lookups and SOCKS5.
+    - We now check for the case when common DNS requests are going to
+      wildcarded addresses, and change our exit policy to reject *:* if
+      it's happening.  (Bug #364)
 
   o Security bugfixes:
     - Stop sending the HttpProxyAuthenticator string to directory

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/doc/TODO	2006-12-28 21:29:11 UTC (rev 9199)
@@ -107,8 +107,8 @@
       o address_is_invalid_destination() is the right thing to call here
         (and feel free to make that function smarter)
       o add a config option to turn it off.
-      - and a man page for that option
-    - Bug 364: notice when all the DNS requests we get back (including a few
+      o and a man page for that option
+    o Bug 364: notice when all the DNS requests we get back (including a few
       well-known sites) are all going to the same place.
     o Bug 363: Warn and die if we can't find a nameserver and we're running a
       server; don't fall back to 127.0.0.1.

Modified: tor/trunk/doc/tor.1.in
===================================================================
--- tor/trunk/doc/tor.1.in	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/doc/tor.1.in	2006-12-28 21:29:11 UTC (rev 9199)
@@ -704,6 +704,14 @@
 this.  This option only affects name lookup for addresses requested by
 clients; and only takes effect if Tor was built with eventdns support.
 (Defaults to "1".)
+.LP
+.TP
+\fBServerDNSTestAddresses \fR\fIaddress\fR,\fIaddress\fR,\fI...\fP
+When we're detecting DNS hijacking, make sure that these \fIvalid\fP
+addresses aren't getting redirected.  If they are, then our DNS is
+completely useless, and we'll reset our exit policy to "reject *:*".
+(Defaults to "www.google.com, www.mit.edu, www.yahoo.com,
+www.slashdot.org".)
 
 .SH DIRECTORY SERVER OPTIONS
 .PP

Modified: tor/trunk/src/or/config.c
===================================================================
--- tor/trunk/src/or/config.c	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/src/or/config.c	2006-12-28 21:29:11 UTC (rev 9199)
@@ -232,6 +232,8 @@
   VAR("ServerDNSDetectHijacking",BOOL,   ServerDNSDetectHijacking,"1"),
   VAR("ServerDNSResolvConfFile", STRING, ServerDNSResolvConfFile, NULL),
   VAR("ServerDNSSearchDomains",  BOOL,   ServerDNSSearchDomains,  "0"),
+  VAR("ServerDNSTestAddresses",  CSV,    ServerDNSTestAddresses,
+      "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
   VAR("ShutdownWaitLength",  INTERVAL, ShutdownWaitLength,   "30 seconds"),
   VAR("SocksListenAddress",  LINELIST, SocksListenAddress,   NULL),
   VAR("SocksPolicy",         LINELIST, SocksPolicy,          NULL),

Modified: tor/trunk/src/or/dns.c
===================================================================
--- tor/trunk/src/or/dns.c	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/src/or/dns.c	2006-12-28 21:29:11 UTC (rev 9199)
@@ -122,6 +122,7 @@
 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 @@
 
   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 @@
 }
 
 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 @@
  */
 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 @@
                   "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 @@
     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,14 +1658,20 @@
  * 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. */
 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,24 +1685,49 @@
   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;
+  }
+}
+
 /** Callback function when we get an answer (possibly failing) for a request
  * 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 @@
       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 @@
     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 @@
   }
 }
 
+/* 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

Modified: tor/trunk/src/or/main.c
===================================================================
--- tor/trunk/src/or/main.c	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/src/or/main.c	2006-12-28 21:29:11 UTC (rev 9199)
@@ -729,7 +729,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;
+  static time_t time_to_check_for_correct_dns = 0;
   or_options_t *options = get_options();
   int i;
   int have_dir_info;
@@ -937,12 +937,12 @@
 
   /** 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);
+  if (server_mode(options) && time_to_check_for_correct_dns < now) {
+    if (!time_to_check_for_correct_dns) {
+      time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120);
     } else {
-      dns_launch_wildcard_checks();
-      time_to_check_for_wildcarded_dns = now + 12*3600 +
+      dns_launch_correctness_checks();
+      time_to_check_for_correct_dns = now + 12*3600 +
         crypto_rand_int(12*3600);
     }
   }

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/src/or/or.h	2006-12-28 21:29:11 UTC (rev 9199)
@@ -1656,6 +1656,9 @@
   char *ServerDNSResolvConfFile; /**< If provided, we configure our internal
                      * resolver from the file here rather than from
                      * /etc/resolv.conf (Unix) or the registry (Windows). */
+  smartlist_t *ServerDNSTestAddresses; /**< A list of addresses that definitely
+                                        * should be resolveable. Used for
+                                        * testing our DNS server. */
   int EnforceDistinctSubnets; /**< If true, don't allow multiple routers in the
                                * same network zone in the same circuit. */
   int TunnelDirConns; /**< If true, use BEGIN_DIR rather than BEGIN when
@@ -2318,7 +2321,8 @@
 void assert_all_pending_dns_resolves_ok(void);
 void dns_cancel_pending_resolve(const char *question);
 int dns_resolve(edge_connection_t *exitconn, or_circuit_t *circ);
-void dns_launch_wildcard_checks(void);
+void dns_launch_correctness_checks(void);
+int dns_seems_to_be_broken(void);
 
 /********************************* hibernate.c **********************/
 

Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c	2006-12-28 21:29:03 UTC (rev 9198)
+++ tor/trunk/src/or/router.c	2006-12-28 21:29:11 UTC (rev 9199)
@@ -1204,7 +1204,14 @@
   }
 
   /* Write the exit policy to the end of 's'. */
-  for (tmpe=router->exit_policy; tmpe; tmpe=tmpe->next) {
+  tmpe = router->exit_policy;
+  if (dns_seems_to_be_broken()) {
+    /* DNS is screwed up; don't claim to be an exit. */
+    strlcat(s+written, "reject *:*\n", maxlen-written);
+    written += strlen("reject *:*\n");
+    tmpe = NULL;
+  }
+  for ( ; tmpe; tmpe=tmpe->next) {
     /* Write: "accept 1.2.3.4" */
     in.s_addr = htonl(tmpe->addr);
     tor_inet_ntoa(&in, addrbuf, sizeof(addrbuf));