Rotas divididas L2TP no Mac: por que um endereço de host não funciona
setadditionalroutes quer pares de rede e máscara, substitui toda a lista e exige o nome literal do serviço. Verifique a tabela antes de culpar o gateway.
A VPN conecta, a barra de menus mostra, e um host interno continua a expirar. Nessa situação há três causas possíveis, e qual se aplica depende de como o túnel foi configurado. Ou o comando de rota usou um endereço de host onde era necessário um endereço de rede, ou o próprio perfil instala uma rota predefinida que engole a decisão, ou o cliente é um túnel PPP que precisa de um hook em vez de uma chave de perfil. Verifique-as nessa ordem, porque a primeira é a mais barata de descartar.
O destino é um endereço de rede, a máscara descreve o prefixo
networksetup -setadditionalroutes recebe trios de destino, máscara de sub-rede e gateway. A chamada que envia uma sub-rede interna pelo túnel é assim:
sudo networksetup -setadditionalroutes "VPN (L2TP)" 192.168.1.0 255.255.255.0 10.2.0.0
Repare no que é o destino: o endereço de rede, não o endereço do servidor que tenta alcançar. No caso que originou este artigo, o comando idêntico com 192.168.1.20 nessa posição não fez nada de útil, e substituí-lo por 192.168.1.0 funcionou imediatamente. Mesma máscara, mesmo gateway, um número diferente. É toda a falha em miniatura.
A razão é aritmética, não política. Um endereço de host emparelhado com uma máscara /24 não descreve 192.168.1.0/24; descreve algo que a tabela de rotas não consegue reter de forma útil, pelo que a entrada é rejeitada ou ignorada e o túnel acaba por transportar menos do que pretendia.
Quando quer exatamente um host, use o endereço de host com uma máscara 255.255.255.255. É nos pares mistos que isto falha, não no uso de um endereço de host como tal. Uma /32 construída a partir de um endereço é uma rota legítima; uma /24 construída a partir de um endereço é um erro.
A chamada substitui a lista, e o nome é literal
Dois comportamentos surpreendem à primeira tentativa. O comando define a lista completa de rotas adicionais em vez de acrescentar, pelo que uma chamada que adiciona um prefixo remove silenciosamente as outras que lá estavam. Construa o conjunto inteiro numa única chamada.
O nome do serviço também não é a etiqueta que inventou. Leia-o da ferramenta e copie-o exatamente, incluindo o sufixo de tipo:
networksetup -listallnetworkservices
Um nome que difere num carácter não produz nenhum erro que valha a pena ler nem qualquer rota. Copiar e colar é a técnica correta aqui, não reescrever de memória.
Quando o perfil reclama a rota predefinida
As rotas divididas perdem para uma rota predefinida em qualquer destino que não cubram explicitamente, e um perfil L2TP configurado para túnel completo instala exatamente isso. Se o perfil diz que tudo passa pelo túnel, a lista de rotas adicionais muda muito pouco. A sua entrada não está errada; é simplesmente irrelevante para os destinos que nunca nomeia. O controlo disto costuma estar na definição de enviar todo o tráfego do perfil, não em qualquer comando de rota.
Decida que modelo quer realmente antes de editar mais entradas. O túnel completo com exceções é uma configuração diferente do túnel dividido com prefixos específicos, e misturar os dois produz uma tabela que ninguém consegue prever.
Se a organização exige túnel completo, deixe de tentar dividi-lo localmente e leve o requisito a quem detém a política. Uma rota adicionada localmente que a contradiga será removida pela próxima atualização do perfil de qualquer forma.
Os túneis PPP precisam de um hook em vez de uma chave
Para túneis baseados em PPP, defaultroute é a chave de perfil que cria uma rota predefinida; remova-a e o cliente deixa de reclamar cada destino. As rotas são depois adicionadas após o aparecimento da interface, normalmente a partir de /etc/ppp/ip-up:
#!/bin/sh
/sbin/route add -net 192.168.1.0 -interface ppp0
Mantenha o script propriedade de root e executável, e acrescente uma proteção ao nome da interface quando existir mais de um perfil de túnel na máquina. Um hook que corre para cada ligação PPP e assume um único nome de dispositivo é um erro pequeno com uma vida longa.
Verifique a divisão com três pedidos
Capture a tabela enquanto está ligado e anote que interface serve o túnel. Depois verifique o destino concreto em vez de confiar no estado de saída do comando que o criou. Um código de saída informa se a ferramenta aceitou os argumentos, não se o tráfego segue o caminho pretendido.
Termine com três pedidos que provam a divisão: um host interno por endereço, um nome interno através do resolver interno e um site público que ainda deve usar a ligação local. Se o site público agora também passa pelo túnel, a divisão nunca aconteceu, diga o que disser a lista de rotas.
Volte a ligar mais uma vez e repita o pedido interno, porque as rotas adicionadas à mão podem sobreviver à interface que as tornou válidas e transformar silenciosamente o tráfego num buraco negro depois de o túnel cair.