O que você realmente ganha ao esconder a origem
Três coisas, e vale a pena ser preciso sobre elas. Primeiro, a inundação para de chegar à máquina que não consegue absorvê-la: um único VPS tem um uplink finito, e quando o endereço que engole os pacotes é um edge construído especificamente para isso, em vez da máquina que guarda o seu banco de dados, um ataque volumétrico vira problema de engenharia de outra pessoa. Segundo, a aplicação deixa de poder ser alcançada por quem contorna as próprias defesas — limites de taxa, regras antibot, um WAF e geobloqueio são todos trivialmente burlados por qualquer um que consiga se conectar direto na origem, e a maioria de quem implanta essas defesas nunca verifica se isso ainda é possível. Terceiro, o endereço que serve o seu conteúdo para de ser o endereço que guarda os seus dados, que é a separação que faz uma denúncia de abuso, uma varredura ou uma sondagem direcionada caírem em algo barato e substituível.
E agora a metade honesta. Esconder uma origem não é anonimato — isso esconde um endereço, não uma pessoa, e o rastro de pagamento, o registro do domínio e a conta por trás deles são um problema à parte, que tem o seu próprio guia. Isso não corrige a sua aplicação: uma origem que ninguém consegue encontrar continua explorável no momento em que alguém a encontrar, e origens são encontradas. Isso não esconde nada do seu provedor, que por definição sabe qual máquina responde em qual endereço. Trate isso como uma camada que aumenta o custo de um ataque, sentada em cima de uma máquina que foi devidamente protegida antes — não como substituto de nenhuma das duas coisas.
SP·02Todas as formas como um IP de origem vaza
O motivo de tantas origens escondidas não estarem realmente escondidas é que as pessoas fecham um canal e presumem que o resto acompanhou. Não acompanha. Aqui está a lista que percorremos, em uma ordem aproximada de qual delas mais frequentemente é a que realmente queimou alguém:
- DNS histórico. Coletores de DNS passivo registram o seu registro A desde muito antes de você se mudar para trás de um proxy. O endereço que você usava no ano passado é uma consulta permanente, pesquisável e gratuita.
- Transparência de certificados. Todo certificado publicamente confiável é publicado em logs públicos append-only, com todo hostname que ele cobre. Um certificado emitido para
origin.example.comanuncia esse nome para o mundo, e o registro A dele faz o resto. - Subdomínios que nunca se moveram.
mail,ftp,webmail,cpanel,dev,staging,vpn,monitor— a raiz do domínio foi movida para trás do CDN e esses continuaram apontando para a máquina. - E-mail. Um registro MX na origem entrega o endereço diretamente; o mesmo vale para um cabeçalho
Received:em um e-mail que a sua aplicação enviou, algo que qualquer um consegue disparar com um formulário de redefinição de senha. - Requisições de saída. Webhooks, busca de avatares, leitura de RSS, pré-visualizações de link, checagens de atualização, callbacks OAuth. Cada um deles revela o endereço da origem para quem quer que opere a outra ponta — e uma funcionalidade de pré-visualização de URL deixa um atacante escolher essa outra ponta.
- Responder no endereço puro. Se a origem ainda serve o seu site para uma requisição sem um cabeçalho
Hostcorrespondente, scanners que varrem a internet inteira já indexaram isso: hash do favicon, título da página, fingerprint do certificado e a ordem dos cabeçalhos HTTP são todos pesquisáveis. - O registro IPv6 que você esqueceu. O registro A se mudou para o proxy; o registro AAAA continua apontando para casa.
- A aplicação falando sobre si mesma. URLs absolutas em uma configuração de CMS, redirecionamentos para um hostname interno, stack traces, banners de
Server, source maps, um endpoint de status sem autenticação.
Repare no que a maioria dessas formas tem em comum: elas são permanentes. Os logs de certificado são append-only, e o DNS passivo é um arquivo. Você não consegue retratar um endereço depois que ele foi publicado — só consegue parar de usá-lo, e é exatamente por isso que a ordem das operações abaixo importa.
SP·03Dois formatos de edge: um CDN, ou uma máquina sua
Um CDN comercial te dá uma capacidade anycast que nenhum servidor único consegue igualar, em dezenas de cidades, muitas vezes em um nível gratuito. A troca é que o TLS termina em uma infraestrutura que você não controla: o operador vê o seu tráfego em texto puro, sabe a qual conta ele pertence, e pode ser obrigado a agir com base nesse conhecimento, ou simplesmente decidir numa bela manhã que o seu conteúdo não é bem-vindo. Existe também um problema mais sutil, específico de fachadas compartilhadas — se o firewall da sua origem permite as faixas de endereço publicadas do CDN, então qualquer outra pessoa com conta nesse mesmo CDN está dentro do seu allowlist e pode apontar o próprio hostname para a sua origem. Isso é um bypass real, não teórico, e é por isso que existe o origin pull autenticado.
Um edge que você mesmo opera é a troca oposta. Ninguém além de você detém a chave privada, a máquina fica em uma jurisdição que você escolheu deliberadamente, e custa $8.00/mês no plano menor — genuinamente um erro de arredondamento perto do que ele protege. O que você não ganha é anycast: uma inundação de 200 Gbps vai saturar o uplink do edge não importa quão elegante seja a sua configuração do nginx, então a absorção em nível de rede precisa vir de algum lugar. No nosso caso, isso é 1.5 Tbps de mitigação a montante na frente de cada máquina da frota, que é o que torna um edge autogerenciado viável em vez de um ponto único de colapso. Os dois formatos também se combinam: CDN na frente para alcance e volume, o seu próprio nó atrás dele para a parte que você se recusa a entregar. Escolha com base em qual falha você prefere ter que explicar.
SP·04O túnel é a parte em que as pessoas erram
A configuração comum é uma origem que escuta em 0.0.0.0:443 com um firewall que coloca os endereços do proxy em uma allowlist. Funciona, e é o elo mais fraco do desenho. Allowlists ficam desatualizadas — as faixas publicadas mudam e a atualização nunca é aplicada; elas são compartilhadas, então em um CDN público elas admitem todos os outros clientes; e falham de forma aberta bem na direção que importa, porque a origem continua sendo um listener público ativo o tempo todo, esperando por uma configuração errada ou por um ufw disable no meio de uma sessão de debug.
A versão que aguenta inverte isso: a origem não tem listener público nenhum. Um túnel WireGuard é estabelecido entre o edge e a origem, o servidor web se vincula somente ao endereço do túnel, e a interface pública tem uma política de negar tudo por padrão nas duas famílias de IP, sem exceção para a porta 80 ou 443. Aí a acessibilidade deixa de ser uma regra que alguém pode esquecer de renovar — ela vira a ausência de uma rota. O WireGuard é a ferramenta certa aqui porque é um módulo de kernel com uma superfície de ataque minúscula, é silencioso para scanners não autenticados (um pacote não autenticado não recebe resposta nenhuma, então a porta UDP nem parece existir), e custa microssegundos por pacote — um número de um dígito só. Se você nunca configurou um antes, o guia de WireGuard cobre o básico; aqui só precisamos de um enlace ponto a ponto de dois peers.
Uma regra antes de começar, e é a que salva a sua tarde: mantenha uma segunda sessão SSH aberta o tempo todo. Trancar o SSH atrás de um túnel que você ainda está reconfigurando é assim que as pessoas perdem uma máquina, e em um host sem identidade registrada não existe uma escada de suporte para subir, nem uma sessão de console que alguém possa conceder a você — o caminho de volta é reimplantar e restaurar, o que é rápido se os seus backups estiverem em dia, e definitivo se não estiverem.
SP·05Certificados, e o log que publica os seus hostnames
A transparência de certificados é uma coisa genuinamente boa que vai destruir a sua semana com o maior prazer. Todo certificado emitido por uma CA pública é enviado para logs append-only que qualquer um pode pesquisar, e o registro contém todo nome presente no certificado. Emita um para origin.example.com ou direct.example.com e você terá publicado, de forma permanente e em um formato estruturado, exatamente o hostname que você estava tentando não divulgar. Pior, o hábito de colocar hostnames de staging e de admin na mesma lista de SAN transforma uma única renovação descuidada em um mapa da sua infraestrutura.
A disciplina é simples. Certificados públicos ficam somente no edge, cobrindo só os nomes que o público de fato usa. A origem recebe um certificado autoassinado ou um de uma pequena CA privada, fixado na configuração do proxy com proxy_ssl_trusted_certificate — nada em um enlace que só o seu próprio proxy fala precisa ser publicamente confiável, e emitir um certificado público para ele não traz nada além de uma entrada em um log. Se você precisa de muitos subdomínios públicos, um certificado wildcard publica um nome só em vez de trinta. E troque o ACME para o desafio DNS-01: o HTTP-01 exige que algo responda na porta 80 para o hostname sendo validado, que é precisamente o listener público que você acabou de remover. Por fim, aceite a assimetria — os logs são append-only, então um hostname que você já publicou não pode ser retirado. Se ele resolvia para a origem, a origem precisa de um endereço novo.
E-mail, e os outros serviços respondendo no endereço errado
O e-mail é o bypass clássico porque, por definição, ele precisa ser alcançável. Se o registro MX do seu domínio aponta para a origem, o exercício termina antes mesmo de começar — o registro é público, e um único dig encerra a caça. Mesmo com o MX em outro lugar, uma aplicação que envia e-mail diretamente a partir da origem carimba o endereço do host remetente na cadeia Received: de cada mensagem, e qualquer formulário que manda e-mail para um usuário sob demanda transforma isso em uma consulta self-service. O ajuste é fazer da origem um cliente, nunca um servidor: retransmita o e-mail de saída por um serviço de submission ou por uma máquina separada, mantenha o MX em uma máquina que pode ser encontrada sem problema, e leia os cabeçalhos completos de uma mensagem de teste antes de dar por encerrado. Rodar o seu próprio e-mail em escala é um projeto à parte, e ele não tem lugar na máquina que você está escondendo.
Depois faça uma varredura atrás de tudo o mais que está escutando silenciosamente. Agentes de monitoramento, dashboards de contêiner, portas de banco de dados abertas "temporariamente", um endpoint de métricas na porta 9100, um painel de controle em uma porta alta, um daemon SSH na interface pública. Cada um deles é um serviço que responde no endereço que você está tentando manter privado, e scanners encontram portas altas com a mesma facilidade que encontram portas baixas. A auditoria é um único comando — ss -tulpn — e a saída correta é uma lista em que nada está vinculado a um endereço público. O passo três, mais abaixo, é o que torna isso verdade e mantém isso verdade.
Egress: as conexões que a sua origem inicia
Uma origem que não aceita nada ainda pode se trair, porque ela não só recebe conexões — ela também as abre. Mirrors de pacotes, NTP, um webhook para um processador de pagamento, uma API de bot, uma imagem buscada para uma pré-visualização de link, uma checagem de licença, uma sessão SMTP de saída, um remote do Git, um relator de erros. Para a outra ponta de cada uma dessas, o endereço público da origem é simplesmente o endereço de origem da conexão. Na maior parte do tempo isso é inofensivo, porque você escolheu a outra ponta e confia nela. O problema é o punhado de endpoints que um atacante escolhe: colar um link em qualquer coisa que renderize uma pré-visualização, registrar um webhook, ou encontrar uma falsificação de solicitação do lado do servidor em um importador de imagens, e a origem resolve e se conecta a um host que o atacante está observando. Isso é uma desanonimização de dois minutos, sem nenhum exploit envolvido.
Existem duas respostas defensáveis. A estrita roteia todo o egress pelo túnel e deixa o edge fazer o NAT, de modo que o endereço de saída da origem passa a ser o do edge — um único ajuste na configuração do peer, mais encaminhamento e uma regra de masquerade na outra ponta. O wg-quick cuida do loop de roteamento para você: com uma rota 0.0.0.0/0, ele instala uma regra de fwmark para que os próprios pacotes do túnel ainda alcancem o endpoint diretamente, que é a parte que as pessoas quebram quando escrevem as rotas manualmente. A resposta pragmática mantém o egress direto para o tráfego que você controla e coloca um proxy na frente de qualquer coisa que busque uma URL fornecida pelo usuário. O que não é defensável é não saber qual das duas você tem. Decida isso deliberadamente, e depois verifique com uma requisição para um host que é seu, olhando o endereço de origem nos logs dele.
Quanto isso custa, e como provar que funciona
A linha de orçamento é um VPS a mais. O plano menor, a $8.00/mês, termina o TLS e faz proxy de um site pequeno sem nem notar a carga — um proxy reverso é basicamente uma cópia de socket, e 2 vCPU com 4 GB de RAM é mais que confortável, bem além do ponto em que a origem por trás dele vira o gargalo. Coloque-o em uma região diferente da origem, para que um único instrumento jurídico ou um único problema de instalação física não alcance as duas, e lembre-se da latência: um salto extra adiciona milissegundos de verdade, então um edge em Amsterdã na frente de uma origem em Kuala Lumpur é uma decisão de design, não um acidente. Pares dentro do mesmo continente normalmente custam milissegundos de um dígito só, e o reaproveitamento de sessão TLS que você ganha no edge muitas vezes se paga sozinho no carregamento real de uma página.
Provar que funciona é a parte que separa uma configuração de um controle, e é um trabalho recorrente, não algo feito uma vez só — cada novo subdomínio, cada novo certificado, cada nova integração é uma nova chance de republicar o endereço. A bateria de testes do passo sete leva cerca de dez minutos: tentar alcançar o seu site diretamente pelo endereço da origem, listar todo hostname que você já certificou, percorrer os nomes de subdomínio óbvios, checar o registro AAAA que você esqueceu, e mandar um e-mail para você mesmo. Rode isso depois de toda mudança de infraestrutura. E tenha a conclusão em mente enquanto faz isso: se a origem responde, o ajuste correto não é mais uma regra de firewall — é um endereço novo, porque o antigo já está no arquivo de alguém. Na pilha, essa camada fica depois da proteção do servidor e ao lado dos backups fora do site: a proteção decide o quão difícil é quebrar a máquina, os backups decidem a rapidez com que você se recupera, e isso decide o quão difícil é encontrar a máquina, para começo de conversa.
SP·09Passo a passo
-
01
Implante o edge e dê a ele exatamente um trabalho
Implante um segundo VPS em uma região que não seja onde a origem mora, e trate-o como um equipamento de propósito único: terminação de TLS, um proxy reverso, e mais nada. Nenhum banco de dados, nenhum código de aplicação, nenhum shell script que alguém sentiria falta. Rode nele o checklist da primeira hora — SSH só com chave, firewall com negação por padrão nas duas famílias de IP, atualizações de segurança automáticas — e depois abra exatamente três portas.
ssh root@198.51.100.20 apt update && apt full-upgrade -y hostnamectl set-hostname edge-01 apt install -y nginx wireguard-tools ufw unattended-upgrades ufw default deny incoming && ufw default allow outgoing ufw limit 22/tcp ufw allow 80,443/tcp ufw allow 51820/udp ufw --force enable
-
02
Suba o túnel antes de mexer no DNS
Dois peers, um enlace só. Gere um par de chaves em cada máquina e dê ao túnel a sua própria sub-rede pequena — a origem vai acabar acessível em
10.66.0.2e em mais lugar nenhum. A origem disca para o edge (é o lado que vai ficar sem nenhuma porta aberta), então é ela que carrega oEndpointe um keepalive; o edge só escuta.# on both machines umask 077; wg genkey | tee privkey | wg pubkey > pubkey # edge-01 — /etc/wireguard/wg0.conf [Interface] Address = 10.66.0.1/24 ListenPort = 51820 PrivateKey = <edge-privkey> [Peer] PublicKey = <origin-pubkey> AllowedIPs = 10.66.0.2/32 # origin-01 — /etc/wireguard/wg0.conf [Interface] Address = 10.66.0.2/24 PrivateKey = <origin-privkey> [Peer] PublicKey = <edge-pubkey> Endpoint = 198.51.100.20:51820 AllowedIPs = 10.66.0.1/32 PersistentKeepalive = 25
Habilite o túnel nas duas pontas e confirme o handshake antes de ir além — um túnel que só funciona até o próximo reboot é pior do que nenhum túnel.
systemctl enable --now wg-quick@wg0 wg show # expect a recent handshake and non-zero transfer ping -c3 10.66.0.1 # from the origin
-
03
Torne a origem inacessível a partir da internet pública
Este é o passo que faz o trabalho de verdade, e também aquele em que as pessoas se trancam para fora. Abra uma segunda sessão SSH e deixe-a conectada antes de rodar qualquer coisa abaixo — aqui não há console de suporte nenhum para recorrer. Depois vincule o servidor web ao endereço do túnel, derrube tudo na interface pública, e permita só o túnel mais o próprio endpoint do WireGuard.
# /etc/nginx/sites-available/app — listen on the tunnel only listen 10.66.0.2:8080; ufw --force reset ufw default deny incoming ufw default allow outgoing ufw allow in on wg0 to any port 8080 proto tcp ufw allow in on wg0 to any port 22 proto tcp ufw allow from 198.51.100.20 to any port 51820 proto udp ufw --force enable # the audit: nothing may be bound to a public address ss -tulpn | grep -Ev '10\.66\.0\.2|127\.0\.0|\[::1\]'
Se esse último comando imprimir algum serviço, é um vazamento — corrija o endereço de vínculo em vez de adicionar uma regra de firewall em volta dele. Dois listeners têm permissão para sobreviver: o WireGuard na 51820, e o sshd, caso você ainda não o tenha movido para o túnel.
-
04
Termine o TLS no edge e faça proxy pelo túnel
Emita o certificado público no edge, para os nomes que o público de fato usa, e faça proxy upstream para o endereço do túnel. O segundo bloco de servidor não é decoração opcional: é o que impede o edge de servir o seu site para um scanner que se conecta pelo IP sem um cabeçalho
Host, que é como a porta da frente acaba sendo reconhecida por fingerprint.# edge-01 — /etc/nginx/sites-available/example.com server { listen 443 ssl; http2 on; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; add_header Strict-Transport-Security "max-age=63072000" always; location / { proxy_pass http://10.66.0.2:8080; 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; proxy_http_version 1.1; } } # anything that is not a known hostname gets nothing at all server { listen 80 default_server; listen 443 ssl default_server; ssl_reject_handshake on; return 444; } -
05
Devolva à origem o IP real do cliente
Atrás de um proxy, toda requisição chega a partir de
10.66.0.1. Se nada for feito, os seus logs de acesso ficam inúteis, a limitação de taxa por IP passa a estrangular o túnel em vez do atacante, e ofail2banacaba banindo o edge e derrubando o site — uma forma genuinamente popular de causar uma queda bem no meio da proteção do servidor. Confie no cabeçalho encaminhado, mas só quando ele vier do endereço do túnel, nunca do mundo externo.# origin-01 — /etc/nginx/conf.d/realip.conf set_real_ip_from 10.66.0.1; real_ip_header X-Forwarded-For; real_ip_recursive off;
Faça o equivalente na aplicação —
ProxyFixno Flask,TRUSTED_PROXIESno Laravel,set_real_ip_frommais a própria lista de proxies confiáveis do framework — e coloque a limitação de taxa no edge, onde o endereço real do cliente existe nativamente:# edge-01 — /etc/nginx/nginx.conf (http block) limit_req_zone $binary_remote_addr zone=front:10m rate=20r/s; # then, inside the location block limit_req zone=front burst=40 nodelay;
-
06
Tire o e-mail e o egress do endereço da origem
Aponte o MX para uma máquina que pode ser encontrada sem problema, envie o e-mail de saída por um relay em vez de diretamente pela origem, e troque a renovação de certificado para o desafio DNS-01, para que nada precise responder na porta 80. Depois decida o que acontece com o resto do tráfego de saída. Para rotear tudo isso pelo edge, amplie o
AllowedIPsda origem e deixe o edge fazer o masquerade — owg-quickinstala a regra de fwmark que mantém o próprio túnel acessível, então você não precisa escrever a rota do endpoint à mão.# origin-01 — /etc/wireguard/wg0.conf, in [Peer] AllowedIPs = 0.0.0.0/0, ::/0 # edge-01 — forward and NAT the tunnel echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-fwd.conf && sysctl --system ufw route allow in on wg0 out on eth0 # in /etc/ufw/before.rules, above the *filter block: # *nat # :POSTROUTING ACCEPT [0:0] # -A POSTROUTING -s 10.66.0.0/24 -o eth0 -j MASQUERADE # COMMIT systemctl restart ufw && wg-quick down wg0 && wg-quick up wg0
Depois confira a partir da origem:
curl -s https://ifconfig.coprecisa retornar o endereço do edge, não o dela mesma. -
07
Cace a sua própria origem, depois escreva o runbook
Ataque-a do jeito que outra pessoa atacaria. O primeiro comando é o importante — se a origem ainda serve o seu site quando endereçada diretamente, nada do que veio antes está funcionando ainda.
# does the origin answer for your hostname? curl -sk --resolve example.com:443:203.0.113.10 https://example.com/ \ -o /dev/null -w '%{http_code}\n' # want: a timeout, not 200 # every hostname you have ever certified, from the public logs curl -s 'https://crt.sh/?q=%25.example.com&output=json' \ | grep -o '"name_value":"[^"]*"' | sort -u # records that never moved dig +short example.com A; dig +short example.com AAAA; dig +short example.com MX for h in www mail ftp webmail cpanel dev staging vpn monitor origin direct; do printf '%-9s %s\n' "$h" "$(dig +short $h.example.com | tr '\n' ' ')" doneDepois mande um e-mail para você mesmo a partir da aplicação e leia a cadeia
Received:completa, e cole um link para um host que você controla em qualquer funcionalidade que renderize pré-visualizações, e confira qual endereço buscou o link. Anote como é um resultado correto para cada checagem, e rode tudo de novo depois de toda mudança de DNS, todo certificado novo e toda integração nova. Se qualquer uma delas revelar a origem, reconstrua-a em um endereço novo — o que foi publicado já está arquivado, e nenhuma regra de firewall vai trazê-lo de volta.


