Next.js (Middleware)
Next.js Middleware работает на Edge, то есть выполняется максимально близко к вашим пользователям, прежде чем запрос достигнет стандартных API-маршрутов, серверных действий (Server Actions) или базы данных. Это оптимальная точка для отсечения вредоносного трафика.
Middleware
Эта реализация использует встроенный объект NextRequest для надежного извлечения IP-адреса клиента. Запрос к API ProxyTracer выполняется в легковесной среде Edge Runtime со строгим таймаутом в 500 мс, чтобы страницы загружались молниеносно.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
// 1. Извлечь IP (Next.js безопасно заполняет request.ip на Vercel/Edge)
// Использовать заголовки как резервный вариант при self-hosting за кастомным reverse proxy
const ip = request.ip || request.headers.get('x-forwarded-for')?.split(',')[0].trim()
// Пропустить при локальной разработке
if (!ip || ip === '127.0.0.1' || ip === '::1') {
return NextResponse.next()
}
try {
// 2. Выполнить запрос к API ProxyTracer с использованием нативного fetch и строгого таймаута
const ptResponse = await fetch(`https://api.proxytracer.com/v1/check/${ip}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${process.env.PROXYTRACER_API_KEY}`
},
signal: AbortSignal.timeout(500) // Разрывает соединение, если оно занимает > 500 мс
})
if (ptResponse.ok) {
const data = await ptResponse.json()
// 3. Немедленно сбросить соединение, если обнаружен прокси/VPN
if (data.proxy === true) {
return NextResponse.json(
{ error: "Access Denied: VPN or Proxy detected." },
{ status: 403 }
)
}
}
} catch (error) {
// Fail open: если время ожидания API истекло, разрешить трафик для обеспечения непрерывной работы
console.error('ProxyTracer API Error:', error)
}
// 4. Трафик чист, перейти к запрошенной странице или маршруту API
return NextResponse.next()
}
// 5. Настроить Matcher
// Примените этот middleware к чувствительным маршрутам или оставьте глобальным для полной защиты
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!_next/static|_next/image|favicon.ico).*)',
],
}Заметка по развертыванию в Vercel: Если вы используете Vercel, request.ip гарантированно содержит реальный IP клиента. Вам не нужно вручную парсить заголовки прокси, если только вы не размещаете приложение на собственной инфраструктуре Node/Docker.