diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-14 13:40:33 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-14 13:43:40 +0000 |
| commit | 5897e4bccd41f1a9ebb01a11280cea929c93d2c0 (patch) | |
| tree | cbe4d2447312b7bc7653bef874b6fb23d60a0ede /src | |
| parent | 4c8f1813fada9ce2bfd371095b0721bff68173e3 (diff) | |
| parent | 2821578202d1313c23c30a5dbae39548822e3c55 (diff) | |
Add defensive relay features with rate limiting and connection limits
Implement defensive measures to protect against DoS attacks:
- Add explicit rate limits (500 subscriptions, 60 events/min per connection)
- Add total connection limit (default: 500, configurable via NGIT_MAX_CONNECTIONS)
- Update configuration across all 4 locations (src, nix, docs, .env.example)
Per-IP rate limiting deferred until abuse is detected in production or
implemented in rust-nostr relay-builder to benefit the entire Nostr ecosystem.
Documentation added explaining the defensive features and rationale.
Detailed analysis of other relay implementations preserved in commit history.
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.rs | 6 | ||||
| -rw-r--r-- | src/nostr/builder.rs | 8 |
2 files changed, 14 insertions, 0 deletions
diff --git a/src/config.rs b/src/config.rs index 0f0d853..0014003 100644 --- a/src/config.rs +++ b/src/config.rs | |||
| @@ -469,6 +469,11 @@ pub struct Config { | |||
| 469 | /// All events from these authors are blocked from both relay storage and purgatory | 469 | /// All events from these authors are blocked from both relay storage and purgatory |
| 470 | #[arg(long, env = "NGIT_EVENT_BLACKLIST", default_value = "")] | 470 | #[arg(long, env = "NGIT_EVENT_BLACKLIST", default_value = "")] |
| 471 | pub event_blacklist: String, | 471 | pub event_blacklist: String, |
| 472 | |||
| 473 | /// Maximum total connections to the relay (default: 500) | ||
| 474 | /// Prevents connection exhaustion DoS attacks | ||
| 475 | #[arg(long, env = "NGIT_MAX_CONNECTIONS", default_value_t = 500)] | ||
| 476 | pub max_connections: usize, | ||
| 472 | } | 477 | } |
| 473 | 478 | ||
| 474 | impl Config { | 479 | impl Config { |
| @@ -703,6 +708,7 @@ impl Config { | |||
| 703 | repository_whitelist: String::new(), | 708 | repository_whitelist: String::new(), |
| 704 | repository_blacklist: String::new(), | 709 | repository_blacklist: String::new(), |
| 705 | event_blacklist: String::new(), | 710 | event_blacklist: String::new(), |
| 711 | max_connections: 500, | ||
| 706 | } | 712 | } |
| 707 | } | 713 | } |
| 708 | } | 714 | } |
diff --git a/src/nostr/builder.rs b/src/nostr/builder.rs index c2de1df..ef1b700 100644 --- a/src/nostr/builder.rs +++ b/src/nostr/builder.rs | |||
| @@ -624,6 +624,14 @@ pub async fn create_relay( | |||
| 624 | let relay = LocalRelayBuilder::default() | 624 | let relay = LocalRelayBuilder::default() |
| 625 | .database(database.clone()) | 625 | .database(database.clone()) |
| 626 | .write_policy(write_policy.clone()) | 626 | .write_policy(write_policy.clone()) |
| 627 | // Explicitly set rate limits (make defaults visible in code) | ||
| 628 | // Per-connection limits: 500 max subscriptions, 60 events/min | ||
| 629 | .rate_limit(RateLimit { | ||
| 630 | max_reqs: 500, // Max concurrent subscriptions per connection | ||
| 631 | notes_per_minute: 60, // Max events per minute per connection | ||
| 632 | }) | ||
| 633 | // Total connection limit to prevent DoS attacks | ||
| 634 | .max_connections(config.max_connections) | ||
| 627 | .build(); | 635 | .build(); |
| 628 | 636 | ||
| 629 | tracing::info!( | 637 | tracing::info!( |