Misteriosas rejeições de “fragmentação necessária” do gateway VM

6

Estou resolvendo um grave problema de velocidade da WAN. Eu consertei, mas para o benefício dos outros:

Via WireShark, registrando e simplificando a configuração, reduzi-a a um comportamento estranho de um gateway fazendo DNAT para servidores na rede interna. O gateway (uma caixa do CentOS) e os servidores estão sendo executados no mesmo host do VMware ESXi 5 (e isso é significativo).

Aqui está a sequência de eventos que aconteceram - bastante consistentemente - quando tentei baixar um arquivo de um servidor HTTP atrás do DNAT, usando um cliente de teste conectado diretamente ao lado da WAN do gateway (ignorando a conexão real da Internet normalmente usado aqui):

  1. O estabelecimento habitual da conexão TCP (SYN, SYN ACK, ACK) procede normalmente; o gateway remapeia o IP do servidor corretamente nos dois sentidos.

  2. O cliente envia um único segmento TCP com o HTTP GET e também é DNATted corretamente para o servidor de destino.

  3. O servidor envia um segmento TCP de 1460 bytes com a resposta 200 e parte do arquivo, por meio do gateway. O tamanho do quadro no fio é 1514 bytes - 1500 em carga útil. Este segmento deve cruzar o gateway, mas não o faz.

  4. O servidor envia um segundo segmento TCP de 1460 bytes, continuando o arquivo pelo gateway. Novamente, a carga útil do link é de 1500 bytes. Este segmento não atravessa o gateway e nunca é contabilizado.

  5. O gateway envia um pacote ICMP Tipo 3 Código 4 (destino inacessível - fragmentação necessária) de volta ao servidor, citando o pacote enviado no Evento 3. O pacote ICMP indica que o próximo salto MTU é 1500. Isso parece ser sem sentido, já que a rede é limpa de 1500 bytes e as cargas de link em 3 e 4 já estavam dentro do limite de 1500 bytes declarado. O servidor, compreensivelmente, ignora essa resposta. (Originalmente, o ICMP tinha sido descartado por um firewall com excesso de zelo, mas isso foi corrigido.)

  6. Após um atraso considerável (e, em algumas configurações, ACKs duplicados do servidor), o servidor decide reenviar o segmento do Evento 3, somente neste momento. Além do campo de identificação de IP e da soma de verificação, o quadro é idêntico ao do Evento 3. Eles são o mesmo comprimento e o novo ainda tem o conjunto de sinalizadores Não Fragmentar. / em> No entanto, desta vez, o gateway passa o segmento para o cliente - de uma só vez - em vez de enviar uma rejeição de ICMP.

  7. O cliente confirma isso, e a transferência continua, embora extremamente lenta , já que os segmentos subseqüentes passam aproximadamente pelo mesmo padrão de rejeição, tempo limite, reenvio e, depois, passagem.

O cliente e o servidor trabalham juntos normalmente se o cliente é movido para a LAN para acessar o servidor diretamente.

Esse comportamento estranho varia imprevisivelmente com base em detalhes aparentemente irrelevantes do servidor de destino.

Por exemplo, no Server 2003 R2, o arquivo de teste de 7MB levaria mais de 7h para transmitir se o Firewall do Windows estivesse habilitado (mesmo que permitisse HTTP e todos os ICMP), enquanto o problema não apareceria e paradoxalmente a rejeição nunca seria enviada pelo gateway em primeiro lugar se o Firewall do Windows estivesse desativado. Por outro lado, no Server 2008 R2, desabilitar o Firewall do Windows não teve efeito algum, mas a transferência, embora ainda estivesse prejudicada, ocorreria muito mais rapidamente do que no Server 2003 R2 com o firewall ativado. (Acho que isso acontece porque o 2008 R2 está usando heurística de tempo limite mais inteligente e retransmissão rápida de TCP.)

Ainda mais estranhamente, o problema desapareceria se o WireShark fosse instalado no servidor de destino. Como tal, para diagnosticar o problema, eu tive que instalar o WireShark em uma VM separada para assistir ao tráfego de rede do lado da LAN (provavelmente uma idéia melhor, de qualquer maneira, por outros motivos).

