Nginx como reverse proxy

1. Conceitos Fundamentais de Reverse Proxy

Um reverse proxy atua como intermediário entre clientes externos e servidores internos, recebendo requisições e encaminhando-as para o backend apropriado. Diferente de um proxy direto, que representa o cliente, o reverse proxy representa o servidor, ocultando a infraestrutura interna.

Os principais benefícios incluem:
- Balanceamento de carga: distribuição de tráfego entre múltiplos servidores
- Caching: armazenamento de respostas frequentes para reduzir latência
- Segurança: proteção contra ataques diretos aos servidores backend
- Terminação SSL: centralização do gerenciamento de certificados

No ecossistema DevOps, o Nginx se destaca por sua alta performance, baixo consumo de recursos e configuração declarativa, sendo amplamente utilizado em ambientes Docker e Kubernetes.

2. Configuração Básica do Nginx como Reverse Proxy

A estrutura de configuração do Nginx é hierárquica. O arquivo principal nginx.conf inclui contextos como http, server e location.

Exemplo de configuração básica:

server {
    listen 80;
    server_name exemplo.com;

    location / {
        proxy_pass http://backend:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

A diretiva proxy_pass define o destino do encaminhamento. Os cabeçalhos HTTP são essenciais para que o backend receba informações reais do cliente, preservando o IP original e o protocolo utilizado.

3. Balanceamento de Carga com Nginx

O Nginx permite definir grupos de servidores backend através de upstream blocks. Algoritmos comuns de balanceamento:

  • round-robin: distribuição sequencial (padrão)
  • least_connections: envia para servidor com menos conexões ativas
  • ip_hash: mantém cliente no mesmo servidor baseado no IP

Exemplo de configuração com balanceamento:

upstream backend_servers {
    least_connections;
    server app1:3000 weight=3;
    server app2:3000;
    server app3:3000 backup;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend_servers;
        proxy_next_upstream error timeout http_500;
    }
}

Health checks automáticos são ativados com proxy_next_upstream, removendo servidores falhos do pool até que se recuperem.

4. Segurança e Otimização no Reverse Proxy

Rate limiting protege contra abusos e ataques de força bruta:

http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

    server {
        location /api/ {
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://backend_api;
        }
    }
}

Para filtragem de IPs:

location /admin {
    allow 192.168.1.0/24;
    deny all;
    proxy_pass http://backend_admin;
}

Otimizações de buffers e timeouts:

proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;

5. Terminação SSL e HTTPS

Configuração de certificados TLS:

server {
    listen 443 ssl;
    server_name exemplo.com;

    ssl_certificate /etc/nginx/certs/cert.pem;
    ssl_certificate_key /etc/nginx/certs/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://backend;
    }
}

Redirecionamento HTTP para HTTPS:

server {
    listen 80;
    server_name exemplo.com;
    return 301 https://$server_name$request_uri;
}

HSTS para forçar conexões seguras:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

6. Integração com Docker

Dockerfile para imagem Nginx personalizada:

FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY sites-enabled/ /etc/nginx/sites-enabled/
RUN mkdir -p /etc/nginx/certs
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]

Docker Compose com Nginx como proxy:

version: '3.8'
services:
  nginx-proxy:
    build: ./nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
    depends_on:
      - web-app
      - api-service

  web-app:
    image: node:18
    expose:
      - "3000"
    environment:
      - PORT=3000

  api-service:
    image: python:3.11
    expose:
      - "5000"
    environment:
      - PORT=5000

Exemplo de configuração para rotear para múltiplos serviços:

server {
    listen 80;

    location /app {
        proxy_pass http://web-app:3000;
    }

    location /api {
        proxy_pass http://api-service:5000;
    }
}

7. Integração com Kubernetes

No Kubernetes, o Ingress Controller Nginx gerencia o roteamento externo. Instalação via Helm:

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install nginx-ingress ingress-nginx/ingress-nginx

Definição de regras com recurso Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-service-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: app.exemplo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app-service
            port:
              number: 80
  - host: api.exemplo.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 5000

Para expor múltiplos serviços com paths diferentes no mesmo host:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-based-ingress
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: meuservico.com
    http:
      paths:
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80
      - path: /api/.*
        pathType: ImplementationSpecific
        backend:
          service:
            name: backend-service
            port:
              number: 8080

Referências