← Todos os posts
26 de jun. de 2026

Headscale e Tailscale no OPNSense: Subnet Router e Anúncio de Rotas via WebUI

TL;DR: O plugin oficial os-tailscale do OPNSense cuida de auth e anúncio de rotas pela WebUI, mas rotas anunciadas são inertes até aprovação manual no control server (painel admin do Tailscale ou headscale routes enable), e o plugin cria a interface tailscale0 sem nenhuma regra de firewall — tráfego da tailnet para subnets locais é bloqueado por padrão. Este post documenta o setup completo: instalação via lista de plugins da comunidade, configuração de URL do control server e auth key, anúncio de CIDRs de subnet, aprovação no control server, regras de firewall explícitas para tailnet → LAN/DMZ, e habilitação da tailscale0 nas interfaces de listen do WebGUI e SSH para que o próprio OPNSense seja acessível pela tailnet.

O plugin os-tailscale do OPNSense faz mais do que a maioria das pessoas espera e menos do que a documentação sugere. A WebUI cobre auth e anúncio de rotas, mas o firewall deliberadamente não sabe nada sobre a nova interface — e o próprio listener de serviços do OPNSense também não. Fazer a tailnet chegar a uma DMZ exige que três subsistemas distintos estejam de acordo: o control server, o conjunto de regras do firewall e os bindings de interface de administração. Este post documenta onde cada uma dessas lacunas se esconde e como fechá-las.

O nó estava na tailnet. A rota estava anunciada. O tráfego ainda não chegava. A subnet aparecia no tailscale status nos dispositivos clientes, as rotas estavam listadas no lado do Headscale e, mesmo assim, nada da tailnet conseguia alcançar 192.168.50.0/24. Nenhum erro, nenhum ICMP unreachable — os pacotes sumiam em algum ponto entre a interface Tailscale e a DMZ. Foram necessários três lugares diferentes para montar o quadro completo: aprovação de rota no control server, uma regra de firewall ausente na tailscale0 e um deny padrão que se aplica ao próprio host do firewall.

Este post é para operadores de homelab que rodam OPNSense, já entendem conceitos básicos de firewall — interfaces, regras, aliases — e querem o Tailscale funcionando como subnet router sem precisar abrir o shell. Pressupõe que você tenha uma conta Tailscale ou uma instância Headscale própria já em funcionamento.

Veja também SSH e Tailscale Persistentes no Steam Deck / SteamOS pro lado cliente da mesma tailnet — este post cobre o gateway, aquele cobre um cliente.

Instalar o os-tailscale pela lista de plugins da comunidade

Acesse System → Firmware → Plugins. Por padrão a lista mostra apenas plugins oficiais — clique em “Click to view the community plugins” no canto inferior esquerdo para expandir.

Pesquise por os-tailscale e clique em + para instalar. Recarregue a página após a conclusão. O menu VPN → Tailscale aparecerá na sidebar.

Conectar à Tailscale ou Headscale e verificar que o nó está online

Em VPN → Tailscale → Settings, configure o servidor de controle (padrão para Tailscale, ou a URL da sua instância Headscale) e a auth key gerada no painel admin. Salve e aplique.

Para verificar que o nó está conectado, acesse VPN → Tailscale → Settings → Status:

Status do Tailscale no OPNSense

O nó do OPNSense deve aparecer como online com um IP na faixa 100.64.0.0/10.

Anunciar rotas de subnet — a metade que o plugin faz

Para que dispositivos na tailnet alcancem redes locais do OPNSense — como uma DMZ — é preciso anunciar as subnets em VPN → Tailscale → Settings → Advertised Routes.

Adicione o CIDR da DMZ: 192.168.50.0/24.

Configuração de subnet da DMZ

Aprovar a rota anunciada no control server — esse passo não é opcional

Rotas anunciadas não funcionam até serem aprovadas. O plugin não pode fazer isso por você; ele não tem acesso de escrita ao plano de controle.

Tailscale: no painel admin em login.tailscale.com/admin/machines, localize o nó do OPNSense, clique nos três pontos → Edit route settings e habilite a subnet.

Headscale: liste as rotas pendentes e ative pelo ID:

headscale routes list
headscale routes enable -r <id>

