Problem
The relay's bootstrap ID HTTP handler (crates/relay/src/lib.rs:196-222) reads the request line byte-by-byte with a per-read timeout of BOOTSTRAP_IO_TIMEOUT = 5 seconds but no total connection time limit. The connection count is bounded by MAX_CONCURRENT_BOOTSTRAP_CONNECTIONS = 1024 via a semaphore.
A Slowloris-style attack can exhaust all 1024 slots:
- Attacker opens 1024 TCP connections to the bootstrap port
- Each connection sends 1 byte every ~4.9 seconds (just under the 5s per-read timeout)
- All connections stay alive indefinitely, consuming semaphore permits
- Legitimate clients cannot fetch the bootstrap node ID → new peers cannot discover the relay
Severity
MEDIUM — DoS on bootstrap discovery. Does not affect already-connected peers, but prevents new peers from joining.
Fix
Add a total connection deadline separate from the per-read timeout:
let deadline = tokio::time::Instant::now() + Duration::from_secs(10);
// In the read loop:
let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());
if remaining.is_zero() {
return Err(std::io::Error::new(
std::io::ErrorKind::TimedOut,
"total connection time exceeded",
));
}
let timeout = remaining.min(BOOTSTRAP_IO_TIMEOUT);
Also consider reducing MAX_CONCURRENT_BOOTSTRAP_CONNECTIONS and adding per-IP connection limits.
Locations
crates/relay/src/lib.rs:59 — MAX_CONCURRENT_BOOTSTRAP_CONNECTIONS = 1024
crates/relay/src/lib.rs:75 — BOOTSTRAP_IO_TIMEOUT = 5 seconds
crates/relay/src/lib.rs:196-222 — request reading loop
Problem
The relay's bootstrap ID HTTP handler (
crates/relay/src/lib.rs:196-222) reads the request line byte-by-byte with a per-read timeout ofBOOTSTRAP_IO_TIMEOUT = 5 secondsbut no total connection time limit. The connection count is bounded byMAX_CONCURRENT_BOOTSTRAP_CONNECTIONS = 1024via a semaphore.A Slowloris-style attack can exhaust all 1024 slots:
Severity
MEDIUM — DoS on bootstrap discovery. Does not affect already-connected peers, but prevents new peers from joining.
Fix
Add a total connection deadline separate from the per-read timeout:
Also consider reducing
MAX_CONCURRENT_BOOTSTRAP_CONNECTIONSand adding per-IP connection limits.Locations
crates/relay/src/lib.rs:59—MAX_CONCURRENT_BOOTSTRAP_CONNECTIONS = 1024crates/relay/src/lib.rs:75—BOOTSTRAP_IO_TIMEOUT = 5 secondscrates/relay/src/lib.rs:196-222— request reading loop