¿Cómo decide NAT qué conexiones son entrantes y cuáles son salientes?

7

Estoy construyendo una aplicación P2P que necesita poder acceder a los nodos detrás de un NAT. Este NAT no permite conexiones entrantes, por lo tanto, los nodos fuera de la red no pueden llegar a los nodos detrás del NAT.

Mi solución a este problema es que el nodo detrás del NAT llegaría al nodo externo, y el nodo externo, cuando el tiempo esté listo, se conectará al nodo que está dentro del NAT utilizando esa conexión TCP preestablecida. Dado que esta conexión la establecería el nodo dentro de NAT, NAT no la bloquearía.

Aquí está mi pregunta. No sé cuáles de las interpretaciones subrayadas son correctas o si ambas están equivocadas.

Interpretación # 1

No es un concepto de una conexión TCP, efectivamente un tubo, y cuando un nodo dentro de la NAT hace una petición a cualquier cosa en el mundo exterior, que tubo se abre, la respuesta se pone en él, y el tubo se cierra para siempre.

Resultado: el NAT no permitirá más conexiones TCP al cliente desde el nodo externo después de que se cierre el tubo.

Interpretación # 2

No existe una conexión TCP, sino una transmisión TCP. Dado que una conexión TCP se define como a local ip:port, y a remote ip:port, después de que un nodo detrás del NAT llama a un nodo externo, el nodo externo puede volver a llamar utilizando el mismo puerto desde el cual el cliente realizó la solicitud, y eso "contaría" como el mismo TCP conexión, no una llamada no solicitada por el NAT.

Resultado: el NAT efectivamente adivina si esta conexión fue una respuesta a lo que el nodo dentro del NAT solicitó al mirar el registro histórico. Como el nodo detrás del NAT realizó la primera llamada, el nodo externo puede volver a llamar utilizando el mismo puerto de cliente y funcionaría.

Mi modelo mental estaba más cerca del número 1, pero cuando inspeccioné las conexiones con Wireshark, aparecían como conexiones TCP separadas, o al menos como entidades separadas.

¿Está más cerca del # 1, o del # 2, o estoy irremediablemente confundido?

Dean M.
fuente
Es posible que desee buscar STUN y trabajos relacionados: en.wikipedia.org/wiki/STUN
pjc50
55
Recomiendo encarecidamente que primero implemente una versión IPv6 de su aplicación para que no tenga que lidiar con toda la complejidad de NAT en la primera versión. Una vez que tenga una versión que funcione en IPv6, comience a considerar cómo hacer que funcione en IPv4.
kasperd

Respuestas:

9

TCP es un protocolo orientado a la conexión, y solo puede comunicarse a través de conexiones.

Antes de comenzar a programar utilizando TCP, sería útil comprender primero cómo funciona TCP, y debe comenzar con RFC 793, Protocolo de control de transmisión , que es la definición de TCP.

El RFC explica los enchufes y conexiones:

Multiplexación

Para permitir que muchos procesos dentro de un único Host utilicen las instalaciones de comunicación TCP simultáneamente, el TCP proporciona un conjunto de direcciones o puertos dentro de cada host. Concatenado con la red y las direcciones de host de la capa de comunicación de Internet, esto forma un socket. Un par de sockets identifica de forma exclusiva cada conexión. Es decir, un socket puede usarse simultáneamente en múltiples conexiones.

El enlace de los puertos a los procesos es manejado independientemente por cada host. Sin embargo, resulta útil adjuntar procesos utilizados con frecuencia (por ejemplo, un "registrador" o servicio de tiempo compartido) a sockets fijos que se dan a conocer al público. Se puede acceder a estos servicios a través de las direcciones conocidas. Establecer y aprender las direcciones de puerto de otros procesos puede implicar mecanismos más dinámicos.

Conexiones:

Los mecanismos de confiabilidad y control de flujo descritos anteriormente requieren que los TCP inicialicen y mantengan cierta información de estado para cada flujo de datos. La combinación de esta información, incluidos los sockets, los números de secuencia y los tamaños de las ventanas, se denomina conexión. Cada conexión se especifica de forma exclusiva mediante un par de enchufes que identifican sus dos lados.

Cuando dos procesos desean comunicarse, sus TCP deben establecer primero una conexión (inicializar la información de estado en cada lado). Cuando se completa su comunicación, la conexión se termina o se cierra para liberar los recursos para otros usos.

Dado que las conexiones deben establecerse entre hosts no confiables y a través del sistema de comunicación de Internet no confiable, se utiliza un mecanismo de protocolo de enlace con números de secuencia basados ​​en el reloj para evitar la inicialización errónea de las conexiones.

