Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions packages/configuration/src/v2_0_0/udp_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ pub struct UdpTracker {
/// > be disabled; setting this to `false` is a no-op.
#[serde(default = "UdpTracker::default_ipv6_v6only")]
pub ipv6_v6only: bool,

/// The maximum number of connection ID errors per IP before the client is
/// banned. Default is `10`.
#[serde(default = "UdpTracker::default_max_connection_id_errors_per_ip")]
pub max_connection_id_errors_per_ip: u32,
}
impl Default for UdpTracker {
fn default() -> Self {
Expand All @@ -40,6 +45,7 @@ impl Default for UdpTracker {
cookie_lifetime: Self::default_cookie_lifetime(),
tracker_usage_statistics: Self::default_tracker_usage_statistics(),
ipv6_v6only: Self::default_ipv6_v6only(),
max_connection_id_errors_per_ip: Self::default_max_connection_id_errors_per_ip(),
}
}
}
Expand All @@ -60,4 +66,8 @@ impl UdpTracker {
fn default_ipv6_v6only() -> bool {
false
}

fn default_max_connection_id_errors_per_ip() -> u32 {
10
}
}
3 changes: 1 addition & 2 deletions packages/rest-api-core/src/statistics/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ mod tests {
use torrust_tracker_http_core::statistics::repository::Repository;
use torrust_tracker_swarm_coordination_registry::container::SwarmCoordinationRegistryContainer;
use torrust_tracker_test_helpers::configuration;
use torrust_tracker_udp_core::MAX_CONNECTION_ID_ERRORS_PER_IP;
use torrust_tracker_udp_core::services::banning::BanService;

use crate::statistics::metrics::{ProtocolMetrics, TorrentsMetrics};
Expand All @@ -224,7 +223,7 @@ mod tests {
let tracker_core_container =
TrackerCoreContainer::initialize_from(&core_config, &swarm_coordination_registry_container.clone()).await;

let _ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP)));
let _ban_service = Arc::new(RwLock::new(BanService::new(10)));

// HTTP core stats
let http_core_broadcaster = Broadcaster::default();
Expand Down
1 change: 1 addition & 0 deletions packages/test-helpers/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub fn ephemeral() -> Configuration {
cookie_lifetime: Duration::from_secs(120),
tracker_usage_statistics: true,
ipv6_v6only: false,
max_connection_id_errors_per_ip: 10,
}]);

// Ephemeral socket address for HTTP tracker
Expand Down
1 change: 1 addition & 0 deletions packages/udp-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives"
torrust-tracker-swarm-coordination-registry = { version = "3.0.0-develop", path = "../swarm-coordination-registry" }
tracing = "0"
zerocopy = "0.8"
async-trait = "0"

[dev-dependencies]
mockall = "0"
Expand Down
13 changes: 9 additions & 4 deletions packages/udp-core/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::services::banning::BanService;
use crate::services::connect::ConnectService;
use crate::services::scrape::ScrapeService;
use crate::statistics::repository::Repository;
use crate::{MAX_CONNECTION_ID_ERRORS_PER_IP, event, services, statistics};
use crate::{event, services, statistics};

