Detect and remove unreachable intro points

This commit is contained in:
Robert Ransom 2011-09-17 03:53:07 -07:00
parent 34a6b8b7e5
commit fbea8c8ef1
5 changed files with 54 additions and 0 deletions

8
changes/bug3825a Normal file
View file

@ -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.

View file

@ -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 <b>reason</b> 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);

View file

@ -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

View file

@ -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 <b>failure_type</b> 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;
}

View file

@ -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,