Por que um servidor não enviaria um pacote SYN / ACK em resposta a um pacote SYN

46

Ultimamente, tomamos conhecimento de um problema de conexão TCP que se limita principalmente a usuários de Mac e Linux que navegam em nossos sites.

Do ponto de vista do usuário, ele se apresenta como um tempo de conexão muito longo para nossos sites (> 11 segundos).

Conseguimos rastrear a assinatura técnica desse problema, mas não conseguimos descobrir por que isso está acontecendo ou como corrigi-lo.

Basicamente, o que está acontecendo é que a máquina do cliente está enviando o pacote SYN para estabelecer a conexão TCP e o servidor da Web a recebe, mas não responde com o pacote SYN / ACK. Depois que o cliente enviou muitos pacotes SYN, o servidor finalmente responde com um pacote SYN / ACK e tudo fica bem pelo restante da conexão.

E, claro, o pontapé inicial do problema: é intermitente e não acontece o tempo todo (embora ocorra entre 10 a 30% do tempo)

Estamos usando o Fedora 12 Linux como sistema operacional e o Nginx como servidor da web.

Captura de tela da análise do wireshark

Captura de tela da análise do wireshark

Atualizar:

Desativar o dimensionamento da janela no cliente interrompeu o problema. Agora eu só preciso de uma resolução do lado do servidor (não podemos fazer com que todos os clientes façam isso) :)

Atualização final:

A solução foi desativar o dimensionamento da janela TCP e os registros de data e hora do TCP em nossos servidores acessíveis ao público.

codemonkey
fonte
1
Acho que precisamos ver algum tcpdump acontecendo.
Coredump
Você tem acls ou regras baseadas no DNS reverso? Pode ser necessário examinar mais do que apenas a conexão entre o cliente e o servidor. Talvez uma pesquisa de DNS esteja atingindo o tempo limite?
Zoredache
@coredump: aqui está uma captura de tela da análise wireshark que mostra a questão i.imgur.com/Bnzrm.png (não conseguia descobrir como exportar apenas o fluxo ....)
codemonkey
@ Zoredache: não, não temos nenhuma regra ou regra baseada no DNS reverso. Este é um servidor web enfrentando pública e permitir que todos possam acessá-lo
codemonkey
Apenas um palpite, mas você está fazendo algum tipo de limitação de taxa de conexão de entrada no servidor? Digamos, com iptables?
Steven segunda-feira

Respostas:

15

Tivemos exatamente o mesmo problema. A desativação do registro de data e hora do TCP resolveu o problema.

sysctl -w net.ipv4.tcp_timestamps=0

Para tornar essa alteração permanente, faça uma entrada /etc/sysctl.conf.

Tenha muito cuidado ao desativar a opção TCP Window Scale. Esta opção é importante para fornecer o máximo desempenho pela Internet. Alguém com uma conexão de 10 megabit / s terá uma transferência abaixo do ideal se o tempo de ida e volta (basicamente o mesmo que o ping) for superior a 55 ms.

Percebemos realmente esse problema quando havia vários dispositivos atrás do mesmo NAT. Suspeito que o servidor possa ter ficado confuso ao ver registros de data e hora de dispositivos Android e máquinas OSX ao mesmo tempo, pois eles colocam valores completamente diferentes nos campos de registro de data e hora.

mcdizzle
fonte
4
Caso alguém acabe aqui pela mesma toca de coelho que acabei de descer: Antes de desativar os carimbos de data / hora TCP ou o dimensionamento de janelas, que podem ter graves conseqüências de desempenho em um link de tráfego intenso, verifique se o problema é tcp_tw_recycle: stackoverflow .com / questions / 8893888 /…
nephtes
12

No meu caso, o seguinte comando corrigiu o problema com respostas SYN / ACK ausentes do servidor Linux:

sysctl -w net.ipv4.tcp_tw_recycle=0

Eu acho que é mais correto do que desativar os carimbos de data / hora TCP, pois os carimbos de hora TCP são úteis para alto desempenho (PAWS, redimensionamento de janelas, etc.).

A documentação tcp_tw_recycleafirma explicitamente que não é recomendável habilitá-lo, pois muitos roteadores NAT preservam os carimbos de data e hora e, portanto, o PAWS entra em ação, pois os carimbos de data e hora do mesmo IP não são consistentes.

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this
          option is not recommended for devices communicating with the
          general Internet or using NAT (Network Address Translation).
          Since some NAT gateways pass through IP timestamp values, one
          IP can appear to have non-increasing timestamps.  See RFC 1323
          (PAWS), RFC 6191.
lav
fonte
1
boa explicação aqui: vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux No lado do servidor, não ative o net.ipv4.tcp_tw_recycle, a menos que tenha certeza de que nunca terá dispositivos NAT na mistura.
Gnought
1
No meu caso, net.ipv4.tcp_tw_recycleé a verdadeira razão. Obrigado.
precisa
O tcp_tw_recycle foi removido nos kernels recentes. Existe outra solução semelhante? @nephtes implica desabilitar o registro de data e hora prejudica o desempenho.
MappaM 6/03
Como tcp_tw_recycle foi removido, o problema não deve ocorrer novamente, pois ocorreu apenas com um valor não padrão de tcp_tw_recycle.
lav
5

