diff options
author | Mike Perry <mikeperry-git@torproject.org> | 2017-12-02 02:28:16 +0000 |
---|---|---|
committer | Mike Perry <mikeperry-git@torproject.org> | 2018-01-19 22:21:48 +0000 |
commit | 86ee771c28777141ee5eec30fa9739a7cec32981 (patch) | |
tree | 039b7b171a38052c4fae2e92b3b4de7a46c453a4 | |
parent | 20a3f611057cb81c489ccf9d40438bc5d930d766 (diff) | |
download | tor-86ee771c28777141ee5eec30fa9739a7cec32981.tar.gz tor-86ee771c28777141ee5eec30fa9739a7cec32981.zip |
Add new circuit purposes for hsdir activity.
This lets us control their path len and usage.
-rw-r--r-- | src/or/circuitbuild.c | 13 | ||||
-rw-r--r-- | src/or/circuitlist.c | 14 | ||||
-rw-r--r-- | src/or/circuituse.c | 76 | ||||
-rw-r--r-- | src/or/connection_edge.c | 2 | ||||
-rw-r--r-- | src/or/or.h | 29 |
5 files changed, 113 insertions, 21 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 707654adf2..680b32953f 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1662,11 +1662,14 @@ route_len_for_purpose(uint8_t purpose, extend_info_t *exit_ei) if (circuit_should_use_vanguards(purpose)) { /* Clients want an extra hop for rends to avoid linkability. * Services want it for intro points to avoid publishing their - * layer3 guards. + * layer3 guards. They want it for hsdir posts to use + * their full layer3 guard set for those connections. * Ex: C - G - L2 - L3 - R + * S - G - L2 - L3 - HSDIR * S - G - L2 - L3 - I */ if (purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND || + purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) return routelen+1; @@ -1683,9 +1686,11 @@ route_len_for_purpose(uint8_t purpose, extend_info_t *exit_ei) * Same goes for intro points. Note that the route len * includes the intro point or hsdir, hence the +2. * Ex: C - G - L2 - L3 - M - I + * C - G - L2 - L3 - M - HSDIR * S - G - L2 - L3 - M - R */ if (purpose == CIRCUIT_PURPOSE_S_CONNECT_REND || + purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || purpose == CIRCUIT_PURPOSE_C_INTRODUCING) return routelen+2; } @@ -1706,6 +1711,8 @@ route_len_for_purpose(uint8_t purpose, extend_info_t *exit_ei) /* These three purposes connect to a router that someone else * might have chosen, so add an extra hop to protect anonymity. */ case CIRCUIT_PURPOSE_C_GENERAL: + case CIRCUIT_PURPOSE_C_HSDIR_GET: + case CIRCUIT_PURPOSE_S_HSDIR_POST: /* connecting to hidden service directory */ case CIRCUIT_PURPOSE_C_INTRODUCING: /* client connecting to introduction point */ @@ -2271,6 +2278,8 @@ choose_good_exit_server(uint8_t purpose, flags |= CRN_RENDEZVOUS_V3; switch (purpose) { + case CIRCUIT_PURPOSE_C_HSDIR_GET: + case CIRCUIT_PURPOSE_S_HSDIR_POST: case CIRCUIT_PURPOSE_C_GENERAL: if (is_internal) /* pick it like a middle hop */ return router_choose_random_node(NULL, options->ExcludeNodes, flags); @@ -2315,6 +2324,8 @@ warn_if_last_router_excluded(origin_circuit_t *circ, (int)purpose, circuit_purpose_to_string(purpose)); return; + case CIRCUIT_PURPOSE_S_HSDIR_POST: + case CIRCUIT_PURPOSE_C_HSDIR_GET: case CIRCUIT_PURPOSE_C_GENERAL: if (circ->build_state->is_internal) return; diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 028fdbfc2f..03e1a71074 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -689,6 +689,10 @@ circuit_purpose_to_controller_string(uint8_t purpose) case CIRCUIT_PURPOSE_C_GENERAL: return "GENERAL"; + + case CIRCUIT_PURPOSE_C_HSDIR_GET: + return "HS_CLIENT_HSDIR"; + case CIRCUIT_PURPOSE_C_INTRODUCING: case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: case CIRCUIT_PURPOSE_C_INTRODUCE_ACKED: @@ -700,6 +704,9 @@ circuit_purpose_to_controller_string(uint8_t purpose) case CIRCUIT_PURPOSE_C_REND_JOINED: return "HS_CLIENT_REND"; + case CIRCUIT_PURPOSE_S_HSDIR_POST: + return "HS_SERVICE_HSDIR"; + case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: case CIRCUIT_PURPOSE_S_INTRO: return "HS_SERVICE_INTRO"; @@ -753,6 +760,7 @@ circuit_purpose_to_controller_hs_state_string(uint8_t purpose) case CIRCUIT_PURPOSE_REND_ESTABLISHED: return "OR_HS_R_JOINED"; + case CIRCUIT_PURPOSE_C_HSDIR_GET: case CIRCUIT_PURPOSE_C_INTRODUCING: return "HSCI_CONNECTING"; case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT: @@ -769,6 +777,7 @@ circuit_purpose_to_controller_hs_state_string(uint8_t purpose) case CIRCUIT_PURPOSE_C_REND_JOINED: return "HSCR_JOINED"; + case CIRCUIT_PURPOSE_S_HSDIR_POST: case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: return "HSSI_CONNECTING"; case CIRCUIT_PURPOSE_S_INTRO: @@ -813,6 +822,9 @@ circuit_purpose_to_string(uint8_t purpose) return "Hidden service client: Pending rendezvous point (ack received)"; case CIRCUIT_PURPOSE_C_REND_JOINED: return "Hidden service client: Active rendezvous point"; + case CIRCUIT_PURPOSE_C_HSDIR_GET: + return "Hidden service client: Fetching HS descriptor"; + case CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT: return "Measuring circuit timeout"; @@ -824,6 +836,8 @@ circuit_purpose_to_string(uint8_t purpose) return "Hidden service: Connecting to rendezvous point"; case CIRCUIT_PURPOSE_S_REND_JOINED: return "Hidden service: Active rendezvous point"; + case CIRCUIT_PURPOSE_S_HSDIR_POST: + return "Hidden service: Uploading HS descriptor"; case CIRCUIT_PURPOSE_TESTING: return "Testing circuit"; diff --git a/src/or/circuituse.c b/src/or/circuituse.c index e7be8fa22a..96eb43162d 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -156,7 +156,9 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, if (need_internal != build_state->is_internal) return 0; - if (purpose == CIRCUIT_PURPOSE_C_GENERAL) { + if (purpose == CIRCUIT_PURPOSE_C_GENERAL || + purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || + purpose == CIRCUIT_PURPOSE_C_HSDIR_GET) { tor_addr_t addr; const int family = tor_addr_parse(&addr, conn->socks_request->address); if (!exitnode && !build_state->onehop_tunnel) { @@ -238,6 +240,8 @@ circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob, return 1; /* oa is better. It's not relaxed. */ switch (purpose) { + case CIRCUIT_PURPOSE_S_HSDIR_POST: + case CIRCUIT_PURPOSE_C_HSDIR_GET: case CIRCUIT_PURPOSE_C_GENERAL: /* if it's used but less dirty it's best; * else if it's more recently created it's best @@ -323,6 +327,8 @@ circuit_get_best(const entry_connection_t *conn, tor_assert(conn); tor_assert(purpose == CIRCUIT_PURPOSE_C_GENERAL || + purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || + purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT || purpose == CIRCUIT_PURPOSE_C_REND_JOINED); @@ -1458,6 +1464,8 @@ circuit_expire_old_circuits_clientside(void) } else if (!circ->timestamp_dirty && circ->state == CIRCUIT_STATE_OPEN) { if (timercmp(&circ->timestamp_began, &cutoff, OP_LT)) { 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_C_MEASURE_TIMEOUT || circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO || circ->purpose == CIRCUIT_PURPOSE_TESTING || @@ -1650,6 +1658,8 @@ circuit_has_opened(origin_circuit_t *circ) hs_client_circuit_has_opened(circ); break; case CIRCUIT_PURPOSE_C_GENERAL: + case CIRCUIT_PURPOSE_C_HSDIR_GET: + case CIRCUIT_PURPOSE_S_HSDIR_POST: /* Tell any AP connections that have been waiting for a new * circuit that one is ready. */ circuit_try_attaching_streams(circ); @@ -1786,6 +1796,8 @@ circuit_build_failed(origin_circuit_t *circ) } switch (circ->base_.purpose) { + case CIRCUIT_PURPOSE_C_HSDIR_GET: + case CIRCUIT_PURPOSE_S_HSDIR_POST: case CIRCUIT_PURPOSE_C_GENERAL: /* If we never built the circuit, note it as a failure. */ circuit_increment_failure_count(); @@ -1877,14 +1889,14 @@ int circuit_purpose_is_hidden_service(uint8_t purpose) { /* Client-side purpose */ - if (purpose >= CIRCUIT_PURPOSE_C_INTRODUCING && - purpose <= CIRCUIT_PURPOSE_C_REND_JOINED) { + if (purpose >= CIRCUIT_PURPOSE_C_HS_MIN_ && + purpose <= CIRCUIT_PURPOSE_C_HS_MAX_) { return 1; } /* Service-side purpose */ - if (purpose >= CIRCUIT_PURPOSE_S_ESTABLISH_INTRO && - purpose <= CIRCUIT_PURPOSE_S_REND_JOINED) { + if (purpose >= CIRCUIT_PURPOSE_S_HS_MIN_ && + purpose <= CIRCUIT_PURPOSE_S_HS_MAX_) { return 1; } @@ -2009,6 +2021,8 @@ circuit_launch_by_extend_info(uint8_t purpose, case CIRCUIT_PURPOSE_C_INTRODUCING: case CIRCUIT_PURPOSE_S_CONNECT_REND: case CIRCUIT_PURPOSE_C_GENERAL: + case CIRCUIT_PURPOSE_S_HSDIR_POST: + case CIRCUIT_PURPOSE_C_HSDIR_GET: case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: /* need to add a new hop */ tor_assert(extend_info); @@ -2273,7 +2287,9 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, /* If we have specified a particular exit node for our * connection, then be sure to open a circuit to that exit node. */ - if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) { + if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL || + desired_circuit_purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || + desired_circuit_purpose == CIRCUIT_PURPOSE_C_HSDIR_GET) { if (conn->chosen_exit_name) { const node_t *r; int opt = conn->chosen_exit_optional; @@ -2381,7 +2397,9 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, /* Now trigger things that need to happen when we launch circuits */ - if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) { + if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL || + desired_circuit_purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || + desired_circuit_purpose == CIRCUIT_PURPOSE_S_HSDIR_POST) { /* We just caused a circuit to get built because of this stream. * If this stream has caused a _lot_ of circuits to be built, that's * a bad sign: we should tell the user. */ @@ -2510,6 +2528,8 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, /* See if we can use optimistic data on this circuit */ if (optimistic_data_enabled() && (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL || + circ->base_.purpose == CIRCUIT_PURPOSE_C_HSDIR_GET || + circ->base_.purpose == CIRCUIT_PURPOSE_S_HSDIR_POST || circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED)) apconn->may_use_optimistic_data = 1; else @@ -2630,6 +2650,39 @@ connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn, return 1; } +/** + * Return an appropriate circuit purpose for non-rend streams. + * We don't handle rends here because a rend stream triggers two + * circuit builds with different purposes, so it is handled elsewhere. + * + * This function just figures out what type of hsdir activity this is, + * and tells us. Everything else is general. + */ +static int +connection_ap_get_nonrend_circ_purpose(const entry_connection_t *conn) +{ + const connection_t *base_conn = ENTRY_TO_CONN(conn); + tor_assert_nonfatal(!connection_edge_is_rendezvous_stream( + ENTRY_TO_EDGE_CONN(conn))); + + if (base_conn->linked_conn && + base_conn->linked_conn->type == CONN_TYPE_DIR) { + /* Set a custom purpose for hsdir activity */ + if (base_conn->linked_conn->purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2 || + base_conn->linked_conn->purpose == DIR_PURPOSE_UPLOAD_HSDESC) { + return CIRCUIT_PURPOSE_S_HSDIR_POST; + } else if (base_conn->linked_conn->purpose + == DIR_PURPOSE_FETCH_RENDDESC_V2 || + base_conn->linked_conn->purpose + == DIR_PURPOSE_FETCH_HSDESC) { + return CIRCUIT_PURPOSE_C_HSDIR_GET; + } + } + + /* All other purposes are general for now */ + return CIRCUIT_PURPOSE_C_GENERAL; +} + /** Try to find a safe live circuit for stream <b>conn</b>. If we find one, * attach the stream, send appropriate cells, and return 1. Otherwise, * try to launch new circuit(s) for the stream. If we can launch @@ -2728,9 +2781,12 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn) } /* Find the circuit that we should use, if there is one. Otherwise - * launch it. */ - retval = circuit_get_open_circ_or_launch( - conn, CIRCUIT_PURPOSE_C_GENERAL, &circ); + * launch it + */ + retval = circuit_get_open_circ_or_launch(conn, + connection_ap_get_nonrend_circ_purpose(conn), + &circ); + if (retval < 1) { /* We were either told "-1" (complete failure) or 0 (circuit in * progress); we can't attach this stream yet. */ diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 0c4352ea13..4021ca9e0c 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -2592,6 +2592,8 @@ connection_ap_supports_optimistic_data(const entry_connection_t *conn) if (edge_conn->on_circuit == NULL || edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN || (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL && + edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_HSDIR_GET && + edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_S_HSDIR_POST && edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)) return 0; diff --git a/src/or/or.h b/src/or/or.h index 54e9786c75..b878ef8fd4 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -506,6 +506,7 @@ typedef enum { */ /** Client-side circuit purpose: Normal circuit, with cpath. */ #define CIRCUIT_PURPOSE_C_GENERAL 5 +#define CIRCUIT_PURPOSE_C_HS_MIN_ 6 /** Client-side circuit purpose: at the client, connecting to intro point. */ #define CIRCUIT_PURPOSE_C_INTRODUCING 6 /** Client-side circuit purpose: at the client, sent INTRODUCE1 to intro point, @@ -523,28 +524,36 @@ typedef enum { #define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 11 /** Client-side circuit purpose: at the client, rendezvous established. */ #define CIRCUIT_PURPOSE_C_REND_JOINED 12 +/** This circuit is used for getting hsdirs */ +#define CIRCUIT_PURPOSE_C_HSDIR_GET 13 +#define CIRCUIT_PURPOSE_C_HS_MAX_ 13 /** This circuit is used for build time measurement only */ -#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 13 -#define CIRCUIT_PURPOSE_C_MAX_ 13 +#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 14 +#define CIRCUIT_PURPOSE_C_MAX_ 14 + +#define CIRCUIT_PURPOSE_S_HS_MIN_ 15 /** Hidden-service-side circuit purpose: at the service, waiting for * introductions. */ -#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 14 +#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 15 /** Hidden-service-side circuit purpose: at the service, successfully * established intro. */ -#define CIRCUIT_PURPOSE_S_INTRO 15 +#define CIRCUIT_PURPOSE_S_INTRO 16 /** Hidden-service-side circuit purpose: at the service, connecting to rend * point. */ -#define CIRCUIT_PURPOSE_S_CONNECT_REND 16 +#define CIRCUIT_PURPOSE_S_CONNECT_REND 17 /** Hidden-service-side circuit purpose: at the service, rendezvous * established. */ -#define CIRCUIT_PURPOSE_S_REND_JOINED 17 +#define CIRCUIT_PURPOSE_S_REND_JOINED 18 +/** This circuit is used for uploading hsdirs */ +#define CIRCUIT_PURPOSE_S_HSDIR_POST 19 +#define CIRCUIT_PURPOSE_S_HS_MAX_ 19 /** A testing circuit; not meant to be used for actual traffic. */ -#define CIRCUIT_PURPOSE_TESTING 18 +#define CIRCUIT_PURPOSE_TESTING 20 /** A controller made this circuit and Tor should not use it. */ -#define CIRCUIT_PURPOSE_CONTROLLER 19 +#define CIRCUIT_PURPOSE_CONTROLLER 21 /** This circuit is used for path bias probing only */ -#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 20 -#define CIRCUIT_PURPOSE_MAX_ 20 +#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 22 +#define CIRCUIT_PURPOSE_MAX_ 22 /** A catch-all for unrecognized purposes. Currently we don't expect * to make or see any circuits with this purpose. */ #define CIRCUIT_PURPOSE_UNKNOWN 255 |