Tem um requisito que não cede: o lado distante tem de receber o mesmo pacote IP de 1,500 bytes que o emissor produz, cabeçalhos incluídos. Um túnel não consegue envolver esse pacote mais o seu próprio enquadramento dentro de um segundo pacote IP de 1,500 bytes, por isso algo no projeto tem de ceder. A ordem abaixo é a que uso numa janela de mudança: escrever o orçamento em bytes, provar o que a underlay consegue realmente transportar, depois escolher exatamente um mecanismo de transporte e confirmar o pacote interno no lado distante.

Escreva o orçamento em bytes antes de editar um perfil

O encapsulamento acrescenta bytes em várias camadas, e o total é uma propriedade do seu perfil e não uma constante que se possa consultar. A família de endereços, a escolha da cifra, o protocolo de transporte e qualquer opção de compressão ou enquadramento alteram o número, por isso uma subtração copiada de outra instalação é inútil como orçamento. Comece pelo requisito interno, acrescente a sobrecarga medida por pacote da sua configuração e escreva o tamanho externo resultante no ticket de mudança antes de alguém editar um ficheiro.

Dois números decidem o projeto: o maior pacote externo que o caminho transporta sem fragmentação e os bytes extra de que o seu encapsulamento precisa. Quando o primeiro é menor do que o segundo mais 1,500, um deles tem de mudar. A escolha torna-se então estreita e não criativa, e é por isso que escrevo os dois números antes de discutir opções. Nada na camada do túnel comprime esses bytes, e nenhum número inteiro de MTU remove o requisito que lhe foi dado.

Sonde a underlay com ping do-not-fragment

Meça o caminho em vez de confiar no MTU da interface, porque o elo mais pequeno no caminho externo é o que conta. Em Linux, -M do define o bit do-not-fragment e -s recebe o payload ICMP, por isso um frame de 1,500 bytes responde com 1,472 bytes de payload depois de retirar o cabeçalho IP de 20 bytes e o cabeçalho ICMP de 8 bytes. Suba o payload até a sonda falhar e depois salte para um tamanho jumbo para ver se o caminho o transporta de todo.

ping -M do -s 1472 -c 2 198.51.100.10
ping -M do -s 8972 -c 2 198.51.100.10
tracepath -n 198.51.100.10

Um caminho que passa 1,472 e falha 8,972 não consegue transportar um pacote interno de 1,500 bytes mais a sobrecarga num único pacote externo. É a resposta de que precisava antes de abrir a configuração da VPN. Também decide qual das duas secções seguintes se aplica a si, por isso guarde os dois resultados das sondas junto ao ticket. Adivinhar aqui custa uma janela de manutenção, porque um túnel que se declara ativo não lhe diz nada sobre o maior pacote que o caminho aceitará.

Aumente o MTU do caminho apenas onde todos os saltos concordam

As frames jumbo são uma propriedade end-to-end, não um ajuste que ativa nos dois pontos finais que por acaso controla. Cada switch, router e entrega do fornecedor no caminho externo tem de concordar com o tamanho maior, e um único salto de 1,500 bytes descartará silenciosamente o pacote que acabou de aumentar. Aumentar apenas a interface local é a clássica meia-mudança que faz o túnel parecer avariado enquanto a underlay descarta em silêncio.

ip link set dev eth1 mtu 9000
ip link show dev eth1
ping -M do -s 8972 -c 2 198.51.100.10

Altere a interface e depois volte a sondar o mesmo caminho antes de mudar mais alguma coisa. Se a sonda continuar a falhar, reverta com ip link set dev eth1 mtu 1500 e passe à fragmentação em vez de discutir com um fornecedor sobre uma ligação que não é sua.

Use fragmentação do túnel quando a underlay não pode crescer

Um mecanismo de fragmentação suportado abaixo do pacote interno permite que vários pacotes externos transportem um pacote interno, e o ponto final do túnel do lado oposto remonta-os antes de entregar o original à pilha. A opção de fragmentação UDP do Community OpenVPN é uma implementação dessa ideia e não é o mesmo que a fragmentação IP comum do pacote externo. Os dois pares têm de correr uma versão que suporte o formato, e o caminho de dados tem de ser o que pensa: os clientes OpenVPN 3 e os canais de dados acelerados pelo kernel têm limites diferentes, por isso um perfil que funciona num cliente pode falhar noutro.

openvpn --config client.ovpn --tun-mtu 1500 --fragment 1400 --verb 4

A fragmentação externa comum é a outra opção, e é a mais fraca. Os routers IPv6 não fragmentam de todo um pacote reencaminhado, por isso um pacote externo demasiado grande simplesmente morre e o emissor só o descobre se a mensagem ICMPv6 relevante sobreviver ao caminho. Os fragmentos também convidam à filtragem e à amplificação de perdas, e é por isso que trato isto como uma alternativa e não como um plano.

Um transportador externo baseado em stream contorna a questão do tamanho segmentando o seu próprio fluxo de bytes, e o pacote interno reconstruído pode continuar a ter 1,500 bytes. É uma decisão de transporte com o seu próprio custo, incluindo o conhecido comportamento de TCP dentro de TCP, por isso tome-a deliberadamente e não como efeito secundário de uma discussão sobre MTU.

Confirme que o pacote interno chega inalterado

A verificação não é um handshake bem-sucedido. Capture na interface do túnel nas duas pontas e compare o tamanho e o conteúdo do pacote que a aplicação enviou de facto com o que o lado distante recebeu.

ip link show dev tun0
ping -M do -s 1472 -c 2 10.8.0.1
tcpdump -ni tun0 -c 5 'icmp and greater 1000'

Se a captura mostrar o pacote interno de tamanho completo na outra ponta, a escolha de transporte funciona e o trabalho restante é registá-la. Se não mostrar nada enquanto o túnel se declara ativo, o pacote externo está a ser descartado em algum ponto entre os pontos finais, o que o devolve à sonda e não às definições da cifra.

Registe três coisas no ticket de mudança antes de o fechar: o orçamento externo medido, o mecanismo que escolheu e o comando que provou que o pacote interno sobreviveu. A próxima pessoa a mexer neste túnel vai precisar das três, e nenhuma delas pode ser reconstruída apenas a partir do ficheiro de configuração.

Artigos relacionados