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?
Respuestas:
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:
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 .
fuente
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.
fuente
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:
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:
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:
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.
fuente