Ir al contenido
Guide

API de detección de VPN y proxy: marcar el abuso sin bloquear a los usuarios

| 7 min read

Detecte conexiones VPN, proxy, Tor y centros de datos con una solicitud POST. Incluye ejemplos de middleware Next.js, limitación de velocidad Express y puntuación de fraude.

Digital shield icon with network connections
Photo by Privecstasy on Unsplash

Su aplicación SaaS ofrece una prueba gratuita por usuario. Los usuarios se registran, activan una VPN y se registran nuevamente. El abuso de promociones le cuesta ingresos y distorsiona sus métricas de conversión. Necesitas marcar VPN y proxy conexiones en el momento de registrarse.

Esta guía cubre el botoi. POST /v1/vpn-detect punto final: qué devuelve, cómo integrarlo en las aplicaciones Next.js y Express, cómo combinarlo con otras señales de fraude y dónde se queda corto.

El punto final

Una solicitud POST con una dirección IP en el cuerpo. Sin encabezados especiales, no se requiere clave API para acceso anónimo.

curl -X POST https://api.botoi.com/v1/vpn-detect \\
  -H "Content-Type: application/json" \\
  -d '{ "ip": "185.220.101.1" }'

Respuesta para un nodo de salida de Tor conocido:

{
  "success": true,
  "data": {
    "ip": "185.220.101.1",
    "is_vpn": true,
    "is_proxy": false,
    "is_tor": true,
    "is_datacenter": false,
    "provider": null,
    "risk_score": 90,
    "checks": {
      "tor": true,
      "datacenter": false,
      "suspicious_hostname": false
    }
  }
}

Respuesta para una IP residencial limpia:

{
  "success": true,
  "data": {
    "ip": "73.162.45.118",
    "is_vpn": false,
    "is_proxy": false,
    "is_tor": false,
    "is_datacenter": false,
    "provider": null,
    "risk_score": 0,
    "checks": {
      "tor": false,
      "datacenter": false,
      "suspicious_hostname": false
    }
  }
}

Campos de respuesta

  • es_vpn (booleano): Verdadero si la IP pertenece a un rango de centro de datos conocido o tiene un nombre de host DNS inverso sospechoso que contiene palabras clave relacionadas con VPN.
  • es_proxy (booleano): Verdadero si el nombre de host DNS inverso sugiere un servidor proxy.
  • es_tor (booleano): Verdadero si la IP coincide con un nodo de salida de Tor conocido.
  • is_datacenter (booleano): Verdadero si la IP se encuentra dentro de los rangos de AWS, Google Cloud, Azure, DigitalOcean o Linode CIDR.
  • proveedora (cadena o nulo): el nombre del proveedor de la nube cuando is_datacenter es verdad. Nulo para IP residenciales y Tor.
  • puntuación_riesgo (número, 0-100): las conexiones Tor obtienen una puntuación de 90, las IP del centro de datos obtienen una puntuación de 60, los nombres de host sospechosos obtienen una puntuación de 40. Las IP residenciales limpias obtienen una puntuación de 0.
  • cheques (objeto): desglose de los métodos de detección que se activaron, para la depuración.

Marcar a los usuarios de VPN al registrarse con el middleware Next.js

Este middleware intercepta solicitudes POST a su ruta de registro, verifica la IP de la persona que llama con la API de detección de VPN y adjunta un encabezado a la solicitud cuando se detecta una VPN. Su controlador de registro lee el encabezado y decide qué hacer: solicitar verificación por correo electrónico, agregar una marca de revisión manual o reducir el período de prueba.

import { NextRequest, NextResponse } from 'next/server';

const VPN_DETECT_URL = 'https://api.botoi.com/v1/vpn-detect';

export async function middleware(req: NextRequest) {
  if (req.method !== 'POST') {
    return NextResponse.next();
  }

  const ip = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim()
    || req.ip
    || '127.0.0.1';

  try {
    const res = await fetch(VPN_DETECT_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ip }),
      signal: AbortSignal.timeout(3000),
    });

    const { data } = await res.json();

    if (data.is_vpn || data.is_tor || data.is_proxy) {
      // Add a header so your signup handler can flag the account
      const response = NextResponse.next();
      response.headers.set('x-vpn-detected', 'true');
      response.headers.set('x-vpn-risk-score', String(data.risk_score));
      return response;
    }
  } catch {
    // Fail open: if the API is unreachable, let the request through
    console.warn('VPN detection check failed, allowing request');
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/api/auth/signup', '/api/auth/register'],
};

