- В чём принцип работы STUN?
- WireGuard, настройка нескольких клиентов за NAT и причем здесь STUN?
- Прямой VPN-туннель между компьютерами через NAT’ы провайдеров (без VPS, с помощью STUN-сервера и Яндекс.диска)
- Введение
- Теория
- Практика
- Заключение
- Stun клиент для windows
- Contents
- Список STUN-серверов [ edit ]
- XMPP-клиенты с поддержкой STUN [ edit ]
- Тип NAT [ edit ]
В чём принцип работы STUN?
Всем, доброго дня! Мне стало интересно, как реализовать передачу данные p2p. Для этого решил использовать tcp/ip протокол. Узнал, что всё объединяется(локальные пк в сети провайдера) в NAT сервера. И чтобы NAT обменивались данные (локальный p2p мне не нужен) есть много путей, но основные:
1. Проброс портов (пробовал Mono.Nat для C#, miniupnp для python) — ничего не сработало
2. STUN сервер, вроде, код, что нашёл в интернете работает, но как-то некорректно, только отправляет, но не получает данные. (ниже приложу код) Но я вот не могу понять, а зачем STUN нужен? Чтобы узнать внешний ip? Так может просто мой друг кинуть, но я законнектиться не смогу, ибо мы просто не найдем друг друга.
- Вопрос задан 09 февр.
- 235 просмотров
tcp для p2p требует еще одного stun\turn\ice сервера для проведения хендшейка. иначе никак.
чтоб было чуть понятней в чем проблема — если второй клиент за натом, то внутри адрес у него какой-то 192.168.22.88, а наружу он идет через нат с ипшником 172.22.20.20. проблема в том, что за этим натом может быть еще несколько сотень других компов, каждый с которых (снаружи) виден под этим ипшником. Именно по этой причине попытке законнектится к ипшнику вашего друга заканчивается провалом. нат просто не понимает что с этим запросом делать, потому отбрасывает его.
Аркадий Баганин,
ваш «настоящий» ип/порт является таким только во время жизни коннекшена (если мы все-еще про тсп говорим). сессию закрыли/долго не было трафика/етц — и нат этот порт может закрыть/отдать кому-то другому. кроме того, нат — достаточно сложная штука которая может проверять любые хедеры от сетевого уровня и выше. сначала инициировали тсп подключение, а потом вдруг начали слать юдп? звучит как вполне себе причина проигнорировать такое.
т.е. да, подключится напрямую без явного использования стана можно. но фактически — вы этот стан сами и реализуете. ну и все-равно сервер для хендшейка будет нужен.
И в чём отличия stun под tcp от stun под udp?
WireGuard, настройка нескольких клиентов за NAT и причем здесь STUN?
На данный момент мы запускаем доступ к серверам на базе WireGuard и сегодня я хочу рассказать, как настраивать клиентов, которые находятся за NAT, хотя про настройку сервера, тоже не забудем.
Сначала, о преимуществах WireGuard и обратной стороне медали, о сложностях, которые возникают вместе с преимуществами. WireGuard достаточно молодая реализация туннеля между двумя точками, как протокол передачи используется UDP. Именно поэтому и еще потому, что сама реализация в Linux выполнена в виде модуля ядра, тесты показывают порядочное преимущество в скорости, по отношению к конкурентам. Пиринговой сетью это считать нельзя, хотя конечные узлы и называются Peer. Суть пиринговой сети не только в том, что бы можно было соединить два произвольных узла. Конечно же на данном инструментарии, можно построить весьма замысловатую сетевую инфраструктуру, но у меня такой цели не стоит. Мы рассмотрим подключение к серверному узлу и выход посредством него в интернет.
Очевидно, что если два узла, сервер и один клиент имеют белые IP, в этом случае не должно возникать никаких сложностей в настройке. Но часто клиенты находятся за NAT и в этом случае при настройке сервера необходимо указывать совсем не тот IP адрес, который выдан/прописан на устройстве. В этом отношении, может помочь STUN протокол. Этот протокол, часто используется при работе VoIP, особенно, когда оба клиента находятся за NAT. Но в нашем случае он тоже поможет. Судя из информации в википедии, STUN работает не со всеми типами NAT, в одном из 4 типов NAT (симметричный) клиент может иметь другой IP, чем тот, что может быть определен снаружи с помощью STUN клиента.
Клиенты STUN, существуют на всех популярных операционных системах, кроме iOS. Под эту операционную систему, STUN клиент мне найти не удалось. Пример я приведу для macOS. Для начала, необходимо установить сам STUN клиент.
В интернете существует масса STUN серверов и не сложно в поиске найти любой сервер для теста. Я буду использовать stun.ekiga.net. Для теста необходимо будет использовать локальный порт, тот который мы будем использовать для настройки:
При удачном тесте мы получим, примерно такой вывод:
Mapped address это именно тот IP, который необходимо будет использовать при настройке сервера. На самом деле, это тот IP адрес, который в моем случае выдаст любой сервис по определению внешнего IP. Поэтому можно воспользоваться вашим любимым сервисом по определению IP, но конечно, стоит учитывать, что этот тест будет косвенным и гарантии никакой нет, что все будет работать так как задумывалось.
Для подключения, со стороны клиента, для сервера, необходимо предоставить: IP, порт и публичный ключ. Для настройки на стороне клиента, необходим точно такой же список предоставленный со стороны сервера. Далее я предложу варианты конфигов, если вы будете использовать их у себя в качестве примеров, рекомендуется перегенерировать ключи.
На Linux, это можно сделать из командной строки, на macOS — через UI официального клиента.
В данном случае по месту вызова приватный ключ будет создан в файле privatekey, публичный в в publickey соответственно.
Первым рассмотрим клиентский конфиг:
Теперь пришло время серверного конфига:
При использовании данных конфигов как примеров, рекомендуется удалить комментарии на русском языке, работа сервера и клиента в случае оставленных комментариев — не гарантируется.
Для настройки я пользовался следующими ресурсами: официальным сайтом, ArchWiki и вот этим туториалом.
В конце, я хотел бы также прояснить пару возможных вопросов:
1. Можно ли на сервере сделать несколько секций одинаковых Peer, которые будут отличаться только EndPoint?
Да можно, и это даже может быть полезно в том случае, когда вы пользуетесь сервисом из разных мест, к примеру, на работе и дома. Но проблемы могут возникнуть если такие Peer, выйдут в онлайн одновременно, в этом случае будет конфликт IP адресов.
2. Какой внешний IP и порт будет определяться по STUN протоколу для нескольких клиентов за NAT?
Один и тот же для всех клиентов, он будет одинаковый. Будет ли это проблемой? Это все зависит от настроек вашего провайдера/роутера, но принципиально проблемы возникать не должны, так как роутер должен широковещательно ретранслировать UDP пакеты внутри сети по маске локальной сети, соответственно те принимающие стороны, которые смогут расшифровать пакеты, должны их успешно принимать. Мы проводили тесты, на нашем оборудовании, тесты прошли успешно.
Целью статьи не было написать полный туториал как настроить WireGuard, это не сложно сделать воспользовавшись официальной документацией. Мы хотели показать, как WireGuard может работать за NAT.
Если вы хотите попробовать WireGuard в деле, вы можете обратиться к нам, у нас есть доступ в тестовом режиме.
UPD:
Как справедливо заметил хабражитель aborouhin, достаточно только одно белого IP для того что бы канал передачи данных работал без проблем. Соотвественно EndPoint для Peer в серверном конфиге можно не указывать и это облегчает настройку. А описаный мануал, может быть полезен, если оба узла находятся за NAT.
Прямой VPN-туннель между компьютерами через NAT’ы провайдеров (без VPS, с помощью STUN-сервера и Яндекс.диска)
Введение
Прочитав комментарии прошлого поста я понял, что главным недостатком реализации было использование посредника — третьей стороны (VPS) которая указывала текущие параметры узла, куда и как подключаться. Учитывая рекомендации использовать настоящий STUN (коих очень много) для определения текущих параметров подключения. Первым делом я решил посмотреть при помощи TCPDump содержимое пакетов при работе STUN-сервера с клиентами и получил совершенно нечитабельное содержимое. Погуглив протокол наткнулся на статью с описанием протокола. Я понял что самостоятельно реализовать запрос к STUN-серверу я не могу и убрал задумку в «далекий ящик».
Теория
Недавно мне пришлось устанавливать STUN-сервер на Debian из пакета и в зависимостях я увидел пакет stun-client, но как-то не придал этому значения. Но позже я вспомнил про пакет stun-client и решил разобраться как он работает, погуглив и пояндексив я получил:
В ответ я получил:
STUN client version 0.97
Opened port 21234 with fd 3
Opened port 21235 with fd 4
Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Received stun message: 92 bytes
MappedAddress = :2885
SourceAddress = 216.93.246.18:3478
ChangedAddress = 216.93.246.17:3479
Unknown attribute: 32800
ServerName = Vovida.org 0.98-CPC
Received message of type 257 > Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to 216.93.246.17:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to :2885
Received stun message: 28 bytes
ChangeRequest = 0
Received message of type 1 > Encoding stun message:
Encoding ChangeRequest: 0
About to send msg of len 28 to 216.93.246.17:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Received stun message: 92 bytes
MappedAddress = :2885
SourceAddress = 216.93.246.17:3479
ChangedAddress = 216.93.246.18:3478
Unknown attribute: 32800
ServerName = Vovida.org 0.98-CPC
Received message of type 257 > Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 4
About to send msg of len 28 to 216.93.246.18:3478
Encoding stun message:
Encoding ChangeRequest: 2
About to send msg of len 28 to 216.93.246.18:3478
test I = 1
test II = 0
test III = 0
test I(2) = 1
is nat = 1
mapped IP same = 1
hairpin = 1
preserver port = 0
Primary: Independent Mapping, Port Dependent Filter, random port, will hairpin
Return value is 0x000006
как раз то, что надо! Она отображала текущее состояние для соединения на локальном UDP порту 21234. Но это всего лишь пол дела, встал вопрос как передать эти данные удаленному узлу и организовать VPN-соединение. Использование почтового протокола, а может Telegram?! Вариантов много и решил использовать Яндекс.диск, так как попадалась мне статья о работе Curl через WebDav с Яндекс.диском. Подумав над реализацией я пришел к такой схеме:
- Сигнализировать о готовности узлов к установке соединения наличием определенного файла с временной меткой на Яндекс.диске;
- Если узлы готовы, то получать текущие параметры от STUN-сервера;
- Выгружать текущие параметры на Яндекс.диск;
- Проверять наличие и считывать параметры удаленного узла из файла на Яндекс.диске;
- Установка соединения с удаленным узлом с помощью OpenVPN.
Практика
Для работы скрипта нужно:
- Скопировать в буфер и вставить в редактор, например:
- указать логин и пароль от Яндекс.диска.
- в поле «—ifconfig 10.45.54.(1 или 2) 255.255.255.252» указать внутренний IP-адрес интерфейса
- cоздать secret.key командой:
- сделать скрипт исполняемым:
- запустить скрипт:
где nZbVGBuX5dtturD — ID-соединения сгенерированный тут
На удаленном узле произвести всё тоже самое за исключением генерации secret.key и ID-соединения, они должны быть идентичными.
Обновленный вариант (для корректной работы время должно быть сихронизировано):
Для работы скрипта нужно:
- Скопировать в буфер и вставить в редактор, например:
- указать логин (2я строка) и пароль от Яндекс.диска (3я строка).
- указать внутренний IP-адрес туннеля (4я строка).
- сделать скрипт исполняемым:
- запустить скрипт:
где nZbVGBuX5dtturD — ID-соединения сгенерированный тут
На удаленном узле произвести всё тоже самое, указать соответствующий внутренний IP-адрес туннеля и ID-соединения.
Для автозапуска скрипта при включении я использую команду «nohup / /vpn10.sh nZbVGBuX5dtturD > /var/log/vpn10.log 2>/dev/null &» содержащиюся в файле /etc/rc.local
Заключение
Скрипт работает, проверен на Ubuntu (18.04, 19.10, 20.04) и Debian 9. В качестве передатчика можно использовать любой другой сервис, но для опыта я использовал Яндекс.диск.
В процессе экспериментов было обнаружено, что некоторые типы NAT провайдеров не позволяют организовать соединение. В основном у сотовых операторов, где заблокированы торренты.
Stun клиент для windows
STUN — протокол, позволяющий обходить ограничения, связанные с работой за NAT. Его применение весьма востребовано, потому что большинство домашних интернет-провайдеров используют NAT, а также почти все корпоративные способы доступа в интернет реализованы с использованием NAT и различных видов прокси. Для использования нужно знать адрес STUN-сервера, а также убедиться что нужная вам программа поддерживает STUN (обычно на это указывает наличие в её настройках соответствующих полей).
В случае XMPP — STUN нужен для работы Jingle, когда собеседники находятся за NAT и не имеют прямого IP-адреса. В ряде случаев чтобы работала передача файлов, а также общение голосом и видео нужно указывать STUN-сервер.
Contents
Список STUN-серверов [ edit ]
Для работы с xmpp-клиентом годится любой STUN-сервер, не обязательно такой который поднят вместе с тем или иным xmpp-сервером. Т.е. при желании и возможности вы можете запустить сервер самостоятельно. Во FreeBSD он находится в портах net/stund.
По умолчанию STUN-сервер разрешает использование любыми пользователями без авторизации, если это не включили явно администраторы.
- stun.jabber.ru стандартный порт с шифрованием — 5249 (jabber.ru)
- stun.habahaba.im стандартный порт — 3478 (сервис Habahaba, STUN прописан в SRV и не требуется указывать явно)
- stunserver.org
- stun.ekiga.net (если не получится, то пропишите IP-адрес), порт 3478 (проект ekiga)
XMPP-клиенты с поддержкой STUN [ edit ]
- Psi и Psi+ в настройках аккаунта
- Pidgin
- Gajim в общих настройках на вкладке Audio/Video
Тип NAT [ edit ]
Определить тип NAT можно запустив stun-клиент. Версию для MS Windows скачать можно отсюда. Запускать следующим образом
В случае NAT, реализованного средствами FreeBSD с natd, будет получен результат Primary: Port Restricted Nat, preserves ports, no hairpin. Единственный типа NAT, который нельзя обойти это симметричный (symmetric NAT).
В Unix то же самое запускается аналогичным образом (в портах FreeBSD /usr/ports/net/stund/)