pub struct UdpTrackerCoreContainer {
pub udp_tracker_config: Arc<UdpTracker>,
Expand Down Expand Up @@ -47,7 +47,9 @@ impl UdpTrackerCoreContainer {
tracker_core_container: &Arc<TrackerCoreContainer>,
udp_tracker_config: &Arc<UdpTracker>,
) -> Arc<UdpTrackerCoreContainer> {
let udp_tracker_core_services = UdpTrackerCoreServices::initialize_from(tracker_core_container);
let max_connection_id_errors_per_ip = udp_tracker_config.max_connection_id_errors_per_ip;
let udp_tracker_core_services =
UdpTrackerCoreServices::initialize_from(tracker_core_container, max_connection_id_errors_per_ip);

Self::initialize_from_services(tracker_core_container, &udp_tracker_core_services, udp_tracker_config)
}
Expand Down Expand Up @@ -87,7 +89,10 @@ pub struct UdpTrackerCoreServices {

impl UdpTrackerCoreServices {
#[must_use]
pub fn initialize_from(tracker_core_container: &Arc<TrackerCoreContainer>) -> Arc<Self> {
pub fn initialize_from(
tracker_core_container: &Arc<TrackerCoreContainer>,
max_connection_id_errors_per_ip: u32,
) -> Arc<Self> {
let udp_core_broadcaster = Broadcaster::default();
let udp_core_stats_repository = Arc::new(Repository::new());
let event_bus = Arc::new(EventBus::new(
Expand All @@ -96,7 +101,7 @@ impl UdpTrackerCoreServices {
));

let udp_core_stats_event_sender = event_bus.sender();
let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP)));
let ban_service = Arc::new(RwLock::new(BanService::new(max_connection_id_errors_per_ip)));
let connect_service = Arc::new(ConnectService::new(udp_core_stats_event_sender.clone()));
let announce_service = Arc::new(AnnounceService::new(
tracker_core_container.announce_handler.clone(),
Expand Down
4 changes: 0 additions & 4 deletions packages/udp-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ pub(crate) type CurrentClock = clock::Stopped;
use crypto::ephemeral_instance_keys;
use tracing::instrument;

/// The maximum number of connection id errors per ip. Clients will be banned if
/// they exceed this limit.
pub const MAX_CONNECTION_ID_ERRORS_PER_IP: u32 = 10;

pub const UDP_TRACKER_LOG_TARGET: &str = "UDP TRACKER";

/// It initializes the static values.
Expand Down
12 changes: 12 additions & 0 deletions packages/udp-core/src/services/banning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ use tokio::time::Instant;

use crate::UDP_TRACKER_LOG_TARGET;

/// Trait exposing only the banning statistics that external consumers need.
pub trait BanningStats: Send + Sync {
/// Returns the total number of banned IPs.
fn get_banned_ips_total(&self) -> usize;
}

pub struct BanService {
max_connection_id_errors_per_ip: u32,
fuzzy_error_counter: CountingBloomFilter,
Expand Down Expand Up @@ -88,6 +94,12 @@ impl BanService {
}
}

impl BanningStats for BanService {
fn get_banned_ips_total(&self) -> usize {
self.accurate_error_counter.len()
}
}

#[cfg(test)]
mod tests {
use std::net::IpAddr;
Expand Down
15 changes: 14 additions & 1 deletion packages/udp-core/src/statistics/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ use tokio::sync::{RwLock, RwLockReadGuard};
use torrust_clock::DurationSinceUnixEpoch;
use torrust_metrics::label::LabelSet;
use torrust_metrics::metric::MetricName;
use torrust_metrics::metric_collection::Error;
use torrust_metrics::metric_collection::{Error, MetricCollection};

use super::describe_metrics;
use super::metrics::Metrics;

/// Trait exposing only the UDP core statistics that external consumers need.
#[async_trait::async_trait]
pub trait UdpCoreStatsRepository: Send + Sync {
async fn get_metrics_collection(&self) -> MetricCollection;
}

/// A repository for the tracker metrics.
#[derive(Clone)]
pub struct Repository {
Expand Down Expand Up @@ -52,3 +58,10 @@ impl Repository {
result
}
}

#[async_trait::async_trait]
impl UdpCoreStatsRepository for Repository {
async fn get_metrics_collection(&self) -> MetricCollection {
self.stats.read().await.metric_collection.clone()
}
}
1 change: 1 addition & 0 deletions packages/udp-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ torrust-tracker-primitives = { version = "3.0.0-develop", path = "../primitives"
torrust-tracker-swarm-coordination-registry = { version = "3.0.0-develop", path = "../swarm-coordination-registry" }
tracing = "0"
url = { version = "2", features = [ "serde" ] }
async-trait = "0"
uuid = { version = "1", features = [ "v4" ] }
zerocopy = "0.8"
socket2 = "0.6.4"
Expand Down
1 change: 1 addition & 0 deletions packages/udp-server/examples/udp_only_public_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ async fn main() {
cookie_lifetime: Duration::from_secs(120),
tracker_usage_statistics: false,
ipv6_v6only: false,
max_connection_id_errors_per_ip: 10,
};

println!("Types from torrust-tracker-configuration used by this binary:");
Expand Down
15 changes: 14 additions & 1 deletion packages/udp-server/src/statistics/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ use tokio::sync::{RwLock, RwLockReadGuard};
use torrust_clock::DurationSinceUnixEpoch;
use torrust_metrics::label::LabelSet;
use torrust_metrics::metric::MetricName;
use torrust_metrics::metric_collection::Error;
use torrust_metrics::metric_collection::{Error, MetricCollection};

use super::describe_metrics;
use super::metrics::Metrics;

/// Trait exposing only the UDP server statistics that external consumers need.
#[async_trait::async_trait]
pub trait UdpServerStatsRepository: Send + Sync {
async fn get_metrics_collection(&self) -> MetricCollection;
}

/// A repository for the tracker metrics.
#[derive(Clone)]
pub struct Repository {
Expand Down Expand Up @@ -89,6 +95,13 @@ impl Repository {
}
}

#[async_trait::async_trait]
impl UdpServerStatsRepository for Repository {
async fn get_metrics_collection(&self) -> MetricCollection {
self.stats.read().await.metric_collection.clone()
}
}

#[cfg(test)]
mod tests {
use core::f64;
Expand Down
15 changes: 14 additions & 1 deletion src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,20 @@ impl AppContainer {

// UDP

let udp_tracker_core_services = UdpTrackerCoreServices::initialize_from(&tracker_core_container);
use torrust_tracker_configuration::UdpTracker as UdpTrackerConfig;

let default_max_connection_id_errors = UdpTrackerConfig::default().max_connection_id_errors_per_ip;

let max_connection_id_errors = configuration
.udp_trackers
.as_ref()
.and_then(|trackers| trackers.first())
.map_or(default_max_connection_id_errors, |config| {
config.max_connection_id_errors_per_ip
});

let udp_tracker_core_services =
UdpTrackerCoreServices::initialize_from(&tracker_core_container, max_connection_id_errors);

let udp_tracker_server_container = UdpTrackerServerContainer::initialize(&core_config);

Expand Down
Loading