npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

cyberwatch-ddos

v1.2.0

Published

ML-powered DDoS detection middleware for Express.js — real-time anomaly detection using Isolation Forest trained on CIC-DDoS2019 dataset

Readme

cyberwatch-ddos

ML-powered DDoS detection middleware for Express.js — protect your Node.js API with real-time anomaly detection powered by an Isolation Forest model trained on the CIC-DDoS2019 dataset.

npm version Docker Image License: MIT

Normal User → ✅ Express App
Attacker    → 🛡️ CyberWatch → 🚫 429 Blocked

Table of Contents


How It Works

CyberWatch consists of two components that work together:

| Component | What it does | Where it runs | |-----------|-------------|---------------| | npm package (cyberwatch-ddos) | Express middleware — intercepts requests, extracts traffic features, blocks attackers | Inside your Node.js app | | ML service (Docker image) | Python FastAPI server — runs the Isolation Forest model, returns anomaly predictions | Docker container (or any server) |

Request flow:

  1. HTTP request hits your Express app
  2. cyberwatch middleware extracts the client IP
  3. Per-IP traffic patterns are tracked (rate, bytes, timing, etc.)
  4. After enough history (default: 3 requests), 18 network flow features are extracted
  5. Features are sent to the ML service via POST /predict
  6. If the model says anomaly with confidence above threshold → 429 Too Many Requests
  7. Normal traffic flows through to your routes untouched

Key principle: CyberWatch is fail-open — if the ML service is down or slow, all traffic passes through. Your app never breaks.


Quick Start (3 Steps)

Step 1: Start the ML Service (Docker)

docker run -d -p 5000:5000 --name cyberwatch-ml rohitpagi33/cyberwatch-ml:latest

Verify it's running:

curl http://localhost:5000/health
# → {"status": "healthy", "model_loaded": true}

Don't have Docker? See ML Service Setup for alternatives.

Step 2: Install the npm package

npm install cyberwatch-ddos

Step 3: Add to your Express app

const express = require('express');
const { cyberwatch } = require('cyberwatch-ddos');

const app = express();

// Add DDoS protection — that's it!
const guard = cyberwatch({
  mlServiceUrl: 'http://localhost:5000',
});
app.use(guard);

// Your routes work exactly as before
app.get('/', (req, res) => res.send('Hello, protected world!'));

// Optional: expose live metrics
app.get('/metrics', (req, res) => res.json(guard.getMetrics()));

app.listen(3000, () => console.log('🛡️ Protected server on :3000'));

That's it — 3 steps. Your app now has ML-powered DDoS protection.


Complete Example

This is a full Express API with DDoS protection, metrics endpoints, and manual IP management:

const express = require('express');
const cors = require('cors');
const { cyberwatch } = require('cyberwatch-ddos');

const app = express();
app.use(cors());
app.use(express.json());

// ── Initialize CyberWatch DDoS Guard ────────────────────────
const guard = cyberwatch({
  mlServiceUrl: process.env.ML_SERVICE_URL || 'http://localhost:5000',

  // Detection tuning (all optional — defaults work well)
  anomalyThreshold: 0.5,           // block if ML confidence > 50%
  blockDuration: 5 * 60 * 1000,    // block attackers for 5 minutes
  minRequestsBeforeML: 3,          // allow first 3 requests from any IP
  skipPaths: ['/health'],          // don't analyze health-check requests
  whitelist: ['127.0.0.1'],        // never block these IPs

  // Get notified when an attack is blocked
  onAnomaly: (ip, score) => {
    console.log(`🚨 Blocked — IP: ${ip} | Score: ${score}`);
    // Send to your logging/alerting system here
  },

  debug: false,  // set true during development
});
app.use(guard);

// ── Your API routes (completely unchanged) ──────────────────

app.get('/', (req, res) => {
  res.json({ message: 'Welcome to My API', protected: true });
});

