Cómo detectar una VPN en Node.js (paso a paso)
Un tutorial práctico de Node.js: llama a una API de detección de VPN desde tu backend, lee el veredicto y la puntuación de confianza, y condiciona registros o inicios de sesión al resultado.
Esta es una guía práctica para detectar tráfico VPN desde un backend de Node.js. Consultaremos la IP del visitante en una API de detección de VPN, leeremos el veredicto y la puntuación de confianza, y la usaremos para condicionar un registro. El mismo patrón funciona para inicios de sesión y pagos.
Antes de empezar
Necesitarás una clave API (el plan gratuito es suficiente para probar) y Node 18+ para que el
fetch global esté disponible. Guarda la clave en una variable de entorno, nunca en código de
cliente.
Prueba primero la búsqueda con cualquier IP
Paso 1: obtener la IP real del cliente
Detrás de un proxy o balanceador de carga, req.socket.remoteAddress es tu infraestructura, no
el usuario. Lee la cabecera forwarded que establece tu proxy de confianza:
function getClientIp(req) {
const xff = req.headers['x-forwarded-for'];
if (xff) return xff.split(',')[0].trim(); // left-most = original client
return req.socket.remoteAddress;
}
Confía en X-Forwarded-For solo si la establece un proxy que controlas; de lo contrario, un
cliente podría falsificarla.
Paso 2: llamar a la API de detección
Envuelve la búsqueda en una pequeña función auxiliar. Devuelve el veredicto y la puntuación, y falla de forma abierta (permite el acceso) ante errores de red, para que un fallo en la detección nunca bloquee a tus usuarios:
const API_BASE = 'https://ipscanner.io';
async function checkVpn(ip) {
try {
const res = await fetch(`${API_BASE}/v1/vpn/${ip}`, {
headers: { Authorization: `Bearer ${process.env.IPSCANNER_API_KEY}` }
});
if (!res.ok) throw new Error(`lookup failed: ${res.status}`);
const data = await res.json();
return { isVpn: Boolean(data.vpn), score: data.score ?? 0 };
} catch (err) {
console.error('vpn check error', err);
return { isVpn: false, score: 0 }; // fail open
}
}
Paso 3: condicionar un registro al resultado
Ahora usa la puntuación para decidir. Por debajo de un umbral, permite; en el rango medio, exige verificación adicional; alto, bloquea:
app.post('/signup', async (req, res) => {
const ip = getClientIp(req);
const { isVpn, score } = await checkVpn(ip);
if (score >= 70) {
return res.status(403).json({ error: 'Signups from this network need verification.' });
}
if (isVpn || score >= 30) {
req.session.requireEmailVerification = true; // add friction, don't block
}
// ...create the account...
res.json({ ok: true });
});
Observa que en la banda intermedia pedimos verificación en lugar de bloquear. Consulta cómo bloquear usuarios de VPN de forma inteligente para entender por qué importa.
Paso 4: usar caché para ahorrar búsquedas
La misma IP suele repetirse con frecuencia. Una caché de corta duración reduce las llamadas a la API sin arriesgar datos obsoletos:
const cache = new Map(); // ip -> { value, expires }
async function checkVpnCached(ip, ttlMs = 10 * 60 * 1000) {
const hit = cache.get(ip);
if (hit && hit.expires > Date.now()) return hit.value;
const value = await checkVpn(ip);
cache.set(ip, { value, expires: Date.now() + ttlMs });
return value;
}
Mantén el TTL corto (minutos, no días), porque el riesgo de una IP cambia. Consulta qué es la reputación de IP.
Para ir más allá
- Añade detección de proxy al mismo flujo para detectar no solo VPN, sino también proxies y Tor.
- Consolida las señales en una única puntuación de fraude por IP y condiciona tus decisiones a ese único número.
- Aplica el mismo patrón a inicio de sesión y pago, ajustando los umbrales según la acción.
En resumen
Detectar una VPN en Node.js se reduce a una sola llamada API del lado del servidor: resolver la IP real del cliente, consultarla y actuar según el veredicto y la puntuación. Falla de forma abierta ante errores, usa caché brevemente, y exige verificación en la banda de riesgo intermedia en lugar de bloquear directamente.