Я хочу сделать TCP Hole Punching (NAT Traversal) в С#. Это может быть сделано с сервером рандеву, если это необходимо. Я нашел http://sharpstunt.codeplex.com/, но не может заставить это работать. В идеале мне нужен какой-то метод, который я предоставляю номер порта (int) в качестве параметра, который после вызова этого метода доступен ( "Port Forwarded" ) в NAT. Было бы также хорошо, если метод просто возвращает номер порта, который затем доступен в NAT. Кто-нибудь сделал это на С#? Можете ли вы дать мне рабочие примеры для sharpstunt или что-то еще?
TCP Hole Punch (NAT Traversal) Библиотека или что-то еще?
Ответ 1
В каждом сетевом сценарии перфорация отверстий TCP работает аналогично пробиванию отверстий UDP. Например, если два одноранговых узла A и B находятся за разными NAT, каждый одноранговый пакет SYN, отправленный другому партнеру, открывает отверстие, связанное с его общедоступным адресом в соответствующем NAT. Если в качестве первого пакета SYN до B доставляется Bs NAT до того, как Bs первый SYN-пакет до A доходит до Bs NAT, Bs NAT рассматривает как пакет SYN незапрашиваемый и опускает его. Однако впоследствии первый BN-пакет SYN может успешно проходить через NAT, поскольку NAT распознает публичный адрес Bs в качестве адресата исходящего сеанса, инициированного A.
Так что да. Это возможно для сквозного прохода TCP. Я не понимаю, почему кто-то мог подумать иначе.
Кроме того, не могли бы вы создать этот тип bahaviour вручную? Он не должен зависеть от какого-либо конкретного протокола, если все шаги одинаковы, чтобы собрать всю необходимую информацию.
Как правило, пробивка отверстий TCP (3.2.1) выполняется следующим образом:
Клиенты: A, B Сервер: S
• A использует его соединение с S для запроса S для соединения с B. • S отвечает на личные и публичные адреса A с Bs, и одновременно отправляет как адреса в B.
• А и В асинхронно выполняют исходящее соединение, соблазняет (посылает пакеты SYN) всем остальным публичным и личные адреса, из того же порта, который они использовали для регистрации в S. В то же время они слушают Попытки TCP-соединения на локальном TCP-соединении порты.
• A и B ждут ответа SYN-ACK на их out- идущие SYN-пакеты или запрос входящего соединения (Пакет SYN). Если соединение терпит неудачу, одноранговый узел может повторить попытку это до максимального периода ожидания.
• Как только процесс трехстороннего рукопожатия завершен, сверстники аутентифицируют друг друга. Если аутентификация не удается, сверстники закрывают эту связь и ждут другое соединение успешно завершено. будет использоваться первая успешно аутентифицированная связь для передачи данных TCP.
(Я знаю, что это не очень ответ, но комментариев не хватало).
Ответ 2
Похоже, вы можете перепутать TCP и UDP. TCP - это протокол, ориентированный на соединение, который легко понимается брандмауэрами и маршрутизаторами и требует одного инициатора (клиента) и одного слушателя (сервера). Если клиент и сервер находятся за брандмауэрами или NAT, вы не можете пробить отверстие, не подключая их к прокси-серверу (который не является межсетевым экраном). Проблема в том, что тогда прокси-сервер будет отвечать за передачу всего своего трафика.
Из вашего вопроса, похоже, вас больше интересует перфорация отверстий UDP, в которой используется жир, который UDP является апатридом, а не ориентирован на соединение. Поэтому большинство брандмауэров, отслеживающих состояние, сделают "лучшее предположение" о потоке данных UDP и предположим, что трафик, отправляемый на данный порт, будет получать ответы на одном и том же порту и автоматически перенаправить их обратно. Если, используя некоторые внеканальные средства (такие как TCP-сервер, который просто передает адреса, а не данные), оба одноранговых узла могут передавать данные друг другу на одних и тех же портах, их соответствующие брандмауэры/NAT-маршрутизаторы откроют отверстия, позволяющие трафик.
Что касается того, как это сделать, все зависит от того, как вы собираетесь получать IP-адрес сверстников друг к другу. После этого просто начните передачу пакетов UDP на согласованном порту и дождитесь ответа.
Ответ 3
Мы собрали библиотеку под названием IceLink, которая делает потоки P2P с использованием ICE/STUN/TURN с полным обходом NAT. STUN-based дыропробивка работает для большинства маршрутизаторов, чтобы установить прямое соединение между одноранговыми узлами, а для "плохих" маршрутизаторов там соединение возвращается к реле на основе TURN.
Ответ 4
Вопрос довольно старый, но для тех, кто ищет решение, вы должны взглянуть на проект 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/
Ответ 5
Я не знаком с вашей темой, но мне известно, что P2PVPN с открытым исходным кодом использует lib для NAT. Вы можете проверить его здесь (www.SocialVPN.org).
Удачи.
Ответ 6
http://sipsorcery.codeplex.com имеет рабочий оглушающий сервер.
SipSorcery.core → SipSorcery.Net → Stun