En lo que respecta al par TCP externo, se está conectando a la dirección externa del dispositivo NAT, aunque ese dispositivo está reenviando al otro par TCP en el interior, en función de la conexión iniciada por el dispositivo interno.

También puede estudiar RFC 5382, Requisitos de comportamiento NAT para TCP .

Ron Maupin
fuente
7

Se considera que una conexión TCP está "vigente" siempre que los procesos de software en cada extremo mantengan el socket abierto.

Cuando el (los) proceso (s) en uno o ambos extremos cierran el socket (ya sea con gracia o la conexión se aborta por alguna razón), esto se traduce, en el cable, a un paquete TCP con el indicador FIN o RST establecido.

La implementación de NAT en el enrutador NAT busca las banderas FIN y RST, y cuando ve un paquete con estas banderas, "cierra el agujero". Después de este punto, el cliente debe iniciar una nueva conexión para "abrir un nuevo agujero".

Para resumir, mientras su cliente y servidor mantengan sus sockets abiertos, la asociación NAT se mantiene viva.

mere3ortal
fuente
4

Cuando escribo "habitual" aquí, estoy pensando en su enrutador WLAN-NAT de consumidor promedio con una configuración sensata, o algunas redes Linux simples con configuraciones predeterminadas. Como de costumbre, esto puede hacerse tan complejo o complicado como sea necesario. Como la pregunta es muy básica, esto parece tener más sentido para mí en lugar de buscar soluciones NAT más complicadas a nivel empresarial.

Ya ha aceptado una respuesta, pero permítame tratar de abordar directamente la pregunta que hizo:

¿Cómo decide NAT qué conexiones son entrantes y cuáles son salientes?

La base de la decisión (para cualquier decisión en un enrutador) es un conjunto de reglas de alguna forma o forma. En este caso, para cada una de las interfaces involucradas (es decir, la interfaz LAN interna frente a la interfaz WAN / enlace ascendente externa), el administrador habrá implementado reglas. Esas reglas son bastante diferentes, es decir, las reglas para una interfaz LAN se ven muy diferentes de las de una interfaz WAN.

Saber de dónde viene un paquete y hacia dónde va es el pan y la mantequilla de lo que hace un enrutador.

Déjame comenzar con un

Ejemplo

La página NAT de Wikipedia tiene mucho texto sobre este tema, pero un caso simple (una LAN de empresa simple frente a un solo enlace ascendente DSL) es lo que sucede:

  1. La PC cliente intenta iniciar una conexión HTTP a un servidor basado en Internet, por ejemplo 198.51.100.20. La PC en sí tiene una dirección no enrutada como 192.0.2.2. El enrutador DSL barato tiene dos interfaces, una interna (192.0.2.1) y una externa (203.0.113.10, muy probablemente cambiando a menudo y proporcionada por algún protocolo de enlace local por el proveedor de DLS). Entonces, la PC envía un paquete SYN a 198.51.100.20:80 a través de su puerta de enlace predeterminada, que es 192.0.2.1.
  2. El enrutador recoge el paquete en su interfaz 192.0.2.1, como también lo haría si no hubiera NAT involucrado en absoluto. Se ha configurado para hacer NAT en esta interfaz, por lo que procede a hacer lo siguiente:
    • Inventa un nuevo número de puerto, que no se ha utilizado hasta ahora. Por ejemplo 12345.
    • Cambie la dirección del "remitente" en el encabezado IP a 203.0.113.10.
    • Recuerde el número de puerto del remitente original en el encabezado TCP (proporcionado por la PC), llamémoslo 4321.
    • Cambie el encabezado TCP para contener el número de puerto del remitente 12345.
    • Agregue una entrada (12345; 192.0.2.2; 4321) en su tabla de traducción NAT.
    • Envíe el paquete de manera alegre a su propio enlace ascendente / puerta de enlace.
  3. 198.51.100.20 finalmente recibe el paquete, se da cuenta de que es un SYN ("establecer una nueva conexión") y envía un mensaje SYN-ACK al remitente. Desde su punto de vista, esta es la dirección IP 203.0.113.10, con el puerto de destino TCP de 12345.
  4. El enrutador recibe este paquete en su interfaz WAN. La interfaz WAN se ha configurado para resolver direcciones NATadas como esta. El enrutador entonces ...
    • ... comprueba su tabla de traducción NAT, encuentra la entrada ...
    • ... modifica el paquete a un destino de 192.0.2.2 ...
    • ... repara el puerto de destino TCP de nuevo a 4321 ...
    • ... y lo envía a lo largo de su alegre camino (en la interfaz LAN).
  5. La PC recibe el paquete y no ve nada sobre el procedimiento NAT. Las miradas de paquetes simplemente como si 198.51.100.20 lo había enviado, como si el router NAT no estaba allí en absoluto.

