
VPN WireGuard no pfSense com cliente Linux — Documentação de Implantação
VPN WireGuard no pfSense: acesso remoto seguro a um cluster Kubernetes, passo a passo
Muitas infraestruturas começam com algumas portas abertas "só por enquanto": um RDP para a VM de suporte, um SSH para o servidor de aplicação, uma porta da API do Kubernetes. O provisório fica permanente, e a borda da rede vira uma lista de exceções que ninguém revisa.
Neste artigo mostramos, com um caso real anonimizado, como substituir esse modelo por uma VPN WireGuard no pfSense, conectar um cliente Linux e liberar o acesso a um cluster Kubernetes de homologação. Também mostramos o troubleshooting que apareceu no caminho. Os problemas reais ensinam mais que o roteiro ideal.
O cenário
-
Firewall: pfSense CE 2.8.1, rodando como VM, com IP público direto na WAN.
-
Rede interna:
10.20.0.0/16, gateway10.20.0.1(o próprio pfSense). -
Destino do acesso: um cluster Kubernetes de homologação (3 control-planes, 3 workers) e um Nginx de borda que publica o portal (
443) e a API do Kubernetes (6443). -
Cliente: um desktop Linux (Linux Mint Debian Edition, base Debian 13) em outra cidade, atrás de um roteador doméstico comum.
-
Situação anterior: acesso por port forwards na WAN (RDP e SSH abertos para qualquer origem) e por um gateway de acesso remoto web.
Objetivo: acessar a rede interna e o cluster como se o cliente estivesse no local, sem expor serviços administrativos na internet.
Topologia
flowchart LR
subgraph Remoto["Cliente remoto"]
C["Desktop Linux<br/>LAN 192.168.1.0/24<br/>wg0: 10.200.0.2/32"]
end
subgraph Site["Site principal"]
FW["pfSense<br/>WAN: 203.0.113.10<br/>LAN: 10.20.0.1/16<br/>tun_wg0: 10.200.0.1/24"]
NG["nginx-proxy<br/>10.20.0.10<br/>:443 portal · :6443 API"]
M["k8s-master-01..03<br/>10.20.0.21-23"]
W["k8s-worker-01..03<br/>10.20.0.31-33"]
end
C -- "UDP 51820<br/>(WireGuard)" --> FW
FW --> NG
FW --> M
FW --> W
Regra de ouro do endereçamento: a rede do túnel não pode colidir com a LAN do firewall nem com a rede de onde o cliente se conecta. Faixas como
10.200.0.0/24costumam ficar fora das redes domésticas e corporativas mais comuns.
Por que WireGuard (e quando preferir OpenVPN)
O pfSense oferece OpenVPN, IPsec e WireGuard. Para este caso, com um operador e poucos dispositivos, o WireGuard ganhou com folga:
Resumo: WireGuard para administradores, poucos dispositivos e site-to-site. OpenVPN quando há muitos usuários, exigência de MFA ou autenticação centralizada, ou clientes em redes que bloqueiam UDP.
Parte 1: configurando o pfSense
1.1 Instalar o pacote
System → Package Manager → Available Packages, pesquise wireguard e clique em Install → Confirm. Aguarde o log terminar com Success.
1.2 Criar o túnel
VPN → WireGuard → Tunnels → Add Tunnel
Save Tunnel → Apply Changes.
Túnel atribuído ou não? Para acesso remoto simples, não é preciso atribuir o túnel a uma interface. O endereço fica no próprio túnel e as regras vão na aba WireGuard do firewall. Atribuir a interface só é necessário em cenários com gateway, roteamento por política ou NAT por interface.
1.3 Habilitar o serviço
VPN → WireGuard → Settings → ☑ Enable WireGuard → Save → Apply Changes. Mantenha Hide Secrets ativado, para que chaves privadas não fiquem visíveis na interface.
1.4 Cadastrar o cliente (peer)
Para este passo, você precisa da chave pública do cliente, gerada na Parte 2. Na prática, gere as chaves no cliente e volte aqui.
VPN → WireGuard → Peers → Add Peer
O campo Allowed IPs do lado do servidor tem dupla função: filtra quais IPs de origem são aceitos daquele peer e define para qual peer o tráfego destinado a esse IP é roteado. Use um /32 exclusivo por cliente.
1.5 Regras de firewall
Regra 1: permitir o WireGuard na WAN (Firewall → Rules → WAN → Add)
Regra 2: permitir o tráfego que sai do túnel (Firewall → Rules → WireGuard → Add)
Sem a segunda regra, o túnel estabelece o handshake normalmente, mas todo o tráfego para a LAN é bloqueado. Esse é um dos erros mais comuns.
Parte 2: configurando o cliente Linux
2.1 Instalação
sudo apt update
sudo apt install wireguard wireguard-tools resolvconf -y
O resolvconf permite que o wg-quick aplique a diretiva DNS = da configuração.
2.2 Gerar as chaves no próprio cliente
sudo -i
cd /etc/wireguard
umask 077
wg genkey | tee cliente.key | wg pubkey > cliente.pub
cat cliente.pub # chave PÚBLICA → cadastre no peer do pfSense
Boa prática de segurança: gere a chave privada no dispositivo que vai usá-la. Ela nunca deve trafegar por e-mail, chat, ticket ou pela interface do firewall. O
umask 077garante que só o root consiga ler os arquivos.
2.3 Arquivo de configuração
O comando abaixo cria o /etc/wireguard/wg0.conf e injeta a chave privada direto do arquivo, sem copiar e colar:
cat > /etc/wireguard/wg0.conf <<EOF
[Interface]
PrivateKey = $(cat /etc/wireguard/cliente.key)
Address = 10.200.0.2/32
DNS = 10.20.0.1
[Peer]
PublicKey = <CHAVE_PUBLICA_DO_SERVIDOR>
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.200.0.0/24, 10.20.0.0/16
PersistentKeepalive = 25
EOF
chmod 600 /etc/wireguard/wg0.conf
2.4 Subir e validar
wg-quick up wg0
wg show
O resultado esperado é este:
peer: <CHAVE_PUBLICA_DO_SERVIDOR>
endpoint: 203.0.113.10:51820
allowed ips: 10.200.0.0/24, 10.20.0.0/16
latest handshake: 20 seconds ago
transfer: 9.23 KiB received, 7.54 KiB sent
persistent keepalive: every 25 seconds
Os dois indicadores que importam:
-
latest handshakepresente significa que o túnel foi negociado; -
received> 0 significa que o servidor está respondendo.
ping -c 4 10.200.0.1 # pfSense pelo túnel
ping -c 4 10.20.0.1 # pfSense pela LAN
No nosso caso, a latência ficou estável em torno de 29 ms entre as duas cidades, com 0% de perda.
Parte 3: o que deu errado (e como resolvemos)
Um roteiro sem problemas ensina pouco. Estes foram os quatro tropeços reais desta implantação, em ordem.
Problema 1: sem handshake, 0 B received
O túnel subia no cliente, mas o wg show não mostrava latest handshake e os pings falhavam.
Causa: o endpoint estava com um dígito errado no IP público. Ele tinha sido transcrito de uma captura de tela em baixa resolução, e os pacotes iam para outro endereço.
Correção:
sed -i 's/<IP_ERRADO>/203.0.113.10/' /etc/wireguard/wg0.conf
wg-quick down wg0 && wg-quick up wg0
Lição: copie o IP da WAN como texto, em Status → Interfaces no pfSense. Nunca transcreva de imagem. O WireGuard não dá erro quando o destino está errado: ele simplesmente não recebe resposta.
Problema 2: "será que estou testando de dentro da rede?"
Antes de culpar o firewall, confirme de onde o cliente está saindo. Testar uma VPN de dentro da própria LAN que ela protege gera falsos negativos, por causa de hairpin NAT e conflito de rotas.
ip -4 -br addr # IP local do cliente
curl -4 -s ifconfig.me # IP público de saída
Se o IP local estiver na LAN remota ou o IP público for o do próprio firewall, o teste não vale. Use outra rede, como o 4G do celular, por exemplo.
Problema 3: porta 443 funciona, porta 6443 dá No route to host
Com a VPN ativa, o portal no Nginx de borda respondia, mas a API do Kubernetes, no mesmo host, retornava No route to host imediatamente.
Diagnóstico: se uma porta do host responde, a rota está correta. Um No route to host instantâneo é a assinatura de um firewall local (firewalld, por padrão) rejeitando com icmp-host-prohibited. Os hosts aceitavam a LAN (10.20.0.0/16), mas não a origem da VPN (10.200.0.0/24).
Havia dois caminhos:
Para um ambiente de homologação, escolhemos o NAT.
Firewall → NAT → Outbound
-
Mude o modo para Hybrid Outbound NAT → Save.
-
Adicione um mapeamento:
-
Save → Apply Changes e limpe os estados antigos em Diagnostics → Command Prompt:
pfctl -k 10.200.0.2
Resultado: nc -vz 10.20.0.10 6443 passou a retornar succeeded.
Erros comuns nessa tela: deixar Address Family em IPv4+IPv6, escolher WAN address em vez de LAN address na tradução (os hosts veriam o IP público), ou digitar a descrição no campo Port or Range.
Para produção: prefira liberar a origem da VPN nos hosts, por exemplo
firewall-cmd --permanent --zone=trusted --add-source=10.200.0.0/24. Assim a rastreabilidade de quem acessou o quê é preservada.
Problema 4: os nós do cluster não respondem
Mesmo com o NAT, ping e SSH para os masters falhavam. Antes de mexer em mais qualquer coisa, isolamos o problema testando a partir do próprio pfSense:
ping -c 2 -S 10.20.0.1 10.20.0.21; nc -vz -w 3 10.20.0.21 22
O pfSense também não alcançava o nó. Então o problema não era a VPN. A causa era a mais simples possível: as VMs do cluster estavam desligadas.
Lição: antes de ajustar o túnel, verifique se o próprio firewall alcança o destino. Se nem ele alcança, a VPN está fora da equação.
Árvore de decisão
Sem handshake?
├─ Endpoint e porta corretos?
├─ Chaves públicas trocadas corretamente (cliente ↔ servidor)?
├─ Regra UDP 51820 na WAN, acima de bloqueios?
└─ Diagnostics → Packet Capture (WAN, UDP 51820) mostra pacotes?
├─ Não → IP errado, CGNAT, roteador da operadora na frente, UDP bloqueado na origem
└─ Sim → chaves ou serviço WireGuard desabilitado
Handshake ok, mas sem acesso?
├─ Regra na aba WireGuard liberando a rede do túnel?
├─ AllowedIPs do cliente inclui a rede de destino?
├─ O próprio pfSense alcança o destino?
│ └─ Não → destino desligado, outra VLAN/bridge, firewall do host
└─ Sim → firewall do host filtrando a origem → Outbound NAT ou liberar a origem no host
Parte 4: acessando o Kubernetes pela VPN
Com o túnel ativo e os nós ligados:
mkdir -p ~/.kube
scp [email protected]:/etc/kubernetes/admin.conf ~/.kube/config-homolog
export KUBECONFIG=~/.kube/config-homolog
kubectl get nodes -o wide
Se aparecer x509: certificate is valid for ..., o endereço em server: não está nos SANs do certificado do apiserver. Aponte para o IP de um master ou inclua o IP do balanceador nos SANs do certificado.
Resultados
Um detalhe importante do WireGuard para quem cuida de segurança: ele não responde a pacotes que não estejam autenticados com uma chave conhecida. Para um scanner na internet, a porta 51820 parece fechada. É uma redução real de superfície de ataque em comparação com RDP ou SSH expostos.
Governança: o que não pode faltar
Configurar a VPN é a parte fácil. Para que ela continue segura daqui a um ano:
-
Feche o que a VPN substituiu. Valide o acesso equivalente pelo túnel e então desative os port forwards antigos. VPN mais portas abertas é só mais uma porta aberta.
-
Inventário de peers. Mantenha uma tabela com IP do túnel, dispositivo, responsável e data. Peer sem dono é peer a revogar.
-
Uma chave por dispositivo, gerada no dispositivo. Nunca reutilize chaves entre máquinas nem transmita chaves privadas.
-
Menor privilégio. Troque o Destination: Any da regra do túnel por aliases com as redes e portas realmente necessárias.
-
Rastreabilidade. Em produção, evite NAT entre a VPN e a LAN, para que os logs dos servidores identifiquem o cliente. Isso pesa em auditorias e em requisitos de LGPD.
-
Pre-shared key. Adicionar uma PSK por peer é simples e acrescenta uma camada extra de proteção, inclusive contra ameaças criptográficas futuras.
-
DDNS. Se a WAN tem IP dinâmico, use um hostname no
Endpointpara a VPN não parar quando a operadora trocar o IP. -
Backup da configuração. Depois de qualquer mudança: Diagnostics → Backup & Restore.
Referência rápida
pfSense
Pacote ............ WireGuard
Túnel ............. tun_wg0 · 51820/UDP · 10.200.0.1/24
Peer .............. admin-desktop · dynamic · 10.200.0.2/32
Regra WAN ......... Pass UDP any → WAN address:51820
Regra WireGuard ... Pass any 10.200.0.0/24 → (redes necessárias)
Outbound NAT ...... Hybrid · LAN · 10.200.0.0/24 → 10.20.0.0/16 → LAN address (opcional, homologação)
Cliente Linux
wg-quick up wg0 # conectar
wg-quick down wg0 # desconectar
wg show # status / handshake
systemctl enable --now wg-quick@wg0 # subir no boot
Precisa de apoio com a sua infraestrutura?
A Nyverra Tecnologia atua com infraestrutura, segurança de borda, virtualização e monitoramento para empresas dos setores de saúde, indústria e serviços. Fazemos desde a revisão de exposição na internet até o desenho de acesso remoto auditável. Fale com a gente pelo [email protected].
Continuar a ler
Leia também
KubernetesKubernetes de Verdade — do zero ao cluster em produção
Uma trilha prática para entender, montar e operar um cluster Kubernetes — do primeiro pod ao failover do Postgres.
4 min de leitura
KubernetesCurso Kubernetes 28 — DR e capstone: provar que o cluster volta
RPO, RTO e drills reais: cenários de desastre, runbook, restore medido e o capstone que fecha o curso com um cluster que se recupera.
5 min de leitura
KubernetesCurso Kubernetes 27 — SLO/SLI, on-call e postmortem blameless
O que prometer, como medir e o que fazer quando o erro estoura: SLI, SLO, error budget, alertas que acordam alguém e postmortem sem caça às bruxas.
4 min de leitura
Comentários
Ainda sem comentários
Seja o primeiro a compartilhar sua opinião sobre este artigo.
Deixe um comentário