Skip to Content

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.

Последнее обновление: