Por que nosso firewall (Ubuntu 8.04) está rejeitando o pacote final (FIN, ACK, PSH) com um RST


20

Em segundo plano, há muito tempo temos tido problemas com nosso firewall que às vezes mantêm as solicitações HTTP suspensas parcialmente carregadas até o tempo limite do TCP.

Após rastrear o tráfego no firewall, notei que ele ocorre apenas durante determinadas condições de tempo, por exemplo, quando o servidor da web envia a resposta inteira antes que o cliente envie sua segunda confirmação na carga útil. [SYN, SYN / ACK, ACK] foi trocado, REQUEST foi enviado e ACK'ed e o primeiro pacote RESPONSE foi recebido e ACK'ed, então o servidor envia o resto do corpo da resposta de uma só vez (8 pacotes incluindo o último FIN, PSH) e antes que o cliente aceite qualquer um desses, o Firewall REJEITA com um RST em relação ao servidor da web e mantém o cliente paralisado infinitamente.

Aqui está todo o rastreamento do wireshark com pacotes de ambos os lados do firewall. 192.168.126.161 é o endereço IP privado do NAT'et do cliente. 172.16.1.2 é o IP do servidor da web (não mostrando o IP público real) e 10.1.1.1 é o IP externo do firewall (não mostrando o IP público real)

2105 0.086275 192.168.126.161  172.16.1.2       TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2106 0.000066 10.1.1.1         172.16.1.2       TCP 37854 > http [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSV=89375083 TSER=0
2107 0.002643 172.16.1.2       10.1.1.1         TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2108 0.007705 172.16.1.2       192.168.126.161  TCP http > 37854 [SYN, ACK] Seq=0 Ack=1 Win=32768 Len=0 MSS=1460
2109 0.006301 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2110 0.000025 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=1 Ack=1 Win=5840 Len=0
2111 0.000007 192.168.126.161  172.16.1.2       HTTP GET /test/style.css HTTP/1.1 
2112 0.000015 10.1.1.1         172.16.1.2       HTTP GET /test/style.css HTTP/1.1 
2113 0.001536 172.16.1.2       10.1.1.1         TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2114 0.000014 172.16.1.2       192.168.126.161  TCP http > 37854 [ACK] Seq=1 Ack=111 Win=32658 Len=0
2115 0.002274 172.16.1.2       10.1.1.1         HTTP HTTP/1.1 200 OK  (text/css)
2116 0.000025 172.16.1.2       192.168.126.161  HTTP HTTP/1.1 200 OK  (text/css)
2117 0.005689 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2118 0.000024 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=1461 Win=8760 Len=0
2119 0.001536 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2120 0.000026 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2121 0.000007 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2122 0.000023 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2123 0.000313 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2124 0.000030 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2125 0.000007 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2126 0.000023 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2127 0.000009 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2128 0.000023 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2129 0.001108 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2130 0.000035 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2131 0.000008 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
2132 0.000022 172.16.1.2       192.168.126.161  HTTP Continuation or non-HTTP traffic
2133 0.000007 172.16.1.2       10.1.1.1         HTTP Continuation or non-HTTP traffic
REJECT-->
2134 0.000089 10.1.1.1         172.16.1.2       TCP 37854 > http [RST] Seq=111 Win=0 Len=0
CLIENT FIRST ACK-->
2135 0.002421 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2136 0.000033 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=2921 Win=11680 Len=0
2137 0.000007 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2138 0.000014 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=4381 Win=14600 Len=0
2139 0.000008 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2140 0.000014 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=5841 Win=17520 Len=0
2141 0.000007 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2142 0.000013 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=7301 Win=20440 Len=0
2143 0.000007 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2144 0.000015 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=8761 Win=23360 Len=0
2145 0.000007 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2146 0.000013 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=10221 Win=26280 Len=0
2147 0.001059 192.168.126.161  172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0
2148 0.000018 10.1.1.1         172.16.1.2       TCP 37854 > http [ACK] Seq=111 Ack=11681 Win=29200 Len=0

Tenho cavado e registrado o percurso de pacotes de acordo com este gráfico e parece que o último pacote de entrada 2133 ultrapassa PREROUTING bruto, conntrack, mangle-PREROUTING bruto, mas depois é perdido. Não tenho regras REJECT em minhas tabelas de ip, registro todas as regras DROP e nenhuma delas mostra onde o pacote 2133 se perde.

Eu adoraria usar o destino TRACE no filtro de entrada, mas infelizmente o ubuntu 8.04 não é fornecido com suporte para o destino TRACE.

Portanto, acredito que algumas regras internas implícitas de roteamento / conexão / rastreamento / mangling se aplicam que, por algum motivo, redefinem a conexão. Talvez o tráfego desencadeie alguma proteção do DOS, mas não tenho idéia de onde configurar / analisar isso. O mais frustrante é que um pacote é rejeitado e nada é registrado ...

A solicitação desse arquivo também funciona 100% nos hosts Windows, mas falha em determinados hosts Linux e 99,9% de todas as solicitações são atendidas, mas às vezes o tempo dos pacotes aciona esse comportamento em nosso firewall.

EDIT Ok, agora eu adicionei toneladas de log no iptables e parece que o seguinte acontece (ainda não sei o porquê!)

Para pacotes que atravessam com sucesso o firewall, as seguintes etapas são seguidas, referências de tabela / etapa daqui

Table 3-3 step

2     raw-pre
      conntrack
3     mangle-pre
4     [nat-pre]
5     routing-decision -> destination forward
6     mangle-fwd
7     filter-fwd
8     mangle-post
9     [nat-post]

O pacote 2133 que é rejeitado atravessa estas etapas:

Table 3-1 steps for the incoming FIN,ACK packet 2133
2     raw-pre
      conntrack
3     mangle-pre
4     [nat-pre]
5     routing-decision -> destination local
6     mangle-input
7     filter-input
8     local process emits RST -> webserver

Table 3-2 steps for the outgoing RST packet 2134 in response to 2133
1     raw-out
2     routing decision
      conntrack
3     mangle-out
      reroute-check
4     [nat-out]
5     filter-out
6     mangle-post
7     nat-post

O que é estranho é que a decisão de roteamento para o pacote 2133 na etapa 5 agora é diferente da decisão de roteamento para os outros pacotes. Ao analisar solicitações que funcionam, por exemplo, não ficam paralisadas, até o último FIN é roteado corretamente. Parece um bug no kernel ou que a decisão de roteamento é estável de alguma maneira.

EDITAR

Uma coisa que pode causar esses problemas é o seguinte: o tráfego é roteado entre o firewall e a LAN local, para que a LAN do cliente não seja conectada diretamente ao firewall por meio do L2.

                +---------------------------+       +------------------+                         +------------------------+
                |                           |       |      Router      |   (   Lab network    )  |                        |
( Internet ) -- + eth1                 eth0 +-------+                  +-- (                  ) -+ Client 192.168.126.161 |
                | 10.1.1.1   192.168.60.254 |       |                  |   ( 192.168.126.0/24 )  |                        |
                +---------------------------+       +------------------+                         +------------------------+

Nesta figura, 10.1.1.1 representa o endereço IP externo do firewall, todos os outros endereços são os endereços IP reais usados.

Aqui está a tabela de roteamento no firewall:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.1.1.0        0.0.0.0         255.255.255.240 U     0      0        0 eth1
192.168.126.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.60.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         10.1.1.15       0.0.0.0         UG    0      0        0 eth1

Observe que 10.1.1.0 e gw padrão 10.1.1.15 são compostos, o restante é exatamente o mesmo que o usado. Eu tive que adicionar manualmente a rota 192.168.126.0/24 para acessar a rede do laboratório a partir de eth0 (192.168.60.254).

Aqui estão alguns logs extensivos no percurso do pacote para o último pacote 2133 que é rejeitado devido ao roteamento para o host local (por exemplo, o firewall).

[16406874.374588] raw pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0 
[16406874.374625] mangle pre IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0 
[16406874.374667] mangle in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0 
[16406874.374699] filter in IN=eth1 OUT= MAC=00:02:b3:b9:ff:b5:00:90:1a:10:06:88:08:00 SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=13739 DF PROTO=TCP SPT=80 DPT=53497 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0 
[16406874.374780] mangle out IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0 
[16406874.374807] mangle post IN= OUT=eth1 SRC=10.1.1.1 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=0 RES=0x00 RST URGP=0 
[16406874.378813] mangle pre IN=eth0 OUT= MAC=00:02:b3:b9:ff:b4:00:90:1a:10:0c:dd:08:00 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0 
[16406874.378863] mangle fwd IN=eth0 OUT=eth1 SRC=192.168.126.161 DST=172.16.1.2 LEN=40 TOS=0x00 PREC=0x00 TTL=62 ID=35424 DF PROTO=TCP SPT=53497 DPT=80 WINDOW=11680 RES=0x00 ACK URGP=0 

Mais uma vez, nosso IP externo fw foi substituído por 10.1.1.1 e o ip do servidor da web fora da rede NAT foi substituído por 172.16.1.2

EDIT Breaking News!

Ok, a última tentativa foi DROP o pacote RST, muito, muito interessante, eu adicionei uma regra do iptables que eliminava todos os pacotes RST destinados ao servidor da Web, dos quais temos problemas ao solicitar arquivos. E então funcionou, por exemplo, o último pacote 2133 FIN, ACK, PSH no log acima foi descartado, mas desde que o RST foi descartado, o servidor da Web tem tempo para obter toda a formiga do ACK e decide retransmitir o último pacote, pacote 2133 mais uma vez, e agora ele passa pelo firewall, já que o módulo contrack agora vê o ACK voltar do cliente e permite o último pacote ACK, FIN com a carga final.

Portanto, é definitivamente um problema de tempo / janela, esse arquivo em particular, com o tempo dos ACKs do cliente, dispara algo no conntrack que rejeita o pacote final do servidor da web.

Até agora, pesquisar no Google e ler os documentos do Kernel não revelam nada que possa causar esse comportamento. O próximo passo será ler o código-fonte do kernel para o módulo routing / conntrack.

PROBLEMA RESOLVIDO

Bem, pelo menos agora sabemos exatamente o que acontece e temos uma solução alternativa que resolve o problema.

Sergey apontou para a muito valiosa regra de correspondência INVALID do estado -m state, que ajudou muito na depuração. Agora percebo que uma configuração do iptables sem uma regra explícita para pacotes INVALID não está completa, então um comportamento estranho às vezes parece acontecer.

Ao ativar o logon no módulo conntrack para o que causa o pacote inválido, o que acontece é bastante óbvio e eu suspeitava disso.

[16659529.322465] nf_ct_tcp: SEQ is over the upper bound (over the window of the receiver) IN= OUT= SRC=172.16.1.2 DST=10.1.1.1 LEN=1004 TOS=0x00 PREC=0x00 TTL=55 ID=40874 DF PROTO=TCP SPT=80 DPT=55498 SEQ=658735108 ACK=1194081763 WINDOW=5840 RES=0x00 ACK PSH FIN URGP=0 

Mais uma vez, 172.16.1.2 é o servidor da web externo (que se comporta incorreto) e 10.1.1.1 é o endereço externo do firewall.

O servidor da web envia mais dados por cabo do que o cliente anunciou na janela de recebimento (o conntrack está cheio de estado e verifica isso); parece que é quando o pacote FIN chega que o conntrack falha porque a janela de recebimento é realmente excedida em muito mais cedo.

Acredito que isso possa ser causado pelo descarregamento incorreto do TCP na placa de rede no servidor da web. Quando comecei a analisar isso, tirei capturas no servidor da web e, de acordo com os traços jumbo tcpdump / wireshark, os quadros jumbo foram gravados pela camada TCP no kernel, que foi segmentada em quadros menores com MTU = 1500 pela placa de rede. Portanto, obviamente, isso precisa ser endereçado no servidor da Web, pois não é o comportamento correto do TCP enviar mais dados do que o destinatário tem anúncios em sua janela de recebimento.

Polynomial e Sergey forneceram informações valiosas, mas Sergey me indicou o comportamento exato do módulo conntrack / NAT em relação à passagem de pacotes.


Você tem alguma instrução REJECT na sua configuração do iptables? Nesse caso, veja se você pode usar o log para descobrir qual é a regra.
Ladadadada 9/09/11

Não, não rejeitar regras parece que o REJEITAR acontece iptablesm fora dela acontece durante a decisão de roteamento
ernelli

É possível que o firewall não suporte janelas deslizantes? Como uma captura de um cliente ativo se compara a esta?
Joeqwerty 9/09/11

Quando funciona, além de todos os pacotes serem encaminhados corretamente para o cliente e nenhum pacote RST ser retornado, o cliente envia ACKs antes do FIN final do servidor. Examinei um despejo de um arquivo grande (300k) e não há problemas. Um rastreamento de um arquivo pequeno também funciona, o pacote final com FIN é encaminhado. Você pode por favor elaborar sobre "firewall não suporta janelas de correr"
ernelli

Você pode expandir a conexão entre o roteador e o cliente de laboratório? Você tem / 24 máscaras de rede nos 60 e 126, portanto não está claro como os clientes do laboratório podem enviar tráfego? A máscara de rede não é um / 24? Algum tipo de proxy arp está acontecendo? Existe um alias no eth0: 1 para o 126.0 / 24?
polinomial

Respostas:


9

Uma situação semelhante é descrita em http://www.spinics.net/lists/netfilter/msg51408.html : alguns pacotes que deveriam ter sido processados ​​pelo NAT de alguma forma foram marcados como INVÁLIDOS, em vez de ESTABELECIDOS, e foram para a cadeia INPUT. Você deve adicionar algumas regras -m state --state INVALIDpara verificar isso, e a resposta em http://www.spinics.net/lists/netfilter/msg51409.html sugere que esse pacote INVALID sempre deve ser DROPped, porque o NAT não é executado corretamente neles , portanto, os endereços neles podem estar errados.

Se seus pacotes problemáticos estiverem realmente marcados como INVÁLIDOS, a adição iptables -I INPUT -m state --state INVALID -j DROPprovavelmente contornará o problema (o pacote quebrado não chegará ao processo local e não causará a resposta RST, o TCP se recuperará do pacote perdido após um tempo limite). Em seguida, você pode tentar depurar o problema ainda mais, conforme descrito em http://www.spinics.net/lists/netfilter/msg51411.html :

echo 255 >/proc/sys/net/netfilter/nf_conntrack_log_invalid

(Nesse caso em particular, o problema foi causado por algum hardware de rede quebrado ao longo do caminho, provavelmente combinado com algumas falhas na descarga da soma de verificação TCP).


4

Eu já vi esse comportamento em outros tipos de firewall e o comportamento era tão idêntico que imaginei que fosse jogá-lo lá fora.

O problema que tive foi que o firewall estava NAT no mesmo espaço que as portas efêmeras na caixa. Isso causaria esse comportamento exato se os dois colidissem porque o kernel agora assumia que a conexão era destinada à máquina local. Para esse fim, há algumas coisas que você pode verificar. Primeiro, você está especificando a configuração da porta de saída no iptables (usando --to-ports)? Ou você modificou o intervalo de portas efêmeras na máquina:

$ cat /proc/sys/net/ipv4/ip_local_port_range

Para diagnosticar, você pode configurar sua captura e ver se você vê outras solicitações usando o mesmo fw ip externo, combinação de portas dentro de 3 * tempo MSL antes do RST (~ 180s, eu acho).

Embora eu ainda não tenha certeza de que essa é a resposta, se eu estivesse nessa situação, descartaria isso primeiro e depois analisaria algumas outras coisas.

É fácil de reproduzir? É possível capturar mais diagnósticos da caixa do firewall e ver o problema ocorrer? Eu tentaria capturar:

$ netstat -anp
$ cat /proc/net/ip_conntrack

a cada segundo, tentando reproduzir e ver se há algo vinculando localmente à porta e como era a tabela de máscaras durante o problema.

Se você firewall da saída RST, o eventual ACK do cliente interno faz com que a conexão seja bem-sucedida?

Última coisa, você está vendo todos os logs? Você já verificou o dmesg? Você configurou *. * Na caixa do firewall na configuração do syslog para um arquivo para ter certeza?

Deixe-me saber o que você encontra! Eu realmente aprecio a quantidade de informações que você forneceu na pergunta, obrigado.


Obrigado pelo seu esforço, posso reproduzir o erro 100%, todas as solicitações através do firewall funcionam, exceto muito poucas. Aqueles que não trabalham parecem ter um problema preciso de tamanho / tempo. Posso adicionar vários rastreamentos do Wireshark para solicitações maiores / menores entre o mesmo cliente / servidor da web através do firewall, o que funciona, mas o rastreamento acima é o que fica preso. Adicionei novas informações acima, que podem agendar um pouco de luz sobre o problema.
ernelli

/ proc / sys / net / ipv4 / ip_local_port_range está definido como [32768 61000] O netstat não mostra nenhuma porta vinculada localmente. ip_conntrack mostra a conexão como estabelecida, por exemplo, acredita que ela ainda está aberta desde que o último FIN não foi encaminhado ao cliente. O status é pacotes = 10 bytes = 12084 marca [ASSURED] = 0 secmark = 0 use = 1
ernelli
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.