app.get('/health', (req, res) => {
  res.json({ status: 'ok', uptime: process.uptime() });
});

app.get('/api/users', (req, res) => {
  res.json([
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
  ]);
});

// ── DDoS metrics & management endpoints (optional) ──────────

app.get('/api/ddos/metrics', (req, res) => {
  res.json(guard.getMetrics());
});

app.get('/api/ddos/blocked', (req, res) => {
  const { blockedIPs } = guard.getMetrics();
  res.json({ blocked: blockedIPs, total: blockedIPs.length });
});

app.post('/api/ddos/block', (req, res) => {
  const { ip } = req.body;
  if (!ip) return res.status(400).json({ error: 'ip required' });
  guard.blockIP(ip);
  res.json({ success: true, message: `Blocked ${ip}` });
});

app.post('/api/ddos/unblock', (req, res) => {
  const { ip } = req.body;
  if (!ip) return res.status(400).json({ error: 'ip required' });
  guard.unblockIP(ip);
  res.json({ success: true, message: `Unblocked ${ip}` });
});

// ── Graceful shutdown ───────────────────────────────────────
process.on('SIGTERM', () => guard.destroy());

app.listen(3000, () => console.log('🛡️ Server running on :3000'));

Running the example

# Terminal 1: Start ML service
docker run -d -p 5000:5000 --name cyberwatch-ml rohitpagi33/cyberwatch-ml:latest

# Terminal 2: Run your app
npm install cyberwatch-ddos express cors
node server.js

# Terminal 3: Test it
curl http://localhost:3000/              # → normal response
curl http://localhost:3000/api/users     # → user list
curl http://localhost:3000/api/ddos/metrics  # → live protection stats

Configuration Reference

const guard = cyberwatch(options);

All Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | mlServiceUrl | string | 'http://localhost:5000' | URL of the ML inference API | | mlServiceTimeout | number | 5000 | Timeout for ML requests in milliseconds | | anomalyThreshold | number | 0.5 | Confidence score (0–1) required to block. Higher = fewer blocks | | minRequestsBeforeML | number | 3 | Allow this many requests from a new IP before ML kicks in | | blockDuration | number | 300000 | How long to block a flagged IP in ms (default: 5 min) | | skipPaths | string[] | ['/health'] | URL paths to skip ML analysis entirely | | whitelist | string[] | [] | IPs that are never blocked, no matter what | | onAnomaly | function | null | Callback when an IP is blocked: (ip, score) => {} | | onRequest | function | null | Callback for every ML-analyzed request: (ip, prediction) => {} | | debug | boolean | false | Enable verbose console logging |

Configuration Examples

Strict protection (block more aggressively):

cyberwatch({
  mlServiceUrl: 'http://localhost:5000',
  anomalyThreshold: 0.3,       // lower threshold = more blocking
  minRequestsBeforeML: 1,      // start analyzing immediately
  blockDuration: 30 * 60 * 1000, // block for 30 minutes
});

Relaxed protection (fewer false positives):

cyberwatch({
  mlServiceUrl: 'http://localhost:5000',
  anomalyThreshold: 0.8,       // only block very obvious attacks
  minRequestsBeforeML: 10,     // give IPs more time
  blockDuration: 60 * 1000,    // block for only 1 minute
  whitelist: ['10.0.0.0/8'],   // trust internal IPs
});

Production with logging (alert your team):

cyberwatch({
  mlServiceUrl: process.env.ML_SERVICE_URL,
  onAnomaly: (ip, score) => {
    // Send to Slack, PagerDuty, Datadog, etc.
    alertService.send(`DDoS blocked: ${ip} (score: ${score})`);
  },
  onRequest: (ip, prediction) => {
    // Log every prediction for analysis
    logger.info({ ip, ...prediction });
  },
});

API Methods

The cyberwatch() function returns an Express middleware with these extra methods:

const guard = cyberwatch({ mlServiceUrl: 'http://localhost:5000' });
app.use(guard);

