TCP Hole Punch (NAT Traversal) Библиотека или что-то? - PullRequest
33 голосов
/ 14 марта 2010

Я хочу сделать TCP Hole Punching (NAT Traversal) в C #. Это может быть сделано с сервером рандеву, если это необходимо. Я нашел http://sharpstunt.codeplex.com/, но не могу заставить это работать. В идеале мне нужен какой-то метод, который я даю в качестве параметра номер порта (int), который после вызова этого метода становится доступен («Port Forwarded») в NAT. Также было бы хорошо, если бы метод просто возвращал какой-то номер порта, который затем доступен в NAT. Кто-нибудь делал это в C #? Можете ли вы дать мне рабочие примеры для sharpstunt или что-то еще?

Ответы [ 6 ]

19 голосов
/ 04 июня 2011

В каждом сетевом сценарии пробивание отверстий по протоколу TCP работает аналогично пробиванию отверстий по протоколу UDP. Например, если два одноранговых узла A и B находятся за разными NAT, первый пакет SYN каждого однорангового узла, отправленный другому одноранговому узлу, открывает дыру, связанную с его публичным адресом в соответствующем NAT. Если первый SYN-пакет A для B достигает NAT B, прежде чем первый SYN-пакет B для A достигает NAT B, NAT B считает пакет SYN A незапрошенным и отбрасывает его. Однако впоследствии первый SYN-пакет B может успешно проходить через NAT A, поскольку NAT A распознает открытый адрес B в качестве пункта назначения исходящего сеанса, который инициировал A.

Так что да. Это возможно для TCP дырокола. Я не понимаю, почему кто-то может думать иначе.

Кроме того, не могли бы вы создать этот тип поведения вручную? Он не должен зависеть от какого-либо конкретного протокола, если все шаги одинаковы для сбора всей необходимой информации.

Как правило, перфорация TCP (3.2.1) происходит следующим образом:

Клиенты: A, B Сервер: S

• A использует свое соединение с S для запроса соединения S с Б. • S отвечает на A с частными и публичными адресами B, и одновременно отправляет адреса А на Б.

• А и В асинхронно устанавливают исходящее соединение на соблазнов (отправка пакетов SYN) друг другу и частные адреса, из того же порта, который они использовали зарегистрироваться в С. В то же время они слушают TCP-входящие попытки подключения по локальному TCP порты.

• A и B ожидают ответа SYN-ACK на их собираются пакеты SYN или запрос на входящее соединение (SYN пакет). Если соединение не удается, узел может повторить до максимального периода ожидания.

• После завершения процесса трехстороннего рукопожатия, сверстники аутентифицируют друг друга. Если подлинность- В этом случае узлы закрывают это соединение и ждут, пока другое соединение успешно аутентифицировано. будет успешно использовано первое аутентифицированное соединение для передачи данных TCP.

(я знаю, что это не слишком хороший ответ, но места для комментариев было недостаточно).

3 голосов
/ 18 мая 2016

Вопрос довольно старый, но для тех, кто ищет решение, вы должны взглянуть на проект Open.NAT , он действительно прост в использовании и работает как с UPNP, так и с PMP NAT!

Допустим, вы хотите перенаправить внешний порт 1700 на локальный порт 1600, все, что вам нужно сделать, это:

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

Вы также можете перечислить все существующие сопоставления, чтобы вы могли проверить, что ваш порт еще не используется.

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());

Существует также сообщение в блоге о NAT Traversal на MSDN: https://blogs.msdn.microsoft.com/ncl/2009/07/27/end-to-end-connectivity-with-nat-traversal/

2 голосов
/ 05 декабря 2012

Мы собрали библиотеку под названием IceLink , которая выполняет потоковую передачу P2P с использованием ICE / STUN / TURN с полным обходом NAT. Штамповка на основе STUN работает для большинства маршрутизаторов для установления прямого соединения между узлами, а для «плохих» маршрутизаторов соединение возвращается к ретрансляции на основе TURN.

2 голосов
/ 08 июля 2010

Похоже, вы перепутали TCP и UDP.TCP - это протокол, ориентированный на установление соединения, легко понимаемый брандмауэрами и маршрутизаторами и требующий одного инициатора (клиента) и одного прослушивателя (сервера).Если и клиент, и сервер находятся за брандмауэрами или NAT, вы не можете пробить дыру, не подключив их обоих к какому-либо прокси-серверу (который не защищен брандмауэром).Проблема в том, что тогда прокси будет отвечать за ретрансляцию всего своего трафика.

Исходя из вашего вопроса, звучит так, как будто вы больше заинтересованы в пробивании UDP-дырок, которое эксплуатирует тот факт, что UDP не поддерживает состояния,и не ориентированный на соединение.Поэтому большинство брандмауэров, отслеживающих состояние, будут «делать правильные предположения» о потоке данных UDP и исходить из того, что трафик, выходящий из данного порта, будет получать ответы на тот же порт и автоматически направлять их обратно.Если при использовании некоторых внеканальных средств (таких как TCP-сервер, который просто передает адреса, а не данные), оба узла могут передавать данные друг другу по одним и тем же портам, их соответствующие брандмауэры / маршрутизаторы NAT откроют дыры, позволяющиетрафик.

Что касается того, как это сделать, все зависит от того, как вы собираетесь получать IP-адреса одноранговых узлов друг другу.Получив его, просто начните передачу пакетов UDP по согласованному порту и дождитесь ответа.

1 голос
/ 26 апреля 2010

http://sipsorcery.codeplex.com имеет работающий сервер оглушения.

SipSorcery.core -> SipSorcery.Net -> Оглушение

0 голосов
/ 23 апреля 2010

Я не знаком с вашей темой, но я знаю P2PVPN с открытым исходным кодом, который использует lib для NAT. Вы можете проверить это здесь (www.SocialVPN.org).

Удачи.

...