Commit e4a9b4de authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

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
parent 04bec675
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
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 @@ Changes in version 0.1.2.2-alpha - 2006-??-??
      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
+2 −2
Original line number Diff line number Diff line
@@ -87,9 +87,9 @@ d - Write limiting; separate token bucket for write
        - 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
+9 −0
Original line number Diff line number Diff line
@@ -647,6 +647,15 @@ domain. For example, if this system is configured to believe it is in
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
+1 −0
Original line number Diff line number Diff line
@@ -222,6 +222,7 @@ static config_var_t _option_vars[] = {
  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"),
+107 −3
Original line number Diff line number Diff line
@@ -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);

      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. */
Loading