Por que o NAT não reserva portas do conjunto 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
O gateway padrão de

A é 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 TCP de A seja mascarada como 192.0.2.1 usando a porta 50000 do R .

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

Em seguida, abri uma conexão de A : nc -4 192.0.2.8 60000

A começou a enviar pacotes com esta aparência:

192.168.0.5:53269 -> 192.0.2.8:60000

R traduziu isso para

192.0.2.1:50000 -> 192.0.2.8:60000

Até agora, tudo bem.

Em seguida, tentei abrir o seguinte cliente em R : nc -4 192.0.2.8 60000 -p 50000 . Eu enviei mensagens, nada acontece. Nenhum pacote pode ser visto no tcpdump de R .

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

Então esperei um pouco para que o mapeamento de conntrack morresse.

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

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

Por exemplo:

  • A faz um pedido normal para B . R máscaras usando a porta 50k.
  • A 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 está agora 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 para o kernel "emprestar" a porta do conjunto de portas TCP quando se torna ativamente mascarada?

Eu sei que posso separar minhas portas efêmeras do meu --to-ports . No entanto, isso não parece ser o comportamento padrão. O NAT e as portas efêmeras assumem o padrão de 32768-61000, o que é assustador.

(Eu encontrei o intervalo efêmero consultando / proc / sys / net / ipv4 / ip_local_port_range, e o intervalo de NAT simplesmente colocando muitos pedidos UDP em uma experiência separada - e imprimindo a porta de origem no lado do servidor. Eu não pude encontre uma maneira de imprimir o intervalo usando iptables.)

    
por Yd Ahhrk 22.08.2015 / 01:35

1 resposta

2

would it hurt the kernel to "borrow" the port from the TCP port pool when it becomes actively masqueraded?

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 para A ou em si. Na verdade, parece usar toda a tupla de endereços de transporte de destino-origem para identificar uma conexão. Portanto, é normal que o NAT crie várias conexões usando a mesma porta ( R propriedade); isso não cria confusão. Conseqüentemente, os pools de portas TCP / UDP não importam.

É bem óbvio agora que penso nisso.

I then tried to open the following client on R: nc -4 192.0.2.8 60000 -p 50000. I sent messages, nothing happens. No packets can be seen on R's tcpdump.

Esta é a parte das experiências em que eu errei.

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

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

I feel the NAT's behaviour is wrong. I could accidentally configure a port for both masquerading (particularly, by not specifying --to-ports during the iptables rule) and a service, and the kernel will drop connections silently.

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

Because the masquerade rule exists, or at least because it's active, I would have expected R's nc to fail with the error message "nc: Address already in use", which is what happens if I bind two ncs to the same port.

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

    
por 07.09.2015 / 19:21