O host ESXi é a versão 5.0 U2.

    
por Kevin 18.04.2013 / 05:33

4 respostas

4

Eu finalmente cheguei ao fundo disso. Acabou sendo um problema com a implementação do descarregamento de segmentação TCP da VMware na NIC virtual do servidor de destino.

A pilha TCP / IP do servidor enviaria um grande bloco para a NIC, com a expectativa de que a NIC dividisse isso em segmentos TCP restritos à MTU do link. No entanto, a VMware decidiu deixar isso em um grande segmento até que - bem, eu não tenho certeza quando.

Parece que na verdade ele permaneceu um grande segmento quando atingiu a pilha TCP / IP da VM, o que provocou a rejeição.

Uma pista importante foi enterrada no pacote ICMP resultante: o cabeçalho IP do pacote rejeitado indicava um tamanho de 2960 bytes - muito maior do que o pacote real que parecia estar rejeitando. Esse também é exatamente o tamanho que um segmento TCP estaria no fio se tivesse combinado os dados de ambos os segmentos enviados até agora.

Uma coisa que tornou o problema muito difícil de diagnosticar foi que os dados transmitidos foram divididos em quadros de 1500 bytes até o WireShark sendo executado em outra VM (conectado ao mesmo vSwitch em um separado , grupo de portas promíscuas) poderia ver. Eu realmente não estou certo porque a VM do gateway viu um pacote enquanto a VM WireShark viu dois. FWIW, o gateway não tem grande sobrecarga de recebimento ativada - eu poderia entender se isso acontecesse. A VM WireShark está executando o Windows 7.

Eu acho que a lógica da VMware em atrasar a segmentação é para que, se os dados forem sair de um NIC físico, o real descarregamento de hardware do NIC possa ser aproveitado. Parece buggy, no entanto, que ele não conseguirá segmentar antes de enviar para outra VM, e inconsistentemente, para esse assunto. Eu já vi esse comportamento mencionado em outro lugar como um bug do VMware.

A solução era simplesmente desativar o descarregamento de segmentação TCP no servidor de destino. O procedimento varia por SO mas fwiw:

No Windows, nas propriedades da conexão, na guia Geral ou na guia Rede, clique em "Configurar ..." ao lado do adaptador e procure na guia Avançado. Para o Server 2003 R2, ele é fornecido como "Descarregamento de Segmentação TCP IPv4". Para o Server 2008 R2, é "Large Send Offload (IPv4)".

Esta solução é um pouco desajeitada e pode afetar o desempenho em alguns ambientes, então ainda aceitarei uma resposta melhor.

    
por 21.04.2013 / 12:30
7

Você não pode descartar mensagens obrigatórias de fragmentação ICMP. Eles são necessários para a descoberta do pMTU, que é necessária para o TCP funcionar corretamente. Por favor, LART o administrador do firewall.

By the transparency rule, a packet-filtering router acting as a firewall which permits outgoing IP packets with the Don't Fragment (DF) bit set MUST NOT block incoming ICMP Destination Unreachable / Fragmentation Needed errors sent in response to the outbound packets from reaching hosts inside the firewall, as this would break the standards-compliant usage of Path MTU discovery by hosts generating legitimate traffic. -- Firewall Requirements - RFC2979 (emphasis in original)

Esta é uma configuração que foi reconhecida como fundamentalmente quebrada por mais de uma década. O ICMP não é opcional.

    
por 18.04.2013 / 06:08
2

Eu tive os mesmos sintomas e o problema acabou sendo esse bug do kernel: link

    
por 03.08.2014 / 00:16
0

Eu vi o mesmo problema em hosts Linux.

A solução foi desativar o Large Receive Offload (LRO) no driver de rede (vmxnet) da máquina do gateway.

Para citar o KB da VMware:

LRO reassembles incoming network packets into larger buffers and transfers the resulting larger but fewer packets to the network stack of the host or virtual machine. The CPU has to process fewer packets than when LRO is disabled, which reduces its utilization for networking.

Veja o link

Assim, os pacotes que chegam na máquina do gateway foram mesclados pelo driver de rede e enviados para a pilha da rede, que os derrubou como maiores que o MTU ...

    
por 24.06.2015 / 00:52