Next.js (Middleware)
Middleware w Next.js działa w środowisku Edge, co oznacza, że wykonuje się niezwykle blisko użytkownika, zanim żądanie dotrze do standardowych tras API, Server Actions czy bazy danych. To optymalne miejsce do odrzucania niepożądanego ruchu.
Middleware
Ta implementacja wykorzystuje natywny obiekt NextRequest do niezawodnego pobierania adresu IP klienta. Odpytuje API ProxyTracer przy użyciu lekkiego środowiska Edge Runtime i wymusza ścisły limit czasu (timeout) 500 ms, dzięki czemu czas ładowania stron pozostaje błyskawiczny.
// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
// 1. Pobierz adres IP (Next.js bezpiecznie wypełnia request.ip w środowisku Vercel/Edge)
// Użyj nagłówków jako fallbacku w przypadku samodzielnego hostingu za własnym reverse proxy
const ip = request.ip || request.headers.get('x-forwarded-for')?.split(',')[0].trim()
// Przepuść żądanie w środowisku deweloperskim (localhost)
if (!ip || ip === '127.0.0.1' || ip === '::1') {
return NextResponse.next()
}
try {
// 2. Odpytaj API ProxyTracer za pomocą natywnego fetch ze ścisłym limitem czasu
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) // Przerywa połączenie, jeśli czas odpowiedzi > 500 ms
})
if (ptResponse.ok) {
const data = await ptResponse.json()
// 3. Natychmiast odrzuć połączenie, jeśli wykryto proxy/VPN
if (data.proxy === true) {
return NextResponse.json(
{ error: "Access Denied: VPN or Proxy detected." },
{ status: 403 }
)
}
}
} catch (error) {
// Fail-open: Jeśli minie limit czasu API, przepuść ruch, aby zapewnić ciągłość działania
console.error('ProxyTracer API Error:', error)
}
// 4. Ruch jest czysty, przejdź do żądanej strony lub trasy API
return NextResponse.next()
}
// 5. Skonfiguruj Matcher tras
// Zastosuj ten middleware do wrażliwych tras lub pozostaw globalnie, aby chronić całą aplikację
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).*)',
],
}Wdrożenie na Vercel: W przypadku wdrażania na platformie Vercel właściwość request.ip gwarantuje poprawny, prawdziwy adres IP klienta. Nie musisz ręcznie przetwarzać nagłówków proxy, chyba że korzystasz z własnego hostingu w niestandardowej infrastrukturze Node/Docker.