diff options
-rw-r--r-- | changes/bug1751 | 5 | ||||
-rw-r--r-- | changes/bug1964 | 3 | ||||
-rw-r--r-- | doc/tor.1.txt | 6 | ||||
-rw-r--r-- | src/or/config.c | 20 | ||||
-rw-r--r-- | src/or/connection_edge.c | 11 | ||||
-rw-r--r-- | src/or/dirserv.c | 12 | ||||
-rw-r--r-- | src/or/geoip.c | 2 | ||||
-rw-r--r-- | src/or/or.h | 11 | ||||
-rw-r--r-- | src/or/router.c | 27 | ||||
-rw-r--r-- | src/or/router.h | 2 |
10 files changed, 85 insertions, 14 deletions
diff --git a/changes/bug1751 b/changes/bug1751 new file mode 100644 index 000000000..58ea9a225 --- /dev/null +++ b/changes/bug1751 @@ -0,0 +1,5 @@ + o Major features: + - Exit relays now try harder to block exit attempts from unknown + relays, to make it harder for people to use them as one-hop proxies. + Controlled by the refuseunknownexits consensus parameter, or you + can override it with the RefuseUnknownExits torrc option. diff --git a/changes/bug1964 b/changes/bug1964 new file mode 100644 index 000000000..d100094eb --- /dev/null +++ b/changes/bug1964 @@ -0,0 +1,3 @@ + o Major bugfixes: + - Fix a segfault that can happen when using bridges. Fixes bug 1964; + bugfix on 0.2.2.15-alpha. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index fe69a2d3f..620f93874 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -908,6 +908,12 @@ is non-zero): the next day. All times are local, and given in 24-hour time. (Defaults to "month 1 0:00".) +**RefuseUnknownExits** **0**|**1**|**auto**:: + Prevent nodes that don't appear in the consensus from exiting using this + relay. If the option is 1, we always block exit attempts from such + nodes; if it's 0, we never do, and if the option is "auto", then we do + whatever the authorities suggest in the consensus. (Defaults to auto.) + **ServerDNSResolvConfFile** __filename__:: Overrides the default DNS configuration with the configuration in __filename__. The file format is the same as the standard Unix diff --git a/src/or/config.c b/src/or/config.c index fa2eb73be..6d8addeb2 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -327,7 +327,7 @@ static config_var_t _option_vars[] = { V(RecommendedClientVersions, LINELIST, NULL), V(RecommendedServerVersions, LINELIST, NULL), OBSOLETE("RedirectExit"), - V(RefuseUnknownExits, BOOL, "0"), + V(RefuseUnknownExits, STRING, "auto"), V(RejectPlaintextPorts, CSV, ""), V(RelayBandwidthBurst, MEMUNIT, "0"), V(RelayBandwidthRate, MEMUNIT, "0"), @@ -1242,6 +1242,18 @@ options_act(or_options_t *old_options) connection_bucket_init(); #endif + /* parse RefuseUnknownExits tristate */ + if (!strcmp(options->RefuseUnknownExits, "0")) + options->RefuseUnknownExits_ = 0; + else if (!strcmp(options->RefuseUnknownExits, "1")) + options->RefuseUnknownExits_ = 1; + else if (!strcmp(options->RefuseUnknownExits, "auto")) + options->RefuseUnknownExits_ = -1; + else { + /* Should have caught this in options_validate */ + return -1; + } + /* Change the cell EWMA settings */ cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus()); @@ -3008,6 +3020,12 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Failed to resolve/guess local address. See logs for details."); } + if (strcmp(options->RefuseUnknownExits, "0") && + strcmp(options->RefuseUnknownExits, "1") && + strcmp(options->RefuseUnknownExits, "auto")) { + REJECT("RefuseUnknownExits must be 0, 1, or auto"); + } + #ifndef MS_WINDOWS if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname)) REJECT("Can't use a relative path to torrc when RunAsDaemon is set."); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 39bc8e7c0..323356067 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -2500,6 +2500,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) char *address=NULL; uint16_t port; or_circuit_t *or_circ = NULL; + or_options_t *options = get_options(); assert_circuit_ok(circ); if (!CIRCUIT_IS_ORIGIN(circ)) @@ -2512,7 +2513,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) * that we have a stream connected to a circuit, and we don't connect to a * circuit until we have a pending/successful resolve. */ - if (!server_mode(get_options()) && + if (!server_mode(options) && circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay begin cell at non-server. Closing."); @@ -2545,13 +2546,11 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) tor_free(address); return 0; } - if (or_circ && or_circ->p_conn && !get_options()->AllowSingleHopExits && + if (or_circ && or_circ->p_conn && !options->AllowSingleHopExits && (or_circ->is_first_hop || (!connection_or_digest_is_known_relay( or_circ->p_conn->identity_digest) && -// XXX022 commented out so we can test it first in 0.2.2.11 -RD -// networkstatus_get_param(NULL, "refuseunknownexits", 1)))) { - get_options()->RefuseUnknownExits))) { + should_refuse_unknown_exits(options)))) { /* Don't let clients use us as a single-hop proxy, unless the user * has explicitly allowed that in the config. It attracts attackers * and users who'd be better off with, well, single-hop proxies. @@ -2571,7 +2570,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) return 0; } } else if (rh.command == RELAY_COMMAND_BEGIN_DIR) { - if (!directory_permits_begindir_requests(get_options()) || + if (!directory_permits_begindir_requests(options) || circ->purpose != CIRCUIT_PURPOSE_OR) { relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_NOTDIRECTORY, NULL); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 397b1c1d2..1f7722f2f 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1153,18 +1153,21 @@ directory_fetches_from_authorities(or_options_t *options) { routerinfo_t *me; uint32_t addr; + int refuseunknown; if (options->FetchDirInfoEarly) return 1; if (options->BridgeRelay == 1) return 0; if (server_mode(options) && router_pick_published_address(options, &addr)<0) return 1; /* we don't know our IP address; ask an authority. */ - if (options->DirPort == 0 && !options->RefuseUnknownExits) + refuseunknown = router_my_exit_policy_is_reject_star() && + should_refuse_unknown_exits(options); + if (options->DirPort == 0 && !refuseunknown) return 0; if (!server_mode(options) || !advertised_server_mode()) return 0; me = router_get_my_routerinfo(); - if (!me || (!me->dir_port && !options->RefuseUnknownExits)) + if (!me || (!me->dir_port && !refuseunknown)) return 0; /* if dirport not advertised, return 0 too */ return 1; } @@ -1208,7 +1211,10 @@ directory_caches_dir_info(or_options_t *options) return 1; if (!server_mode(options) || !advertised_server_mode()) return 0; - return options->RefuseUnknownExits; + /* We need an up-to-date view of network info if we're going to try to + * block exit attempts from unknown relays. */ + return router_my_exit_policy_is_reject_star() && + should_refuse_unknown_exits(options); } /** Return 1 if we want to allow remote people to ask us directory diff --git a/src/or/geoip.c b/src/or/geoip.c index 7f1052e98..ee8d72ee1 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -254,6 +254,8 @@ geoip_get_country_by_ip(uint32_t ipaddr) int geoip_get_n_countries(void) { + if (!geoip_countries) + init_geoip_countries(); return (int) smartlist_len(geoip_countries); } diff --git a/src/or/or.h b/src/or/or.h index f4f511ad0..5a9fbf26f 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2532,10 +2532,13 @@ typedef struct { int ConstrainedSockets; /**< Shrink xmit and recv socket buffers. */ uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */ - /** Whether we should drop exit streams from Tors that we don't know - * are relays. XXX022 In here for 0.2.2.11 as a temporary test before - * we switch over to putting it in consensusparams. -RD */ - int RefuseUnknownExits; + /** Whether we should drop exit streams from Tors that we don't know are + * relays. One of "0" (never refuse), "1" (always refuse), or "auto" (do + * what the consensus says, defaulting to 'refuse' if the consensus says + * nothing). */ + char *RefuseUnknownExits; + /** Parsed version of RefuseUnknownExits. -1 for auto. */ + int RefuseUnknownExits_; /** Application ports that require all nodes in circ to have sufficient * uptime. */ diff --git a/src/or/router.c b/src/or/router.c index 978078bf7..621cbaace 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -18,6 +18,7 @@ #include "geoip.h" #include "hibernate.h" #include "main.h" +#include "networkstatus.h" #include "policies.h" #include "relay.h" #include "rephist.h" @@ -975,6 +976,19 @@ server_mode(or_options_t *options) return (options->ORPort != 0 || options->ORListenAddress); } +/** Return true iff the combination of options in <b>options</b> and parameters + * in the consensus mean that we don't want to allow exits from circuits + * we got from addresses not known to be servers. */ +int +should_refuse_unknown_exits(or_options_t *options) +{ + if (options->RefuseUnknownExits_ != -1) { + return options->RefuseUnknownExits_; + } else { + return networkstatus_get_param(NULL, "refuseunknownexits", 1); + } +} + /** Remember if we've advertised ourselves to the dirservers. */ static int server_is_advertised=0; @@ -1137,6 +1151,17 @@ router_compare_to_my_exit_policy(edge_connection_t *conn) desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; } +/** Return true iff my exit policy is reject *:*. Return -1 if we don't + * have a descriptor */ +int +router_my_exit_policy_is_reject_star(void) +{ + if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ + return -1; + + return desc_routerinfo->policy_is_reject_star; +} + /** Return true iff I'm a server and <b>digest</b> is equal to * my identity digest. */ int @@ -1300,6 +1325,8 @@ router_rebuild_descriptor(int force) policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy, options->ExitPolicyRejectPrivate, ri->address, !options->BridgeRelay); + ri->policy_is_reject_star = + policy_is_reject_star(ri->exit_policy); if (desc_routerinfo) { /* inherit values */ ri->is_valid = desc_routerinfo->is_valid; diff --git a/src/or/router.h b/src/or/router.h index d90a7cff9..c17fc78bd 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -51,6 +51,7 @@ int server_mode(or_options_t *options); int advertised_server_mode(void); int proxy_mode(or_options_t *options); void consider_publishable_server(int force); +int should_refuse_unknown_exits(or_options_t *options); void router_upload_dir_desc_to_dirservers(int force); void mark_my_descriptor_dirty_if_older_than(time_t when); @@ -60,6 +61,7 @@ void check_descriptor_ipaddress_changed(time_t now); void router_new_address_suggestion(const char *suggestion, const dir_connection_t *d_conn); int router_compare_to_my_exit_policy(edge_connection_t *conn); +int router_my_exit_policy_is_reject_star(void); routerinfo_t *router_get_my_routerinfo(void); extrainfo_t *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); |