[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] Introduce per-service HiddenServiceExportCircuitID torrc option.
commit 27d7491f5a761c58fc687f0b816b80ff9f7a1a1d
Author: George Kadianakis <desnacked@xxxxxxxxxx>
Date: Wed Sep 12 14:40:19 2018 +0300
Introduce per-service HiddenServiceExportCircuitID torrc option.
Moves code to a function, better viewed with --color-moved.
---
changes/bug4700 | 5 +++++
src/app/config/config.c | 1 +
src/core/or/connection_edge.c | 52 ++++++++++++++++++++++++++-----------------
src/feature/hs/hs_config.c | 20 ++++++++++++++++-
src/feature/hs/hs_service.c | 13 +++++++++++
src/feature/hs/hs_service.h | 5 +++++
6 files changed, 75 insertions(+), 21 deletions(-)
diff --git a/changes/bug4700 b/changes/bug4700
new file mode 100644
index 000000000..3c8d9b19b
--- /dev/null
+++ b/changes/bug4700
@@ -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.
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 1adeb75c9..13421f103 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -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),
diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c
index a85419376..8b333a6f4 100644
--- a/src/core/or/connection_edge.c
+++ b/src/core/or/connection_edge.c
@@ -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. */
@@ -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 */
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index eaeb58829..16bfe7c54 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -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 :). */
@@ -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. */
};
@@ -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;
@@ -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
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 30d23eb77..75d7cb75e 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -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. */
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 735266071..e541cb28b 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -210,6 +210,9 @@ typedef struct hs_service_config_t {
/* Is this service ephemeral? */
unsigned int is_ephemeral : 1;
+
+ /* Does this service export the circuit ID of its clients? */
+ bool export_circuit_id;
} hs_service_config_t;
/* 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 routerstatus_t *hsdir_rs);
+bool hs_service_exports_circuit_id(const ed25519_public_key_t *pk);
+
#ifdef HS_SERVICE_PRIVATE
#ifdef TOR_UNIT_TESTS
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits