mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
metrics: Add metrics for rendezvous and introduction request failures.
This introduces a couple of new service side metrics: * `hs_intro_rejected_intro_req_count`, which counts the number of introduction requests rejected by the hidden service * `hs_rdv_error_count`, which counts the number of rendezvous errors as seen by the hidden service (this number includes the number of circuit establishment failures, failed retries, end-to-end circuit setup failures) Closes #40755. This partially addresses #40717. Signed-off-by: Gabriela Moldovan <gabi@torproject.org>
This commit is contained in:
parent
482ce87a8d
commit
db4c4d656a
3
changes/ticket40755
Normal file
3
changes/ticket40755
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
o Minor features (metrics):
|
||||||
|
- Add service side metrics for REND and introduction request failures.
|
||||||
|
Closes ticket 40755.
|
@ -51,6 +51,7 @@
|
|||||||
#include "feature/hs/hs_client.h"
|
#include "feature/hs/hs_client.h"
|
||||||
#include "feature/hs/hs_common.h"
|
#include "feature/hs/hs_common.h"
|
||||||
#include "feature/hs/hs_ident.h"
|
#include "feature/hs/hs_ident.h"
|
||||||
|
#include "feature/hs/hs_metrics.h"
|
||||||
#include "feature/hs/hs_stats.h"
|
#include "feature/hs/hs_stats.h"
|
||||||
#include "feature/nodelist/describe.h"
|
#include "feature/nodelist/describe.h"
|
||||||
#include "feature/nodelist/networkstatus.h"
|
#include "feature/nodelist/networkstatus.h"
|
||||||
@ -1751,8 +1752,10 @@ circuit_build_failed(origin_circuit_t *circ)
|
|||||||
circuit_purpose_to_string(TO_CIRCUIT(circ)->purpose));
|
circuit_purpose_to_string(TO_CIRCUIT(circ)->purpose));
|
||||||
|
|
||||||
/* If the path failed on an RP, retry it. */
|
/* If the path failed on an RP, retry it. */
|
||||||
if (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND)
|
if (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) {
|
||||||
|
hs_metrics_failed_rdv(&circ->hs_ident->identity_pk);
|
||||||
hs_circ_retry_service_rendezvous_point(circ);
|
hs_circ_retry_service_rendezvous_point(circ);
|
||||||
|
}
|
||||||
|
|
||||||
/* In all other cases, just bail. The rest is just failure accounting
|
/* In all other cases, just bail. The rest is just failure accounting
|
||||||
* that we don't want to do */
|
* that we don't want to do */
|
||||||
@ -1862,6 +1865,8 @@ circuit_build_failed(origin_circuit_t *circ)
|
|||||||
"(%s hop failed).",
|
"(%s hop failed).",
|
||||||
escaped(build_state_get_exit_nickname(circ->build_state)),
|
escaped(build_state_get_exit_nickname(circ->build_state)),
|
||||||
failed_at_last_hop?"last":"non-last");
|
failed_at_last_hop?"last":"non-last");
|
||||||
|
|
||||||
|
hs_metrics_failed_rdv(&circ->hs_ident->identity_pk);
|
||||||
hs_circ_retry_service_rendezvous_point(circ);
|
hs_circ_retry_service_rendezvous_point(circ);
|
||||||
break;
|
break;
|
||||||
/* default:
|
/* default:
|
||||||
|
@ -494,6 +494,7 @@ retry_service_rendezvous_point(const origin_circuit_t *circ)
|
|||||||
if (new_circ == NULL) {
|
if (new_circ == NULL) {
|
||||||
log_warn(LD_REND, "Failed to launch rendezvous circuit to %s",
|
log_warn(LD_REND, "Failed to launch rendezvous circuit to %s",
|
||||||
safe_str_client(extend_info_describe(bstate->chosen_exit)));
|
safe_str_client(extend_info_describe(bstate->chosen_exit)));
|
||||||
|
hs_metrics_failed_rdv(&circ->hs_ident->identity_pk);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -831,6 +832,7 @@ hs_circ_service_rp_has_opened(const hs_service_t *service,
|
|||||||
{
|
{
|
||||||
size_t payload_len;
|
size_t payload_len;
|
||||||
uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
|
uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
|
||||||
|
int reason = 0;
|
||||||
|
|
||||||
tor_assert(service);
|
tor_assert(service);
|
||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
@ -862,10 +864,11 @@ hs_circ_service_rp_has_opened(const hs_service_t *service,
|
|||||||
payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
|
payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
|
if ((reason = relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
|
||||||
RELAY_COMMAND_RENDEZVOUS1,
|
RELAY_COMMAND_RENDEZVOUS1,
|
||||||
(const char *) payload, payload_len,
|
(const char *) payload,
|
||||||
circ->cpath->prev) < 0) {
|
payload_len,
|
||||||
|
circ->cpath->prev)) < 0) {
|
||||||
/* On error, circuit is closed. */
|
/* On error, circuit is closed. */
|
||||||
log_warn(LD_REND, "Unable to send RENDEZVOUS1 cell on circuit %u "
|
log_warn(LD_REND, "Unable to send RENDEZVOUS1 cell on circuit %u "
|
||||||
"for service %s",
|
"for service %s",
|
||||||
@ -875,15 +878,19 @@ hs_circ_service_rp_has_opened(const hs_service_t *service,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup end-to-end rendezvous circuit between the client and us. */
|
/* Setup end-to-end rendezvous circuit between the client and us. */
|
||||||
if (hs_circuit_setup_e2e_rend_circ(circ,
|
if ((reason = hs_circuit_setup_e2e_rend_circ(circ,
|
||||||
circ->hs_ident->rendezvous_ntor_key_seed,
|
circ->hs_ident->rendezvous_ntor_key_seed,
|
||||||
sizeof(circ->hs_ident->rendezvous_ntor_key_seed),
|
sizeof(circ->hs_ident->rendezvous_ntor_key_seed),
|
||||||
1) < 0) {
|
1)) < 0) {
|
||||||
log_warn(LD_GENERAL, "Failed to setup circ");
|
log_warn(LD_GENERAL, "Failed to setup circ");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
if (reason < 0) {
|
||||||
|
hs_metrics_failed_rdv(&service->keys.identity_pk);
|
||||||
|
}
|
||||||
|
|
||||||
memwipe(payload, 0, sizeof(payload));
|
memwipe(payload, 0, sizeof(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,8 +72,8 @@ init_store(hs_service_t *service)
|
|||||||
* value used to update the entry. */
|
* value used to update the entry. */
|
||||||
void
|
void
|
||||||
hs_metrics_update_by_service(const hs_metrics_key_t key,
|
hs_metrics_update_by_service(const hs_metrics_key_t key,
|
||||||
hs_service_t *service, const uint16_t port,
|
const hs_service_t *service,
|
||||||
int64_t n)
|
uint16_t port, int64_t n)
|
||||||
{
|
{
|
||||||
tor_assert(service);
|
tor_assert(service);
|
||||||
|
|
||||||
|
@ -28,13 +28,17 @@ void hs_metrics_update_by_ident(const hs_metrics_key_t key,
|
|||||||
const ed25519_public_key_t *ident_pk,
|
const ed25519_public_key_t *ident_pk,
|
||||||
const uint16_t port, int64_t n);
|
const uint16_t port, int64_t n);
|
||||||
void hs_metrics_update_by_service(const hs_metrics_key_t key,
|
void hs_metrics_update_by_service(const hs_metrics_key_t key,
|
||||||
hs_service_t *service, const uint16_t port,
|
const hs_service_t *service,
|
||||||
int64_t n);
|
uint16_t port, int64_t n);
|
||||||
|
|
||||||
/** New introducion request received. */
|
/** New introducion request received. */
|
||||||
#define hs_metrics_new_introduction(s) \
|
#define hs_metrics_new_introduction(s) \
|
||||||
hs_metrics_update_by_service(HS_METRICS_NUM_INTRODUCTIONS, (s), 0, 1)
|
hs_metrics_update_by_service(HS_METRICS_NUM_INTRODUCTIONS, (s), 0, 1)
|
||||||
|
|
||||||
|
/** Introducion request rejected. */
|
||||||
|
#define hs_metrics_reject_intro_req(s) \
|
||||||
|
hs_metrics_update_by_service(HS_METRICS_NUM_REJECTED_INTRO_REQ, (s), 0, 1)
|
||||||
|
|
||||||
/** Number of bytes written to the application from the service. */
|
/** Number of bytes written to the application from the service. */
|
||||||
#define hs_metrics_app_write_bytes(i, port, n) \
|
#define hs_metrics_app_write_bytes(i, port, n) \
|
||||||
hs_metrics_update_by_ident(HS_METRICS_APP_WRITE_BYTES, (i), (port), (n))
|
hs_metrics_update_by_ident(HS_METRICS_APP_WRITE_BYTES, (i), (port), (n))
|
||||||
@ -48,6 +52,10 @@ void hs_metrics_update_by_service(const hs_metrics_key_t key,
|
|||||||
#define hs_metrics_new_established_rdv(s) \
|
#define hs_metrics_new_established_rdv(s) \
|
||||||
hs_metrics_update_by_service(HS_METRICS_NUM_ESTABLISHED_RDV, (s), 0, 1)
|
hs_metrics_update_by_service(HS_METRICS_NUM_ESTABLISHED_RDV, (s), 0, 1)
|
||||||
|
|
||||||
|
/** New rendezvous circuit failure. */
|
||||||
|
#define hs_metrics_failed_rdv(i) \
|
||||||
|
hs_metrics_update_by_ident(HS_METRICS_NUM_FAILED_RDV, (i), 0, 1)
|
||||||
|
|
||||||
/** Established rendezvous closed. This is called when the circuit in
|
/** Established rendezvous closed. This is called when the circuit in
|
||||||
* REND_JOINED state is marked for close. */
|
* REND_JOINED state is marked for close. */
|
||||||
#define hs_metrics_close_established_rdv(i) \
|
#define hs_metrics_close_established_rdv(i) \
|
||||||
|
@ -45,13 +45,19 @@ const hs_metrics_entry_t base_metrics[] =
|
|||||||
.key = HS_METRICS_NUM_ESTABLISHED_RDV,
|
.key = HS_METRICS_NUM_ESTABLISHED_RDV,
|
||||||
.type = METRICS_TYPE_GAUGE,
|
.type = METRICS_TYPE_GAUGE,
|
||||||
.name = METRICS_NAME(hs_rdv_established_count),
|
.name = METRICS_NAME(hs_rdv_established_count),
|
||||||
.help = "Total number of established rendezvous circuit",
|
.help = "Total number of established rendezvous circuits",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.key = HS_METRICS_NUM_RDV,
|
.key = HS_METRICS_NUM_RDV,
|
||||||
.type = METRICS_TYPE_COUNTER,
|
.type = METRICS_TYPE_COUNTER,
|
||||||
.name = METRICS_NAME(hs_rdv_num_total),
|
.name = METRICS_NAME(hs_rdv_num_total),
|
||||||
.help = "Total number of rendezvous circuit created",
|
.help = "Total number of rendezvous circuits created",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.key = HS_METRICS_NUM_FAILED_RDV,
|
||||||
|
.type = METRICS_TYPE_COUNTER,
|
||||||
|
.name = METRICS_NAME(hs_rdv_error_count),
|
||||||
|
.help = "Total number of rendezvous circuit errors",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.key = HS_METRICS_NUM_ESTABLISHED_INTRO,
|
.key = HS_METRICS_NUM_ESTABLISHED_INTRO,
|
||||||
@ -59,6 +65,12 @@ const hs_metrics_entry_t base_metrics[] =
|
|||||||
.name = METRICS_NAME(hs_intro_established_count),
|
.name = METRICS_NAME(hs_intro_established_count),
|
||||||
.help = "Total number of established introduction circuit",
|
.help = "Total number of established introduction circuit",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.key = HS_METRICS_NUM_REJECTED_INTRO_REQ,
|
||||||
|
.type = METRICS_TYPE_COUNTER,
|
||||||
|
.name = METRICS_NAME(hs_intro_rejected_intro_req_count),
|
||||||
|
.help = "Total number of rejected introduction circuits",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Size of base_metrics array that is number of entries. */
|
/** Size of base_metrics array that is number of entries. */
|
||||||
|
@ -25,8 +25,12 @@ typedef enum {
|
|||||||
HS_METRICS_NUM_ESTABLISHED_RDV = 3,
|
HS_METRICS_NUM_ESTABLISHED_RDV = 3,
|
||||||
/** Number of rendezsvous circuits created. */
|
/** Number of rendezsvous circuits created. */
|
||||||
HS_METRICS_NUM_RDV = 4,
|
HS_METRICS_NUM_RDV = 4,
|
||||||
|
/** Number of failed rendezsvous. */
|
||||||
|
HS_METRICS_NUM_FAILED_RDV = 5,
|
||||||
/** Number of established introducton points. */
|
/** Number of established introducton points. */
|
||||||
HS_METRICS_NUM_ESTABLISHED_INTRO = 5,
|
HS_METRICS_NUM_ESTABLISHED_INTRO = 6,
|
||||||
|
/** Number of rejected introducton requests. */
|
||||||
|
HS_METRICS_NUM_REJECTED_INTRO_REQ = 7,
|
||||||
} hs_metrics_key_t;
|
} hs_metrics_key_t;
|
||||||
|
|
||||||
/** The metadata of an HS metrics. */
|
/** The metadata of an HS metrics. */
|
||||||
|
@ -144,7 +144,7 @@ hs_service_ht_hash(const hs_service_t *service)
|
|||||||
sizeof(service->keys.identity_pk.pubkey));
|
sizeof(service->keys.identity_pk.pubkey));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This is _the_ global hash map of hidden services which indexed the service
|
/** This is _the_ global hash map of hidden services which indexes the services
|
||||||
* contained in it by master public identity key which is roughly the onion
|
* contained in it by master public identity key which is roughly the onion
|
||||||
* address of the service. */
|
* address of the service. */
|
||||||
static struct hs_service_ht *hs_service_map;
|
static struct hs_service_ht *hs_service_map;
|
||||||
@ -3524,6 +3524,10 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
|
if (service) {
|
||||||
|
hs_metrics_reject_intro_req(service);
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,23 @@ test_metrics(void *arg)
|
|||||||
service, 0, 42);
|
service, 0, 42);
|
||||||
tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 84);
|
tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 84);
|
||||||
|
|
||||||
|
/* Update tor_hs_intro_rejected_intro_req_count */
|
||||||
|
hs_metrics_update_by_ident(HS_METRICS_NUM_REJECTED_INTRO_REQ,
|
||||||
|
&service->keys.identity_pk, 0, 112);
|
||||||
|
|
||||||
|
entries = metrics_store_get_all(service->metrics.store,
|
||||||
|
"tor_hs_intro_rejected_intro_req_count");
|
||||||
|
tt_assert(entries);
|
||||||
|
tt_int_op(smartlist_len(entries), OP_EQ, 1);
|
||||||
|
entry = smartlist_get(entries, 0);
|
||||||
|
tt_assert(entry);
|
||||||
|
tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 112);
|
||||||
|
|
||||||
|
/* Update tor_hs_intro_rejected_intro_req_count entry by service now. */
|
||||||
|
hs_metrics_update_by_service(HS_METRICS_NUM_REJECTED_INTRO_REQ,
|
||||||
|
service, 0, 10);
|
||||||
|
tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 122);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
hs_free_all();
|
hs_free_all();
|
||||||
}
|
}
|
||||||
|
@ -1183,6 +1183,8 @@ test_bad_introduce2(void *arg)
|
|||||||
origin_circuit_t *circ = NULL;
|
origin_circuit_t *circ = NULL;
|
||||||
hs_service_t *service = NULL;
|
hs_service_t *service = NULL;
|
||||||
hs_service_intro_point_t *ip = NULL;
|
hs_service_intro_point_t *ip = NULL;
|
||||||
|
const smartlist_t *entries = NULL;
|
||||||
|
const metrics_store_entry_t *entry = NULL;
|
||||||
|
|
||||||
(void) arg;
|
(void) arg;
|
||||||
|
|
||||||
@ -1227,6 +1229,17 @@ test_bad_introduce2(void *arg)
|
|||||||
"an INTRODUCE2 cell on circuit");
|
"an INTRODUCE2 cell on circuit");
|
||||||
teardown_capture_of_logs();
|
teardown_capture_of_logs();
|
||||||
|
|
||||||
|
/* Make sure the tor_hs_intro_rejected_intro_req_count metric was
|
||||||
|
* incremented */
|
||||||
|
entries = metrics_store_get_all(service->metrics.store,
|
||||||
|
"tor_hs_intro_rejected_intro_req_count");
|
||||||
|
|
||||||
|
tt_assert(entries);
|
||||||
|
tt_int_op(smartlist_len(entries), OP_EQ, 1);
|
||||||
|
entry = smartlist_get(entries, 0);
|
||||||
|
tt_assert(entry);
|
||||||
|
tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 1);
|
||||||
|
|
||||||
/* Set an IP object now for this circuit. */
|
/* Set an IP object now for this circuit. */
|
||||||
{
|
{
|
||||||
ip = helper_create_service_ip();
|
ip = helper_create_service_ip();
|
||||||
@ -1243,6 +1256,10 @@ test_bad_introduce2(void *arg)
|
|||||||
tt_int_op(ret, OP_EQ, -1);
|
tt_int_op(ret, OP_EQ, -1);
|
||||||
tt_u64_op(ip->introduce2_count, OP_EQ, 0);
|
tt_u64_op(ip->introduce2_count, OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Make sure the tor_hs_intro_rejected_intro_req_count metric was incremented
|
||||||
|
* a second time */
|
||||||
|
tt_int_op(metrics_store_entry_get_value(entry), OP_EQ, 2);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
or_state_free(dummy_state);
|
or_state_free(dummy_state);
|
||||||
dummy_state = NULL;
|
dummy_state = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user