Pregunta

Quiero hacer un perforación de agujeros TCP (NAT Traversal) en C#. Se puede hacer con un servidor Rendezvous si es necesario. encontré http://sharpstunt.codeplex.com/ pero no puedo hacer que esto funcione. Idealmente, necesito algún método que proporcione un número de puerto (int) como parámetro que después de una llamada a este método está disponible ("puerto reenviado") en el NAT. También estaría bien si el método solo devuelve algún número de puerto que luego está disponible en el NAT. ¿Alguien ha hecho esto en C#? ¿Puedes darme ejemplos de trabajo para Sharpstunt o algo más?

¿Fue útil?

Solución

En cada escenario de red, TCP Hole Punching opera de manera similar al perforador de agujeros UDP. Por ejemplo, si dos compañeros A y B están detrás de diferentes nats, el primer paquete SYN de cada par enviado al otro par abre un agujero asociado con su dirección pública en su respectivo NAT. Si el primer paquete SYN de A alcanza B NAT de B antes de B antes de B El primer paquete SYN a A LA A NAT de B, B's NAT considera el paquete SYN de A no solicitado y lo deja caer. Sin embargo, posteriormente, el primer paquete SYN de B puede viajar a través de NAT de A con éxito porque el NAT de A reconoce la dirección pública de B como el destino de la sesión saliente que A ha iniciado.

Entonces sí. Es posible TCP Holepunch. No veo por qué alguien pensaría lo contrario.

Además, ¿no podrías crear este tipo de bahaviour manualmente? No necesita depender de ningún protocolo específico siempre que los pasos sean los mismos para recopilar toda la información requerida.

En general, TCP Hole Punching (3.2.1) procede de la siguiente manera:

Clientes: A, B Server: S

• A utiliza su conexión con S para solicitar una conexión con B. • S respuestas a A con las direcciones privadas y públicas de B, y simultáneamente envía direcciones de A a B.

• A y B hacen que los tempts de conexión saliente asincrónicamente (envíen paquetes SYN) a las direcciones públicas y privadas del otro, desde el mismo puerto que solían registrarse en S. al mismo tiempo, escuchan los intentos de conexión entrantes de TCP en sus puertos TCP locales.

• A y B esperan una respuesta SYN-Aack a sus paquetes SYN, o una solicitud de conexión entrante (paquete SYN). Si falla una conexión, el par puede volver a intentarlo hasta un período de tiempo de espera máximo.

• Una vez que se ha completado el proceso de apretón de manos de tres vías, los pares se autentican entre sí. Si la autenticación falla, los pares cierran esa conexión y esperan hasta que otra conexión se autentique con éxito. La primera conexión autenticada exitosamente se utilizará para transferir los datos de TCP.

(Sé que esto no es una gran respuesta, pero no había suficiente espacio para un comentario).

Otros consejos

La pregunta es bastante antigua, pero para cualquiera que busque una solución, debe echar un vistazo a Open.nat Project ¡Es realmente fácil de usar y trabajar con UPNP y PMP NATS!

Digamos que desea reenviar el puerto externo 1700 al puerto local 1600, todo lo que tiene que hacer es:

var discoverer = new NatDiscoverer();
var device = await discoverer.DiscoverDeviceAsync();
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, 1600, 1700, "The mapping name"));

También puede enumerar todas las asignaciones existentes, para que pueda validar que su puerto aún no se use.

var sb = new StringBuilder();
var ip = await device.GetExternalIPAsync();

sb.AppendFormat("\nAdded mapping: {0}:1700 -> 127.0.0.1:1600\n", ip);
sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
sb.AppendFormat("\n| PROT | PUBLIC (Reacheable)           | PRIVATE (Your computer)        | Descriptopn                        |                         |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
sb.AppendFormat("\n|      | IP Address           | Port   | IP Address            | Port   |                                    | Expires                 |");
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
foreach (var mapping in await device.GetAllMappingsAsync())
{
    sb.AppendFormat("\n|  {5} | {0,-20} | {1,6} | {2,-21} | {3,6} | {4,-35}|{6,25}|",
        ip, mapping.PublicPort, mapping.PrivateIP, mapping.PrivatePort, mapping.Description, mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP", mapping.Expiration.ToLocalTime());
}
sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
Console.WriteLine(sb.ToString());

También hay una publicación de blog sobre NAT Traversal en MSDN: https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/

Parece que podrías mezclar TCP y UDP. TCP es un protocolo orientado a la conexión, fácilmente entendido por firewalls y enrutadores, y requiere un iniciador (cliente) y un oyente (servidor). Si tanto el cliente como el servidor están detrás de los firewalls o NAT, no puede hacer un hoyo sin que ambos se conecten a algún servidor proxy (que no es firewalled). El problema con esto es que el proxy sería responsable de transmitir todo su tráfico.

Según su pregunta, parece que está más interesado en el perforación de agujeros de UDP, lo que explota la grasa que UDP es apátrida y no orientada a la conexión. Por lo tanto, la mayoría de los firewalls de rastreo estatal harán una "mejor suposición" sobre el flujo de datos de UDP, y suponga que el tráfico que sale en un puerto determinado recibirá respuestas en el mismo puerto y las enrutará automáticamente. Si, utilizando algunos medios fuera de canal (como un servidor TCP que simplemente pasa direcciones y no datos), ambos pares pueden transmitir datos entre sí en los mismos puertos, sus respectivos enrutadores de firewalls/Nat se abrirán agujeros que permitan el tráfico en.

En cuanto a cómo hacerlo, todo depende de cómo va a obtener la dirección IP de los compañeros entre sí. Una vez que lo tenga, simplemente comience a transmitir paquetes UDP en un puerto acordado y espere una respuesta.

Armamos una biblioteca llamada ICelink Eso realiza transmisión P2P usando hielo/aturdimiento/giro con transversal NAT completa. El salto a base de aturdir funciona para que la mayoría de los enrutadores establezcan una conexión directa entre sus pares, y para los enrutadores "malos", la conexión se remonta a un relevo por turnos.

http://sipsorcery.codeplex.com tiene un servidor de aturdimiento en funcionamiento.

Sipsorcery.core -> sipsorcery.net -> aturdimiento

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top