Comment détecter un VPN en Node.js (étape par étape)
Un tutoriel Node.js pratique : appelez une API de détection de VPN depuis votre backend, lisez le verdict et le score de confiance, et conditionnez les inscriptions ou connexions au résultat.
Voici un guide pratique pour détecter le trafic VPN depuis un backend Node.js. Nous allons interroger l'IP du visiteur via une API de détection de VPN, lire le verdict et le score de confiance, puis nous en servir pour conditionner une inscription. Le même schéma fonctionne pour les connexions et les paiements.
Avant de commencer
Il vous faut une clé API (le plan gratuit suffit pour tester) et Node 18+ pour disposer du
fetch global. Conservez la clé dans une variable d'environnement, jamais dans le code client.
Testez d'abord la recherche sur une IP quelconque
Étape 1 : récupérer la véritable IP du client
Derrière un proxy ou un load balancer, req.socket.remoteAddress correspond à votre
infrastructure, pas à l'utilisateur. Lisez l'en-tête forwarded défini par votre proxy de
confiance :
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;
}
Ne faites confiance à X-Forwarded-For que si un proxy que vous contrôlez le définit, sinon un
client pourrait le falsifier.
Étape 2 : appeler l'API de détection
Encapsulez la recherche dans une petite fonction utilitaire. Elle renvoie le verdict et le score, et échoue de façon permissive (autorise) en cas d'erreur réseau, afin qu'une panne de la détection ne bloque jamais vos utilisateurs :
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
}
}
Étape 3 : conditionner une inscription au résultat
Utilisez maintenant le score pour décider. En dessous d'un seuil, on autorise ; au milieu, on exige une vérification supplémentaire ; au-dessus, on bloque :
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 });
});
Remarquez que dans la tranche intermédiaire, on ajoute une vérification plutôt que de bloquer. Pour comprendre pourquoi c'est important, voir comment bloquer intelligemment les utilisateurs de VPN.
Étape 4 : mettre en cache pour économiser des recherches
La même IP revient souvent à plusieurs reprises. Un cache de courte durée réduit les appels API sans risquer des données périmées :
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;
}
Gardez une TTL courte (des minutes, pas des jours), car le risque associé à une IP évolue. Voir qu'est-ce que la réputation IP.
Pour aller plus loin
- Ajoutez la détection de proxy au même flux pour repérer non seulement les VPN, mais aussi les proxys et Tor.
- Regroupez les signaux en un seul score de fraude IP et conditionnez vos décisions sur ce chiffre unique.
- Appliquez le même schéma à la connexion et au paiement, en ajustant les seuils selon l'action.
En résumé
Détecter un VPN en Node.js se résume à un seul appel API côté serveur : résoudre la véritable IP du client, l'interroger, puis agir selon le verdict et le score. Échouez de façon permissive en cas d'erreur, mettez en cache brièvement, et exigez une vérification dans la tranche de risque intermédiaire plutôt que de bloquer d'emblée.