El middleware no bloquea el registro. Pasa una señal a su manejador. este es el derecho enfoque porque el tráfico VPN no es prueba de fraude. Un usuario en una VPN corporativa o viajando a través de una red restrictiva es un cliente legítimo.

Límites de velocidad más estrictos para IP VPN en Express

Si ejecuta una API, puede aplicar límites de velocidad más estrictos a las conexiones VPN y proxy sin bloquear ellos directamente. Este middleware ofrece a los usuarios estándar 100 solicitudes por hora y a los usuarios de VPN 20.

import type { Request, Response, NextFunction } from 'express';

const VPN_DETECT_URL = 'https://api.botoi.com/v1/vpn-detect';
const BOTOI_API_KEY = process.env.BOTOI_API_KEY;

// Standard limits
const STANDARD_LIMIT = 100; // requests per hour
const VPN_LIMIT = 20;       // requests per hour for VPN users

const requestCounts = new Map<string, { count: number; resetAt: number }>();

export async function vpnAwareRateLimit(
  req: Request,
  res: Response,
  next: NextFunction
) {
  const ip = req.headers['x-forwarded-for']?.toString().split(',')[0]?.trim()
    || req.socket.remoteAddress
    || 'unknown';

  let isVpn = false;

  try {
    const vpnRes = await fetch(VPN_DETECT_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': \`Bearer \${BOTOI_API_KEY}\`,
      },
      body: JSON.stringify({ ip }),
      signal: AbortSignal.timeout(2000),
    });

    const { data } = await vpnRes.json();
    isVpn = data.is_vpn || data.is_tor || data.is_proxy;
  } catch {
    // Fail open: use standard limits if detection fails
  }

  const limit = isVpn ? VPN_LIMIT : STANDARD_LIMIT;
  const now = Date.now();
  const entry = requestCounts.get(ip);

  if (!entry || entry.resetAt < now) {
    requestCounts.set(ip, { count: 1, resetAt: now + 3600_000 });
    res.setHeader('X-RateLimit-Limit', limit);
    return next();
  }

  entry.count++;

  if (entry.count > limit) {
    return res.status(429).json({
      error: 'Rate limit exceeded',
      retryAfter: Math.ceil((entry.resetAt - now) / 1000),
    });
  }

  res.setHeader('X-RateLimit-Limit', limit);
  res.setHeader('X-RateLimit-Remaining', limit - entry.count);
  next();
}

La proporción de 5:1 entre los límites estándar y VPN es un punto de partida. Sintonízalo según tu abuso patrones. Si su API maneja pagos o modificaciones de cuentas, tiene sentido establecer límites de VPN más estrictos. Para puntos finales de solo lectura, es posible que no necesite ningún límite diferencial.

Puntuación de fraude: combine la detección de VPN con otras señales

La detección de VPN por sí sola es una señal débil de fraude. Una VPN + correo electrónico desechable + cuenta nueva + fallida Los intentos de pago son una señal fuerte. Esta función combina múltiples entradas en un solo fraude puntuación.

interface FraudSignals {
  vpnDetected: boolean;
  riskScore: number;
  disposableEmail: boolean;
  accountAge: number; // days
  failedPayments: number;
}

function calculateFraudScore(signals: FraudSignals): number {
  let score = 0;

  // VPN/proxy risk contributes up to 30 points
  if (signals.vpnDetected) {
    score += Math.round(signals.riskScore * 0.3);
  }

  // Disposable email: strong signal
  if (signals.disposableEmail) {
    score += 35;
  }

  // New account + VPN is a red flag
  if (signals.accountAge < 1 && signals.vpnDetected) {
    score += 20;
  }

  // Failed payment history
  score += Math.min(signals.failedPayments * 10, 30);

  return Math.min(score, 100);
}

