Sign In
Access your IPWhois.net account
No account? Create one
Node.js Integration
Express middleware with in-memory cache for checking IPs against the IPWhois Blacklist. Block malicious requests at the application layer.
5 min setup Express / Fastify In-memory cache
Blacklist / Docs / Node.js
Installation

No additional packages required. The middleware uses the built-in fetch API (Node 18+) or you can use node-fetch for older versions.

# For Node.js < 18, install node-fetch npm install node-fetch
Express Middleware
middleware/ipwhois-guard.js
const cache = new Map(); const CACHE_TTL = 3600000; // 1 hour in milliseconds const MIN_CONFIDENCE = 70; async function ipwhoisGuard(req, res, next) { // Extract real IP (handle proxies) const ip = (req.headers['x-forwarded-for'] || '').split(',')[0].trim() || req.socket.remoteAddress || req.ip; // Check cache first const cached = cache.get(ip); if (cached && Date.now() - cached.ts < CACHE_TTL) { if (cached.blocked) { return res.status(403).json({ error: 'Blocked', reason: cached.threat_type || 'blacklisted' }); } return next(); } try { const response = await fetch( `https://bl.ipwhois.net/api/check?ip=${encodeURIComponent(ip)}`, { signal: AbortSignal.timeout(3000) } ); const data = await response.json(); const blocked = data.listed && (data.confidence || 0) >= MIN_CONFIDENCE; cache.set(ip, { blocked, threat_type: data.threat_type, ts: Date.now() }); if (blocked) { return res.status(403).json({ error: 'Blocked', reason: data.threat_type }); } } catch (err) { // Fail open: allow request if API is unreachable console.error('IPWhois check failed:', err.message); } next(); } // Clean up stale cache entries every 10 minutes setInterval(() => { const now = Date.now(); for (const [ip, entry] of cache) { if (now - entry.ts > CACHE_TTL) cache.delete(ip); } }, 600000); module.exports = ipwhoisGuard;

Usage

app.js
const express = require('express'); const ipwhoisGuard = require('./middleware/ipwhois-guard'); const app = express(); // Protect specific routes app.use('/login', ipwhoisGuard); app.use('/api', ipwhoisGuard); // Or protect all routes // app.use(ipwhoisGuard); app.listen(3000);
Reporting Middleware

Report suspicious IPs to the blacklist from your Node.js app:

async function reportToIPWhois(ip, type = 'brute-force', message = '') { try { await fetch('https://bl.ipwhois.net/api/report', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ ip, type, message }), signal: AbortSignal.timeout(5000) }); } catch (err) { console.error('IPWhois report failed:', err.message); } } // Example: report after 5 failed logins app.post('/login', (req, res) => { // ... your auth logic ... if (failedAttempts >= 5) { reportToIPWhois(req.ip, 'brute-force', 'Login brute-force'); } });
Testing
# Test the check endpoint from your server curl -s "https://bl.ipwhois.net/api/check?ip=8.8.8.8" # Should return: {"listed":false,...} # Start your app and test node app.js & curl -s http://localhost:3000/login # Should return normally for clean IPs
Troubleshooting
  • fetch is not defined: You need Node.js 18+ for built-in fetch. For older versions: npm install node-fetch and add const fetch = require('node-fetch');
  • AbortSignal.timeout not available: Requires Node.js 18+. For older versions, use AbortController with setTimeout.
  • Getting 127.0.0.1 as IP: If behind a proxy, set app.set('trust proxy', true) so Express uses X-Forwarded-For.
  • Memory growth: The cache cleanup interval prevents unbounded growth. For high-traffic apps, consider using Redis instead of the in-memory Map.
IPWhois Blacklist — Community-driven IP threat intelligence — ipwhois.net