Apenas imaginando, mas por que, para o pacote SYN (quadro 539; o que foi aceito), os campos WS e TSV estão ausentes na coluna "Informações"?

WS é TCP Window Scaling e TSV é Timestamp Value . Ambos são encontrados no campo tcp.options e o Wireshark ainda deve mostrá-los se estiverem presentes. Talvez a pilha TCP / IP do cliente tenha se ressentido de pacotes SYN diferentes na 8ª tentativa e essa foi a razão pela qual foi subitamente reconhecida?

Você poderia nos fornecer os valores internos do quadro 539? O SYN / ACK sempre vem para um pacote SYN que não possui o WS ativado?

Hans Solo
fonte
@Ansis: aqui estão algumas capturas de tela para o frame 539 detalhes (tinha de fazê-lo em duas partes): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey
@ cododeckey: O seu 8º pacote SYN parece ser diferente dos sete primeiros pacotes SYN. O servidor responde com SYN / ACK ao SYN do cliente somente quando o campo tcp.options tiver tamanho 8 bytes (os primeiros sete pacotes SYN provavelmente têm tcp.options com tamanho 20 bytes)? Você pode desativar o dimensionamento da janela TCP no lado do cliente para ver se o problema desaparece? Parece ser um problema com a pilha TCP / IP no lado do servidor ou mal configurado firewall em algum lugar ...
Hans Solo
@Ansis: sim, eu estive olhando isso desde que você apontou e todos os outros pacotes SYN são 24 bytes. Vou tentar desabilitar o dimensionamento da janela no cliente e verificar novamente com os resultados pela manhã.
Codemonkey
@Ansis: desativar o dimensionamento de janelas no cliente interrompeu o problema. Obrigado! No entanto, agora eu preciso descobrir como consertar isso no lado do servidor (uma vez que não podemos fazer todos os nossos clientes desabilitar o Windows escala) :) O servidor em questão tem net.ipv4.tcp_windows_scaling = 1
codemonkey
@ Codemonkey: Concordo que desabilitar o WS em todos os clientes não é uma solução, mas pelo menos rastreamos o problema para problemas de tamanho de pacote / WS. Para encontrar mais a causa, devemos examinar como o seu firewall está configurado. Você pode estabelecer conexões TCP com o WS para diferentes portas TCP? De IPs de origem diferentes?
Hans Solo
4

Acabamos de encontrar exatamente o mesmo problema (realmente demorou um pouco para fixá-lo no servidor que não está enviando o syn-ack).

"A solução foi desativar o dimensionamento de janelas TCP e os carimbos de data e hora TCP em nossos servidores acessíveis ao público".

Alex Li
fonte
2

Para continuar o que a Ansis declarou, vi problemas como este quando o firewall não suporta o TCP Windows Scaling. O firewall de marca / modelo está entre esses dois hosts?

joeqwerty
fonte
O firewall é uma caixa do Fedora 13 usando iptables. net.ipv4.tcp_windows_scaling é definido como 1 nesta máquina também
codemonkey
2

O SYN / ACK ausente pode ser causado por limites muito baixos da proteção do SYNFLOOD no firewall. Depende de quantas conexões o usuário do servidor cria. O uso de spdy reduziria o número de conexões e poderia ajudar em situações nas quais net.ipv4.tcp_timestampsdesligar não ajuda.

brablc
fonte
1

Esse é o comportamento de um soquete TCP de escuta quando seu backlog está cheio.

O Ngnix permite que o argumento da lista de pendências seja escutado na configuração: http://wiki.nginx.org/HttpCoreModule#listen

listen 80 backlog = num

Tente definir num para algo maior que o padrão, como 1024.

Não garanto que uma fila de escuta completa seja realmente o seu problema, mas é uma boa primeira coisa a verificar.

akramer
fonte
Obrigado pela dica. Vou experimentar. Definimos a lista de pendências no nível do sistema operacional, mas não explicitamente na configuração do Nginx. Vou atualizar com o resultado.
Codemonkey
isso não mudou o comportamento. Acho que não é o problema? ou o único problema ...
codemonkey 16/02
1
aplicação de nível backlog parâmetro controla o tamanho da fila para conexões TCP concluídas, ou seja, 3-way handshake terminou, ou seja, syn-ack recebido - por isso não corresponde situação OP
Ygrek
1

Acabei de descobrir que os clientes TCP do Linux alteram o pacote SYN após três tentativas e removem a opção Window Scaling. Eu acho que os desenvolvedores do kernel descobriram que essa é uma causa comum de falha de conexão na Internet

Explica por que esses clientes conseguem se conectar após 11 segundos (o TCP SYN sem janela acontece após 9 segundos no meu breve teste com as configurações padrão)

Jeroen van Bemmel
fonte
0

Eu tive um problema semelhante, mas no meu caso, foi a soma de verificação TCP que foi calculada incorretamente. O cliente estava atrás de um veth e executando o ethtool -K veth0 rx off tx off fez o truque.

Baroudi Safwen
fonte