O ID corresponde à rota listada para o nó do OPNSense. Confirme com headscale routes list novamente — o campo Enabled deve aparecer como true.

Adicionar regras de firewall — o plugin cria a interface, mas não a política

O plugin cria a interface tailscale0, mas as regras precisam ser adicionadas manualmente. A postura padrão do OPNSense é deny-all em novas interfaces; a tailnet consegue alcançar o IP do OPNSense, mas não pode encaminhar tráfego além dele sem regras explícitas.

Antes de criar as regras, crie um alias para a rede Tailscale em Firewall → Aliases:

CampoValor
Nametailscale_net
TypeNetwork
Network100.64.0.0/10
DescriptionTailscale CGNAT range

Usar um alias evita hardcodar o CIDR em cada regra e facilita manutenção.

Permitir tráfego Tailscale → DMZ

Em Firewall → Rules → Tailscale:

CampoValor
ActionPass
InterfaceTailscale
Directionin
Protocolany
Sourcetailscale_net
Destination192.168.50.0/24
DescriptionTailscale → DMZ

Permitir acesso da DMZ à tailnet (opcional)

Em Firewall → Rules → DMZ (ou na interface correspondente):

CampoValor
ActionPass
Protocolany
Source192.168.50.0/24
Destinationtailscale_net
DescriptionDMZ → Tailscale

Sem a segunda regra, o tráfego iniciado por hosts da DMZ em direção à tailnet é bloqueado pelo estado padrão do firewall.

Permitir acesso ao próprio OPNSense via Tailscale — o firewall também é um host

Por padrão, o OPNSense não aceita conexões destinadas a si mesmo vindas da interface Tailscale. Para acessar a WebGUI e SSH pelo endereço Tailscale do firewall (100.64.x.x), adicione uma regra em Firewall → Rules → Tailscale:

CampoValor
ActionPass
InterfaceTailscale
Directionin
Protocolany
Sourcetailscale_net
DestinationThis Firewall
DescriptionTailscale → OPNSense (WebGUI, SSH, serviços)

Sem essa regra, pacotes destinados ao próprio firewall chegam pela tailscale0 mas são descartados antes de atingir qualquer serviço.

Associar WebGUI e SSH à interface Tailscale — regras são necessárias, mas não suficientes

Mesmo com a regra de firewall, o OPNSense só responde nas interfaces explicitamente configuradas para cada serviço. Vá em System → Settings → Administration:

Salve e aplique. Após isso, curl https://100.64.x.x:443 (ou a porta configurada) deve retornar a página de login do OPNSense.

O que esse setup não cobre e quando reconsiderá-lo

Essa configuração cria um subnet router: qualquer dispositivo na tailnet consegue alcançar a DMZ via OPNSense, e opcionalmente o caminho inverso também. O que ela não oferece é comportamento de exit node, split DNS ou resolução MagicDNS para hostnames dentro da DMZ — esses recursos exigem configuração adicional tanto no lado Tailscale/Headscale quanto no resolver DNS do OPNSense.

O modelo mental dos três checkpoints — aprovação no control server, conjunto de regras do firewall, binding de listener de serviço — se aplica toda vez que você adiciona uma nova interface no OPNSense, não apenas com Tailscale. O plugin cuida do daemon Tailscale e do gerenciamento de chaves; todo o resto é comportamento padrão do OPNSense. Se você atualizar o os-tailscale ou o próprio OPNSense no futuro, as regras de firewall e as configurações de listen interface persistem independentemente do plugin — elas não serão apagadas, mas também não são gerenciadas por ele, então detectar drift é sua responsabilidade.

Se o seu modelo de ameaça exige isolar o acesso da tailnet a usuários ou dispositivos específicos em vez de toda a faixa 100.64.0.0/10, substitua o alias tailscale_net por IPs Tailscale individuais por dispositivo e ajuste as regras conforme necessário. O alias CGNAT é um ponto de partida para uma tailnet confiável; ele não é adequado se sua tailnet incluir dispositivos sobre os quais você não tem controle total.

Referências


Breno Zanato Detomini
Breno Zanato Detomini

Engenheiro de sistemas embarcados e redes, baseado no Brasil.

← Todos os posts