mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Don't close HS client circs which are 'almost connected' on timeout
This commit is contained in:
parent
c6a8ee36fb
commit
4b13c33c0c
12
changes/bug1297b
Normal file
12
changes/bug1297b
Normal file
@ -0,0 +1,12 @@
|
||||
o Minor bugfixes:
|
||||
|
||||
- Don't close hidden service client circuits which have almost
|
||||
finished connecting to their destination when they reach the
|
||||
normal circuit-build timeout. Previously, we would close
|
||||
introduction circuits which are waiting for an acknowledgement
|
||||
from the introduction-point relay and rendezvous circuits which
|
||||
have been specified in an INTRODUCE1 cell sent to a hidden
|
||||
service after the normal CBT; now, we mark them as 'timed out',
|
||||
and launch another rendezvous attempt in parallel. Fixes part
|
||||
of bug 1297.
|
||||
|
@ -75,6 +75,11 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If this is a timed-out hidden service circuit, skip it. */
|
||||
if (origin_circ->hs_circ_has_timed_out) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
|
||||
purpose == CIRCUIT_PURPOSE_C_REND_JOINED)
|
||||
if (circ->timestamp_dirty &&
|
||||
@ -351,7 +356,9 @@ circuit_expire_building(void)
|
||||
* circuit_build_times_get_initial_timeout() if we haven't computed
|
||||
* custom timeouts yet */
|
||||
struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff,
|
||||
cannibalize_cutoff, close_cutoff, extremely_old_cutoff;
|
||||
cannibalize_cutoff, close_cutoff, extremely_old_cutoff,
|
||||
hs_extremely_old_cutoff;
|
||||
const or_options_t *options = get_options();
|
||||
struct timeval now;
|
||||
cpath_build_state_t *build_state;
|
||||
|
||||
@ -371,6 +378,10 @@ circuit_expire_building(void)
|
||||
SET_CUTOFF(close_cutoff, circ_times.close_ms);
|
||||
SET_CUTOFF(extremely_old_cutoff, circ_times.close_ms*2 + 1000);
|
||||
|
||||
SET_CUTOFF(hs_extremely_old_cutoff,
|
||||
MAX(circ_times.close_ms*2 + 1000,
|
||||
options->SocksTimeout * 1000));
|
||||
|
||||
while (next_circ) {
|
||||
struct timeval cutoff;
|
||||
victim = next_circ;
|
||||
@ -392,6 +403,9 @@ circuit_expire_building(void)
|
||||
else
|
||||
cutoff = general_cutoff;
|
||||
|
||||
if (TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)
|
||||
cutoff = hs_extremely_old_cutoff;
|
||||
|
||||
if (timercmp(&victim->timestamp_created, &cutoff, >))
|
||||
continue; /* it's still young, leave it alone */
|
||||
|
||||
@ -497,6 +511,43 @@ circuit_expire_building(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a hidden-service circuit which is far enough along
|
||||
* in connecting to its destination, and we haven't already
|
||||
* flagged it as 'timed out', flag it as 'timed out' so we'll
|
||||
* launch another intro or rend circ, but don't mark it for close
|
||||
* yet.
|
||||
*
|
||||
* (Circs flagged as 'timed out' are given a much longer timeout
|
||||
* period above, so we won't close them in the next call to
|
||||
* circuit_expire_building.) */
|
||||
if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)) {
|
||||
switch (victim->purpose) {
|
||||
case CIRCUIT_PURPOSE_C_REND_READY:
|
||||
/* We only want to spare a rend circ if it has been specified in
|
||||
* an INTRODUCE1 cell sent to a hidden service. A circ's
|
||||
* pending_final_cpath field is non-NULL iff it is a rend circ
|
||||
* and we have tried to send an INTRODUCE1 cell specifying it.
|
||||
* Thus, if the pending_final_cpath field *is* NULL, then we
|
||||
* want to not spare it. */
|
||||
if (TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
|
||||
NULL)
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
|
||||
case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
|
||||
/* If we have reached this line, we want to spare the circ for now. */
|
||||
log_info(LD_CIRC,"Marking circ %s:%d:%d (state %d:%s, purpose %d) "
|
||||
"as timed-out HS circ",
|
||||
victim->n_conn->_base.address, victim->n_conn->_base.port,
|
||||
victim->n_circ_id,
|
||||
victim->state, circuit_state_to_string(victim->state),
|
||||
victim->purpose);
|
||||
TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (victim->n_conn)
|
||||
log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
|
||||
victim->n_conn->_base.address, victim->n_conn->_base.port,
|
||||
|
@ -2607,6 +2607,13 @@ typedef struct origin_circuit_t {
|
||||
* cannibalized circuits. */
|
||||
unsigned int has_opened : 1;
|
||||
|
||||
/** Set iff this is a hidden-service circuit which has timed out
|
||||
* according to our current circuit-build timeout, but which has
|
||||
* been kept around because it might still succeed in connecting to
|
||||
* its destination, and which is not a fully-connected rendezvous
|
||||
* circuit. */
|
||||
unsigned int hs_circ_has_timed_out : 1;
|
||||
|
||||
/** What commands were sent over this circuit that decremented the
|
||||
* RELAY_EARLY counter? This is for debugging task 878. */
|
||||
uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
|
||||
|
@ -895,6 +895,11 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
|
||||
hop->package_window = circuit_initial_package_window();
|
||||
hop->deliver_window = CIRCWINDOW_START;
|
||||
|
||||
/* Now that this circuit has finished connecting to its destination,
|
||||
* make sure circuit_get_open_circ_or_launch is willing to return it
|
||||
* so we can actually use it. */
|
||||
circ->hs_circ_has_timed_out = 0;
|
||||
|
||||
onion_append_to_cpath(&circ->cpath, hop);
|
||||
circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user