diff options
author | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2015-12-22 11:31:54 +1100 |
---|---|---|
committer | teor (Tim Wilson-Brown) <teor2345@gmail.com> | 2016-01-29 07:13:57 +1100 |
commit | c3cc8e16e9655ffcaead811675c360b6764f2992 (patch) | |
tree | 3a41bf415f509f70d521cbb065377aa5fa86239e | |
parent | e72cbf7a4e346f0d379961520db8bea7e9249f88 (diff) | |
download | tor-c3cc8e16e9655ffcaead811675c360b6764f2992.tar.gz tor-c3cc8e16e9655ffcaead811675c360b6764f2992.zip |
Log when IPv4/IPv6 restrictions or preferences weren't met
-rw-r--r-- | src/or/connection.c | 65 | ||||
-rw-r--r-- | src/or/directory.c | 12 | ||||
-rw-r--r-- | src/or/routerlist.c | 49 |
3 files changed, 123 insertions, 3 deletions
diff --git a/src/or/connection.c b/src/or/connection.c index d59e07bdbe..f252d2faa1 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -19,6 +19,7 @@ */ #define TOR_CHANNEL_INTERNAL_ #define CONNECTION_PRIVATE +#include "backtrace.h" #include "channel.h" #include "channeltls.h" #include "circuitbuild.h" @@ -1721,6 +1722,66 @@ connection_connect_sockaddr,(connection_t *conn, return inprogress ? 0 : 1; } +/* Log a message if connection violates ClientUseIPv4 0 or ClientUseIPv6 0. + * Log a less severe message if we couldn't conform to ClientPreferIPv6ORPort + * or ClientPreferIPv6ORPort. */ +static void +connection_connect_log_client_use_ip_version(const connection_t *conn) +{ + const or_options_t *options = get_options(); + + /* Only non-bridge clients care about ClientUseIPv4/6, bail out early on + * servers and bridge clients */ + if (options->UseBridges || server_mode(options) || !conn + || conn->type == CONN_TYPE_EXIT) { + return; + } + + /* We're only prepared to log OR and DIR connections here */ + if (conn->type != CONN_TYPE_OR && conn->type != CONN_TYPE_DIR) { + return; + } + + const int must_ipv4 = (options->ClientUseIPv6 == 0); + const int must_ipv6 = (options->ClientUseIPv4 == 0); + const int pref_ipv6 = (conn->type == CONN_TYPE_OR + ? nodelist_prefer_ipv6_orport(options) + : nodelist_prefer_ipv6_dirport(options)); + tor_addr_t real_addr; + tor_addr_make_null(&real_addr, AF_UNSPEC); + + /* OR conns keep the original address in real_addr, as addr gets overwritten + * with the descriptor address */ + if (conn->type == CONN_TYPE_OR) { + const or_connection_t *or_conn = TO_OR_CONN((connection_t *)conn); + tor_addr_copy(&real_addr, &or_conn->real_addr); + } else if (conn->type == CONN_TYPE_DIR) { + tor_addr_copy(&real_addr, &conn->addr); + } + + /* Check if we broke a mandatory address family restriction */ + if ((must_ipv4 && tor_addr_family(&real_addr) == AF_INET6) + || (must_ipv6 && tor_addr_family(&real_addr) == AF_INET)) { + log_warn(LD_BUG, "%s connection to %s violated ClientUseIPv%s 0.", + conn->type == CONN_TYPE_OR ? "OR" : "Dir", + fmt_addr(&real_addr), + options->ClientUseIPv4 == 0 ? "4" : "6"); + log_backtrace(LOG_WARN, LD_BUG, "Address came from"); + } + + /* Check if we couldn't satisfy an address family preference */ + if ((!pref_ipv6 && tor_addr_family(&real_addr) == AF_INET6) + || (pref_ipv6 && tor_addr_family(&real_addr) == AF_INET)) { + log_info(LD_NET, "Connection to %s doesn't satisfy ClientPreferIPv6%sPort " + "%d, with ClientUseIPv4 %d and ClientUseIPv6 %d.", + fmt_addr(&real_addr), + conn->type == CONN_TYPE_OR ? "OR" : "Dir", + conn->type == CONN_TYPE_OR ? options->ClientPreferIPv6ORPort + : options->ClientPreferIPv6DirPort, + options->ClientUseIPv4, options->ClientUseIPv4); + } +} + /** Take conn, make a nonblocking socket; try to connect to * addr:port (port arrives in *host order*). If fail, return -1 and if * applicable put your best guess about errno into *<b>socket_error</b>. @@ -1745,6 +1806,10 @@ connection_connect(connection_t *conn, const char *address, const or_options_t *options = get_options(); int protocol_family; + /* Log if we didn't stick to ClientUseIPv4/6 or ClientPreferIPv6OR/DirPort + */ + connection_connect_log_client_use_ip_version(conn); + if (tor_addr_family(addr) == AF_INET6) protocol_family = PF_INET6; else diff --git a/src/or/directory.c b/src/or/directory.c index 438b5d823f..20ffcee8dd 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -4,6 +4,7 @@ /* See LICENSE for licensing information */ #include "or.h" +#include "backtrace.h" #include "buffers.h" #include "circuitbuild.h" #include "config.h" @@ -692,11 +693,13 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, /* We rejected both addresses. This isn't great. */ if (!have_or && !have_dir) { - log_info(LD_DIR, "Rejected both the OR and Dir address when launching a " - "directory connection to: IPv4 %s OR %d Dir %d IPv6 %s OR %d " - "Dir %d", fmt_addr32(status->addr), status->or_port, + log_warn(LD_BUG, "Rejected all OR and Dir addresses from %s when " + "launching a directory connection to: IPv4 %s OR %d Dir %d " + "IPv6 %s OR %d Dir %d", routerstatus_describe(status), + fmt_addr32(status->addr), status->or_port, status->dir_port, fmt_addr(&status->ipv6_addr), status->ipv6_orport, status->dir_port); + log_backtrace(LOG_WARN, LD_BUG, "Addresses came from"); return; } @@ -1050,10 +1053,13 @@ directory_initiate_command_rend(const tor_addr_port_t *or_addr_port, if (or_connection && (!or_addr_port->port || tor_addr_is_null(&or_addr_port->addr))) { log_warn(LD_DIR, "Cannot make an OR connection without an OR port."); + log_backtrace(LOG_WARN, LD_BUG, "Address came from"); return; } else if (!or_connection && (!dir_addr_port->port || tor_addr_is_null(&dir_addr_port->addr))) { log_warn(LD_DIR, "Cannot make a Dir connection without a Dir port."); + log_backtrace(LOG_WARN, LD_BUG, "Address came from"); + return; } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 4a3c1cd434..2923da311f 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -13,6 +13,7 @@ #define ROUTERLIST_PRIVATE #include "or.h" +#include "backtrace.h" #include "crypto_ed25519.h" #include "circuitstats.h" #include "config.h" @@ -1536,6 +1537,50 @@ router_is_already_dir_fetching_rs(const routerstatus_t *rs, || router_is_already_dir_fetching(&ipv6_dir_ap, serverdesc, microdesc)); } +#ifndef LOG_FALSE_POSITIVES_DURING_BOOTSTRAP +#define LOG_FALSE_POSITIVES_DURING_BOOTSTRAP 0 +#endif + +/* Log a message if rs is not found or not a preferred address */ +static void +router_picked_poor_directory_log(const routerstatus_t *rs) +{ + const networkstatus_t *usable_consensus; + usable_consensus = networkstatus_get_reasonably_live_consensus(time(NULL), + usable_consensus_flavor()); + +#if !LOG_FALSE_POSITIVES_DURING_BOOTSTRAP + /* Don't log early in the bootstrap process, it's normal to pick from a + * small pool of nodes. Of course, this won't help if we're trying to + * diagnose bootstrap issues. */ + if (!smartlist_len(nodelist_get_list()) || !usable_consensus + || !router_have_minimum_dir_info()) { + return; + } +#endif + + /* We couldn't find a node, or the one we have doesn't fit our preferences. + * This might be a bug. */ + if (!rs) { + log_warn(LD_BUG, "Firewall denied all OR and Dir addresses for all relays " + "when searching for a directory."); + log_backtrace(LOG_WARN, LD_BUG, "Node search initiated by"); + } else if (!fascist_firewall_allows_rs(rs, FIREWALL_OR_CONNECTION, 1) + && !fascist_firewall_allows_rs(rs, FIREWALL_DIR_CONNECTION, 1) + ) { + log_warn(LD_BUG, "Selected a directory %s with non-preferred OR and Dir " + "addresses for launching a connection: " + "IPv4 %s OR %d Dir %d IPv6 %s OR %d Dir %d", + routerstatus_describe(rs), + fmt_addr32(rs->addr), rs->or_port, + rs->dir_port, fmt_addr(&rs->ipv6_addr), + rs->ipv6_orport, rs->dir_port); + log_backtrace(LOG_WARN, LD_BUG, "Node search initiated by"); + } +} + +#undef LOG_FALSE_POSITIVES_DURING_BOOTSTRAP + /** How long do we avoid using a directory server after it's given us a 503? */ #define DIR_503_TIMEOUT (60*60) @@ -1711,6 +1756,8 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags, if (n_busy_out) *n_busy_out = n_busy; + router_picked_poor_directory_log(result ? result->rs : NULL); + return result ? result->rs : NULL; } @@ -1843,6 +1890,8 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, RETRY_WITHOUT_EXCLUDE(retry_search); + router_picked_poor_directory_log(result); + if (n_busy_out) *n_busy_out = n_busy; return result; |