diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-14 13:40:20 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-01-14 13:40:20 +0000 |
| commit | 2821578202d1313c23c30a5dbae39548822e3c55 (patch) | |
| tree | cbe4d2447312b7bc7653bef874b6fb23d60a0ede /docs/explanation/defensive-measures.md | |
| parent | 50000cd9d47681390c3c45feef98fe51c7b79a0f (diff) | |
docs: add defensive measures explanation
Add comprehensive documentation explaining the defensive features
implemented in ngit-grasp. The detailed analysis of other relay
implementations is now preserved in commit history (e3792b9).
Diffstat (limited to 'docs/explanation/defensive-measures.md')
| -rw-r--r-- | docs/explanation/defensive-measures.md | 64 |
1 files changed, 9 insertions, 55 deletions
diff --git a/docs/explanation/defensive-measures.md b/docs/explanation/defensive-measures.md index f7abc30..51f7278 100644 --- a/docs/explanation/defensive-measures.md +++ b/docs/explanation/defensive-measures.md | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | This document describes the defensive measures implemented in ngit-grasp to protect against abuse, spam, and denial-of-service attacks. | 3 | This document describes the defensive measures implemented in ngit-grasp to protect against abuse, spam, and denial-of-service attacks. |
| 4 | 4 | ||
| 5 | **Note:** A point-in-time analysis of defensive measures in other Nostr relays (strfry, nostr-rs-relay, khatru) was conducted to inform these design decisions. The analysis examined connection limits, rate limiting approaches, and per-IP enforcement strategies across the ecosystem. | ||
| 6 | |||
| 5 | ## Overview | 7 | ## Overview |
| 6 | 8 | ||
| 7 | ngit-grasp employs multiple layers of defense: | 9 | ngit-grasp employs multiple layers of defense: |
| @@ -35,7 +37,7 @@ These limits prevent individual connections from overwhelming the relay. | |||
| 35 | - **Privacy:** IP addresses never exposed in Prometheus metrics, only aggregate counts | 37 | - **Privacy:** IP addresses never exposed in Prometheus metrics, only aggregate counts |
| 36 | - Logs warnings when threshold exceeded | 38 | - Logs warnings when threshold exceeded |
| 37 | 39 | ||
| 38 | **Future:** Could be extended to enforce per-IP connection limits. | 40 | **Note on enforcement:** Per-IP connection limits are not built into rust-nostr relay-builder (tracks per WebSocket connection, not per IP). If abuse is detected via metrics, enforcement should be implemented as a PR to rust-nostr/relay-builder to benefit the entire Nostr ecosystem, rather than custom code in ngit-grasp. |
| 39 | 41 | ||
| 40 | ### Content Filtering (Blacklists/Whitelists) | 42 | ### Content Filtering (Blacklists/Whitelists) |
| 41 | 43 | ||
| @@ -111,69 +113,21 @@ These limits prevent individual connections from overwhelming the relay. | |||
| 111 | 113 | ||
| 112 | **To implement:** Would require custom middleware/WritePolicy to aggregate across connections from the same IP. | 114 | **To implement:** Would require custom middleware/WritePolicy to aggregate across connections from the same IP. |
| 113 | 115 | ||
| 114 | ### Total Connection Limit | ||
| 115 | |||
| 116 | **Status:** Supported by relay-builder but not currently configured in ngit-grasp. | ||
| 117 | |||
| 118 | **To implement:** Add `max_connections(n)` to relay builder configuration. | ||
| 119 | |||
| 120 | ### Query Filtering | 116 | ### Query Filtering |
| 121 | 117 | ||
| 122 | **Status:** QueryPolicy trait available but not currently used. | 118 | **Status:** QueryPolicy trait available but not currently used. |
| 123 | 119 | ||
| 124 | **Potential uses:** Rate limit queries per IP, block expensive queries, restrict access to certain event kinds. | 120 | **Potential uses:** Rate limit queries per IP, block expensive queries, restrict access to certain event kinds. |
| 125 | 121 | ||
| 126 | ## Future Enhancements: Per-IP Rate Limiting (Deferred) | 122 | ## Future Enhancements |
| 127 | |||
| 128 | ### Decision: Defer Until Abuse Detected | ||
| 129 | |||
| 130 | After comprehensive review (2026-01-14), we decided to defer per-IP rate limiting (Phase 2 & 3) until abuse patterns are detected in production. | ||
| 131 | |||
| 132 | **Current protection (Phase 1):** | ||
| 133 | - Per-connection limits: 500 subscriptions, 60 events/min | ||
| 134 | - Total connection limit: 500 (configurable via `NGIT_MAX_CONNECTIONS`) | ||
| 135 | - Connection monitoring: Tracks IPs, flags abuse at 10 connections | ||
| 136 | - Content filtering: Event blacklist, repository blacklist/whitelist | ||
| 137 | |||
| 138 | **Deferred features (Phase 2 & 3):** | ||
| 139 | - Per-IP connection enforcement (reject after 10 connections) | ||
| 140 | - Per-IP event rate limiting (reject after 100 events/min) | ||
| 141 | 123 | ||
| 142 | ### Rationale for Deferral | 124 | ### Per-IP Rate Limiting |
| 143 | |||
| 144 | 1. **Config-only approach sufficient** - Total connection limit addresses primary DoS vector | ||
| 145 | 2. **Git relay context** - Developer users less likely to abuse than general public | ||
| 146 | 3. **Existing protections strong** - Per-connection limits + content filtering already robust | ||
| 147 | 4. **Data-driven approach** - Monitor ConnectionTracker metrics, implement if needed | ||
| 148 | 5. **Minimal maintenance** - Avoid custom rate limiting code until proven necessary | ||
| 149 | |||
| 150 | ### Implementation Path if Needed | ||
| 151 | |||
| 152 | **Preferred approach:** Contribute to rust-nostr/relay-builder as PR | ||
| 153 | - Propose IP-based rate limiting as optional feature | ||
| 154 | - Let upstream maintain the code | ||
| 155 | - Benefits entire Nostr ecosystem | ||
| 156 | |||
| 157 | **Fallback:** Implement in ngit-grasp | ||
| 158 | - Per-IP connection enforcement via actix middleware | ||
| 159 | - Per-IP event rate limiting via token bucket in WritePolicy | ||
| 160 | - See issue d6ee for detailed implementation plan | ||
| 161 | |||
| 162 | ### Monitoring for Abuse | ||
| 163 | |||
| 164 | Watch these metrics to determine if Phase 2 is needed: | ||
| 165 | - `ngit_connections_per_ip` - IPs exceeding 10 connections | ||
| 166 | - `ngit_flagged_abusers` - IPs flagged by ConnectionTracker | ||
| 167 | - Event publishing patterns from single IPs | ||
| 168 | 125 | ||
| 169 | **Trigger for Phase 2:** If abuse detected for 2-4 weeks after Phase 1 deployment | 126 | Per-IP connection and event rate limiting were considered but deferred until abuse is detected in production. The current protections (per-connection limits, total connection limit, content filtering) are sufficient for the git relay use case. |
| 170 | 127 | ||
| 171 | ### Related Work | 128 | **Decision rationale:** The primary DoS vector is connection exhaustion, which is addressed by the total connection limit (`NGIT_MAX_CONNECTIONS`). Per-IP enforcement would require custom middleware in rust-nostr relay-builder (which currently tracks limits per WebSocket connection, not per IP). If abuse is detected via the per-IP monitoring metrics, enforcement should be implemented as a PR to rust-nostr/relay-builder to benefit the entire Nostr ecosystem. |
| 172 | 129 | ||
| 173 | **Git endpoint throttling:** Separate concern, tracked in issue ff38 | 130 | **Related:** Git endpoint throttling (issue ff38) is a separate concern with different requirements. |
| 174 | - Git HTTP endpoints have different threat model (bandwidth/CPU intensive) | ||
| 175 | - Requires separate IP-based throttling (5 concurrent, 30/min per IP) | ||
| 176 | - No interaction with relay code | ||
| 177 | 131 | ||
| 178 | ## Summary Table | 132 | ## Summary Table |
| 179 | 133 | ||
| @@ -198,7 +152,7 @@ Watch these metrics to determine if Phase 2 is needed: | |||
| 198 | | Naughty list | ✅ Active | Yes | Yes (12h default) | | 152 | | Naughty list | ✅ Active | Yes | Yes (12h default) | |
| 199 | | Rate limit detection | ✅ Active | Yes | Automatic | | 153 | | Rate limit detection | ✅ Active | Yes | Automatic | |
| 200 | | Domain throttling | ✅ Active | Yes | Hardcoded (5/30) | | 154 | | Domain throttling | ✅ Active | Yes | Hardcoded (5/30) | |
| 201 | | **Deferred (Phase 2)** | | 155 | | **Not Implemented** | |
| 202 | | Per-IP connection limit | ⚠️ Deferred | No | - | | 156 | | Per-IP connection limit | ⚠️ Deferred | No | - | |
| 203 | | Per-IP rate limiting | ⚠️ Deferred | No | - | | 157 | | Per-IP rate limiting | ⚠️ Deferred | No | - | |
| 204 | | Query filtering | ⚠️ Available | No | Not implemented | | 158 | | Query filtering | ⚠️ Available | No | Not implemented | |