mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-24 22:58:50 +01:00
Introduce per-service HiddenServiceExportCircuitID torrc option.
Moves code to a function, better viewed with --color-moved.
This commit is contained in:
parent
be142194cd
commit
27d7491f5a
6 changed files with 75 additions and 21 deletions
5
changes/bug4700
Normal file
5
changes/bug4700
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
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.
|
|
@ -457,6 +457,7 @@ static config_var_t option_vars_[] = {
|
||||||
VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL),
|
VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL),
|
||||||
VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
|
VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
|
||||||
VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL),
|
VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL),
|
||||||
|
VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL),
|
||||||
VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"),
|
VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"),
|
||||||
V(HidServAuth, LINELIST, NULL),
|
V(HidServAuth, LINELIST, NULL),
|
||||||
V(ClientOnionAuthDir, FILENAME, NULL),
|
V(ClientOnionAuthDir, FILENAME, NULL),
|
||||||
|
|
|
@ -597,6 +597,33 @@ connected_cell_format_payload(uint8_t *payload_out,
|
||||||
return connected_payload_len;
|
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
|
/** Connected handler for exit connections: start writing pending
|
||||||
* data, deliver 'CONNECTED' relay cells as appropriate, and check
|
* data, deliver 'CONNECTED' relay cells as appropriate, and check
|
||||||
* any pending data that may have been received. */
|
* any pending data that may have been received. */
|
||||||
|
@ -618,28 +645,13 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
|
||||||
|
|
||||||
conn->state = EXIT_CONN_STATE_OPEN;
|
conn->state = EXIT_CONN_STATE_OPEN;
|
||||||
|
|
||||||
/* Include Proxy Protocol header. */
|
/* If it's an onion service connection, we might want to include the proxy
|
||||||
char buf[512];
|
* protocol header */
|
||||||
char dst_ipv6[39] = "::1";
|
if (edge_conn->hs_ident &&
|
||||||
/* See RFC4193 regarding fc00::/7 */
|
hs_service_exports_circuit_id(&edge_conn->hs_ident->identity_pk)) {
|
||||||
char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:";
|
send_ha_proxy_header(edge_conn, conn);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
|
connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
|
||||||
if (connection_get_outbuf_len(conn)) /* in case there are any queued relay
|
if (connection_get_outbuf_len(conn)) /* in case there are any queued relay
|
||||||
* cells */
|
* cells */
|
||||||
|
|
|
@ -188,6 +188,11 @@ config_has_invalid_options(const config_line_t *line_,
|
||||||
NULL /* End marker. */
|
NULL /* End marker. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *opts_exclude_v2[] = {
|
||||||
|
"HiddenServiceExportCircuitID",
|
||||||
|
NULL /* End marker. */
|
||||||
|
};
|
||||||
|
|
||||||
/* Defining the size explicitly allows us to take advantage of the compiler
|
/* 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
|
* 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 :). */
|
* array. The plus one is because we have a version 0 :). */
|
||||||
|
@ -196,7 +201,7 @@ config_has_invalid_options(const config_line_t *line_,
|
||||||
} exclude_lists[HS_VERSION_MAX + 1] = {
|
} exclude_lists[HS_VERSION_MAX + 1] = {
|
||||||
{ NULL }, /* v0. */
|
{ NULL }, /* v0. */
|
||||||
{ NULL }, /* v1. */
|
{ NULL }, /* v1. */
|
||||||
{ NULL }, /* v2 */
|
{ opts_exclude_v2 }, /* v2 */
|
||||||
{ opts_exclude_v3 }, /* v3. */
|
{ opts_exclude_v3 }, /* v3. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -262,6 +267,7 @@ config_service_v3(const config_line_t *line_,
|
||||||
hs_service_config_t *config)
|
hs_service_config_t *config)
|
||||||
{
|
{
|
||||||
int have_num_ip = 0;
|
int have_num_ip = 0;
|
||||||
|
bool export_circuit_id = false; /* just to detect duplicate options */
|
||||||
const char *dup_opt_seen = NULL;
|
const char *dup_opt_seen = NULL;
|
||||||
const config_line_t *line;
|
const config_line_t *line;
|
||||||
|
|
||||||
|
@ -288,6 +294,18 @@ config_service_v3(const config_line_t *line_,
|
||||||
have_num_ip = 1;
|
have_num_ip = 1;
|
||||||
continue;
|
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
|
/* We do not load the key material for the service at this stage. This is
|
||||||
|
|
|
@ -3762,6 +3762,19 @@ hs_service_set_conn_addr_port(const origin_circuit_t *circ,
|
||||||
return -1;
|
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
|
/* 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
|
* dir_list every directory path used by a configured hidden service. This is
|
||||||
* used by the sandbox subsystem to whitelist those. */
|
* used by the sandbox subsystem to whitelist those. */
|
||||||
|
|
|
@ -210,6 +210,9 @@ typedef struct hs_service_config_t {
|
||||||
|
|
||||||
/* Is this service ephemeral? */
|
/* Is this service ephemeral? */
|
||||||
unsigned int is_ephemeral : 1;
|
unsigned int is_ephemeral : 1;
|
||||||
|
|
||||||
|
/* Does this service export the circuit ID of its clients? */
|
||||||
|
bool export_circuit_id;
|
||||||
} hs_service_config_t;
|
} hs_service_config_t;
|
||||||
|
|
||||||
/* Service state. */
|
/* Service state. */
|
||||||
|
@ -316,6 +319,8 @@ void hs_service_upload_desc_to_dir(const char *encoded_desc,
|
||||||
const ed25519_public_key_t *blinded_pk,
|
const ed25519_public_key_t *blinded_pk,
|
||||||
const routerstatus_t *hsdir_rs);
|
const routerstatus_t *hsdir_rs);
|
||||||
|
|
||||||
|
bool hs_service_exports_circuit_id(const ed25519_public_key_t *pk);
|
||||||
|
|
||||||
#ifdef HS_SERVICE_PRIVATE
|
#ifdef HS_SERVICE_PRIVATE
|
||||||
|
|
||||||
#ifdef TOR_UNIT_TESTS
|
#ifdef TOR_UNIT_TESTS
|
||||||
|
|
Loading…
Add table
Reference in a new issue