En ningún momento aparece el tema de una "conexión". El enrutador NAT (en su forma más simple) no necesita preocuparse por el contenido de los mensajes. Se preocupa por las direcciones IP y los puertos del remitente y el receptor, pero nada más. (De acuerdo: es probable que esto se salte todo tipo de problemas relacionados con la seguridad y el rendimiento; pero se trata del principio muy básico como el que se encuentra en esta pregunta).

Entonces, ¿cómo lo sabe el enrutador?

El enrutador no necesita saber nada sobre "conexiones". De hecho, existen procedimientos similares a los descritos para TCP para el protocolo UDP sin conexión (perforación de agujeros UDP), o podrían, realmente, implementarse para cualquier protocolo que tenga algo como números de puerto en la capa de transporte.

La razón por la cual el enrutador necesita conocer el protocolo de nivel de transporte (TCP, UDP, ...) con respecto a NAT es principalmente que los puertos en sí no son parte de IP; y los puertos son los que hacen que el "pirateo" que (este tipo de) NAT es, sea fácilmente posible.

Entonces, a su pregunta:

¿Cómo decide NAT qué conexiones son entrantes y cuáles son salientes?

Las conexiones salientes son, por definición, aquellas que comienzan con un paquete SYN (o un pinchazo UDP inicial en el caso de UDP) que aparece en la interfaz LAN. Llamarlos "conexión" en el caso de NAT es un poco demasiado; terminan simplemente como una entrada temporal en una tabla de traducción NAT (más cualquier adición de seguridad / rendimiento que el enrutador NAT individual pueda emplear también).

Las conexiones entrantes no existen en el escenario que utilicé en la respuesta hasta ahora. Por supuesto, hay variantes de NAT que hacen esto; por ejemplo, puede identificar estáticamente un puerto en la interfaz WAN del enrutador con una IP específica: PUERTO en la interfaz LAN, lo que hace posible ejecutar un servidor dentro de su LAN NATada. A menudo, esto también es compatible con los enrutadores DSL / WLAN de bajo consumo. Y con los enrutadores "reales", obviamente puede configurarlos de la forma o forma que desee.

Los paquetes IP entrantes / salientes adicionales no son diferentes de los que se dan en el ejemplo. Una vez que se ha realizado el protocolo de enlace SYN inicial y el enrutador tiene la entrada en su tabla de traducción, pasará (con la misma traducción que se explica en el ejemplo) todos los paquetes adicionales en ambas direcciones.

Si, en el contexto de una conexión TCP así establecida, el servidor desea enviar datos al cliente (lo cual es perfectamente posible, TCP es bidireccional), estos son solo paquetes IP adicionales, en lo que respecta al enrutador NAT. Realmente no le importará mucho el contenido de esos paquetes (es decir, si contienen ciertas cargas útiles o si son simplemente paquetes de "administración" de TCP o lo que sea).

En ningún momento el enrutador de alguna manera "cierra el tubo" mientras lo coloca. Obviamente, el enrutador tendrá alguna noción de cuándo puede borrar la entrada de la tabla de traducción (probablemente cuando note un apretón de manos FIN que finalice la conexión, o por algún tiempo de espera o algún estado de error), pero de principio a fin es Un asunto continuo.

AnoE
fuente
1
Utilice las direcciones IP de RFC5737, definidas específicamente para fines de documentación, en lugar de "secuestrar" las válidas, especialmente de Google.
Patrick Mevzek
1
Las conexiones son bidireccionales, por lo que son entrantes y salientes. Es el inicio de la conexión que sería entrante o saliente.
Ron Maupin
@RonMaupin, sí, lo explico en los últimos párrafos, especialmente el penúltimo. ¿Coincide con lo que querías decir o lo escribí de manera oscura?
AnoE
@PatrickMevzek, aprende algo nuevo todos los días. Listo + gracias!
AnoE
Gracias. Estoy de acuerdo, mi pregunta quizás se exprese más específicamente como el inicio de la conexión, no como una pregunta con respecto a la bidireccionalidad general. Ya he implementado la asignación de puertos, y los enrutadores que actúan normalmente funcionarán. He hecho esta pregunta para averiguar qué se puede hacer para los enrutadores que no colaboran, como los que se encuentran en cafeterías, lugares públicos, etc. Sin embargo, esta es una gran respuesta que pasa por encima de la situación general, muy apreciada.
Dean M.