Commit 9aa706e2 authored by Nick Mathewson's avatar Nick Mathewson 🥄
Browse files

Bug 691 fix: do not shutdown Tor servers right away if the network is down.

svn:r17566
parent 355369a2
...@@ -6,6 +6,10 @@ Changes in version 0.2.1.9-alpha - 200?-??-?? ...@@ -6,6 +6,10 @@ Changes in version 0.2.1.9-alpha - 200?-??-??
- When a directory authority gives us a new guess for our IP address, - When a directory authority gives us a new guess for our IP address,
log which authority we used. Hopefully this will help us debug log which authority we used. Hopefully this will help us debug
the recent complaints about bad IP address guesses. the recent complaints about bad IP address guesses.
- When we can't initialize DNS because the network is down, do not
automatically stop Tor from starting. Instead, we retry failed
dns_inits() every 10 minutes, and change the exit policy to reject *:*
until one succeeds. Fixes bug 691.
o Minor features (controller): o Minor features (controller):
- New CONSENSUS_ARRIVED event to note when a new consensus has - New CONSENSUS_ARRIVED event to note when a new consensus has
...@@ -23,7 +27,7 @@ Changes in version 0.2.1.9-alpha - 200?-??-?? ...@@ -23,7 +27,7 @@ Changes in version 0.2.1.9-alpha - 200?-??-??
o Minor bugfixes (hidden services): o Minor bugfixes (hidden services):
- Do not throw away existing introduction points on SIGHUP; do not - Do not throw away existing introduction points on SIGHUP; do not
stall hidden services because of introduction points thrown away. stall hidden services because of introduction points thrown away.
Patch by Karsten. Fixes bug 874. Patch by Karsten. Fixes bug 874ma.
Changes in version 0.2.1.8-alpha - 2008-12-08 Changes in version 0.2.1.8-alpha - 2008-12-08
......
...@@ -290,7 +290,7 @@ static config_var_t _option_vars[] = { ...@@ -290,7 +290,7 @@ static config_var_t _option_vars[] = {
V(RunTesting, BOOL, "0"), V(RunTesting, BOOL, "0"),
V(SafeLogging, BOOL, "1"), V(SafeLogging, BOOL, "1"),
V(SafeSocks, BOOL, "0"), V(SafeSocks, BOOL, "0"),
V(ServerDNSAllowBrokenResolvConf, BOOL, "0"), V(ServerDNSAllowBrokenResolvConf, BOOL, "1"),
V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"), V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
V(ServerDNSDetectHijacking, BOOL, "1"), V(ServerDNSDetectHijacking, BOOL, "1"),
V(ServerDNSRandomizeCase, BOOL, "1"), V(ServerDNSRandomizeCase, BOOL, "1"),
......
...@@ -33,6 +33,8 @@ const char dns_c_id[] = ...@@ -33,6 +33,8 @@ const char dns_c_id[] =
/** Have we currently configured nameservers with eventdns? */ /** Have we currently configured nameservers with eventdns? */
static int nameservers_configured = 0; static int nameservers_configured = 0;
/** Did our most recent attempt to configure nameservers with eventdns fail? */
static int nameserver_config_failed = 0;
/** What was the resolv_conf fname we last used when configuring the /** What was the resolv_conf fname we last used when configuring the
* nameservers? Used to check whether we need to reconfigure. */ * nameservers? Used to check whether we need to reconfigure. */
static char *resolv_conf_fname = NULL; static char *resolv_conf_fname = NULL;
...@@ -220,12 +222,20 @@ dns_reset(void) ...@@ -220,12 +222,20 @@ dns_reset(void)
tor_free(resolv_conf_fname); tor_free(resolv_conf_fname);
resolv_conf_mtime = 0; resolv_conf_mtime = 0;
} else { } else {
if (configure_nameservers(0) < 0) if (configure_nameservers(0) < 0) {
return -1; return -1;
}
} }
return 0; return 0;
} }
/**DOCDOC*/
int
has_dns_init_failed(void)
{
return nameserver_config_failed;
}
/** Helper: Given a TTL from a DNS response, determine what TTL to give the /** Helper: Given a TTL from a DNS response, determine what TTL to give the
* OP that asked us to resolve it. */ * OP that asked us to resolve it. */
uint32_t uint32_t
...@@ -1109,10 +1119,11 @@ evdns_err_is_transient(int err) ...@@ -1109,10 +1119,11 @@ evdns_err_is_transient(int err)
} }
/** Configure eventdns nameservers if force is true, or if the configuration /** Configure eventdns nameservers if force is true, or if the configuration
* has changed since the last time we called this function. On Unix, this * has changed since the last time we called this function, or if we failed on
* reads from options->ServerDNSResolvConfFile or /etc/resolv.conf; on * our last attempt. On Unix, this reads from /etc/resolv.conf or
* Windows, this reads from options->ServerDNSResolvConfFile or the registry. * options->ServerDNSResolvConfFile; on Windows, this reads from
* Return 0 on success or -1 on failure. */ * options->ServerDNSResolvConfFile or the registry. Return 0 on success or
* -1 on failure. */
static int static int
configure_nameservers(int force) configure_nameservers(int force)
{ {
...@@ -1132,7 +1143,7 @@ configure_nameservers(int force) ...@@ -1132,7 +1143,7 @@ configure_nameservers(int force)
if (stat(conf_fname, &st)) { if (stat(conf_fname, &st)) {
log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s': %s", log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s': %s",
conf_fname, strerror(errno)); conf_fname, strerror(errno));
return options->ServerDNSAllowBrokenResolvConf ? 0 : -1; goto err;
} }
if (!force && resolv_conf_fname && !strcmp(conf_fname,resolv_conf_fname) if (!force && resolv_conf_fname && !strcmp(conf_fname,resolv_conf_fname)
&& st.st_mtime == resolv_conf_mtime) { && st.st_mtime == resolv_conf_mtime) {
...@@ -1147,11 +1158,11 @@ configure_nameservers(int force) ...@@ -1147,11 +1158,11 @@ configure_nameservers(int force)
if ((r = evdns_resolv_conf_parse(DNS_OPTIONS_ALL, conf_fname))) { if ((r = evdns_resolv_conf_parse(DNS_OPTIONS_ALL, conf_fname))) {
log_warn(LD_EXIT, "Unable to parse '%s', or no nameservers in '%s' (%d)", log_warn(LD_EXIT, "Unable to parse '%s', or no nameservers in '%s' (%d)",
conf_fname, conf_fname, r); conf_fname, conf_fname, r);
return options->ServerDNSAllowBrokenResolvConf ? 0 : -1; goto err;
} }
if (evdns_count_nameservers() == 0) { if (evdns_count_nameservers() == 0) {
log_warn(LD_EXIT, "Unable to find any nameservers in '%s'.", conf_fname); log_warn(LD_EXIT, "Unable to find any nameservers in '%s'.", conf_fname);
return options->ServerDNSAllowBrokenResolvConf ? 0 : -1; goto err;
} }
tor_free(resolv_conf_fname); tor_free(resolv_conf_fname);
resolv_conf_fname = tor_strdup(conf_fname); resolv_conf_fname = tor_strdup(conf_fname);
...@@ -1167,13 +1178,12 @@ configure_nameservers(int force) ...@@ -1167,13 +1178,12 @@ configure_nameservers(int force)
} }
if (evdns_config_windows_nameservers()) { if (evdns_config_windows_nameservers()) {
log_warn(LD_EXIT,"Could not config nameservers."); log_warn(LD_EXIT,"Could not config nameservers.");
return options->ServerDNSAllowBrokenResolvConf ? 0 : -1; goto err;
} }
if (evdns_count_nameservers() == 0) { if (evdns_count_nameservers() == 0) {
log_warn(LD_EXIT, "Unable to find any platform nameservers in " log_warn(LD_EXIT, "Unable to find any platform nameservers in "
"your Windows configuration. Perhaps you should list a " "your Windows configuration.");
"ServerDNSResolvConfFile file in your torrc?"); goto err;
return options->ServerDNSAllowBrokenResolvConf ? 0 : -1;
} }
if (nameservers_configured) if (nameservers_configured)
evdns_resume(); evdns_resume();
...@@ -1193,7 +1203,18 @@ configure_nameservers(int force) ...@@ -1193,7 +1203,18 @@ configure_nameservers(int force)
dns_servers_relaunch_checks(); dns_servers_relaunch_checks();
nameservers_configured = 1; nameservers_configured = 1;
if (nameserver_config_failed) {
nameserver_config_failed = 0;
mark_my_descriptor_dirty();
}
return 0; return 0;
err:
nameservers_configured = 0;
if (! nameserver_config_failed) {
nameserver_config_failed = 1;
mark_my_descriptor_dirty();
}
return -1;
} }
/** For eventdns: Called when we get an answer for a request we launched. /** For eventdns: Called when we get an answer for a request we launched.
...@@ -1284,8 +1305,9 @@ launch_resolve(edge_connection_t *exitconn) ...@@ -1284,8 +1305,9 @@ launch_resolve(edge_connection_t *exitconn)
if (!nameservers_configured) { if (!nameservers_configured) {
log_warn(LD_EXIT, "(Harmless.) Nameservers not configured, but resolve " log_warn(LD_EXIT, "(Harmless.) Nameservers not configured, but resolve "
"launched. Configuring."); "launched. Configuring.");
if (configure_nameservers(1) < 0) if (configure_nameservers(1) < 0) {
return -1; return -1;
}
} }
r = parse_inaddr_arpa_address(exitconn->_base.address, &in); r = parse_inaddr_arpa_address(exitconn->_base.address, &in);
......
...@@ -839,6 +839,7 @@ run_scheduled_events(time_t now) ...@@ -839,6 +839,7 @@ run_scheduled_events(time_t now)
static time_t time_to_recheck_bandwidth = 0; static time_t time_to_recheck_bandwidth = 0;
static time_t time_to_check_for_expired_networkstatus = 0; static time_t time_to_check_for_expired_networkstatus = 0;
static time_t time_to_dump_geoip_stats = 0; static time_t time_to_dump_geoip_stats = 0;
static time_t time_to_retry_dns_init = 0;
or_options_t *options = get_options(); or_options_t *options = get_options();
int i; int i;
int have_dir_info; int have_dir_info;
...@@ -981,6 +982,14 @@ run_scheduled_events(time_t now) ...@@ -981,6 +982,14 @@ run_scheduled_events(time_t now)
time_to_clean_caches = now + CLEAN_CACHES_INTERVAL; time_to_clean_caches = now + CLEAN_CACHES_INTERVAL;
} }
#define RETRY_DNS_INTERVAL (10*60)
/* If we're a server and initializing dns failed, retry periodically. */
if (time_to_retry_dns_init < now) {
time_to_retry_dns_init = now + RETRY_DNS_INTERVAL;
if (server_mode(options) && has_dns_init_failed())
dns_init();
}
/** 2. Periodically, we consider force-uploading our descriptor /** 2. Periodically, we consider force-uploading our descriptor
* (if we've passed our internal checks). */ * (if we've passed our internal checks). */
...@@ -1367,8 +1376,13 @@ do_main_loop(void) ...@@ -1367,8 +1376,13 @@ do_main_loop(void)
/* initialize dns resolve map, spawn workers if needed */ /* initialize dns resolve map, spawn workers if needed */
if (dns_init() < 0) { if (dns_init() < 0) {
log_err(LD_GENERAL,"Error initializing dns subsystem; exiting"); if (get_options()->ServerDNSAllowBrokenResolvConf)
return -1; log_warn(LD_GENERAL, "Couldn't set up any working nameservers. "
"Network not up yet? Will try again soon.");
else {
log_err(LD_GENERAL,"Error initializing dns subsystem; exiting. To "
"retry instead, set the ServerDNSAllowBrokenResolvConf option.");
}
} }
handle_signals(1); handle_signals(1);
......
...@@ -3456,6 +3456,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, ...@@ -3456,6 +3456,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_key,
/********************************* dns.c ***************************/ /********************************* dns.c ***************************/
int dns_init(void); int dns_init(void);
int has_dns_init_failed(void);
void dns_free_all(void); void dns_free_all(void);
uint32_t dns_clip_ttl(uint32_t ttl); uint32_t dns_clip_ttl(uint32_t ttl);
int dns_reset(void); int dns_reset(void);
......
...@@ -1733,7 +1733,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, ...@@ -1733,7 +1733,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
} }
/* Write the exit policy to the end of 's'. */ /* Write the exit policy to the end of 's'. */
if (dns_seems_to_be_broken() || if (dns_seems_to_be_broken() || has_dns_init_failed() ||
!router->exit_policy || !smartlist_len(router->exit_policy)) { !router->exit_policy || !smartlist_len(router->exit_policy)) {
/* DNS is screwed up; don't claim to be an exit. */ /* DNS is screwed up; don't claim to be an exit. */
strlcat(s+written, "reject *:*\n", maxlen-written); strlcat(s+written, "reject *:*\n", maxlen-written);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment