Por que o NAT não reserva portas do pool de portas TCP e UDP da máquina?

8

Eu fiz dois experimentos. Esta é a rede para os dois:

        [private network]     [public network]
    A -------------------- R ----------------- B
192.168.0.5     192.168.0.1|192.0.2.1       192.0.2.8

Um gateway padrão 's é R . R tem o encaminhamento de IPv4 ativo e a seguinte regra de iptables:

iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 50000

A intenção é que qualquer coisa de TCP de A seja mascarada como 192.0.2.1 usando a porta 50000 de R.

Publiquei um serviço TCP na porta 60000 em B usando nc -4l 192.0.2.8 60000.

Então eu abri uma conexão de A :nc -4 192.0.2.8 60000

A começou a enviar pacotes parecidos com este:

192.168.0.5:53269 -> 192.0.2.8:60000

R traduziu isso para

192.0.2.1:50000 -> 192.0.2.8:60000

Por enquanto, tudo bem.

Então eu tentei abrir a seguinte cliente em R : nc -4 192.0.2.8 60000 -p 50000. Enviei mensagens, nada acontece. Nenhum pacote pode ser visto no tcpdump de R.

Como a regra de mascarada existe, ou pelo menos porque está ativa, eu esperaria que o R 's nc falhasse com a mensagem de erro "nc: Endereço já em uso", que é o que acontece se eu vincular dois ncs à mesma porta.

Esperei um pouco para que o mapeamento do conntrack morresse.

O segundo experimento consistiu em tentar abrir o cliente de R primeiro. R começa a conversar com B muito bem. Se eu abrir a conexão de A , seus pacotes serão ignorados. Os SYNs de A chegam ao R , mas eles não são respondidos, nem mesmo por erros de ICMP. Não sei se isso ocorre porque o R sabe que ficou sem portas mascaradas ou porque o Linux está totalmente confuso (tecnicamente mascara a porta, mas a conexão já estabelecida de alguma forma interfere).

Sinto que o comportamento do NAT está errado. Eu poderia configurar acidentalmente uma porta para mascaramento (principalmente, não especificando --to-portsdurante a regra iptables) e um serviço, e o kernel eliminará as conexões silenciosamente. Também não vejo nada disso documentado em lugar algum.

Por exemplo:

  • Um faz um pedido normal B . R mascara usando a porta 50k.
  • Um faz uma consulta DNS para R . Sendo que T é recursivo, R (usando, por pura coincidência, porta efêmera 50k) consulta o servidor de nomes autoritativo Z na porta 53.

Uma colisão acabou de acontecer; R agora está usando a porta 50k para duas conexões TCP separadas.

Eu acho que é porque você normalmente não publica serviços em roteadores. Mas, novamente, seria prejudicial ao kernel "emprestar" a porta do pool de portas TCP quando ela se tornar ativamente mascarada?

Eu sei que posso separar meus portos efêmeros dos meus --to-ports. No entanto, esse não parece ser o comportamento padrão. As portas NAT e efêmeras têm como padrão 32768-61000, o que é assustador.

(Encontrei o intervalo efêmero consultando / proc / sys / net / ipv4 / ip_local_port_range, e o intervalo NAT simplesmente NATting muitas solicitações UDP em um experimento separado - e imprimindo a porta de origem no lado do servidor. uma maneira de imprimir o intervalo usando o iptables.)

Yd Ahhrk
fonte
2
Por que é assustador que o NAT use o intervalo de portas etéreo? Se um cliente em A usar uma porta etéreo também em uso no R, ele receberá o NAT para uma nova. E por que ter um serviço como DNS ou DHCP no R tem a ver com isso? DNS e DHCP não usam portas efêmeras (no lado do servidor). E por que usar apenas uma única porta para mascarar?
Thomas Erker 5/09
@ Thomas: Suas perguntas realmente me levaram na direção certa, e sou muito grato, mas parece que você também tem um pequeno equívoco: se um cliente em A usa uma porta efêmera também em uso em R, isso não necessariamente obter NAT para um novo; O NAT não consulta os conjuntos de portas TCP / UDP. Na verdade, notei que as conexões NAT em colisão são normais e inofensivas; veja minha resposta.
Yd Ahhrk
@ Thomas: Eu não pensei sobre o DHCP; Eu estava pensando sobre o DNS. Eu imagino que o DNS use portas efêmeras, se for um servidor de nomes recursivo (para consultar as autoritativas); veja minha edição.
Yd Ahhrk
@ Thomas: Todo o experimento tem como objetivo ver o que acontece quando há colisões; Reduzi o alcance efêmero para uma única porta para forçar a colisão.
Yd Ahhrk

Respostas:

2

prejudicaria o kernel "emprestar" a porta do pool de portas TCP quando esta se tornar ativamente disfarçada?

Eu acho que a resposta é "não, mas não importa muito".

Eu assumi incorretamente que R usava apenas o endereço de transporte de destino do pacote de resposta para dizer se ele estava indo em direção a A ou a si próprio. Na verdade, parece usar toda a tupla de endereços de transporte de destino de origem para identificar uma conexão. Portanto, é realmente normal que o NAT crie várias conexões usando a mesma porta (de propriedade da R ); isso não cria nenhuma confusão. Conseqüentemente, os conjuntos de portas TCP / UDP não importam.

É bastante óbvio agora que penso nisso.

Então eu tentei abrir a seguinte cliente em R : nc -4 192.0.2.8 60000 -p 50000. Enviei mensagens, nada acontece. Nenhum pacote pode ser visto no tcpdump de R.

Essa é a parte dos experimentos em que eu errei.

A falha ocorre porque os endereços de transporte de origem e de destino são os mesmos, não apenas porque o endereço de origem é o mesmo.

Se sim, digamos, nc -4 192.0.2.8 60001 -p 50000realmente funciona. Mesmo se estiver usando a mesma porta que uma máscara NAT.

Sinto que o comportamento do NAT está errado. Eu poderia configurar acidentalmente uma porta para mascaramento (principalmente, não especificando --to-portsdurante a regra iptables) e um serviço, e o kernel eliminará as conexões silenciosamente.

Não vai, porque as conexões mascaradas e as conexões iniciadas com R provavelmente terão destinos diferentes.

Como a regra de mascarada existe, ou pelo menos porque está ativa, eu esperaria que o R 's nc falhasse com a mensagem de erro "nc: Endereço já em uso", que é o que acontece se eu vincular dois ncs à mesma porta.

Ainda estou procurando uma resposta à prova de balas para isso, mas tudo parece apontar para "é uma conseqüência adversa de como é implementada e é tão pequena que estamos dispostos a conviver com ela".

Yd Ahhrk
fonte