From ff9bdbd56ffdc4d91da377ca5e1624b58aeaab8e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 17 Jan 2013 18:07:36 -0500 Subject: When excluding nodes by country, exclude {??} and {A1} too This is ticket 7706, reported by "bugcatcher." The rationale here is that if somebody says 'ExcludeNodes {tv}', then they probably don't just want to block definitely Tuvaluan nodes: they also want to block nodes that have unknown country, since for all they know such nodes are also in Tuvalu. This behavior is controlled by a new GeoIPExcludeUnknown autobool option. With the default (auto) setting, we exclude ?? and A1 if any country is excluded. If the option is 1, we add ?? and A1 unconditionally; if the option is 0, we never add them. (Right now our geoip file doesn't actually seem to include A1: I'm including it here in case it comes back.) This feature only takes effect if you have a GeoIP file. Otherwise you'd be excluding every node. --- changes/feature7706 | 9 +++++++++ doc/tor.1.txt | 8 ++++++++ src/or/config.c | 13 +++++++++++++ src/or/or.h | 5 +++++ src/or/routerset.c | 39 +++++++++++++++++++++++++++++++++++++++ src/or/routerset.h | 1 + 6 files changed, 75 insertions(+) create mode 100644 changes/feature7706 diff --git a/changes/feature7706 b/changes/feature7706 new file mode 100644 index 000000000..69b91a67e --- /dev/null +++ b/changes/feature7706 @@ -0,0 +1,9 @@ + o Minor features: + - When any country code is listed in ExcludeNodes or + ExcludeExitNodes, and we have GeoIP information, also exclude + all nodes with unknown countries ({??} and {A1} if + present). This behavior is controlled by the new + GeoIPExcludeUnknown option: you can make such nodes always + excluded with 'GeoIPExcludeUnknown 1', and disable the feature + with 'GeoIPExcludeUnknown 0'. Setting 'GeoIPExcludeUnknown auto' + gets you the default behavior. Implements feature 7706. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 40cf66dbc..3b13a6180 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -689,6 +689,14 @@ The following options are useful only for clients (that is, if node listed in ExcludeNodes is automatically considered to be part of this list too. See also the caveats on the "ExitNodes" option below. +**GeoIPExcludeUnknown** **0**|**1**|**auto**:: + If this option is set to 'auto', then whenever any country code is set in + ExcludeNodes or ExcludeEntryNodes, all nodes with unknown country (?? and + possibly A1) are treated as excluded as well. If this option is set to + '1', then all unknown countries are treated as excluded in ExcludeNodes + and ExcludeEntryNodes. This option has no effect when a GeoIP file isn't + configured or can't be found. (Default: auto) + **ExitNodes** __node__,__node__,__...__:: A list of identity fingerprints, nicknames, country codes and address patterns of nodes to use as exit node---that is, a diff --git a/src/or/config.c b/src/or/config.c index 4349b670b..ce751122f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -242,6 +242,7 @@ static config_var_t option_vars_[] = { V(FetchHidServDescriptors, BOOL, "1"), V(FetchUselessDescriptors, BOOL, "0"), V(FetchV2Networkstatus, BOOL, "0"), + V(GeoIPExcludeUnknown, AUTOBOOL, "auto"), #ifdef _WIN32 V(GeoIPFile, FILENAME, ""), V(GeoIPv6File, FILENAME, ""), @@ -1567,6 +1568,18 @@ options_act(const or_options_t *old_options) config_maybe_load_geoip_files_(options, old_options); + if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { + /* ExcludeUnknown is true or "auto" */ + const int is_auto = options->GeoIPExcludeUnknown == -1; + int changed; + + changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); + changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); + + if (changed) + routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); + } + if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || options->ConnDirectionStatistics || diff --git a/src/or/or.h b/src/or/or.h index a6f3d3e88..328e8dfa7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3840,6 +3840,11 @@ typedef struct { char *GeoIPFile; char *GeoIPv6File; + /** Autobool: if auto, then any attempt to Exclude{Exit,}Nodes a particular + * country code will exclude all nodes in ?? and A1. If true, all nodes in + * ?? and A1 are excluded. Has no effect if we don't know any GeoIP data. */ + int GeoIPExcludeUnknown; + /** If true, SIGHUP should reload the torrc. Sometimes controllers want * to make this false. */ int ReloadTorrcOnSIGHUP; diff --git a/src/or/routerset.c b/src/or/routerset.c index 5154e2808..4b519034d 100644 --- a/src/or/routerset.c +++ b/src/or/routerset.c @@ -226,6 +226,45 @@ routerset_contains(const routerset_t *set, const tor_addr_t *addr, return 0; } +/** If *setp includes at least one country code, or if + * only_some_cc_set is 0, add the ?? and A1 country codes to + * *setp, creating it as needed. Return true iff *setp changed. + */ +int +routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set) +{ + routerset_t *set; + int add_unknown, add_a1; + if (only_if_some_cc_set) { + if (!*setp || smartlist_len((*setp)->country_names) == 0) + return 0; + } + if (!*setp) + *setp = routerset_new(); + + set = *setp; + + add_unknown = ! smartlist_contains_string_case(set->country_names, "??") && + geoip_get_country("??") >= 0; + add_a1 = ! smartlist_contains_string_case(set->country_names, "a1") && + geoip_get_country("A1") >= 0; + + if (add_unknown) { + smartlist_add(set->country_names, tor_strdup("??")); + smartlist_add(set->list, tor_strdup("{??}")); + } + if (add_a1) { + smartlist_add(set->country_names, tor_strdup("a1")); + smartlist_add(set->country_names, tor_strdup("{a1}")); + } + + if (add_unknown || add_a1) { + routerset_refresh_countries(set); + return 1; + } + return 0; +} + /** Return true iff we can tell that ei is a member of set. */ int routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei) diff --git a/src/or/routerset.h b/src/or/routerset.h index cd4a8375e..bfa0c59ac 100644 --- a/src/or/routerset.h +++ b/src/or/routerset.h @@ -31,6 +31,7 @@ int routerset_contains_node(const routerset_t *set, const node_t *node); void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, const routerset_t *excludeset, int running_only); +int routerset_add_unknown_ccs(routerset_t **setp, int only_if_some_cc_set); #if 0 void routersets_get_node_disjunction(smartlist_t *target, const smartlist_t *source, -- cgit v1.2.3 From ec7ffed79da3f84d4bff7b92434f872dd228102c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 30 Jan 2013 10:19:41 -0500 Subject: Document the ?? country code. --- doc/tor.1.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 3b13a6180..947322161 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -679,7 +679,11 @@ The following options are useful only for clients (that is, if Note also that if you are a relay, this (and the other node selection options below) only affects your own circuits that Tor builds for you. Clients can still build circuits through you to any node. Controllers - can tell Tor to build circuits through any node. + can tell Tor to build circuits through any node. + + + + Country codes are case-insensitive. The code "\{??}" refers to nodes whose + country can't be identified. No country code, including \{??}, works if + no GeoIPFile can be loaded. See also the GeoIPExcludeUnknown option below. **ExcludeExitNodes** __node__,__node__,__...__:: @@ -691,8 +695,8 @@ The following options are useful only for clients (that is, if **GeoIPExcludeUnknown** **0**|**1**|**auto**:: If this option is set to 'auto', then whenever any country code is set in - ExcludeNodes or ExcludeEntryNodes, all nodes with unknown country (?? and - possibly A1) are treated as excluded as well. If this option is set to + ExcludeNodes or ExcludeEntryNodes, all nodes with unknown country (\{??} and + possibly \{A1}) are treated as excluded as well. If this option is set to '1', then all unknown countries are treated as excluded in ExcludeNodes and ExcludeEntryNodes. This option has no effect when a GeoIP file isn't configured or can't be found. (Default: auto) -- cgit v1.2.3