Pourquoi le NAT ne réserve-t-il pas les ports du pool de ports TCP et UDP de la machine?

8

J'ai fait deux expériences. C'est le réseau pour les deux:

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

Une passerelle par défaut de l » est R . R a le transfert IPv4 actif et la règle iptables suivante:

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

L'intention est que tout TCP de A sera masqué comme 192.0.2.1 en utilisant le port 50000 de R.

J'ai publié un service TCP sur le port 60000 sur B en utilisant nc -4l 192.0.2.8 60000.

Ensuite, j'ai ouvert une connexion depuis A :nc -4 192.0.2.8 60000

A a commencé à envoyer des paquets qui ressemblaient à ceci:

192.168.0.5:53269 -> 192.0.2.8:60000

R traduit cela en

192.0.2.1:50000 -> 192.0.2.8:60000

Jusqu'ici tout va bien.

J'ai ensuite essayé d'ouvrir le client suivant sur R : nc -4 192.0.2.8 60000 -p 50000. J'ai envoyé des messages, rien ne se passe. Aucun paquet ne peut être vu sur tcpdump de R.

Parce que la règle de mascarade existe, ou du moins parce qu'elle est active, je m'attendais à ce que le nc de R échoue avec le message d'erreur "nc: Adresse déjà utilisée", ce qui se produit si je lie deux ncs au même port.

J'ai ensuite attendu un moment pour que la cartographie de conntrack meure.

La deuxième expérience a consisté à essayer d'abord d'ouvrir le client de R. R commence à parler à B très bien. Si j'ouvre ensuite la connexion depuis A , ses paquets sont ignorés. A SYNs de arrivent à R , mais ils ne sont pas exaucées, même pas par des erreurs ICMP. Je ne sais pas si c'est parce que R sait qu'il n'a plus de ports de masquage ou parce que Linux est tout simplement confus (il masque techniquement le port mais la connexion déjà établie interfère en quelque sorte).

Je sens que le comportement du NAT est mauvais. Je pourrais accidentellement configurer un port pour le masquage (en particulier, en ne spécifiant pas --to-portspendant la règle iptables) et un service, et le noyau abandonnera les connexions en silence. Je ne vois également rien de tout cela documenté.

Par exemple:

  • A fait une demande normale de B . Masques R utilisant le port 50k.
  • A fait une requête DNS pour R . Étant donné que T est récursif, R (en utilisant, par pure coïncidence, le port éphémère 50k) interroge le serveur de noms faisant autorité Z sur le port 53.

Une collision vient de se produire; R utilise maintenant le port 50k pour deux connexions TCP distinctes.

Je suppose que c'est parce que vous ne publiez pas normalement de services sur des routeurs. Mais encore une fois, cela nuirait-il au noyau d'emprunter le port du pool de ports TCP lorsqu'il est activement masqué?

Je sais que je peux séparer mes ports éphémères des miens --to-ports. Cependant, cela ne semble pas être le comportement par défaut. Le NAT et les ports éphémères sont par défaut 32768-61000, ce qui est effrayant.

(J'ai trouvé la plage éphémère en interrogeant / proc / sys / net / ipv4 / ip_local_port_range, et la plage NAT en faisant simplement NATter de nombreuses demandes UDP dans une expérience distincte - et en imprimant le port source côté serveur. Je n'ai pas pu trouver un moyen d'imprimer la gamme à l'aide d'iptables.)

Yd Ahhrk
la source
2
Pourquoi est-ce effrayant que NAT utilise la gamme de ports éthéméraux? Si un client sur A utilise un port ethemeral également utilisé sur R, il devient NAT pour un nouveau. Et pourquoi avoir un service comme DNS ou DHCP sur R doit-il faire quoi que ce soit avec cela? DNS et DHCP n'utilisent pas de ports éphémères (côté serveur). Et pourquoi utiliser un seul port pour le masquage?
Thomas Erker
@Thomas: Vos questions m'ont en fait conduit dans la bonne direction, et je suis très reconnaissant, mais il semble que vous ayez également une légère idée fausse: si un client sur A utilise un port éphémère également utilisé sur R, il ne le fait pas nécessairement obtenir NATed à un nouveau; NAT n'interroge pas les pools de ports TCP / UDP. J'ai remarqué que les connexions NAT en collision sont normales et inoffensives; voir ma réponse.
Yd Ahhrk
@ Thomas: Je n'ai pas réfléchi au DHCP; Je pensais en fait au DNS. J'imagine que DNS utilise des ports éphémères s'il s'agit d'un serveur de noms récursif (pour interroger ceux qui font autorité); voir mon montage.
Yd Ahhrk
@ Thomas: L'expérience entière est destinée à voir ce qui se passe quand il y a des collisions; J'ai réduit la portée éphémère à un seul port pour forcer la collision.
Yd Ahhrk

Réponses:

2

cela nuirait-il au noyau d'emprunter le port du pool de ports TCP lorsqu'il est activement masqué?

Je suppose que la réponse est "non, mais cela n'a pas beaucoup d'importance".

J'ai supposé à tort que R n'utilisait que l'adresse de transport de destination du paquet de réponse pour dire s'il se dirigeait vers A ou lui-même. Il semble effectivement utiliser l'intégralité du tuple des adresses de transport source-destination pour identifier une connexion. Par conséquent, il est en fait normal que NAT crée plusieurs connexions en utilisant le même port ( appartenant à R ); cela ne crée aucune confusion. Par conséquent, les pools de ports TCP / UDP n'ont pas d'importance.

C'est assez évident maintenant que j'y pense.

J'ai ensuite essayé d'ouvrir le client suivant sur R : nc -4 192.0.2.8 60000 -p 50000. J'ai envoyé des messages, rien ne se passe. Aucun paquet ne peut être vu sur tcpdump de R.

C'est la partie des expériences où j'ai foiré.

L'échec se produit car les adresses de transport source et de destination sont les mêmes, pas seulement parce que l'adresse source est la même.

Si je le fais, disons nc -4 192.0.2.8 60001 -p 50000, cela fonctionne réellement. Même s'il utilise le même port qu'un masque NAT.

Je sens que le comportement du NAT est mauvais. Je pourrais accidentellement configurer un port pour le masquage (en particulier, en ne spécifiant pas --to-portspendant la règle iptables) et un service, et le noyau abandonnera les connexions en silence.

Ce ne sera pas le cas, car les connexions masquées et les connexions démarrées par R auront très probablement des destinations différentes.

Parce que la règle de mascarade existe, ou du moins parce qu'elle est active, je m'attendais à ce que le nc de R échoue avec le message d'erreur "nc: Adresse déjà utilisée", ce qui se produit si je lie deux ncs au même port.

Je suis toujours à la recherche d'une réponse à toute épreuve, mais tout semble indiquer "c'est une conséquence défavorable de la façon dont il est mis en œuvre, et il est si petit que nous sommes prêts à vivre avec."

Yd Ahhrk
la source