Usas uma VPN auto-hospedada. Perguntas-te o que acontece se o túnel cair durante 12 segundos a meio de um upload de algo sensível. Na maioria das configurações padrão do Linux: o tráfego flui livremente pela tua rota padrão, sem qualquer indicação visível. Vazamentos de DNS local, IP real aparece nos logs do servidor remoto. Um interruptor de segurança a nível de aplicação não te salvará — isto deve ser bloqueado ao nível do kernel.
Este guia configura um interruptor de segurança iptables + systemd que garante que nada sai da tua máquina em claro, mesmo durante o intervalo de 50 ms entre dois handshakes WireGuard.
Por que um interruptor de segurança netfilter é a única garantia séria
A indústria de VPNs comerciais fala sobre "interruptores de segurança" há sete anos, mas a maioria das implementações é frágil porque operam ao nível da aplicação: a aplicação da NordVPN ou ExpressVPN detecta uma queda no túnel e corta o tráfego manipulando a tabela de rotas. O problema: durante os 200 a 800 milissegundos que a aplicação leva para detectar a queda e reagir, os pacotes saem em claro pela interface padrão. Isso é suficiente para uma conexão BitTorrent ativa expor o teu IP real ao tracker, ou para um upload multipart S3 em progresso revelar a tua origem geográfica.
O interruptor de segurança netfilter (iptables ou nftables) contorna este problema colocando a regra de filtragem no próprio kernel do Linux, não num processo em espaço de utilizador. Os pacotes atravessam o subsistema netfilter em cada syscall send/sendmsg/sendto — não há janela de latência da aplicação. Se o WireGuard falhar, os pacotes continuam a ser DROP-ed pelo netfilter até que o túnel volte, independentemente do estado do processo WireGuard. É por isso que a Mullvad recomenda o netfilter como uma segunda camada além da sua aplicação, e por que os guias do Projeto Tor mencionam explicitamente o interruptor de segurança netfilter para hosts que executam relays.
A nossa escolha por iptables em vez de nftables deve-se ao suporte: o Ubuntu Server 22.04 LTS e o Debian 12 ainda têm o iptables como ferramenta de facto, mesmo que o backend seja nftables por baixo. Os comandos iptables são copiáveis de qualquer documentação dos últimos 10 anos, o que reduz o risco de erros de digitação e facilita a manutenção. Se estás a começar do zero em 2026 num novo host e conheces nftables, vai diretamente com nftables — a sintaxe é mais limpa e a ordem das cadeias é explícita.
O modelo que construímos
A ideia central em 3 frases:
- Todo o tráfego OUTPUT é DROP por padrão a menos que saia pela interface VPN (
wg0). - Exceção: a conexão UDP com o servidor VPN (handshake) permanece permitida — sem ela, o túnel não pode ser restabelecido após uma queda.
- systemd garante que essas regras de iptables se aplicam antes do WireGuard e sobrevivem a reinícios do túnel.
Resultado: se o WireGuard falhar, a tua máquina literalmente não pode enviar nada exceto o handshake VPN. Vês "sem conexão" no navegador, mas nenhum pacote vaza.
Preparação
No Ubuntu/Debian (testado no Ubuntu 22.04 e 24.04, kernel 5.15+):
sudo apt update
sudo apt install -y iptables iptables-persistent
# No prompt do netfilter-persistent: SIM para IPv4 e IPv6
Nota estes itens antes de continuar:
- O IP público da VPN:
nslookup vpn.example.comou verifica a linhaEndpointemwg0.conf. - A porta UDP da VPN: geralmente
51820para WireGuard. - A interface VPN:
wg0por padrão, pode serwg1com múltiplos túneis. - A sub-rede LAN local a manter acessível (192.168.1.0/24, 10.0.0.0/8, etc.) — para que a impressora e o NAS não deixem de funcionar.
Regras iptables para IPv4
Cria /etc/iptables/rules.v4 com este conteúdo (adapta os valores entre colchetes):
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
# Loopback sempre permitido
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
# Conexões já estabelecidas (respostas de handshake VPN, etc.)
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH de entrada (se administras remotamente — caso contrário, remove estas 2 linhas)
-A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
# Handshake VPN de saída: apenas tráfego fora do túnel permitido
-A OUTPUT -p udp -d 1.2.3.4 --dport 51820 -j ACCEPT
# DNS LAN local (Pi-hole, router) — opcional
-A OUTPUT -d 192.168.1.0/24 -j ACCEPT
# Todo o resto OUTPUT vai via interface VPN
-A OUTPUT -o wg0 -j ACCEPT
# Permitir entrada em wg0
-A INPUT -i wg0 -j ACCEPT
COMMIT
Substitui:
1.2.3.4pelo IP público real do teu servidor VPN51820pela tua porta WireGuard192.168.1.0/24pela tua sub-rede LAN- Remove a linha
--dport 22se não precisas de administração SSH de entrada
Carrega as regras:
sudo iptables-restore < /etc/iptables/rules.v4
sudo iptables -L -v -n
# Confirma que os contadores da cadeia DROP estão a 0
Regras ip6tables (CRÍTICO)
Sem o bloqueio explícito de IPv6, muitas distribuições ativam-no por padrão e o tráfego vaza. Cria /etc/iptables/rules.v6:
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Se a tua VPN suporta IPv6 (raro em auto-hospedadas):
# -A OUTPUT -p udp -d 2001:db8::1 --dport 51820 -j ACCEPT
# -A OUTPUT -o wg0 -j ACCEPT
# -A INPUT -i wg0 -j ACCEPT
# Caso contrário, todo o IPv6 fora do loopback é DROP
COMMIT
Carrega:
sudo ip6tables-restore < /etc/iptables/rules.v6
Neste ponto, podes testar: sem o túnel WireGuard, nenhum ping para a Internet passa. Esperado.
Ordenação do serviço systemd para WireGuard após iptables
Problema padrão: wg-quick@wg0 pode iniciar antes de netfilter-persistent. Durante essa janela (~1-3 segundos), o túnel está ATIVO, mas as regras iptables não estão carregadas → possível vazamento.
Solução: substituição systemd forçando a ordem.
Cria /etc/systemd/system/wg-quick@wg0.service.d/killswitch.conf:
sudo mkdir -p /etc/systemd/system/wg-quick@wg0.service.d
sudo nano /etc/systemd/system/wg-quick@wg0.service.d/killswitch.conf
Conteúdo:
[Unit]
After=netfilter-persistent.service
Wants=netfilter-persistent.service
Requires=netfilter-persistent.service
[Service]
# Se wg-quick falhar, força OUTPUT DROP para prevenir qualquer vazamento
ExecStopPost=/sbin/iptables -P OUTPUT DROP
ExecStopPost=/sbin/ip6tables -P OUTPUT DROP
Recarrega o systemd:
sudo systemctl daemon-reload
sudo systemctl enable wg-quick@wg0
sudo systemctl enable netfilter-persistent
sudo systemctl restart netfilter-persistent
sudo systemctl restart wg-quick@wg0
A cada arranque, o systemd inicia netfilter-persistent primeiro (iptables carregado), depois wg-quick@wg0 (túnel ativo). Sem janela de vazamento.
Testes de validação
Teste 1 — Derruba o túnel, verifica o silêncio
# Túnel ativo
sudo wg show
# Deve mostrar um handshake recente
# Testa o acesso à Internet
curl -s -m 5 https://ifconfig.me
# Deve retornar o IP do VPS
# Derruba o túnel
sudo wg-quick down wg0
# Re-testa
curl -s -m 5 https://ifconfig.me
# Deve dar timeout sem resposta — INTERRUPTOR DE SEGURANÇA ATIVO
Se vires um IP no segundo comando → vazamento, as regras iptables não estão aplicadas. Verifica sudo iptables -L -v -n e confirma que o OUTPUT padrão é DROP.
Teste 2 — Simula uma falha do WireGuard
# Túnel ativo
sudo wg-quick up wg0
ping -c 2 1.1.1.1
# Deve pingar OK
# Morte brutal do processo WireGuard (simula falha)
sudo pkill -9 wg
sudo ip link delete wg0 2>/dev/null
# Re-testa
ping -c 2 1.1.1.1
# Deve falhar "Operação não permitida"
O kernel recusa o ping porque nenhuma rota permanece permitida. Sem ExecStopPost na substituição systemd, algumas distribuições deixam uma janela de vazamento após a falha — essa linha é importante.
Teste 3 — Vazamento de DNS
# Túnel ATIVO
dig @9.9.9.9 ifconfig.me +short
# Deve retornar o IP do VPS
# Derruba o túnel
sudo wg-quick down wg0
# Re-testa
dig @9.9.9.9 ifconfig.me +short
# Deve dar timeout / "nenhum servidor pôde ser alcançado"
Mesmo o DNS é bloqueado fora do túnel. Objetivo alcançado.
Casos especiais
Corres vários túneis (wg0 + wg1)
Duplica a exceção OUTPUT:
-A OUTPUT -p udp -d 1.2.3.4 --dport 51820 -j ACCEPT # túnel principal
-A OUTPUT -p udp -d 5.6.7.8 --dport 51820 -j ACCEPT # túnel secundário
-A OUTPUT -o wg0 -j ACCEPT
-A OUTPUT -o wg1 -j ACCEPT
Executa Tailscale em paralelo
O Tailscale usa UDP 41641 por padrão. Adiciona:
-A OUTPUT -p udp --dport 41641 -j ACCEPT
-A OUTPUT -o tailscale0 -j ACCEPT
Mantém a LAN local acessível (NAS, impressora)
A regra de modelo -A OUTPUT -d 192.168.1.0/24 -j ACCEPT já faz isso. Adapta a sub-rede.
Não quer SSH de entrada (estação de trabalho móvel)
Remove a linha --dport 22 -m state --state NEW -j ACCEPT. A conexão existente (ESTABLISHED) permanece OK.
Registo de pacotes descartados (debug)
Para ver o que teria vazado sem o interruptor de segurança:
sudo iptables -I OUTPUT 1 -j LOG --log-prefix "OUTPUT-DROP: " --log-level 4
Depois:
sudo journalctl -k -f | grep "OUTPUT-DROP"
Verás cada pacote que o teu SO tenta enviar em claro quando o túnel está inativo (DNS da Apple, NTP, batimento cardíaco do Spotify, etc.). Educativo.
Depois de terminar o debug, remove a regra LOG (senão journalctl enche-se):
sudo iptables -D OUTPUT -j LOG --log-prefix "OUTPUT-DROP: " --log-level 4
Bónus: interruptor de segurança diretamente dentro de wg0.conf
Se preferires não gerir iptables separadamente, o WireGuard aceita PostUp/PreDown fazendo o mesmo trabalho:
[Interface]
# ...
PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PostUp = ip6tables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
PreDown = ip6tables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
Pró: zero ficheiros extra. Contra: as regras desaparecem se o WireGuard falhar sem chamar PreDown (pânico do kernel, OOM kill). A abordagem systemd acima é mais robusta para produção a longo prazo.
Veja também o modelo de interruptor de segurança de viagem no guia WireGuard 2026 para a versão inline-wg0.conf.
Verificação final
# Reboot completo
sudo reboot
# Após o reboot, sem passos manuais
ip a show wg0
# Deve mostrar túnel ATIVO
iptables -L OUTPUT -v -n | head -5
# A política padrão deve ser DROP, os contadores de aceitação devem crescer
curl -s ifconfig.me
# Deve retornar o IP do VPS
Tudo verde: o teu interruptor de segurança está em funcionamento, inicia no arranque, sobrevive a falhas. Podes ligar a máquina a uma rede hostil sem risco de vazamento.
Indo mais além
O interruptor de segurança bloqueia vazamentos. Mas para verdadeira paz de espírito, adiciona:
- Monitorização Prometheus + Grafana para a tua VPN VPS — estado do túnel em tempo real, throughput, peers conectados.
- Túnel dividido com tabelas de roteamento — útil quando algumas aplicações devem contornar a VPN (downloads Steam, Time Machine para NAS local) enquanto o resto permanece tunelado.
- Modelos WireGuard prontos para uso — 8 configurações testadas em produção.
- Gerador de configuração WireGuard — gera um
wg0.confcom regras de interruptor de segurança PostUp/PreDown pré-preenchidas, sem necessidade de escrever INI. - Melhor VPN auto-hospedada 2026 — compara WireGuard com Tailscale e Headscale antes de te comprometeres com uma stack.
E a base: Configuração WireGuard na Contabo em 20 minutos.
★ Datacenter GDPR em Nuremberg · ✓ IPv4 dedicado incluído · 200+ Mbps garantidos
Self-host your VPN on your own VPS → ContaboFull root access · public IPv4 · pick your region→