Problem
The relay has no rate limiting, making it vulnerable to DoS attacks where a malicious client could send unlimited messages and overwhelm the server, especially problematic on resource-constrained mobile devices.
Solution
Implement a simple per-connection rate limiter that tracks message count per time window and rejects messages when the limit is exceeded.
Implementation Details
1. Add connection tracking Map after line 8:
const connections = new Map() // Track per-connection stats
2. Add rate limiting logic in the message handler (after line 30):
socket.on('message', async (message) => {
// Rate limiting check
const now = Date.now()
const stats = connections.get(socket) || { count: 0, lastReset: now }
// Reset counter every minute
if (now - stats.lastReset > 60000) {
stats.count = 0
stats.lastReset = now
}
stats.count++
connections.set(socket, stats)
// Enforce rate limit (100 messages per minute)
if (stats.count > 100) {
socket.send('["NOTICE", "Rate limit exceeded. Please slow down."]')
return // Don't process the message
}
// Continue with existing message processing...
message = message?.toString()
// ...
})
3. Add cleanup on connection close (after line 37):
socket.on('close', () => {
subscribers.delete(socket)
connections.delete(socket) // Clean up rate limit tracking
})
4. Optional: Make rate limit configurable
const RATE_LIMIT = parseInt(process.env.RATE_LIMIT) || 100 // Messages per minute
const RATE_WINDOW = parseInt(process.env.RATE_WINDOW) || 60000 // Time window in ms
Testing
- Create a client that sends messages rapidly
- Verify that after 100 messages in a minute, further messages are rejected
- Wait 1 minute and verify the counter resets
- Verify memory is cleaned up when connections close
Impact
- Lines of code: ~20 lines
- Complexity: Minimal
- Breaking changes: None (legitimate clients won't hit the limit)
- Performance: O(1) operations only
Priority
HIGH - Essential for preventing abuse and ensuring stability on mobile devices.
Notes
- 100 messages/minute is reasonable for Nostr relay usage
- Could be enhanced later with per-IP limiting or more sophisticated algorithms
- Consider adding metrics for monitoring rate limit hits
Problem
The relay has no rate limiting, making it vulnerable to DoS attacks where a malicious client could send unlimited messages and overwhelm the server, especially problematic on resource-constrained mobile devices.
Solution
Implement a simple per-connection rate limiter that tracks message count per time window and rejects messages when the limit is exceeded.
Implementation Details
1. Add connection tracking Map after line 8:
2. Add rate limiting logic in the message handler (after line 30):
3. Add cleanup on connection close (after line 37):
4. Optional: Make rate limit configurable
Testing
Impact
Priority
HIGH - Essential for preventing abuse and ensuring stability on mobile devices.
Notes