diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 56c49c2479..5198c13882 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -2132,7 +2132,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, { if (!ap_stream_wants_exit_attention(conn)) continue; /* Skip everything but APs in CIRCUIT_WAIT */ - if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) { + if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router, 1)) { ++n_supported[i]; // log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.", // router->nickname, i, n_supported[i]); @@ -2200,8 +2200,9 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, tor_free(n_supported); return choose_good_exit_server_general(dir, 0, 0); } - log_notice(LD_CIRC, "All routers are down or won't exit -- choosing a " - "doomed exit at random."); + log_notice(LD_CIRC, "All routers are down or won't exit%s -- " + "choosing a doomed exit at random.", + options->_ExcludeExitNodesUnion ? " or are Excluded" : ""); } supporting = smartlist_create(); use = smartlist_create(); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 145aefe984..59b6998b99 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -115,7 +115,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, return 0; } } - if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) { + if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter, 0)) { /* can't exit from this router */ return 0; } @@ -424,7 +424,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn, if (exitrouter && (!need_uptime || build_state->need_uptime)) { int ok; if (conn) { - ok = connection_ap_can_use_exit(conn, exitrouter); + ok = connection_ap_can_use_exit(conn, exitrouter, 0); } else { addr_policy_result_t r = compare_addr_to_addr_policy( 0, port, exitrouter->exit_policy); @@ -1111,7 +1111,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, /* XXXX022 Duplicates checks in connection_ap_handshake_attach_circuit */ routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); int opt = conn->chosen_exit_optional; - if (router && !connection_ap_can_use_exit(conn, router)) { + if (router && !connection_ap_can_use_exit(conn, router, 0)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, "Requested exit point '%s' would refuse request. %s.", conn->chosen_exit_name, opt ? "Trying others" : "Closing"); @@ -1431,7 +1431,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) } return -1; } - if (router && !connection_ap_can_use_exit(conn, router)) { + if (router && !connection_ap_can_use_exit(conn, router, 0)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, "Requested exit point '%s' would refuse request. %s.", conn->chosen_exit_name, opt ? "Trying others" : "Closing"); diff --git a/src/or/config.c b/src/or/config.c index b67ed3f52e..0f6d99765f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1424,10 +1424,15 @@ options_act(or_options_t *old_options) !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)) || (options->ExcludeExitNodes && !routerset_equal(old_options->ExcludeExitNodes, - options->ExcludeExitNodes))) { + options->ExcludeExitNodes)) || + (options->EntryNodes && + !routerset_equal(old_options->EntryNodes, options->EntryNodes)) || + (options->ExitNodes && + !routerset_equal(old_options->ExitNodes, options->ExitNodes)) || + options->StrictNodes != old_options->StrictNodes) { log_info(LD_CIRC, - "Changed to using entry guards, or changed ExcludeNodes, or " - "changed ExcludeExitNodes. Abandoning previous circuits."); + "Changed to using entry guards, or changed preferred or " + "excluded node lists. Abandoning previous circuits."); circuit_mark_all_unused_circs(); circuit_expire_all_dirty_circs(); } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index b1e952d465..47230da2e0 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -2840,9 +2840,13 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn) * to exit from it, or 0 if it probably will not allow it. * (We might be uncertain if conn's destination address has not yet been * resolved.) + * + * If excluded_means_no is 1 and Exclude*Nodes is set and excludes + * this relay, return 0. */ int -connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) +connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit, + int excluded_means_no) { tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_AP); @@ -2889,6 +2893,21 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy)) return 0; } + if (options->_ExcludeExitNodesUnion && + (options->StrictNodes || excluded_means_no) && + routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) { + /* If we are trying to avoid this node as exit, and we have StrictNodes + * set, then this is not a suitable exit. Refuse it. + * + * If we don't have StrictNodes set, then this function gets called in + * two contexts. First, we've got a circuit open and we want to know + * whether we can use it. In that case, we somehow built this circuit + * despite having the last hop in ExcludeExitNodes, so we should be + * willing to use it. Second, we are evaluating whether this is an + * acceptable exit for a new circuit. In that case, skip it. */ + return 0; + } + return 1; } diff --git a/src/or/or.h b/src/or/or.h index dabc40145a..431b62e8de 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3452,7 +3452,8 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ); void connection_exit_connect(edge_connection_t *conn); int connection_edge_is_rendezvous_stream(edge_connection_t *conn); -int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit); +int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit, + int excluded_means_no); void connection_ap_expire_beginning(void); void connection_ap_attach_pending(void); void connection_ap_fail_onehop(const char *failed_digest,