From 34a6b8b7e588b6f10e6e87cf876ef6ada49f8b8a Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Sat, 17 Sep 2011 03:23:26 -0700 Subject: Clear the timed_out flag when an HS connection attempt ends --- changes/bug1297b | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changes/bug1297b (limited to 'changes') diff --git a/changes/bug1297b b/changes/bug1297b new file mode 100644 index 000000000..6b0169d82 --- /dev/null +++ b/changes/bug1297b @@ -0,0 +1,8 @@ + o Minor bugfixes: + + - When one of a hidden service's introduction points times out, + consider trying it again during the next attempt to connect to + the HS. Previously, we would not try it again unless a newly + fetched descriptor contained it. Required by fixes for bugs + 1297 and 3825. + -- cgit v1.2.3 From fbea8c8ef1e2f549e84ee681a9640c3006f7ad64 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Sat, 17 Sep 2011 03:53:07 -0700 Subject: Detect and remove unreachable intro points --- changes/bug3825a | 8 ++++++++ src/or/circuitlist.c | 16 ++++++++++++++++ src/or/or.h | 10 ++++++++++ src/or/rendclient.c | 19 +++++++++++++++++++ src/or/rendclient.h | 1 + 5 files changed, 54 insertions(+) create mode 100644 changes/bug3825a (limited to 'changes') diff --git a/changes/bug3825a b/changes/bug3825a new file mode 100644 index 000000000..6606e36ef --- /dev/null +++ b/changes/bug3825a @@ -0,0 +1,8 @@ + o Major bugfixes: + + - When one of a hidden service's introduction points appears to be + unreachable, stop trying it. Previously, we would keep trying + to build circuits to the introduction point until we lost the + descriptor, usually because the user gave up and restarted Tor. + Partly fixes bug 3825. + diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 2fc645af1..b25a71e6b 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1121,6 +1121,9 @@ circuit_expire_all_dirty_circs(void) * to note stats. * - If purpose is C_INTRODUCE_ACK_WAIT, report the intro point * failure we just had to the hidden service client module. + * - If purpose is C_INTRODUCING and reason isn't TIMEOUT, + * report to the hidden service client module that the intro point + * we just tried may be unreachable. * - Send appropriate destroys and edge_destroys for conns and * streams attached to circ. * - If circ->rend_splice is set (we are the midpoint of a joined @@ -1203,6 +1206,19 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, timed_out ? INTRO_POINT_FAILURE_TIMEOUT : INTRO_POINT_FAILURE_GENERIC); + } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING && + reason != END_STREAM_REASON_TIMEOUT) { + origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); + tor_assert(ocirc->build_state->chosen_exit); + tor_assert(ocirc->rend_data); + log_info(LD_REND, "Failed intro circ %s to %s " + "(building circuit to intro point). " + "Marking intro point as possibly unreachable.", + safe_str_client(ocirc->rend_data->onion_address), + safe_str_client(build_state_get_exit_nickname(ocirc->build_state))); + rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit, + ocirc->rend_data, + INTRO_POINT_FAILURE_UNREACHABLE); } if (circ->n_conn) { circuit_clear_cell_queue(circ, circ->n_conn); diff --git a/src/or/or.h b/src/or/or.h index 32d4b112f..f884c12ec 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3456,6 +3456,11 @@ typedef struct rend_encoded_v2_service_descriptor_t { char *desc_str; /**< Descriptor string. */ } rend_encoded_v2_service_descriptor_t; +/** The maximum number of non-circuit-build-timeout failures a hidden + * service client will tolerate while trying to build a circuit to an + * introduction point. See also rend_intro_point_t.unreachable_count. */ +#define MAX_INTRO_POINT_REACHABILITY_FAILURES 5 + /** Introduction point information. Used both in rend_service_t (on * the service side) and in rend_service_descriptor_t (on both the * client and service side). */ @@ -3470,6 +3475,11 @@ typedef struct rend_intro_point_t { * hidden service connection attempt, but it may be tried again * during a future connection attempt. */ unsigned int timed_out : 1; + + /** (Client side only) The number of times we have failed to build a + * circuit to this intro point for some reason other than our + * circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */ + unsigned int unreachable_count : 3; } rend_intro_point_t; /** Information used to connect to a hidden service. Used on both the diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 3c1c116af..0a9e2a605 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -662,6 +662,11 @@ rend_client_cancel_descriptor_fetches(void) * current hidden service connection attempt has ended or it has * appeared in a newly fetched rendezvous descriptor. * + * If failure_type is INTRO_POINT_FAILURE_UNREACHABLE, + * increment the intro point's reachability-failure count; if it has + * now failed MAX_INTRO_POINT_REACHABILITY_FAILURES or more times, + * remove the intro point from (our parsed copy of) the HS descriptor. + * * Return -1 if error, 0 if no usable intro points remain or service * unrecognized, 1 if recognized and some intro points remain. */ @@ -704,6 +709,20 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro, case INTRO_POINT_FAILURE_TIMEOUT: intro->timed_out = 1; break; + case INTRO_POINT_FAILURE_UNREACHABLE: + ++(intro->unreachable_count); + { + int zap_intro_point = + intro->unreachable_count >= MAX_INTRO_POINT_REACHABILITY_FAILURES; + log_info(LD_REND, "Failed to reach this intro point %u times.%s", + intro->unreachable_count, + zap_intro_point ? " Removing from descriptor.": ""); + if (zap_intro_point) { + rend_intro_point_free(intro); + smartlist_del(ent->parsed->intro_nodes, i); + } + } + break; } break; } diff --git a/src/or/rendclient.h b/src/or/rendclient.h index 46779b72f..d87cb1fe3 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -25,6 +25,7 @@ void rend_client_purge_last_hid_serv_requests(void); #define INTRO_POINT_FAILURE_GENERIC 0 #define INTRO_POINT_FAILURE_TIMEOUT 1 +#define INTRO_POINT_FAILURE_UNREACHABLE 2 int rend_client_report_intro_point_failure(extend_info_t *failed_intro, const rend_data_t *rend_query, -- cgit v1.2.3 From c5226bfe1c26d2cbcc789c1074d8d925e7c7fea1 Mon Sep 17 00:00:00 2001 From: Robert Ransom Date: Tue, 20 Sep 2011 04:26:09 -0700 Subject: Remove an HS's last_hid_serv_requests entries when a conn. attempt ends --- changes/bug3335 | 11 +++++++++++ src/or/rendclient.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 changes/bug3335 (limited to 'changes') diff --git a/changes/bug3335 b/changes/bug3335 new file mode 100644 index 000000000..7e1e89866 --- /dev/null +++ b/changes/bug3335 @@ -0,0 +1,11 @@ + o Major bugfixes: + + - When an attempt to connect to a hidden service ends, consider + refetching its hidden service descriptors from each of the HSDir + relays responsible for them immediately. Previously, we would + not consider refetching the service's descriptors from each + HSDir for 15 minutes after the last fetch; this behaviour was + inconvenient if the hidden service was not running during the + first attempt, for example. Bugfix on 0.2.0.18-alpha; fixes bug + 3335. + diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 9088b92b9..e66b2426f 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -469,6 +469,33 @@ directory_clean_last_hid_serv_requests(void) } } +/** Remove all requests related to the hidden service named + * onion_address from the history of times of requests to + * hidden service directories. */ +static void +purge_hid_serv_from_last_hid_serv_requests(const char *onion_address) +{ + strmap_iter_t *iter; + strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); + /* XXX023 tor_assert(strlen(onion_address) == REND_SERVICE_ID_LEN_BASE32); */ + for (iter = strmap_iter_init(last_hid_serv_requests); + !strmap_iter_done(iter); ) { + const char *key; + void *val; + strmap_iter_get(iter, &key, &val); + /* XXX023 tor_assert(strlen(key) == LAST_HID_SERV_REQUEST_KEY_LEN); */ + if (tor_memeq(key + LAST_HID_SERV_REQUEST_KEY_LEN - + REND_SERVICE_ID_LEN_BASE32, + onion_address, + REND_SERVICE_ID_LEN_BASE32)) { + iter = strmap_iter_next_rmv(last_hid_serv_requests, iter); + tor_free(val); + } else { + iter = strmap_iter_next(last_hid_serv_requests, iter); + } + } +} + /** Purge the history of request times to hidden service directories, * so that future lookups of an HS descriptor will not fail because we * accessed all of the HSDir relays responsible for the descriptor @@ -938,6 +965,9 @@ rend_client_note_connection_attempt_ended(const char *onion_address) rend_intro_point_t *, ip, ip->timed_out = 0; ); } + + /* Remove the HS's entries in last_hid_serv_requests. */ + purge_hid_serv_from_last_hid_serv_requests(onion_address); } /** Return a newly allocated extend_info_t* for a randomly chosen introduction -- cgit v1.2.3