Loading changes/bug4700 0 → 100644 +5 −0 Original line number Diff line number Diff line o Minor features (onion services): - Version 3 onion services can now use the per-service HiddenServiceExportCircuitID option to differentiate client circuits by using the HAProxy proxy protocol which assigns IP addresses to inbound client circuits. Closes ticket 4700. Patch by Mahrud Sayrafi. src/app/config/config.c +1 −0 Original line number Diff line number Diff line Loading @@ -457,6 +457,7 @@ static config_var_t option_vars_[] = { VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), V(HidServAuth, LINELIST, NULL), V(ClientOnionAuthDir, FILENAME, NULL), Loading src/core/or/connection_edge.c +32 −20 Original line number Diff line number Diff line Loading @@ -597,6 +597,33 @@ connected_cell_format_payload(uint8_t *payload_out, return connected_payload_len; } /* DOCDOCDOC */ static void send_ha_proxy_header(const edge_connection_t *edge_conn, connection_t *conn) { char buf[512]; char dst_ipv6[39] = "::1"; /* See RFC4193 regarding fc00::/7 */ char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:"; /* TODO: retain virtual port and use as destination port */ uint16_t dst_port = 443; uint16_t src_port = 0; uint32_t gid = 0; if (edge_conn->on_circuit != NULL) { gid = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit)->global_identifier; src_port = gid & 0x0000ffff; } gid = (gid == 0) ? 1 : gid; src_port = (src_port == 0) ? 1 : src_port; tor_snprintf(buf, sizeof(buf), "PROXY TCP6 %s:%x %s %d %d\r\n", src_ipv6_prefix, gid, dst_ipv6, src_port, dst_port); connection_buf_add(buf, strlen(buf), conn); } /** Connected handler for exit connections: start writing pending * data, deliver 'CONNECTED' relay cells as appropriate, and check * any pending data that may have been received. */ Loading @@ -618,28 +645,13 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) conn->state = EXIT_CONN_STATE_OPEN; /* Include Proxy Protocol header. */ char buf[512]; char dst_ipv6[39] = "::1"; /* See RFC4193 regarding fc00::/7 */ char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:"; /* TODO: retain virtual port and use as destination port */ uint16_t dst_port = 443; uint16_t src_port = 0; uint32_t gid = 0; if (edge_conn->on_circuit != NULL) { gid = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit)->global_identifier; src_port = gid & 0x0000ffff; /* If it's an onion service connection, we might want to include the proxy * protocol header */ if (edge_conn->hs_ident && hs_service_exports_circuit_id(&edge_conn->hs_ident->identity_pk)) { send_ha_proxy_header(edge_conn, conn); } gid = (gid == 0) ? 1 : gid; src_port = (src_port == 0) ? 1 : src_port; tor_snprintf(buf, sizeof(buf), "PROXY TCP6 %s:%x %s %d %d\r\n", src_ipv6_prefix, gid, dst_ipv6, src_port, dst_port); connection_buf_add(buf, strlen(buf), conn); connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay * cells */ Loading src/feature/hs/hs_config.c +19 −1 Original line number Diff line number Diff line Loading @@ -188,6 +188,11 @@ config_has_invalid_options(const config_line_t *line_, NULL /* End marker. */ }; const char *opts_exclude_v2[] = { "HiddenServiceExportCircuitID", NULL /* End marker. */ }; /* Defining the size explicitly allows us to take advantage of the compiler * which warns us if we ever bump the max version but forget to grow this * array. The plus one is because we have a version 0 :). */ Loading @@ -196,7 +201,7 @@ config_has_invalid_options(const config_line_t *line_, } exclude_lists[HS_VERSION_MAX + 1] = { { NULL }, /* v0. */ { NULL }, /* v1. */ { NULL }, /* v2 */ { opts_exclude_v2 }, /* v2 */ { opts_exclude_v3 }, /* v3. */ }; Loading Loading @@ -262,6 +267,7 @@ config_service_v3(const config_line_t *line_, hs_service_config_t *config) { int have_num_ip = 0; bool export_circuit_id = false; /* just to detect duplicate options */ const char *dup_opt_seen = NULL; const config_line_t *line; Loading @@ -288,6 +294,18 @@ config_service_v3(const config_line_t *line_, have_num_ip = 1; continue; } if (!strcasecmp(line->key, "HiddenServiceExportCircuitID")) { config->export_circuit_id = (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok); if (!ok || export_circuit_id) { if (export_circuit_id) { dup_opt_seen = line->key; } goto err; } export_circuit_id = true; continue; } } /* We do not load the key material for the service at this stage. This is Loading src/feature/hs/hs_service.c +13 −0 Original line number Diff line number Diff line Loading @@ -3762,6 +3762,19 @@ hs_service_set_conn_addr_port(const origin_circuit_t *circ, return -1; } /** Does the service with identity pubkey <b>pk</b> export the circuit IDs of * its clients? */ bool hs_service_exports_circuit_id(const ed25519_public_key_t *pk) { hs_service_t *service = find_service(hs_service_map, pk); if (!service) { return 0; } return service->config.export_circuit_id; } /* Add to file_list every filename used by a configured hidden service, and to * dir_list every directory path used by a configured hidden service. This is * used by the sandbox subsystem to whitelist those. */ Loading Loading
changes/bug4700 0 → 100644 +5 −0 Original line number Diff line number Diff line o Minor features (onion services): - Version 3 onion services can now use the per-service HiddenServiceExportCircuitID option to differentiate client circuits by using the HAProxy proxy protocol which assigns IP addresses to inbound client circuits. Closes ticket 4700. Patch by Mahrud Sayrafi.
src/app/config/config.c +1 −0 Original line number Diff line number Diff line Loading @@ -457,6 +457,7 @@ static config_var_t option_vars_[] = { VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), V(HidServAuth, LINELIST, NULL), V(ClientOnionAuthDir, FILENAME, NULL), Loading
src/core/or/connection_edge.c +32 −20 Original line number Diff line number Diff line Loading @@ -597,6 +597,33 @@ connected_cell_format_payload(uint8_t *payload_out, return connected_payload_len; } /* DOCDOCDOC */ static void send_ha_proxy_header(const edge_connection_t *edge_conn, connection_t *conn) { char buf[512]; char dst_ipv6[39] = "::1"; /* See RFC4193 regarding fc00::/7 */ char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:"; /* TODO: retain virtual port and use as destination port */ uint16_t dst_port = 443; uint16_t src_port = 0; uint32_t gid = 0; if (edge_conn->on_circuit != NULL) { gid = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit)->global_identifier; src_port = gid & 0x0000ffff; } gid = (gid == 0) ? 1 : gid; src_port = (src_port == 0) ? 1 : src_port; tor_snprintf(buf, sizeof(buf), "PROXY TCP6 %s:%x %s %d %d\r\n", src_ipv6_prefix, gid, dst_ipv6, src_port, dst_port); connection_buf_add(buf, strlen(buf), conn); } /** Connected handler for exit connections: start writing pending * data, deliver 'CONNECTED' relay cells as appropriate, and check * any pending data that may have been received. */ Loading @@ -618,28 +645,13 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) conn->state = EXIT_CONN_STATE_OPEN; /* Include Proxy Protocol header. */ char buf[512]; char dst_ipv6[39] = "::1"; /* See RFC4193 regarding fc00::/7 */ char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:"; /* TODO: retain virtual port and use as destination port */ uint16_t dst_port = 443; uint16_t src_port = 0; uint32_t gid = 0; if (edge_conn->on_circuit != NULL) { gid = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit)->global_identifier; src_port = gid & 0x0000ffff; /* If it's an onion service connection, we might want to include the proxy * protocol header */ if (edge_conn->hs_ident && hs_service_exports_circuit_id(&edge_conn->hs_ident->identity_pk)) { send_ha_proxy_header(edge_conn, conn); } gid = (gid == 0) ? 1 : gid; src_port = (src_port == 0) ? 1 : src_port; tor_snprintf(buf, sizeof(buf), "PROXY TCP6 %s:%x %s %d %d\r\n", src_ipv6_prefix, gid, dst_ipv6, src_port, dst_port); connection_buf_add(buf, strlen(buf), conn); connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay * cells */ Loading
src/feature/hs/hs_config.c +19 −1 Original line number Diff line number Diff line Loading @@ -188,6 +188,11 @@ config_has_invalid_options(const config_line_t *line_, NULL /* End marker. */ }; const char *opts_exclude_v2[] = { "HiddenServiceExportCircuitID", NULL /* End marker. */ }; /* Defining the size explicitly allows us to take advantage of the compiler * which warns us if we ever bump the max version but forget to grow this * array. The plus one is because we have a version 0 :). */ Loading @@ -196,7 +201,7 @@ config_has_invalid_options(const config_line_t *line_, } exclude_lists[HS_VERSION_MAX + 1] = { { NULL }, /* v0. */ { NULL }, /* v1. */ { NULL }, /* v2 */ { opts_exclude_v2 }, /* v2 */ { opts_exclude_v3 }, /* v3. */ }; Loading Loading @@ -262,6 +267,7 @@ config_service_v3(const config_line_t *line_, hs_service_config_t *config) { int have_num_ip = 0; bool export_circuit_id = false; /* just to detect duplicate options */ const char *dup_opt_seen = NULL; const config_line_t *line; Loading @@ -288,6 +294,18 @@ config_service_v3(const config_line_t *line_, have_num_ip = 1; continue; } if (!strcasecmp(line->key, "HiddenServiceExportCircuitID")) { config->export_circuit_id = (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &ok); if (!ok || export_circuit_id) { if (export_circuit_id) { dup_opt_seen = line->key; } goto err; } export_circuit_id = true; continue; } } /* We do not load the key material for the service at this stage. This is Loading
src/feature/hs/hs_service.c +13 −0 Original line number Diff line number Diff line Loading @@ -3762,6 +3762,19 @@ hs_service_set_conn_addr_port(const origin_circuit_t *circ, return -1; } /** Does the service with identity pubkey <b>pk</b> export the circuit IDs of * its clients? */ bool hs_service_exports_circuit_id(const ed25519_public_key_t *pk) { hs_service_t *service = find_service(hs_service_map, pk); if (!service) { return 0; } return service->config.export_circuit_id; } /* Add to file_list every filename used by a configured hidden service, and to * dir_list every directory path used by a configured hidden service. This is * used by the sandbox subsystem to whitelist those. */ Loading