Практический обход NAT для надежных сетевых подключений

Я видел и читал много похожих вопросов и соответствующих статей в Википедии ( прохождение NAT, STUN, TURN, пробивание дырок TCP), но огромное количество информации на самом деле не помогает мне решить мою очень простую проблему:

Я пишу P2P-приложение и хочу, чтобы два пользователя моего приложения за NAT могли соединяться друг с другом. Соединение должно быть надежным (сопоставимым с надежностью TCP), поэтому я не могу просто переключиться на UDP. Решение должно работать на современных распространенных системах без перенастройки. Если это помогает, решение может включать подключаемое стороннее устройство, если ему не нужно передавать все данные через прокси (например, для получения внешних (WAN) IP-адресов одноранговых узлов).

Насколько я знаю, мой единственный вариант - использовать "надежную библиотеку UDP" + пробивание дырок в UDP. Для этого есть библиотека (C/C++)? Я нашел enet в связанном вопросе, но он заботится только о первой половине решения.

Что-нибудь еще? Вещи, на которые я смотрел:

  1. Туннелирование Teredo - требуется поддержка операционной системы и / или пользовательской конфигурации.
  2. Переадресация портов UPnP - UPnP отсутствует / включена везде
  3. TCP дырокол кажется экспериментальным и работает только при определенных обстоятельствах
  4. SCTP даже менее поддерживается, чем IPv6. SCTP через UDP - это просто надежный UDP (см. Выше)
  5. RUDP - практически нет поддержки мейнстрима
  6. Из того, что я мог понять о STUN, STUNT, TURN и ICE, никто из них не помог бы мне здесь.

2 ответа

Решение

ICE собирает список возможных IP-адресов / портов назначения, к которым необходимо подключиться. Каждый одноранговый узел собирает их, а затем каждый запускает проверку соединения для каждого из кандидатов по порядку, пока либо проверка не пройдет, либо проверка не пройдет.

Когда Алиса пытается соединиться с Бобом, она каким-то образом получает список возможных способов - определенных Бобом - она ​​может соединиться с Бобом. ICE называет этих кандидатов. Боб может сказать, например: "мой локальный сокет 192.168.1.1:1024/udp, моя внешняя привязка NAT (найдена через STUN) - 196.25.1.1:4454/udp, и вы можете вызвать медиаданные (промежуточное окно) на уровне 1.2.3.4:6675/ УДП". Боб помещает это в пакет SDP (описание этих различных кандидатов) и каким-то образом отправляет это Алисе. (В SIP, исходном сценарии использования ICE, SDP переносятся при обмене SIP INVITE/200/ACK, устанавливая сеанс SIP.)

ICE является подключаемым, и вы можете настроить точный характер / количество кандидатов. Вы можете попробовать прямую ссылку, затем запросить привязку у сервера STUN (это пробьет дыру в вашем NAT и сообщит вам внешний IP/ порт той дыры, которую вы вставили в описание сеанса), и откатитесь на попросить сервер TURN передать ваши данные.

Недостатком ICE является то, что ваши коллеги обмениваются описаниями SDP, которые вам могут понравиться или не понравиться. Другая причина заключается в том, что поддержка TCP все еще находится в черновом варианте, что может быть или не быть проблемой для вас. [ОБНОВЛЕНИЕ: ICE теперь официально RFC 6544. ]

Игры часто используют UDP, потому что старые данные бесполезны. (Вот почему RTP обычно работает по протоколу UDP.) Некоторые приложения P2P часто используют промежуточные или сети промежуточных блоков.

IRC использует сеть промежуточных ящиков: серверы IRC образуют сети, а клиенты подключаются к ближайшему серверу. Сообщения от одного клиента другому могут передаваться через сеть серверов.

В противном случае вы могли бы взглянуть на архитектуру BitTorrent и посмотреть, как они решают проблему NAT. Как указывает CodeShadow в комментариях ниже, BitTorrent полагается на достижимые одноранговые узлы в сети: в некотором смысле некоторые одноранговые узлы образуют сеть промежуточных ящиков. Если бы эти промежуточные блоки могли выступать в роли реле, вы бы имели архитектуру, подобную IRC, но такую, которая настроена динамически.

Я рекомендую libjingle, поскольку он используется некоторыми крупными компаниями, производящими видеоигры, которые в значительной степени зависят от P2P-сети. (Вы слышали о Steam? Vavle также использует libjingle, см. Сессию "Одноранговая сеть" на странице: https://partner.steamgames.com/documentation/api)

Тем не менее, всегда работающее решение будет использовать сервер ретрансляции. Поскольку не существует "стандартного" способа прохождения через NAT, вы должны использовать эту опцию сервера ретрансляции в качестве запасной стратегии, если всегда необходимо установить соединение между любыми узлами.

Другие вопросы по тегам