2010-03-14 17 views
32

Quiero hacer TCP Perforación de taladro (NAT Traversal) en C#. Se puede hacer con un servidor de encuentro 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 ("Reenvío de puerto") en el NAT. También estaría bien si el método simplemente devuelve un número de puerto que luego está disponible en el NAT. Alguien ha hecho esto en C#? ¿Me puede dar ejemplos de trabajo para sharpstunt o algo más?TCP Hole Punch (NAT Traversal) ¿Biblioteca o algo así?

+0

Hmm ... Por qué es este el caso especial que se necesita? si solo se trata de la conexión, instale cualquier Proxy y configúrelo en el Webclient. también debería resolverlo. – cRichter

+1

Los proxies son lentos y no son seguros. – Matth3w

Respuesta

15

En cada escenario de red, la perforación de orificios TCP funciona de forma similar a la perforación con orificios UDP. Por ejemplo, si dos pares A y B están detrás de diferentes NAT, 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 llega a B, NAT antes de que el primer paquete SYN de B llegue a la NAT de B, la NAT de B considera el paquete SYN de A no solicitado y lo descarta. Sin embargo, posteriormente, el primer paquete SYN de B puede viajar a través de la NAT de A con éxito porque la NAT de A reconoce la dirección pública de B como el destino de la sesión saliente que A ha iniciado.

Así que sí. Es posible perforar el agujero TCP. No veo por qué alguien pensaría lo contrario.

Además, ¿no podrías crear este tipo de comportamiento de forma manual? No necesita depender de ningún protocolo específico, siempre y cuando los pasos sean los mismos para reunir toda la información requerida.

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

Clientes: A, B Servidor: S

• A utiliza su conexión con S pedir S para una conexión con B. • S respuestas a A con B privado y direcciones públicas, y el envío simultáneo de direcciones de A a B.

• A y B de forma asíncrona hacer conexión saliente en- tienta (enviar paquetes SYN) al público y privada de cada uno direcciones, desde el mismo puerto que usaron para registrarse con S. Al mismo tiempo, escuchan intentos de conexión entrante de TCP en sus puertos TCP locales.

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

• Una vez que se ha completado el proceso de handshake 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 haya autenticado correctamente. La primera conexión autenticada con éxito se usará para transferir datos TCP.

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

+0

Esto no funcionará con NAT de empresa (NAT simétrica). ¿Por qué A y B envían a la dirección privada? No pueden enrutarse a través de Internet. Lo que está describiendo es STUNT – tobias

+1

Me limito a describir el proceso de perforado. STUNT es un conjunto real de herramientas para ayudar en el proceso de perforado. El punto principal de mi respuesta fue mostrar que el perforado de orificios TCP es posible porque alguien había mencionado que no era así. Soy consciente de que hay escenarios en los que no funcionará, pero esa no era la pregunta. (En cuanto a por qué la mención de la dirección privada. No lo sé. Copié la mayoría de los datos de otras fuentes). – SilverX

+1

Wikipedia para STUN bajo "Limitaciones": Como la dirección IP del servidor STUN es diferente de la del punto final, en el caso NAT simétrico, la asignación NAT será diferente para el servidor STUN que para un punto final. TURN ofrece mejores resultados con NAT simétrica. – SilverX

1

No estoy familiarizado con su tema, pero conozco un P2PVPN de código abierto, que usa una lib para hacer NAT. Puede consultarlo aquí (www.SocialVPN.org).

Buena suerte.

1

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

SipSorcery.core -> SipSorcery.Net -> Stun

+0

me encantaría tener STUNT no STUN pero gracias podría ser un punto de partida – TobiHeidi

+0

Creo que tiene ambas cosas. el truco es simplemente aturdir a TCP, ¿verdad? – jgauffin

+0

stunt aturde pero con TCP en lugar de UDP. No puedes simplemente reemplazar UDP con TCP y funciona como magia. Desafortunadamente SipSorcery.core -> SipSorcery.Net -> Stun NO proporciona STUNT ... – TobiHeidi

3

Parece que usted podría estar recibiendo TCP y UDP mezclados. TCP es un protocolo orientado a la conexión, fácil de entender 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 firewalls o NAT, no se puede abrir un agujero sin que ambos se conecten a algún servidor proxy (que no tiene cortafuegos). El problema con esto es que entonces el proxy sería responsable de transmitir todo su tráfico.

De su pregunta, parece que está más interesado en la perforación de agujeros UDP, que explota la grasa de que UDP es sin estado, y no está orientado a la conexión. Por lo tanto, la mayoría de los servidores de seguridad de seguimiento de estado harán una "mejor estimación" sobre el flujo de datos UDP, y supondrán que el tráfico que sale de un puerto determinado recibirá respuestas en el mismo puerto y las redirigirá automáticamente. Si, usando algunos medios fuera del canal (como un servidor TCP que simplemente transfiere direcciones y no datos), ambos pares pueden estar transmitiendo datos entre sí en los mismos puertos, sus respectivos firewalls/enrutadores NAT abrirán agujeros permitiendo el tráfico en.

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

+0

Puedo hacer perforaciones UDP Hole que son conocidas como STUN es bastante fácil. PERO puede hacer perforaciones TCP Hole, es simplemente más complejo y se llama STUNT (la última T es para TCP). http://sharpstunt.codeplex.com/ afirma que puedo hacerlo, pero no puedo hacer que funcione. También hay algunas librerías JAVA que lo hacen ... – TobiHeidi

+0

+1> Si el cliente y el servidor están detrás de firewalls o NAT, no se puede abrir un agujero sin que ambos se conecten a algún servidor proxy. – Valmond

+0

Tenga en cuenta que STUN no lo hace trabajar con todo tipo de NAT. ICE define TURN como alternativa. – tobias

2

Recopilamos una biblioteca llamada IceLink que realiza la transmisión P2P usando ICE/STUN/TURN con recorrido de NAT completo. El taladrado de orificios basado en STUN funciona para la mayoría de los enrutadores para establecer una conexión directa entre pares, y para los enrutadores "malos", la conexión vuelve a un relé basado en TURN.

+0

Parece que es una biblioteca comercial (solo dice) – Valmond

2

La pregunta es bastante antigua, pero para cualquiera que busque una solución, debe echarle un vistazo a Open.NAT project, es muy fácil de usar y funciona tanto con UPNP como con PMP NAT.

Digamos que desea reenviar el puerto externo 1700 a 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 el puerto no es ya usado.

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 un blog acerca de NAT en MSDN: https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/

+0

trabajando intermitentemente para mí ... – beppe9000

+0

Sí, es un poco complicado hacer que funcione perfectamente y con algunos hardware de red puede que no funcione en absoluto. – JPelletier