mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 13:53:31 +01:00
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
This commit is contained in:
parent
04bec67574
commit
e4a9b4de4e
@ -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 @@ 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
|
||||
|
4
doc/TODO
4
doc/TODO
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"),
|
||||
|
110
src/or/dns.c
110
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. */
|
||||
|
@ -722,6 +722,7 @@ run_scheduled_events(time_t now)
|
||||
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 @@ run_scheduled_events(time_t now)
|
||||
* 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;
|
||||
|
@ -1574,6 +1574,8 @@ typedef struct {
|
||||
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_connection_edge_not_dns_pending(edge_connection_t *conn);
|
||||
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 **********************/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user