From 0d784164545b60ea8628fa6204b296a759b9e7e4 Mon Sep 17 00:00:00 2001 From: Simon Wicky Date: Fri, 6 Jun 2025 09:08:58 +0200 Subject: [PATCH] [Stats API] IP from nginx headers if available (#5830) * proper IP handling * workflow doesn't like fancy versions --- Cargo.lock | 3 ++- nym-statistics-api/Cargo.toml | 3 ++- nym-statistics-api/src/http/api/stats.rs | 25 ++++++++++++++---------- nym-statistics-api/src/storage/models.rs | 6 +++--- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4571ebb1b..56b05eef55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7224,10 +7224,11 @@ dependencies = [ [[package]] name = "nym-statistics-api" -version = "0.1.1" +version = "0.1.3" dependencies = [ "anyhow", "axum 0.7.9", + "axum-client-ip", "axum-extra", "celes", "clap", diff --git a/nym-statistics-api/Cargo.toml b/nym-statistics-api/Cargo.toml index a521600d8d..ae26c96a9e 100644 --- a/nym-statistics-api/Cargo.toml +++ b/nym-statistics-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-statistics-api" -version = "0.1.1" +version = "0.1.3" authors.workspace = true repository.workspace = true homepage.workspace = true @@ -16,6 +16,7 @@ rust-version.workspace = true [dependencies] anyhow.workspace = true axum = { workspace = true, features = ["tokio", "macros"] } +axum-client-ip.workspace = true axum-extra = { workspace = true, features = ["typed-header"] } celes.workspace = true clap = { workspace = true, features = ["cargo", "derive", "env", "string"] } diff --git a/nym-statistics-api/src/http/api/stats.rs b/nym-statistics-api/src/http/api/stats.rs index 4490535cc4..7e7a51ec14 100644 --- a/nym-statistics-api/src/http/api/stats.rs +++ b/nym-statistics-api/src/http/api/stats.rs @@ -1,9 +1,5 @@ -use std::net::SocketAddr; - -use axum::{ - extract::{ConnectInfo, State}, - Json, Router, -}; +use axum::{extract::State, Json, Router}; +use axum_client_ip::InsecureClientIp; use axum_extra::{headers::UserAgent, TypedHeader}; use nym_statistics_common::report::vpn_client::VpnClientStatsReport; use tracing::debug; @@ -33,12 +29,16 @@ pub(crate) fn routes() -> Router { #[tracing::instrument(level = "info", skip_all)] async fn submit_stats_report( State(mut state): State, - ConnectInfo(addr): ConnectInfo, TypedHeader(user_agent): TypedHeader, + insecure_ip_addr: InsecureClientIp, Json(report): Json, ) -> HttpResult> { let now = time::OffsetDateTime::now_utc(); - let gateway_record = state.network_view().get_country_by_ip(&addr.ip()).await; + + let gateway_record = state + .network_view() + .get_country_by_ip(&insecure_ip_addr.0) + .await; let from_mixnet = gateway_record.is_some(); let maybe_location = gateway_record.unwrap_or_default(); @@ -50,8 +50,13 @@ async fn submit_stats_report( } let active_device = DailyActiveDeviceDto::new(now, &report, user_agent, from_mixnet); - let maybe_connection_info = - ConnectionInfoDto::maybe_new(now, &report, addr, maybe_location, from_mixnet); + let maybe_connection_info = ConnectionInfoDto::maybe_new( + now, + &report, + insecure_ip_addr.0, + maybe_location, + from_mixnet, + ); state .storage() diff --git a/nym-statistics-api/src/storage/models.rs b/nym-statistics-api/src/storage/models.rs index 5ac863dcd6..669bcf2a54 100644 --- a/nym-statistics-api/src/storage/models.rs +++ b/nym-statistics-api/src/storage/models.rs @@ -1,4 +1,4 @@ -use std::net::SocketAddr; +use std::net::IpAddr; use axum_extra::headers::UserAgent; use celes::Country; @@ -53,13 +53,13 @@ impl ConnectionInfoDto { pub(crate) fn maybe_new( received_at: OffsetDateTime, stats_report: &VpnClientStatsReport, - received_from: SocketAddr, + received_from: IpAddr, maybe_country: Option, from_mixnet: bool, ) -> Option { stats_report.basic_usage.as_ref().map(|usage_report| Self { received_at, - received_from: received_from.ip().to_string(), + received_from: received_from.to_string(), connection_time_ms: usage_report.connection_time_ms, two_hop: usage_report.two_hop, country_code: maybe_country.map(|c| c.alpha2.into()),