Hacer una conexión entre dos computadoras detrás de NAT

Estoy tratando de establecer una conexión entre dos computadoras detrás de NAT. No puedo abrir ningún puerto. Me gustaría usar un corredor que estará en Internet y que pueda comunicarse con los otros 2. Después, me gustaría volver a abrir un túnel entre esos 2. Estoy usando Python y estoy tratando de codificar este agente. ¿Cómo puedo empezar esto?

Lo que quieres hacer es posible, y casi de rutina (al menos para UDP). Se llama perforación de agujeros NAT. No funcionará con todos los NAT del mundo, pero funciona con muchos, incluida la mayoría de las configuraciones de los enrutadores domésticos más actuales.

La idea básica es que, con la mayoría de los enrutadores, si envía un paquete saliente, le reenviará cualquier paquete entrante desde el mismo punto final. De lo contrario, NAT no funcionaría en absoluto, ¿verdad? Por lo tanto, si ambos, usted y yo, intentamos hablar con las direcciones públicas del otro al mismo tiempo, uno de nosotros habrá “perforado un agujero” en su NAT a tiempo para recibir el mensaje. El otro probablemente se perderá el mensaje inicial, porque él perforó su agujero demasiado tarde, pero recibirá la siguiente respuesta que el otro tipo envió, y después de eso, todo está funcionando.

Hay algunos trucos aquí, sin embargo.

Primero, necesitas saber tu dirección pública. Todo lo que puede ver directamente es su dirección privada dentro del NAT, por lo que necesita un servidor fuera del NAT que le pueda decir de dónde viene. Hay un estándar para esto, llamado STUN . No solo hay varias implementaciones gratuitas que puede crear y ejecutar usted mismo, también hay múltiples servidores STUN abiertos en Internet; google para una lista actualizada.

Como mínimo, tiene una dirección privada y su dirección pública, y realmente desea darles a todos los demás, no solo una. (Si solo me da su dirección pública y resulta que estamos en el mismo NAT, es posible que no podamos hablar entre nosotros). Se complica aún más si tiene varias NIC, o si en una LAN corporativa con múltiples capas de NAT, etc. Pero si me da un montón de direcciones, ¿cómo puedo saber cuál usar? Simple, puedo intentar conectarme a cada una de ellas desde cada una de mis direcciones locales, y la primera que funciona es la que sigo usando. Obviamente necesitamos algún tipo de protocolo para esto, así que puedes decirme cuándo ha funcionado uno de ellos, pero puede ser muy simple.

Además, tenga en cuenta que cuando digo “dirección” aquí, eso no solo significa la dirección IP, sino la dirección IP más el puerto . Después de todo, los NAT pueden y deben traducir los puertos junto con las direcciones, y el “agujero” que usted introduce en un NAT a menudo es específico del puerto. Por lo tanto, debe realizar la negociación utilizando los mismos puertos de origen y destino que va a utilizar para la comunicación real. (En realidad, hay algunos bits difíciles aquí, que se explican por los documentos vinculados, pero ahora vamos a repasarlos).

Cuando el taladrado no funciona, y necesita volver a enviar un proxy a través de un servidor, no quiere que el código se vea completamente diferente; Terminarías teniendo que escribir todo dos veces y tener grandes problemas con la depuración. Afortunadamente, existe una solución estándar para esto, llamada TURN , que hace que parezca que en realidad están hablando directamente incluso cuando hablan a través de un relé. Una vez más, hay implementaciones gratuitas, pero, por supuesto, no hay servidores TURN abiertos para su uso (porque eso costaría mucho ancho de banda).

Mientras tanto, una vez que sepa su dirección pública, tendrá que decirme qué es y viceversa. Obviamente, necesitamos algún canal lateral para hablar, como un servidor especial “introductor” o “lobby”. Normalmente, está generando una conexión de igual a igual como una derivación de alguna conexión mediada por el servidor. Por ejemplo, podríamos estar juntos en un canal IRC, o en una red de chat XMPP / Jabber, y decidir que queremos una comunicación de igual a igual (para evitar las escuchas ilegales, compartir archivos de hojas de cálculo gigantes o jugar un juego sin grandes retraso).

Hay un estándar llamado ICE que une todo esto; siempre que tengamos un canal lateral compartido y una lista de servidores STUN (y posiblemente TURN), ICE nos permite negociar una conexión peer-to-peer si es posible (retroceder a TURN si no).

El soporte de ICE es parte de SIP y de una serie de otros protocolos, por lo que si está utilizando una biblioteca para uno de esos protocolos, es probable que solo tenga que descubrir cómo proporcionarle una lista de servidores STUN y TURN, y eso es todo. Si no, probablemente hay bibliotecas para hacer ICE. Si no, definitivamente hay bibliotecas para hacer STUN y TURN (y si no las hubiera, ambos son protocolos bastante simples), así que puedes hacer la negociación tú mismo sobre ellos.

Por supuesto, no tiene que usar ninguno de estos estándares, pero definitivamente debe leer lo que hacen y por qué hacen las cosas de esa manera. (Además, tenga en cuenta que las personas ahora están haciendo enrutadores específicamente para hacer que ICE funcione mejor, y eso no será cierto para nada diferente que usted invente).


Me he vinculado a los artículos de Wikipedia anteriores porque comienzan con una descripción bastante simple de cómo funcionan las tecnologías y la razón detrás de ellas. Hay mejores fonts para las especificaciones de referencia detalladas, código de ejemplo para comenzar, bibliotecas para usar, etc., pero en general Wikipedia tiene enlaces a todo lo que necesita.