[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)
- To: or-cvs@xxxxxxxxxxxxx
- Subject: [or-cvs] r9199: Fix bug 364: check for whether popular hostnames (curently g (in tor/trunk: . doc src/or)
- From: nickm@xxxxxxxx
- Date: Thu, 28 Dec 2006 16:29:15 -0500 (EST)
- Delivered-to: archiver@seul.org
- Delivered-to: or-cvs-outgoing@seul.org
- Delivered-to: or-cvs@seul.org
- Delivery-date: Thu, 28 Dec 2006 16:29:23 -0500
- Reply-to: or-talk@xxxxxxxxxxxxx
- Sender: owner-or-cvs@xxxxxxxxxxxxx
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));