Ponto de partida

Venho avaliando uma ideia para conectar vários sites usando “só Internet”, em vez dos serviços MPLS tradicionais. Das várias opções que tenho em mente, uma é ter um OPNSense como ponto de peering para cada LAN. Todos seriam conectados usando Zerotier SDN em L3 com “managed routes”.

Identifiquei um limite de 128 rotas na opção “managed routes”, então provavelmente vou precisar rodar um route reflector BGP na configuração final, mas para a PoC inicial as managed routes servem.

Esquema básico da PoC

Este é um diagrama básico do que foi testado. Cada endpoint OPNSense rodaria o cliente zerotier e faria o forwarding. A informação de rotas seria enviada pelo controller.

esquema de rede
Imagem 1 - Esquema de rede da PoC

Rotas conforme definidas no controller:

10.1.0.0/24 via 172.16.1.10

10.2.0.0/24 via 172.16.1.20

O problema

Durante meus testes, vi que a conexão entre os sites (LAN do lado A vs LAN do lado B) é muito intermitente, com 30-60% de perda de pacotes.

Análise do problema

Criei um pequeno script para o OPNsense que verifica continuamente o estado do peer.

Para sua referência, o arquivo é criado assim:

mkdir ~/bin
touch ~/bin/check-peer.csh
chmod +x ~/bin/check-peer.csh
vi ~/bin/check-peer.csh

Conteúdo a inserir:

#!/bin/csh

# * Sat Dec  9 16:02:33 -03 2023 - ciro.iriarte (at) gmail.com
# - Basic script to review peer underlay IP

if  ($# != "1") then
        echo "usage:"
        echo "  $0 <peer id>"
        exit
endif

while ( 1 )
  zerotier-cli peers | grep $1
  sleep 3
end

Exemplo de execução:

root@opnsense-A:~/bin # check-peer.sh 0f02bd4XXX
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   252      413      <public IP>/25545
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      <public IP>/25545

O que descobri foi que, quando o cliente ficava sem resposta ao ICMP echo request (o comando ping), a saída mostrava uma mudança no IP do peer para o IP interno da LAN.

root@opnsense-B:~/bin # check-peer.sh 0f02bd4XXX
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   252      413      <public IP>/25545
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      <public IP>/25545
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      10.1.0.1/25645 
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      10.1.0.1/25645
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      10.1.0.1/25645
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      10.1.0.1/25645
0f02bd4XXX 1.12.2 LEAF       0 DIRECT   347      265      <public IP>/25545

No passado, vi pelos logs do firewall e capturas de tcpdump que o Zerotier é muito promíscuo/agressivo e tenta alcançar os peers usando QUALQUER interface disponível. Entendo que isso faz parte da experiência “just works” que eles idealizaram, mas é estranho ele tentar alcançar um peer do underlay através da rede overlay (por meio de L3 para uma rede remota, neste caso).

Eu esperaria que o Zerotier evitasse usar as interfaces zt* por padrão.

Relatos semelhantes

Andy Liebman

Andy Liebman relatou o mesmo cenário no fórum, mas infelizmente ninguém respondeu e, quando cheguei ao post, ele já estava fechado e não era possível adicionar mais comentários.

u/legacyproblems no Reddit

Não necessariamente o mesmo cenário, mas é parecido. Essa pessoa bloqueou os fluxos indesejados com regras de firewall:

I ran into a similar issue a while back where I have some devices acting as gateways onto my ZeroTier LAN and > devices on the real LANs these gateways were connected to would tunnel through the same ZeroTier LAN via the > gateways…

Ended up adding a rule to block 9993 UDP on my ZeroTier LAN via the ZeroTier network rules engine.

referência

Blacklists

Lembro de ter visto relatos parecidos que foram resolvidos com o uso de blacklists, mas não consigo achar esses posts agora para adicionar os links.

Prefiro não seguir por esse caminho porque em firewalls adicionar novas interfaces é bem frequente e muito provavelmente vou esquecer de colocar na blacklist as novas interfaces que não deveriam ser usadas para tráfego de underlay.

Para o meu caso de uso, uma whitelist faria muito mais sentido, dizendo ao Zerotier “use as interfaces WAN1 e WAN2 e mais nada”, mas infelizmente isso não parece ser suportado.

A solução

Descobri que usar a nova implementação de multipath parece imitar a lógica de whitelist que eu procuro. Descobri isso por acidente: o IP privado do peer só era visto no site que não tem multipath configurado.

O site A tem duas interfaces WAN. No passado, vi um comportamento de navegação realmente estranho no OPNSense com um grupo de gateways ativo/ativo, o que me fez voltar para grupos de failover. Neste caso, eu acharia que o Zerotier poderia fazer maravilhas em cenários ativo/ativo, mas, por simplicidade, mantive a configuração ativo/standby também para o Zerotier.

O local.conf ficaria assim:

{
  "settings": {
    "defaultBondingPolicy": "rapid-active-backup",
    "policies": {
      "rapid-active-backup": {
        "basePolicy": "active-backup",
        "failoverInterval": 1000,
        "links":
        {
          "ix0":
          {
            "ipvPref": 46,
            "failoverTo": "ix1"
          },
          "ix1":
          {
            "ipvPref": 46,
            "failoverTo": "ix0"
          }
        }
      }
    }
  }
}

O site B tem uma interface WAN; conceitualmente multipath não faz sentido neste cenário, mas ainda assim resolve o meu problema de “tentar alcançar a LAN remota através de um peer na LAN remota”.

O local.conf ficaria assim:

{
  "settings": {
    "defaultBondingPolicy": "rapid-active-backup",
    "policies": {
      "rapid-active-backup": {
        "basePolicy": "active-backup",
        "failoverInterval": 1000,
        "links":
        {
          "igb1":
          {
            "ipvPref": 46
          }
        }
      }
    }
  }
}

Ainda vejo uma entrada esporádica com o IP de LAN do peer durante meus testes, mas os clientes reportam 0% de pacotes perdidos em um teste ICMP de site a site (ping?/pong!).

Vou atualizar o post se algo mudar.