Capítulo 24 de 35

Rate Limiting: Bloqueando Ataques DDoS e Spam (Vercel KV)

Índice do Manual

No mercado B2B, a segurança do sistema não é uma escolha, é a fundação. Um dos golpes mais silenciosos e custosos que um SaaS pode sofrer não é o roubo de dados, mas o abuso financeiro de APIs.

Seja um script malicioso (bot) tentando descobrir a senha do administrador via Força Bruta (brute-force) ou um concorrente rodando um loop infinito para esgotar as suas cotas pagas da API do ChatGPT (OpenAI), o estrago financeiro pode ser brutal se não houver um escudo.

O erro arquitetural clássico é validar esses limites dentro da própria Rota de API, acessando o banco de dados principal (Postgres). Quando o ataque chega no banco de dados, o dano na infraestrutura e o uso de CPU já ocorreram.

Aqui vamos falar agora sobre a Segurança de Borda (Edge Security). Neste manual, documentamos a implementação do Vercel KV (Redis) diretamente no Middleware do Next.js para interceptar e abater requisições maliciosas antes mesmo que elas cheguem ao núcleo do sistema.


1. A Borda (Edge) e o Vercel KV

O Middleware do Next.js roda na "Borda" (Edge Network), o que significa que ele executa nos servidores de roteamento espalhados pelo mundo, extremamente próximos fisicamente de quem está acessando o site.

O Vercel KV é um banco de dados em memória (Redis) otimizado para essas operações de borda. Ele é brutalmente rápido, capaz de ler e gravar dados em menos de 10 milissegundos. É a ferramenta perfeita para atuar como o "segurança da porta da frente".

Utilizaremos o pacote oficial @upstash/ratelimit integrado ao @vercel/kv.


2. A Blindagem do Middleware (O Código)

Neste cenário de arquitetura, aplicaremos duas proteções críticas simultâneas:

  1. Rota de Login: Um IP não pode errar a senha mais de 5 vezes seguidas na mesma hora.
  2. Rota de Inteligência Artificial: Um usuário (ou IP) não pode gerar mais de 10 respostas de IA por minuto.

O código abaixo deve ser alocado na raiz do projeto Next.js (middleware.ts).

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { Ratelimit } from '@upstash/ratelimit'
import { kv } from '@vercel/kv'

// 1. Criamos os limites de velocidade com base em diferentes cenários
const loginRateLimit = new Ratelimit({
  redis: kv,
  // Limite de Login: 5 tentativas em uma janela de 1 hora
  limiter: Ratelimit.slidingWindow(5, '1 h'), 
})

const aiRateLimit = new Ratelimit({
  redis: kv,
  // Limite de IA: 10 chamadas em uma janela de 1 minuto
  limiter: Ratelimit.slidingWindow(10, '1 m'), 
})

export async function middleware(request: NextRequest) {
  const ip = request.ip ?? '127.0.0.1'
  const path = request.nextUrl.pathname

  // 2. Blindagem da Rota de Autenticação (Anti Força-Bruta)
  if (path.startsWith('/api/auth/login')) {
    const { success, pending, limit, reset, remaining } = await loginRateLimit.limit(
      `ratelimit_login_${ip}`
    )

    if (!success) {
      return new NextResponse(
        JSON.stringify({ error: 'Muitas tentativas de login. Tente novamente mais tarde.' }),
        { status: 429, headers: { 'Content-Type': 'application/json' } }
      )
    }
  }

  // 3. Blindagem de Rotas de Custo Elevado (APIs de Inteligência Artificial)
  if (path.startsWith('/api/ai/')) {
    const { success, limit, remaining } = await aiRateLimit.limit(
      `ratelimit_ai_${ip}`
    )

    if (!success) {
      return new NextResponse(
        JSON.stringify({ error: 'Limite de geração de IA atingido (10/minuto).' }),
        { status: 429, headers: { 'Content-Type': 'application/json' } }
      )
    }
    
    // Podemos também injetar os cabeçalhos para o frontend saber o limite restante
    const response = NextResponse.next()
    response.headers.set('X-RateLimit-Limit', limit.toString())
    response.headers.set('X-RateLimit-Remaining', remaining.toString())
    return response
  }

  return NextResponse.next()
}

// 4. Configuração para ignorar rotas estáticas e imagens, 
// rodando o middleware apenas nas rotas necessárias
export const config = {
  matcher: ['/api/auth/:path*', '/api/ai/:path*'],
}

3. O Veredito Arquitetural

Ao injetar o Ratelimit com Redis no Middleware, garantimos que nenhuma gota de processamento do nosso backend, banco de dados ou integração externa seja desperdiçada com tráfego abusivo.

Se um ataque DDoS bater contra a rota de autenticação, o servidor Edge abate o ataque no nível da infraestrutura da Vercel (com retornos Http Status 429 Too Many Requests), devolvendo a segurança matemática que o seu caixa financeiro precisa para operar com lucro.

Qualquer rota de altíssimo impacto ou processamento desenhada a partir de agora na nossa arquitetura nascerá protegida por essa barreira primária de defesa.