guard.getMetrics()

Returns real-time protection statistics:

app.get('/api/metrics', (req, res) => res.json(guard.getMetrics()));

Response:

{
  "uptime": 120000,
  "totalRequests": 5423,
  "blockedRequests": 342,
  "anomalyDetections": 342,
  "requestsPerSecond": 45.2,
  "blockPercentage": 6.3,
  "blockedIPs": [
    {
      "ip": "45.33.12.1",
      "count": 120,
      "lastScore": -0.65,
      "expiresIn": 180000
    }
  ],
  "mlHealthy": true,
  "recentAnomalies": [
    {
      "ip": "45.33.12.1",
      "score": -0.65,
      "timestamp": "2024-01-15T10:30:00.000Z"
    }
  ]
}

guard.blockIP(ip)

Manually block an IP address. Expires after blockDuration.

guard.blockIP('192.168.1.100');

guard.unblockIP(ip)

Remove a blocked IP immediately:

guard.unblockIP('192.168.1.100');

guard.isBlocked(ip)

Check if an IP is currently blocked:

if (guard.isBlocked('192.168.1.100')) {
  console.log('This IP is blocked');
}

guard.destroy()

Clean up internal timers. Call this on graceful shutdown:

process.on('SIGTERM', () => {
  guard.destroy();
  server.close();
});

ML Service Setup

The ML service is a lightweight Python FastAPI server (~200MB Docker image) that loads a pre-trained Isolation Forest model.

Option A: Docker Hub (Recommended)

# Pull and run
docker run -d -p 5000:5000 --name cyberwatch-ml rohitpagi33/cyberwatch-ml:latest

# Check health
curl http://localhost:5000/health
# → {"status": "healthy", "model_loaded": true}

# View logs
docker logs cyberwatch-ml

# Stop / Remove
docker stop cyberwatch-ml
docker rm cyberwatch-ml

Available tags:

| Tag | Description | |-----|-------------| | rohitpagi33/cyberwatch-ml:latest | Latest stable release | | rohitpagi33/cyberwatch-ml:1.0.0 | Pinned version 1.0.0 |

Option B: Docker Compose

Create a docker-compose.yml:

version: '3.8'
services:
  ml-service:
    image: rohitpagi33/cyberwatch-ml:latest
    ports:
      - '5000:5000'
    restart: unless-stopped
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:5000/health']
      interval: 30s
      timeout: 10s
      retries: 3
docker-compose up -d

Option C: Build from Source

git clone https://github.com/rohitpagi33/CyberWatch---DDOS-Detection.git
cd CyberWatch---DDOS-Detection/ml-service

# Docker build
docker build -t cyberwatch-ml .
docker run -d -p 5000:5000 cyberwatch-ml

Option D: Run with Python directly (no Docker)

git clone https://github.com/rohitpagi33/CyberWatch---DDOS-Detection.git
cd CyberWatch---DDOS-Detection/ml-service

# Create virtual environment
python -m venv venv
# Linux/Mac: source venv/bin/activate
# Windows:   .\venv\Scripts\activate

pip install -r requirements.txt

# Train the model (one-time, requires dataset in datasets/ folder)
python train_model.py

# Start the API
python inference_api.py
# → Uvicorn running on http://0.0.0.0:5000

ML Service API Endpoints

| Endpoint | Method | Description | |----------|--------|-------------| | /health | GET | Returns { status, model_loaded } | | /predict | POST | Single prediction — accepts 18 features, returns { anomaly, confidence } | | /batch-predict | POST | Batch predictions — accepts array of feature vectors |

Example: Test a prediction directly

curl -X POST http://localhost:5000/predict \
  -H "Content-Type: application/json" \
  -d '{"features": [100, 5000, 80, 4000, 1.5, 50, 3000, 0.02, 1, 1, 0, 0, 200, 180, 30, 1500, 25, 1200]}'

Response:

{
  "anomaly": true,
  "confidence": 0.73,
  "raw_score": -0.42
}

Architecture & Request Flow

┌──────────────────┐      ┌──────────────────────────────┐      ┌──────────────┐
│                  │      │        Your Express App       │      │              │
│     Client       │─────▶│                              │─────▶│  Your API    │
│   (Browser /     │      │  ┌────────────────────────┐  │      │  Routes      │
│    API caller)   │      │  │   cyberwatch-ddos      │  │      │              │
│                  │      │  │   middleware            │  │      └──────────────┘
└──────────────────┘      │  └──────────┬─────────────┘  │
                          │             │                 │
                          └─────────────┼─────────────────┘
                                        │
                               HTTP POST /predict
                                        │
                          ┌─────────────▼─────────────────┐
                          │      ML Service (Docker)      │
                          │  FastAPI + Isolation Forest    │
                          │  rohitpagi33/cyberwatch-ml     │
                          └───────────────────────────────┘

Detailed Request Flow

Request arrives
    │
    ▼
Extract client IP
(X-Forwarded-For, CF-Connecting-IP, req.ip)
    │
    ▼
Is IP whitelisted? ──── YES ──→ next() ──→ Your route
    │ NO
    ▼
Is IP already blocked? ── YES ──→ 429 Too Many Requests
    │ NO
    ▼
Record request metrics (rate, bytes, timing)
    │
    ▼
Has IP sent ≥ minRequestsBeforeML? ── NO ──→ next() ──→ Your route
    │ YES
    ▼
Is path in skipPaths? ── YES ──→ next() ──→ Your route
    │ NO
    ▼
Extract 18 features from IP history
    │
    ▼
Send features to ML service (POST /predict)
    │
    ▼
ML service returns { anomaly, confidence }
    │
    ▼
anomaly=true AND confidence > threshold?
    │ YES                           │ NO
    ▼                               ▼
Block IP                        next() ──→ Your route
Call onAnomaly()
Return 429

Fail-Safe Design

| Scenario | Behavior | |----------|----------| | ML service is down | All traffic passes through (fail-open) | | ML prediction times out | Request allowed through | | ML returns an error | Request allowed through | | Middleware throws error | next() called — your app never breaks | | New IP (< 3 requests) | Always allowed through (building traffic history) |


Feature Extraction (18 Features)

For each IP, the middleware tracks per-request metrics and extracts these network flow features (inspired by CICFlowMeter):

| # | Feature | Description | |---|---------|-------------| | 1 | Fwd Packets/s | Forward (incoming) packet rate | | 2 | Fwd Bytes Total | Total bytes received from client | | 3 | Bwd Packets/s | Backward (outgoing) packet rate | | 4 | Bwd Bytes Total | Total response bytes sent | | 5 | Flow Duration | Time elapsed since first request from this IP | | 6 | Packets/s | Overall request/response rate | | 7 | Bytes/s | Total throughput | | 8 | Flow IAT Mean | Average inter-arrival time between requests | | 9 | Fwd PSH Flags | Keep-alive / persistent connection indicators | | 10 | Bwd PSH Flags | Server push indicators | | 11 | Fwd URG Flags | Urgent priority flags (incoming) | | 12 | Bwd URG Flags | Urgent priority flags (outgoing) | | 13 | Fwd Header Length | Average request header size | | 14 | Bwd Header Length | Average response header size | | 15 | Subflow Fwd Packets | Incoming packets in last 5-second window | | 16 | Subflow Fwd Bytes | Incoming bytes in last 5-second window | | 17 | Subflow Bwd Packets | Outgoing packets in last 5-second window | | 18 | Subflow Bwd Bytes | Outgoing bytes in last 5-second window |


Model Performance

| Metric | Value | |--------|-------| | Algorithm | Isolation Forest (scikit-learn, 200 estimators) | | Dataset | CIC-DDoS2019 (125,170 samples) | | Training | Benign traffic only (46,427 samples — unsupervised) | | Contamination | 0.30 | | Precision | 78.3% | | Recall | 63.7% | | F1-Score | 70.2% |

