mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 22:58:50 +01:00
Detect and remove unreachable intro points
This commit is contained in:
parent
34a6b8b7e5
commit
fbea8c8ef1
5 changed files with 54 additions and 0 deletions
8
changes/bug3825a
Normal file
8
changes/bug3825a
Normal 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.
|
||||
|
|
@ -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);
|
||||
|
|
10
src/or/or.h
10
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue