From 3cbc513ae767aa872f690ab23f94535aa121975d Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Wed, 21 Oct 2020 13:50:32 +0300 Subject: [PATCH] Implement support for "v3 rend traffic" stat. --- src/core/or/command.c | 27 +++++++++++++++++++++++++-- src/core/or/or_circuit_st.h | 6 ++++++ src/feature/stats/rephist.c | 14 ++++++++++++++ src/feature/stats/rephist.h | 2 +- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/core/or/command.c b/src/core/or/command.c index 9226309ff7..35dadb9fc8 100644 --- a/src/core/or/command.c +++ b/src/core/or/command.c @@ -331,6 +331,13 @@ command_process_create_cell(cell_t *cell, channel_t *chan) return; } + /* Mark whether this circuit used TAP in case we need to use this + * information for onion service statistics later on. */ + if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_FAST || + create_cell->handshake_type == ONION_HANDSHAKE_TYPE_TAP) { + circ->used_legacy_circuit_handshake = true; + } + if (!channel_is_client(chan)) { /* remember create types we've seen, but don't remember them from * clients, to be extra conservative about client statistics. */ @@ -587,11 +594,27 @@ command_process_relay_cell(cell_t *cell, channel_t *chan) } /* If this is a cell in an RP circuit, count it as part of the - hidden service stats */ + onion service stats */ if (options->HiddenServiceStatistics && !CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->circuit_carries_hs_traffic_stats) { - rep_hist_seen_new_rp_cell(); + /** We need to figure out of this is a v2 or v3 RP circuit to count it + * appropriately. v2 services always use the TAP legacy handshake to + * connect to the RP; we use this feature to distinguish between v2/v3. */ + bool is_v2 = false; + if (TO_OR_CIRCUIT(circ)->used_legacy_circuit_handshake) { + is_v2 = true; + } else if (TO_OR_CIRCUIT(circ)->rend_splice) { + /* If this is a client->RP circuit we need to check the spliced circuit + * (which is the service->RP circuit) to see if it was using TAP and + * hence if it's a v2 circuit. That's because client->RP circuits can + * still use ntor even on v2; but service->RP will always use TAP. */ + or_circuit_t *splice = TO_OR_CIRCUIT(circ)->rend_splice; + if (splice->used_legacy_circuit_handshake) { + is_v2 = true; + } + } + rep_hist_seen_new_rp_cell(is_v2); } } diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h index 4e17b1c143..4da88889ce 100644 --- a/src/core/or/or_circuit_st.h +++ b/src/core/or/or_circuit_st.h @@ -63,6 +63,12 @@ struct or_circuit_t { * statistics. */ unsigned int circuit_carries_hs_traffic_stats : 1; + /** True iff this circuit was made with a CREATE_FAST cell, or a CREATE[2] + * cell with a TAP handshake. If this is the case and this is a rend circuit, + * this is a v2 circuit, otherwise if this is a rend circuit it's a v3 + * circuit. */ + bool used_legacy_circuit_handshake; + /** Number of cells that were removed from circuit queue; reset every * time when writing buffer stats to disk. */ uint32_t processed_cells; diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c index 5858f14245..2ad86ff6d9 100644 --- a/src/feature/stats/rephist.c +++ b/src/feature/stats/rephist.c @@ -1932,6 +1932,20 @@ rep_hist_hsdir_stored_maybe_new_v3_onion(const uint8_t *blinded_key) } } +/** We saw a new HS relay cell: count it! + * If is_v2 is set then it's a v2 RP cell, otherwise it's a v3. */ +void +rep_hist_seen_new_rp_cell(bool is_v2) +{ + log_debug(LD_GENERAL, "New RP cell (%d)", is_v2); + + if (is_v2 && hs_v2_stats) { + hs_v2_stats->rp_v2_relay_cells_seen++; + } else if (!is_v2 && hs_v3_stats && should_collect_v3_stats()) { + hs_v3_stats->rp_v3_relay_cells_seen++; + } +} + /* The number of cells that are supposed to be hidden from the adversary * by adding noise from the Laplace distribution. This value, divided by * EPSILON, is Laplace parameter b. It must be greather than 0. */ diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h index 5873594781..3bb4f996a2 100644 --- a/src/feature/stats/rephist.h +++ b/src/feature/stats/rephist.h @@ -66,7 +66,7 @@ MOCK_DECL(int, rep_hist_get_circuit_handshake_assigned, (uint16_t type)); void rep_hist_hs_v2_stats_init(time_t now); time_t rep_hist_hs_v2_stats_write(time_t now); char *rep_hist_get_hs_v2_stats_string(void); -void rep_hist_seen_new_rp_cell(void); +void rep_hist_seen_new_rp_cell(bool is_v2); void rep_hist_hsdir_stored_maybe_new_v2_onion(const crypto_pk_t *pubkey); time_t rep_hist_hs_v3_stats_write(time_t now);