async function assessSignupRisk(ip: string, email: string) {
  const [vpnRes, emailRes] = await Promise.all([
    fetch('https://api.botoi.com/v1/vpn-detect', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ip }),
    }),
    fetch('https://api.botoi.com/v1/disposable-email/check', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    }),
  ]);

  const vpnData = (await vpnRes.json()).data;
  const emailData = (await emailRes.json()).data;

  const fraudScore = calculateFraudScore({
    vpnDetected: vpnData.is_vpn || vpnData.is_tor,
    riskScore: vpnData.risk_score,
    disposableEmail: emailData.is_disposable,
    accountAge: 0, // new signup
    failedPayments: 0,
  });

  return {
    fraudScore,
    action: fraudScore > 70 ? 'block' : fraudScore > 40 ? 'review' : 'allow',
    details: {
      vpn: vpnData.is_vpn,
      tor: vpnData.is_tor,
      proxy: vpnData.is_proxy,
      disposableEmail: emailData.is_disposable,
    },
  };
}

Ambas llamadas API se ejecutan en paralelo, por lo que la latencia total es la más lenta de las dos (normalmente bajo 100 ms). El action El campo le ofrece tres niveles: permitir, revisar o bloquear. Para puntuaciones entre 40 y 70, dirige el registro a una cola de revisión manual en lugar de rechazarlo automáticamente.

Almacenamiento en caché para reducir las llamadas API

Una dirección IP no cambia su estado de VPN en cada solicitud. Guarde en caché el resultado durante 10 minutos para reduzca el uso de API sin perder cambios de estado.

const vpnCache = new Map<string, { result: VpnResult; expiresAt: number }>();
const CACHE_TTL = 10 * 60 * 1000; // 10 minutes

interface VpnResult {
  isVpn: boolean;
  isTor: boolean;
  isProxy: boolean;
  riskScore: number;
}

async function checkVpn(ip: string): Promise<VpnResult> {
  const cached = vpnCache.get(ip);
  if (cached && cached.expiresAt > Date.now()) {
    return cached.result;
  }

  try {
    const res = await fetch('https://api.botoi.com/v1/vpn-detect', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ip }),
      signal: AbortSignal.timeout(3000),
    });

    const { data } = await res.json();
    const result: VpnResult = {
      isVpn: data.is_vpn,
      isTor: data.is_tor,
      isProxy: data.is_proxy,
      riskScore: data.risk_score,
    };

    vpnCache.set(ip, { result, expiresAt: Date.now() + CACHE_TTL });
    return result;
  } catch {
    return { isVpn: false, isTor: false, isProxy: false, riskScore: 0 };
  }
}

Para implementaciones de múltiples servidores, cambie el mapa en memoria por Redis o Upstash. La misma clave de caché (Dirección IP) y patrón TTL se aplican.

Lo que esta API no puede detectar

La honestidad acerca de las limitaciones importa más que un discurso de venta pulido. Aquí es donde la detección de VPN se queda corto.

  • VPN residenciales. Servicios como iCloud Private Relay y algunas configuraciones de Mullvad enruta el tráfico a través de direcciones IP residenciales. Estas IP parecen idénticas a Conexiones regulares a Internet en casa. Ninguna detección inversa basada en DNS o CIDR los detecta.
  • NAT del operador de telefonía móvil. Los operadores de telefonía móvil utilizan NAT de nivel de operador, lo que significa Miles de usuarios comparten una única dirección IP. Marcar estas IP afecta a los usuarios legítimos. La API puede regresar is_datacenter: false y risk_score: 0 para estos IP incluso cuando un usuario de VPN está detrás de ellas.
  • Proxies SOCKS5 privados. Proxies alojados en servidores personales con acceso residencial. Los ISP no aparecen en los rangos CIDR del centro de datos y no tienen nombres de host sospechosos. ellos son invisible para la detección automática.
  • Conexiones solo IPv6. El punto final actual solo admite direcciones IPv4. La detección de VPN IPv6 no está disponible.
  • Falsos positivos en hosting compartido. Un desarrollador que ejecuta un proyecto paralelo en un La gota de DigitalOcean se activará is_datacenter: true. Eso no significa que sean ocultando su identidad.

La detección funciona bien para proveedores de VPN comerciales (NordVPN, ExpressVPN, Surfshark, CyberGhost) y tráfico Tor. Capta la mayoría de los servidores proxy alojados en centros de datos. No detecta VPN residenciales ni apoderados privados. Espere una detección del 80-90% para los casos comunes y casi cero para los casos extremos.

