Как обнаружить пользователей VPN в вашем приложении с помощью одного вызова API
Добавьте обнаружение VPN, прокси-сервера и Tor в процессы регистрации, оформления заказа и входа в систему. Промежуточное программное обеспечение Express, интеграция Next.js и примеры оценки рисков с рабочим кодом.
На вашу страницу оформления заказа поступает 50 заказов с одного и того же диапазона IP-адресов за 12 часов, и все они выполняются с использованием предоплаченных карт. Ваша бесплатная пробная версия показывает 200 регистраций с IP-адресов центров обработки данных за неделю. Ваша конечная точка входа видит попытки ввода учетных данных с помощью ротации IP-адресов прокси.
Вам необходимо знать, когда трафик поступает от VPN, прокси-сервера или выходного узла Tor. Не для того, чтобы заблокировать это сразу, а для корректировки вашей оценки риска. One API call gives you that signal.
API-вызов
Отправьте IP-адрес пользователя на POST /v1/vpn-detect. Никаких зависимостей, SDK не требуется.
curl -X POST https://api.botoi.com/v1/vpn-detect \\
-H "Content-Type: application/json" \\
-d '{"ip": "185.220.101.1"}'
Ответ для известного выходного узла Tor (оценка риска 90):
{
"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
}
}
}
Ответ на чистый жилой IP (оценка риска 0):
{
"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
}
}
}
Ответ дает вам пять логических флагов (is_vpn, is_proxy,
is_tor, is_datacenter) плюс число risk_score
от 0 до 100. Подключения Tor оцениваются в 90 баллов. IP-адреса центров обработки данных оцениваются в 60 баллов. Подозрительные имена хостов
оценка 40. Чистые жилые IP-адреса — 0 баллов.
Интеграция 1: Экспресс-промежуточное ПО
Это промежуточное программное обеспечение вызывает API обнаружения VPN и присоединяет результат к req.vpnRisk.
Каждый обработчик нисходящего маршрута может проверить req.vpnRisk.isVpn принимать решения
без повторения вызова API.
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;
interface VpnRisk {
isVpn: boolean;
isProxy: boolean;
isTor: boolean;
isDatacenter: boolean;
riskScore: number;
}
declare global {
namespace Express {
interface Request {
vpnRisk?: VpnRisk;
}
}
}
export async function vpnDetectMiddleware(
req: Request,
_res: Response,
next: NextFunction
) {
const ip = req.headers['x-forwarded-for']?.toString().split(',')[0]?.trim()
|| req.socket.remoteAddress
|| 'unknown';
try {
const res = await fetch(VPN_DETECT_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': \`Bearer \${BOTOI_API_KEY}\`,
},
body: JSON.stringify({ ip }),
signal: AbortSignal.timeout(3000),
});
const { data } = await res.json();
req.vpnRisk = {
isVpn: data.is_vpn,
isProxy: data.is_proxy,
isTor: data.is_tor,
isDatacenter: data.is_datacenter,
riskScore: data.risk_score,
};
} catch {
// Fail open: if detection fails, treat as clean
req.vpnRisk = {
isVpn: false,
isProxy: false,
isTor: false,
isDatacenter: false,
riskScore: 0,
};
}
next();
}
// Usage in your route:
// app.use(vpnDetectMiddleware);
//
// app.post('/api/signup', (req, res) => {
// if (req.vpnRisk?.isVpn) {
// // require email verification or flag for review
// }
// });
Промежуточное программное обеспечение не открывается. Если API недоступен или время ожидания истекает через 3 секунды, он устанавливает
все флаги для false и позволяет продолжить запрос. Ваши пользователи никогда не видят ошибок
вызвано сторонним сбоем.
Интеграция 2: защита оформления заказа Next.js
Мошенничество с кассой происходит по схеме: новая учетная запись, карта предоплаты, VPN-соединение. Это Next.js Обработчик маршрута App Router проверяет все три сигнала и направляет подозрительные заказы вручную. просматривать, а не автоматически одобрять их.
import { NextRequest, NextResponse } from 'next/server';
const VPN_DETECT_URL = 'https://api.botoi.com/v1/vpn-detect';
const BOTOI_API_KEY = process.env.BOTOI_API_KEY!;
interface CheckoutBody {
cardType: 'credit' | 'debit' | 'prepaid';
accountCreatedAt: string;
amount: number;
currency: string;
}
export async function POST(req: NextRequest) {
const body: CheckoutBody = await req.json();
const ip = req.headers.get('x-forwarded-for')?.split(',')[0]?.trim()
|| '127.0.0.1';
// Check VPN status
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(3000),
});
const { data: vpnData } = await vpnRes.json();
const accountAge = Date.now() - new Date(body.accountCreatedAt).getTime();
const isNewAccount = accountAge < 24 * 60 * 60 * 1000; // less than 24 hours
const isPrepaid = body.cardType === 'prepaid';
const isVpn = vpnData.is_vpn || vpnData.is_tor || vpnData.is_proxy;
// VPN + new account + prepaid card = manual review
if (isVpn && isNewAccount && isPrepaid) {
return NextResponse.json({
status: 'review',
orderId: crypto.randomUUID(),
message: 'Order placed. We will confirm within 30 minutes.',
}, { status: 202 });
}
// VPN + new account (no prepaid) = proceed with logging
if (isVpn && isNewAccount) {
console.log(JSON.stringify({
event: 'checkout_vpn_new_account',
ip,
riskScore: vpnData.risk_score,
amount: body.amount,
}));
}
// Process the order normally
return NextResponse.json({
status: 'approved',
orderId: crypto.randomUUID(),
});
}
Обработчик не отклоняет заказ. Он возвращает 202 с надписью «мы подтвердим в течение 30 минут». сообщение. Это дает вашей команде время на анализ, не предупреждая о плохом актере, которым они были. помечен. Законные клиенты VPN по-прежнему обрабатывают свои заказы с небольшой задержкой.
Интеграция 3: Ограничение скорости входа в систему
Атаки с подстановкой учетных данных часто происходят с IP-адресов VPN или прокси-сервера, чтобы избежать блокировки на основе IP. Примените более строгие ограничения скорости для этих подключений: 3 попытки входа в систему за 15 минут для пользователей VPN. против 10 для обычных пользователей.
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;
// VPN users: 3 attempts per 15 minutes
// Regular users: 10 attempts per 15 minutes
const VPN_LOGIN_LIMIT = 3;
const STANDARD_LOGIN_LIMIT = 10;
const WINDOW_MS = 15 * 60 * 1000;
const loginAttempts = new Map<string, { count: number; resetAt: number }>();
export async function loginRateLimit(
req: Request,
res: Response,
next: NextFunction
) {
const ip = req.headers['x-forwarded-for']?.toString().split(',')[0]?.trim()
|| req.socket.remoteAddress
|| 'unknown';
// Check VPN status
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
}
const limit = isVpn ? VPN_LOGIN_LIMIT : STANDARD_LOGIN_LIMIT;
const now = Date.now();
const entry = loginAttempts.get(ip);
if (!entry || entry.resetAt < now) {
loginAttempts.set(ip, { count: 1, resetAt: now + WINDOW_MS });
return next();
}
entry.count++;
if (entry.count > limit) {
const retryAfter = Math.ceil((entry.resetAt - now) / 1000);
return res.status(429).json({
error: 'Too many login attempts. Try again later.',
retryAfter,
});
}
next();
}
// Mount on your login route:
// app.post('/api/auth/login', loginRateLimit, loginHandler);
Соотношение 3:10 замедляет автоматические атаки с IP-адресов VPN, не затрагивая при этом большинство реальных пользователей. Законный пользователь корпоративной VPN, который трижды вводит свой пароль с ошибкой, все равно получает четкое сообщение об ошибке и окно повторной попытки, а не постоянный бан.
Построение комплексной оценки риска
Обнаружение VPN само по себе является слабым сигналом мошенничества. Многие законные пользователи используют VPN. Сигнал получает сильнее, если объединить его с другими проверками. Вызовите три конечные точки ботоя параллельно:
/v1/vpn-detectпо типу подключения (VPN, прокси, Tor, дата-центр)/v1/disposable-email/checkкачество электронной почты (одноразовый или постоянный)/v1/ip/lookupиз-за несоответствия географического местоположения (страна IP и страна выставления счета)
Эта функция вызывает все три и выдает оценку риска от 0 до 100:
interface RiskResult {
score: number;
action: 'allow' | 'review' | 'block';
signals: {
vpn: boolean;
tor: boolean;
proxy: boolean;
vpnRiskScore: number;
disposableEmail: boolean;
geoMismatch: boolean;
ipCountry: string;
billingCountry: string;
};
}
async function calculateRisk(
ip: string,
email: string,
billingCountry: string
): Promise<RiskResult> {
const BOTOI_KEY = process.env.BOTOI_API_KEY!;
const headers = {
'Content-Type': 'application/json',
'Authorization': \`Bearer \${BOTOI_KEY}\`,
};
// Run all three checks in parallel
const [vpnRes, emailRes, geoRes] = await Promise.all([
fetch('https://api.botoi.com/v1/vpn-detect', {
method: 'POST',
headers,
body: JSON.stringify({ ip }),
}),
fetch('https://api.botoi.com/v1/disposable-email/check', {
method: 'POST',
headers,
body: JSON.stringify({ email }),
}),
fetch('https://api.botoi.com/v1/ip/lookup', {
method: 'POST',
headers,
body: JSON.stringify({ ip }),
}),
]);
const vpnData = (await vpnRes.json()).data;
const emailData = (await emailRes.json()).data;
const geoData = (await geoRes.json()).data;
const ipCountry = geoData.country_code || '';
const geoMismatch = ipCountry !== '' && billingCountry !== ''
&& ipCountry.toUpperCase() !== billingCountry.toUpperCase();
// Weight each signal
let score = 0;
// VPN/proxy/Tor: up to 30 points
if (vpnData.is_vpn || vpnData.is_tor || vpnData.is_proxy) {
score += Math.round(vpnData.risk_score * 0.3);
}
// Disposable email: 25 points
if (emailData.is_disposable) {
score += 25;
}
// Geo mismatch (IP country != billing country): 20 points
if (geoMismatch) {
score += 20;
}
// VPN + disposable email combo: extra 15 points
if ((vpnData.is_vpn || vpnData.is_tor) && emailData.is_disposable) {
score += 15;
}
score = Math.min(score, 100);
return {
score,
action: score > 70 ? 'block' : score > 30 ? 'review' : 'allow',
signals: {
vpn: vpnData.is_vpn,
tor: vpnData.is_tor,
proxy: vpnData.is_proxy,
vpnRiskScore: vpnData.risk_score,
disposableEmail: emailData.is_disposable,
geoMismatch,
ipCountry,
billingCountry,
},
};
}
// Example usage:
// const risk = await calculateRisk('185.220.101.1', 'user@tempmail.com', 'US');
// if (risk.action === 'review') { queueForManualReview(orderId); }
// if (risk.action === 'block') { rejectTransaction(orderId); }
Все три вызова API выполняются параллельно с Promise.all, поэтому общая задержка равна
самый медленный вызов (обычно менее 100 мс). Веса оценок являются отправной точкой. Настройте их
на основе ваших данных о мошенничестве. Если одноразовые электронные письма являются для вас крупнейшим источником возвратных платежей, увеличьте
этот вес. Если географические несоответствия редки и обычно безвредны для вашей пользовательской базы, уменьшите их.
Когда НЕ блокировать пользователей VPN
Жесткая блокировка VPN-трафика является ошибкой для большинства приложений. Вот распространенные причины люди подключаются через VPN:
- Корпоративная политика. Компании по умолчанию маршрутизируют трафик сотрудников через VPN. Блокировка этих подключений означает, что ваши B2B-клиенты не смогут использовать ваш продукт в рабочее время.
- Конфиденциальность. Пользователи, заботящиеся о конфиденциальности, используют VPN при каждом подключении в качестве базовой линии. мера безопасности. Они платят клиентам, а не мошенникам.
- Ограниченный доступ в Интернет. Пользователи в некоторых странах полагаются на VPN для доступа ваш продукт вообще. Блокировка VPN полностью блокирует их.
- Общественный Wi-Fi. Любой пользователь сети кафе или аэропорта должен использовать VPN. Наказание их за соблюдение правил безопасности создает неправильный стимул.
- Журналисты и исследователи. Люди на этих должностях используют Tor и VPN для защита источника и эксплуатационная безопасность. Их блокирование может иметь огромные последствия.
Правильный подход: отмечайте и оценивайте, а не жестко блокируйте. Используйте обнаружение VPN как один из входных данных для функция риска, которая учитывает несколько сигналов. Направляйте транзакции с высоким риском в очередь проверки. Позвольте людям сделать окончательный выбор в неоднозначных случаях.
Ключевые моменты
-
POST /v1/vpn-detectвозвращаетis_vpn,is_proxy,is_tor,is_datacenter, иrisk_scoreдля любого IP. - Для тестирования не требуется ключ API (5 запросов в минуту). Бесплатные ключи открывают более высокие лимиты для производства.
- Прикрепите проверку VPN к промежуточному программному обеспечению Express, чтобы каждый маршрут имел доступ к данным о рисках. не повторяя звонок.
- Объедините обнаружение VPN с одноразовыми проверками электронной почты и геолокацией IP для комплекса. уровень риска, который достаточно силен, чтобы действовать в соответствии с ним.
- Отметьте VPN-подключения для проверки. Не блокируйте их. Законные пользователи используют VPN для конфиденциальность, корпоративная политика и ограниченный доступ в Интернет.
FAQ
- Как обнаружить пользователей VPN в моем приложении?
- Отправьте IP-адрес пользователя в запросе POST на конечную точку botoi /v1/vpn-detect. Ответ включает логические флаги для is_vpn, is_proxy, is_tor и is_datacenter, а также риск_оценку от 0 до 100. Вызовите эту конечную точку во время регистрации, входа в систему или оформления заказа, чтобы пометить соединения со стороны служб анонимизации.
- Какой API обнаружения VPN лучше всего подходит для производственных приложений?
- Ищите API, который возвращает отдельные флаги для подключений VPN, прокси, Tor и центра обработки данных, а не одно логическое значение. Конечная точка botoi /v1/vpn-detect возвращает все четыре флага плюс числовой показатель риска и работает без ключа API со скоростью 5 запросов в минуту. Для производственных рабочих нагрузок ключи API открывают более высокие ограничения скорости, начиная с бесплатного уровня.
- Должен ли я заблокировать доступ всех пользователей VPN к моему приложению?
- Нет. Многие законные пользователи используют VPN из соображений конфиденциальности, корпоративной политики или потому, что они живут в регионах с ограниченным доступом в Интернет. Блокировка всего VPN-трафика блокирует платежеспособных клиентов. Вместо этого используйте обнаружение VPN как один из сигналов в комплексной оценке риска и помечайте подозрительные соединения для проверки.
- Могу ли я обнаружить соединения прокси и Tor с помощью одного и того же вызова API?
- Да. Конечная точка botoi /v1/vpn-detect возвращает отдельные логические флаги для is_vpn, is_proxy и is_tor в одном ответе. Вам не нужны отдельные вызовы API для каждого типа соединения. Конечная точка также возвращает is_datacenter для идентификации трафика от поставщиков облачных услуг, таких как AWS или Google Cloud.
- Как объединить обнаружение VPN с другими сигналами мошенничества?
- Вызов нескольких конечных точек botoi параллельно: /v1/vpn-detect для типа соединения, /v1/disposable-email/check для качества электронной почты и /v1/ip/lookup для географического несоответствия между страной IP и страной выставления счетов. Взвесьте каждый сигнал и суммируйте их, получив оценку риска от 0 до 100. Результаты, набравшие более 70 баллов, подлежат проверке вручную; баллы ниже 30 проходят.
Начните разработку с botoi
150+ API-эндпоинтов для поиска, обработки текста, генерации изображений и утилит для разработчиков. Бесплатный тариф, без банковской карты.