diff options
author | Mike Perry <mikeperry-git@torproject.org> | 2017-12-22 06:35:29 +0000 |
---|---|---|
committer | Mike Perry <mikeperry-git@torproject.org> | 2018-01-19 22:21:49 +0000 |
commit | 489628a7e4ae716b78a9515fd36d54cca5353272 (patch) | |
tree | d112aacb3b29d7a7c67d665d12ccff6a91dcf875 /src/or/circuituse.c | |
parent | 86ee771c28777141ee5eec30fa9739a7cec32981 (diff) | |
download | tor-489628a7e4ae716b78a9515fd36d54cca5353272.tar.gz tor-489628a7e4ae716b78a9515fd36d54cca5353272.zip |
Bug 23101: Pre-build HS-specific circuits (instead of general).
Prebuilt circs are 4 hops, since only server side HSDIR and intro circs
are 3 hops, and it is OK if those sometimes take longer to build.
Diffstat (limited to 'src/or/circuituse.c')
-rw-r--r-- | src/or/circuituse.c | 96 |
1 files changed, 89 insertions, 7 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 96eb43162d..5f9567ea16 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -54,6 +54,7 @@ #include "rephist.h" #include "router.h" #include "routerlist.h" +#include "config.h" static void circuit_expire_old_circuits_clientside(void); static void circuit_increment_failure_count(void); @@ -133,6 +134,7 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, } if (purpose == CIRCUIT_PURPOSE_C_GENERAL || + purpose == CIRCUIT_PURPOSE_HS_VANGUARDS || purpose == CIRCUIT_PURPOSE_C_REND_JOINED) { if (circ->timestamp_dirty && circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now) @@ -327,6 +329,7 @@ circuit_get_best(const entry_connection_t *conn, tor_assert(conn); tor_assert(purpose == CIRCUIT_PURPOSE_C_GENERAL || + purpose == CIRCUIT_PURPOSE_HS_VANGUARDS || purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT || @@ -1086,7 +1089,8 @@ circuit_is_available_for_use(const circuit_t *circ) return 0; /* Don't mess with marked circs */ if (circ->timestamp_dirty) return 0; /* Only count clean circs */ - if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL) + if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL && + circ->purpose != CIRCUIT_PURPOSE_HS_VANGUARDS) return 0; /* We only pay attention to general purpose circuits. General purpose circuits are always origin circuits. */ @@ -1198,6 +1202,25 @@ needs_circuits_for_build(int num) return 0; } +/** + * Launch the appropriate type of predicted circuit for hidden + * services, depending on our options. + */ +static void +circuit_launch_predicted_hs_circ(int flags) +{ + /* K.I.S.S. implementation of bug #23101: If we are using + * vanguards or pinned middles, pre-build a specific purpose + * for HS circs. */ + if (circuit_should_use_vanguards(CIRCUIT_PURPOSE_HS_VANGUARDS)) { + circuit_launch(CIRCUIT_PURPOSE_HS_VANGUARDS, flags); + } else { + /* If no vanguards, then no HS-specific prebuilt circuits are needed. + * Normal GENERAL circs are fine */ + circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); + } +} + /** Determine how many circuits we have open that are clean, * Make sure it's enough for all the upcoming behaviors we predict we'll have. * But put an upper bound on the total number of circuits. @@ -1251,7 +1274,7 @@ circuit_predict_and_launch_new(void) "Have %d clean circs (%d internal), need another internal " "circ for my hidden service.", num, num_internal); - circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); + circuit_launch_predicted_hs_circ(flags); return; } @@ -1269,7 +1292,8 @@ circuit_predict_and_launch_new(void) "Have %d clean circs (%d uptime-internal, %d internal), need" " another hidden service circ.", num, num_uptime_internal, num_internal); - circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); + + circuit_launch_predicted_hs_circ(flags); return; } @@ -1466,6 +1490,7 @@ circuit_expire_old_circuits_clientside(void) if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL || circ->purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || circ->purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || + circ->purpose == CIRCUIT_PURPOSE_HS_VANGUARDS || circ->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT || circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || circ->purpose == CIRCUIT_PURPOSE_TESTING || @@ -1737,6 +1762,8 @@ circuit_build_failed(origin_circuit_t *circ) circ->cpath->prev->prev->state == CPATH_STATE_OPEN) { failed_at_last_hop = 1; } + + /* Check if we failed at first hop */ if (circ->cpath && circ->cpath->state != CPATH_STATE_OPEN && ! circ->base_.received_destroy) { @@ -1888,6 +1915,10 @@ have_enough_path_info(int need_exit) int circuit_purpose_is_hidden_service(uint8_t purpose) { + if (purpose == CIRCUIT_PURPOSE_HS_VANGUARDS) { + return 1; + } + /* Client-side purpose */ if (purpose >= CIRCUIT_PURPOSE_C_HS_MIN_ && purpose <= CIRCUIT_PURPOSE_C_HS_MAX_) { @@ -1929,6 +1960,55 @@ circuit_should_use_vanguards(uint8_t purpose) return 0; } +/** + * Return true for the set of conditions for which it is OK to use + * a cannibalized circuit. + * + * Don't cannibalize for onehops, or tor2web, or certain purposes. + */ +static int +circuit_should_cannibalize_to_build(uint8_t purpose_to_build, + int has_extend_info, + int onehop_tunnel, + int need_specific_rp) +{ + + /* Do not try to cannibalize if this is a one hop circuit, or + * is a tor2web/special rp. */ + if (onehop_tunnel || need_specific_rp) { + return 0; + } + + /* Don't try to cannibalize for general purpose circuits that do not + * specify a custom exit. */ + if (purpose_to_build == CIRCUIT_PURPOSE_C_GENERAL && !has_extend_info) { + return 0; + } + + /* Don't cannibalize for testing circuits. We want to see if they + * complete normally. Also don't cannibalize for vanguard-purpose + * circuits, since those are specially pre-built for later + * cannibalization by the actual specific circuit types that need + * vanguards. + */ + if (purpose_to_build == CIRCUIT_PURPOSE_TESTING || + purpose_to_build == CIRCUIT_PURPOSE_HS_VANGUARDS) { + return 0; + } + + /* For vanguards, the server-side intro circ is not cannibalized + * because we pre-build 4 hop HS circuits, and it only needs a 3 hop + * circuit. It is also long-lived, so it is more important that + * it have lower latency than get built fast. + */ + if (circuit_should_use_vanguards(purpose_to_build) && + purpose_to_build == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) { + return 0; + } + + return 1; +} + /** Launch a new circuit with purpose <b>purpose</b> and exit node * <b>extend_info</b> (or NULL to select a random exit node). If flags * contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime. If @@ -1963,10 +2043,12 @@ circuit_launch_by_extend_info(uint8_t purpose, need_specific_rp = 1; } - if ((extend_info || purpose != CIRCUIT_PURPOSE_C_GENERAL) && - purpose != CIRCUIT_PURPOSE_TESTING && - !circuit_should_use_vanguards(purpose) && - !onehop_tunnel && !need_specific_rp) { + /* If we can/should cannibalize another circuit to build this one, + * then do so. */ + if (circuit_should_cannibalize_to_build(purpose, + extend_info != NULL, + onehop_tunnel, + need_specific_rp)) { /* see if there are appropriate circs available to cannibalize. */ /* XXX if we're planning to add a hop, perhaps we want to look for * internal circs rather than exit circs? -RD */ |