Пробивка отверстий UDP для связи между сервером и клиентом под NAT с помощью STUN

Проблема

Я пытаюсь разработать систему связи, в которой:

A, B - это машины под NAT, A - это сервер, B - это клиент S - это STUN-сервер

S работает на компьютере, доступном в Интернете.

Поток следующий:

A hits S with an opcode saying he's the server
S registers A as server

B hits S with an opcode saying he's the client
S sends to A B's external infos (IP, PORT)
S sends to B A's external infos (IP, PORT)

A starts sending B an opcode saying he's the server every 500ms
and meanwhile listens for packets saying he's got a client

B starts sending A an opcode saying he's the client every 500ms
and meanwhile listen for packets saying he's got the server


Беда

Вот где начинаются проблемы, STUN-сервер выполняет свою работу, поскольку оба конца получают правильную информацию о другом.

Но тогда я никогда не получаю сообщение на другом конце, поэтому оба конца продолжают слушать, не получая кода операции рукопожатия или чего-либо еще.

Поведение NAT

Я изучил поведение этого NAT и, похоже, это так

A находится по адресу 192.168.X.X, порт 4444 подключается к внешнему, открывая N.N.N.N: 4444, поэтому номер порта сохраняется, пока он свободен, получает новый (случайный?), Если он недоступен.

Тесты

В тестах, которые я проводил, оба конца (A, B), размещенные на одном компьютере, оба были привязаны к внутреннему IP-адресу компьютера, пытались привязать к 127.0.0.1, 0.0.0.0, ничего не изменилось.

Если во время прослушивания рукопожатий я echo что-то с nc по localhost, это будет получено и отображено (как нераспознанное сообщение) без каких-либо проблем. Соединение, маршрутизируемое через NAT, не вызывает затруднений, каждый пакет отбрасывается.

Также пробовали с A, размещенным на машине, B на телефоне Android с мобильными данными, с помощью простого приложения, написанного специально. Блокировки по-прежнему ждут чего-то, например, тестов nodejs.


Обновление. Еще я попытался проделать дыру с помощью nc

На двух разных машинах под одним и тем же NAT я запустил:

echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4567 -p 4568

echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567

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

Я также пробовал:

с локальной машины echo "GREET UNKOWN PEER" | nc -u <PUBLIC IP> 4567 -p 4568

с общедоступной машины echo "GREET UNKOWN PEER" | nc -u <NAT IP> 4568 -p 4567

этот работает, локальная машина под NAT связывается с общедоступной, и после первого отброшенного пакета может принимать и отправлять через назначенный порт. Интересно, почему это не работает на двух машинах под одним NAT (???)


Код

Я не показал никакого кода, потому что думаю, что в этом есть какая-то логическая ошибка, но вот github проект для этого.

index.js содержит STUN-сервер, папка tests содержит тестовые примеры: test.js запускает stun-сервер, PeerClientTest.js и PeerServerTest.js являются макетами клиента и сервера.

Запустите node tests/test.js, чтобы запустить сервер на общедоступном компьютере (измените IP-адреса в config.js и tests/config.js)

затем node tests/PeerServerTest.js для запуска сервера ("A") и node tests/PeerClientTest.js для запуска клиента ("B"). Оба распознают друг друга через STUN, а затем прослушивают код операции рукопожатия на другом конце, отправляя свой собственный код операции. Этого никогда не происходит, поэтому они просто продолжают посылать / слушать вечно.

Узел не требуется, поэтому, если есть лучшие решения на других языках, просто скажите, будем признательны.


person vinzdef    schedule 11.08.2015    source источник


Ответы (1)


NAT B фильтрует пакеты A и не пропускает их. NAT фильтрует отправленные ему неизвестные пакеты. Ваш сервер A отправляет пакет клиенту B. Но клиент B ранее никогда не отправлял пакет через NAT к A. Таким образом, пакеты NAT B неизвестны и отбрасываются.

Вам нужно пробить дыру в NAT B, чтобы NAT разрешил входящие пакеты. Отправьте пакет от B на IP: порт NAT. После этого, когда вы отправляете пакет от A к B, NAT B не отбрасывает пакет A.

Это не сработает, если NAT A и B имеет комбинацию, например, Symmetric и Symmetric / PRC NAT. В этом случае вам придется использовать сервер ретрансляции TURN.

person Tahlil    schedule 12.08.2015
comment
На самом деле я так и делаю ... После того, как A и B связываются с S, они получают адрес другого конца (NAT IP, PORT) и оба начинают посылать пакеты друг другу и прослушивать входящий ответ, что будет означать, что дыра была открыта. Этого никогда не происходит, они застревают при отправке / ожидании ответа. - person vinzdef; 12.08.2015
comment
Что такое NAT типа B? Вы написали, что A находится по адресу 192.168.X.X, порт 4444 подключается к внешнему, открывая N.N.N.N: 4444, поэтому номер порта сохраняется, пока он свободен. Можете ли вы проверить это также с помощью B. Вам нужно знать, остается ли общий порт, который B получил от сервера S, таким же, когда B отправляет пакет на A. - person Tahlil; 12.08.2015
comment
Посмотрите, так ли это в вашем случае ... stackoverflow.com/questions/31702125 / hole-punching-using-stun - person Tahlil; 12.08.2015
comment
В тестах, которые я запускал, и A, и B были размещены на одном компьютере, поэтому один и тот же NAT, один и тот же внешний и даже внутренний IP, просто разные порты. Пробовал использовать эту конфигурацию в двух разных сетях, с разными маршрутизаторами и интернет-провайдерами. Также пробовал с A на моей машине и B под мобильными данными на Android. Те же результаты. - person vinzdef; 12.08.2015
comment
Для той же сети вам не нужно переходить на NAT. Но для разных NAT нужно знать тип NAT на обоих концах. Каждый NAT ведет себя по-разному, и для прохождения NAT эта информация важна. Не зная, что мы не можем сказать ничего определенного. - person Tahlil; 12.08.2015
comment
Я знаю, что мне не нужно проходить через NAT, если я нахожусь в той же сети, это действительно был тест. - person vinzdef; 12.08.2015