You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js WebSocket实时笔记服务器遭DDoS攻击,求防护方案

Got it, let's tackle this WebSocket abuse issue you're facing. It’s super frustrating when bad actors spam garbage data to take down your app—here are several practical, actionable steps tailored to your Node.js + MongoDB setup:

1. Filter Garbage Message Content First

Start with the simplest check: block messages that match the exact pattern of your attacker’s spam (all 'a's). This stops the garbage at the door before it even reaches your database.

Here’s how to implement it with the ws library:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => {
  ws.on('message', (data) => {
    const message = data.toString().trim();
    
    // Reject messages that are only repeated 'a's
    if (/^a+$/.test(message)) {
      // Close the connection with a "policy violation" code
      ws.close(1008, 'Invalid message content');
      return;
    }

    // Proceed with your normal message processing/sync logic...
  });
});

2. Add Rate Limiting Per Client

Malicious actors rely on sending tons of requests quickly. Implement rate limiting to cap how many messages a single client (or IP) can send in a window of time.

You can track message counts with a Map:

const clientRateLimits = new Map(); // key: client IP, value: { count: number, resetTime: number }

wss.on('connection', (ws, req) => {
  const clientIP = ws._socket.remoteAddress;
  
  ws.on('message', (data) => {
    const now = Date.now();
    const limitData = clientRateLimits.get(clientIP) || { count: 0, resetTime: now + 10000 }; // 10-second window

    // Reset count if window has passed
    if (now > limitData.resetTime) {
      limitData.count = 1;
      limitData.resetTime = now + 10000;
    } else {
      limitData.count++;
      // Block if over 50 messages in 10 seconds (adjust based on your app's normal usage)
      if (limitData.count > 50) {
        ws.close(1008, 'Rate limit exceeded');
        clientRateLimits.delete(clientIP);
        return;
      }
    }
    clientRateLimits.set(clientIP, limitData);

    // Process valid messages...
  });

  // Clean up when client disconnects
  ws.on('close', () => {
    clientRateLimits.delete(clientIP);
  });
});

3. Enforce Authentication for WebSocket Connections

Since your app supports multi-device login sync, you already have user authentication—extend that to WebSocket connections. Require clients to send a valid auth token (like JWT) when connecting, and reject unauthenticated connections entirely.

Example with JWT verification:

const jwt = require('jsonwebtoken');

wss.on('connection', (ws, req) => {
  // Extract token from request headers or query params
  const authHeader = req.headers['authorization'];
  const token = authHeader?.split(' ')[1]; // Expecting "Bearer <token>"

  if (!token) {
    ws.close(1008, 'Authentication required');
    return;
  }

  // Verify the token
  jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
    if (err) {
      ws.close(1008, 'Invalid authentication');
      return;
    }
    // Attach user data to the WebSocket for future reference
    ws.user = decoded;
  });

  // In subsequent message handlers, check if ws.user exists before processing
  ws.on('message', (data) => {
    if (!ws.user) {
      ws.close(1008, 'Unauthenticated');
      return;
    }
    // Process valid, authenticated messages...
  });
});

4. Temporarily Ban Malicious IPs

If an IP repeatedly sends garbage data, ban it for a set period to prevent further abuse. Use a Map to track banned IPs and their unban times:

const bannedIPs = new Map(); // key: IP, value: unban timestamp (ms)

wss.on('connection', (ws, req) => {
  const clientIP = ws._socket.remoteAddress;
  
  // Check if IP is currently banned
  const unbanTime = bannedIPs.get(clientIP);
  if (unbanTime && Date.now() < unbanTime) {
    ws.close(1008, 'IP temporarily banned');
    return;
  }

  ws.on('message', (data) => {
    const message = data.toString().trim();
    if (/^a+$/.test(message)) {
      // Ban the IP for 1 hour (adjust as needed)
      bannedIPs.set(clientIP, Date.now() + 3600000);
      ws.close(1008, 'Malicious activity detected');
      return;
    }
    // Process valid messages...
  });
});

5. Add a Reverse Proxy for Extra Protection

Put a reverse proxy like Nginx or Cloudflare in front of your WebSocket server. This lets you handle rate limiting, connection limits, and even WAF rules before requests hit your Node.js app.

For example, here’s a snippet of Nginx config to limit connections and request rates:

location /ws {
  proxy_pass http://localhost:8080;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  
  # Limit each IP to 10 concurrent WebSocket connections
  limit_conn addr 10;
  # Allow 50 requests per second, with a burst of 20
  limit_req zone=ws burst=20 nodelay;
}

# Define the rate limit zone
limit_req_zone $binary_remote_addr zone=ws:10m rate=50r/s;

6. Protect MongoDB from Invalid Writes

Even if some garbage slips through, add a last line of defense at the database level. Validate content before writing to MongoDB, and reject any entries that match the spam pattern:

// Example Mongoose schema with validation
const noteSchema = new mongoose.Schema({
  userId: { type: String, required: true },
  content: { 
    type: String, 
    required: true,
    validate: {
      validator: function(v) {
        // Reject content that's only repeated 'a's
        return !/^a+$/.test(v.trim());
      },
      message: props => `${props.value} is invalid note content!`
    }
  }
});

const Note = mongoose.model('Note', noteSchema);

// When saving, the validation will automatically throw an error for garbage data
async function saveUserNote(userId, content) {
  try {
    await Note.create({ userId, content });
  } catch (err) {
    // Handle validation error (log it, notify admins, etc.)
    console.error('Failed to save note:', err.message);
  }
}

Final Tip: Combine Multiple Layers

For the best protection, use a mix of these methods—authentication blocks unregistered clients, content filtering stops known spam, rate limiting slows down attackers, and reverse proxies add a robust outer layer.

内容的提问来源于stack exchange,提问作者user8438001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:08:03