Marcar, no bloquear

Bloquear directamente a los usuarios de VPN es un error para la mayoría de las aplicaciones. He aquí por qué:

  • Los usuarios preocupados por la privacidad y sin intención de abusar de su servicio ejecutan VPN de forma predeterminada.
  • Los empleados de VPN corporativas dirigen todo su tráfico a través de la infraestructura de la empresa.
  • Los usuarios de países con restricciones de Internet dependen de las VPN para acceder a su producto.
  • Periodistas, activistas e investigadores de seguridad utilizan Tor por motivos legítimos.

El enfoque correcto: agregar un indicador de riesgo a la cuenta, requerir verificación adicional (correo electrónico confirmación, número de teléfono, método de pago) o dirigir el registro a una cola de revisión. Deja que los humanos tomar la decisión final en casos ambiguos.

Puntos clave

  • POST /v1/vpn-detect regresa is_vpn, is_proxy, is_tor, is_datacenter, provider, y risk_score para cualquier dirección IPv4.
  • No se requiere clave API para acceso anónimo (5 solicitudes por minuto). Desbloqueo de llaves gratis 500 solicitudes por día.
  • La detección cubre proveedores de VPN comerciales, nodos de salida Tor conocidos y los principales proveedores de nube. Rangos de IP. Las VPN residenciales y los servidores proxy privados se escapan.
  • Combine la detección de VPN con comprobaciones de correo electrónico desechables, antigüedad de la cuenta e historial de pagos para una puntuación de fraude significativa. El estado de la VPN por sí solo no es suficiente para actuar.
  • Marcar conexiones VPN para su revisión. No los bloquees. Los usuarios legítimos ejecutan VPN por motivos de privacidad, política corporativa y acceso en regiones restringidas.

FAQ

¿Cómo detecto usuarios de VPN en mi aplicación?
Envíe la dirección IP del usuario a una API de detección de VPN (como POST /v1/vpn-detect) y verifique el booleano is_vpn en la respuesta. La API también devuelve indicadores is_proxy, is_tor e is_datacenter para que pueda distinguir entre diferentes métodos de anonimización. Llame a este punto final durante el registro, el inicio de sesión o el pago para marcar conexiones sospechosas para su revisión.
¿Puede una API de detección de VPN detectar todas las conexiones VPN?
No. La detección de VPN funciona comprobando los rangos de IP conocidos del centro de datos, los nombres de host DNS inversos y las listas de nodos de salida de Tor. Los servicios de VPN residenciales enrutan el tráfico a través de direcciones de ISP domésticas, que parecen idénticas al tráfico residencial normal. Espere una detección del 80-90% de VPN comerciales (NordVPN, ExpressVPN, Surfshark), pero tasas más bajas para VPN residenciales y proxies privados.
¿Debo bloquear a todos los usuarios de VPN de mi aplicación?
No. Muchos usuarios legítimos utilizan VPN por motivos de privacidad, políticas corporativas o porque viven en regiones con acceso restringido a Internet. Bloquear el tráfico VPN por completo bloqueará a los clientes que pagan. En su lugar, marque las conexiones VPN como de mayor riesgo y combínelas con otras señales (dominio de correo electrónico, método de pago, antigüedad de la cuenta) para tomar una decisión.
¿Cuál es la diferencia entre detección de VPN, proxy y Tor?
Una VPN cifra todo el tráfico a través de un túnel hacia un servidor, generalmente administrado por un proveedor comercial. Un proxy enruta el tráfico a través de un servidor intermediario sin cifrado completo. Tor dirige el tráfico a través de múltiples retransmisiones operadas por voluntarios para lograr el máximo anonimato. La API de botoi devuelve indicadores booleanos separados para cada tipo, de modo que pueda aplicar políticas diferentes a cada uno.
¿La API de detección de VPN de botoi requiere una clave API?
No. El acceso anónimo permite 5 solicitudes por minuto sin clave API. Para cargas de trabajo de producción, una clave API gratuita aumenta el límite a 500 solicitudes por día. Los planes pagos comienzan en $9/mes para límites de tarifas más altos.

Empieza a construir con botoi

150+ endpoints de API para consultas, procesamiento de texto, generacion de imagenes y utilidades para desarrolladores. Plan gratuito, sin tarjeta de credito.