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
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-fetchand addconst fetch = require('node-fetch'); - AbortSignal.timeout not available: Requires Node.js 18+. For older versions, use
AbortControllerwithsetTimeout. - Getting 127.0.0.1 as IP: If behind a proxy, set
app.set('trust proxy', true)so Express usesX-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