Attack types detected: SYN Flood, UDP Flood, LDAP Amplification, MSSQL Amplification, NetBIOS Amplification, Portmap, UDP-Lag

For detailed model documentation including training pipeline, feature importance, confusion matrix, and tuning guide, see the ML_DOCUMENTATION.md in the GitHub repository.


Deployment Guide

Production Checklist

// production-config.js
const guard = cyberwatch({
  mlServiceUrl: process.env.ML_SERVICE_URL,     // never hardcode in prod
  anomalyThreshold: 0.5,                        // tune based on your traffic
  blockDuration: 10 * 60 * 1000,                // 10 min blocks in prod
  skipPaths: ['/health', '/ready', '/metrics'],  // skip internal paths
  debug: false,                                  // always false in prod

  onAnomaly: (ip, score) => {
    // 1. Log to your monitoring system
    logger.warn({ event: 'ddos_blocked', ip, score });

    // 2. Alert your team (Slack, PagerDuty, etc.)
    alerting.notify(`DDoS attack blocked: ${ip}`);
  },
});

Docker Compose (Full Stack)

version: '3.8'
services:
  ml-service:
    image: rohitpagi33/cyberwatch-ml:latest
    ports:
      - '5000:5000'
    restart: unless-stopped
    healthcheck:
      test: ['CMD', 'curl', '-f', 'http://localhost:5000/health']
      interval: 30s
      timeout: 10s
      retries: 3

  my-api:
    build: .
    ports:
      - '3000:3000'
    environment:
      - ML_SERVICE_URL=http://ml-service:5000
    depends_on:
      ml-service:
        condition: service_healthy
    restart: unless-stopped

Cloud Deployment

AWS / GCP / Azure:

  1. Run the ML service as a container (ECS, Cloud Run, ACI, etc.)
  2. Set ML_SERVICE_URL to the internal service URL
  3. Install cyberwatch-ddos in your Node.js app as usual

Railway / Render / Fly.io:

  1. Deploy the ML service image rohitpagi33/cyberwatch-ml:latest
  2. Note the internal URL (e.g., http://ml-service.internal:5000)
  3. Set ML_SERVICE_URL env var in your Node.js service

Performance

| Metric | Value | |--------|-------| | Added latency | ~50–100ms per request (includes ML roundtrip) | | Throughput | 1,000+ req/s | | Memory | ~50–200MB depending on tracked IPs | | ML inference | <10ms per prediction | | Docker image | ~200MB |


Troubleshooting

| Problem | Solution | |---------|----------| | ECONNREFUSED to ML service | Make sure docker run -d -p 5000:5000 rohitpagi33/cyberwatch-ml is running | | Traffic passes through unblocked | Check debug: true — ML may not be reachable, or threshold may be too high | | Too many false positives | Increase anomalyThreshold (e.g., 0.7 or 0.8) | | Legitimate users getting blocked | Add trusted IPs to whitelist or increase minRequestsBeforeML | | ML health check fails | Run curl http://localhost:5000/health — check Docker logs: docker logs cyberwatch-ml | | Module not found error | Make sure you installed: npm install cyberwatch-ddos | | Can't import { cyberwatch } | Use destructuring: const { cyberwatch } = require('cyberwatch-ddos') |

Quick health check script

# Check ML service
curl -s http://localhost:5000/health | python -m json.tool

# Test a prediction
curl -s -X POST http://localhost:5000/predict \
  -H "Content-Type: application/json" \
  -d '{"features": [1,100,1,100,5,0.4,40,5,0,0,0,0,200,200,1,100,1,100]}' \
  | python -m json.tool

Contributing

Contributions are welcome! See the GitHub repository for source code.

  1. Fork the repo
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make changes and test
  4. Submit a pull request

Links

License

MIT — see LICENSE for details.