У вас один публичный IP и десяток устройств за роутером. Ваш iPad в мобильной сети, за три сети отсюда. И все же приложение удаленного рабочего стола меньше чем за секунду открывает прямое соединение между ними — обычно без ретранслятора посередине. Вот как на самом деле работает эта магия: ICE, STUN, TURN, пробивка и неловкая правда о симметричном NAT.
Почему это важно
Представьте утро вторника. Ваш Mac mini дома за роутером с единственным публичным адресом IPv4. Ваш iPad в поезде, в мобильной сети оператора со своими слоями трансляции адресов. Между устройствами как минимум два NAT, а возможно, и три. Ни одна машина по умолчанию не доступна из внешнего интернета.
И все же вы открываете Remio на iPad, нажимаете на Mac — и через секунду смотрите на свой рабочий стол. Видео и ввод идут напрямую между двумя устройствами — без облачного ретранслятора, без прокси посередине, перекодирующего ваш экран.
У техники, которая это делает возможным, есть название — обход NAT — и семейство четко определенных протоколов: STUN, TURN и ICE. Это те же протоколы, которые WebRTC использует для видеозвонков в браузере, и именно благодаря им любой современный P2P-удаленный рабочий стол может не пропускать кадры вашего экрана через дата-центр третьей стороны. В этой статье разбирается, что делает каждый из них, зачем он нужен и как вместе они находят путь с наименьшей задержкой между двумя устройствами, спрятанными за роутерами.
Проблема NAT за 60 секунд
Интернет проектировали так, чтобы у каждого устройства был собственный публично маршрутизируемый адрес. Во всем пространстве около 4,3 миллиарда адресов IPv4 — в 1981 году этого хватало с запасом, а к концу 1990-х явно не хватало.
Обходным решением стала трансляция сетевых адресов (NAT). Роутер получает от провайдера один публичный адрес IPv4. Внутри дома каждое устройство получает частный адрес из зарезервированного диапазона (обычно 192.168.x.x или 10.x.x.x). Когда ваш ноутбук отправляет пакет наружу, роутер подменяет адрес источника своим публичным IP, запоминает соответствие и пересылает. Когда приходит ответ, роутер находит соответствие и подменяет адрес назначения обратно на ваш ноутбук.
Именно поэтому входящие подключения по умолчанию не работают. Снаружи у ноутбука нет адреса; он есть только у роутера. Пакет постороннего на your-router-public-ip:5060 попадает на роутер без соответствия для него и отбрасывается.
Для P2P-приложения в этом вся игра. Оба участника сидят за роутерами, которые пересылают пакеты, только если помнят, что сначала что-то отправили наружу. Ни одна сторона не может просто «позвонить» другой — им нужно сотрудничать со своими роутерами, чтобы открыть временный путь.
Пробивка: заставить межсетевой экран впустить обратно
Вот трюк. Таблица NAT вашего роутера строится по пятерке значений: IP источника, порт источника, IP назначения, порт назначения и протокол. Когда ваше устройство отправляет исходящий пакет UDP на 1.2.3.4:5678, роутер создает временную запись: «если любой пакет UDP придет с 1.2.3.4:5678 на мой публичный IP на порт X, перешли его этому устройству на порт Y».
Эта запись существует какое-то время — обычно от 30 до 60 секунд — а потом истекает, если ее ничто не обновляет. В течение этого окна будет принят любой пакет с адреса назначения.
Это замочная скважина, которой пользуются P2P-приложения. Если оба участника знают публичный адрес друг друга, каждый может отправить другому один исходящий пакет UDP в один и тот же момент. Роутер каждой стороны открывает исходящее соответствие. Первый пакет каждой стороны вполне может быть отброшен — другой роутер еще не открыл свое соответствие, — но у второго пакета уже есть куда идти. С этого момента оба роутера считают, что пересылают обычный исходящий разговор, а два устройства общаются напрямую.
Это называется пробивкой UDP. Это слегка чудесно, хорошо документировано (RFC 5128) и работает с подавляющим большинством потребительских NAT. Оставшиеся случаи — симметричный NAT, CGNAT, корпоративные межсетевые экраны — и есть причина, по которой существует TURN.
Пробивка — не хак. Это явный контракт, вокруг которого проектировали NAT: исходящий пакет создает разрешение на входящий. P2P-приложения просто отправляют исходящий пакет намеренно.
STUN: «какой у меня публичный адрес?»
Для пробивки нужна одна предпосылка: каждый участник должен знать собственный публичный адрес, чтобы сказать другой стороне, куда слать пакеты. Изнутри устройства этот адрес не виден. Ваш iPad видит свой локальный адрес Wi-Fi (192.168.1.42). То, что видит остальной интернет после подмены пакета роутером, — совсем другое.
STUN — Session Traversal Utilities for NAT, RFC 5389 — это крошечный протокол, решающий эту задачу. Поток почти неприлично прост:
- Участник отправляет пакет UDP на публичный сервер STUN. (Remio использует и публичные серверы STUN Cloudflare, и Google для резервирования.)
- Сервер STUN считывает IP и порт источника из сети — а это по определению публичный адрес участника после трансляции NAT.
- Сервер STUN отвечает этим адресом в качестве содержимого: «Насколько я вижу, вы —
203.0.113.42:48291». - Теперь участник знает, какой адрес объявить другой стороне.
В терминологии ICE этот публичный адрес называется кандидатом, отраженным сервером. Это почти ничего не стоит — один круговой пробег при установке соединения и ноль расходов пропускной способности и задержки после его установки. Единственная задача STUN — познакомить двух участников; когда они разговаривают, сервер STUN больше не участвует.
TURN: когда пробивка не удалась
Пробивка работает для большинства NAT, но не для всех. Случаи неудач реальны, и P2P-приложение, делающее вид, что их нет, просто не сможет подключиться для заметной доли пользователей.
Главные злодеи:
- Симметричный NAT. NAT, который назначает разный публичный порт для каждого отдельного адреса назначения. STUN говорит вашему участнику, что вы на порту 48291 (потому что именно этот порт видел сервер STUN), но когда вы отправляете пакет на адрес вашего участника, ваш роутер выбирает другой порт — скажем, 48317. Роутер вашего участника отвергает пакет, потому что он пришел с неожиданного порта. Пробивка ломается.
- Carrier-grade NAT (CGNAT). Мобильные и многие провайдерские сети накладывают второй NAT на уровне оператора. Вы можете, сами того не зная, находиться за двумя NAT, и оба должны сотрудничать. CGNAT часто симметричен, а доступа администратора к нему у вас нет.
- Строгие корпоративные межсетевые экраны. Некоторые корпоративные сети блокируют весь исходящий UDP или разрешают его только на определенные адреса. Для пробивки нужен путь по UDP; если его нет, шансов нет.
Для таких случаев запасной вариант — TURN, Traversal Using Relays around NAT, RFC 5766. Сервер TURN — это ретранслятор, до которого могут добраться оба участника, потому что у него есть публичный адрес, всегда принимающий входящий трафик. Каждый участник устанавливает обычное исходящее соединение TLS с сервером TURN (которое разрешит любой NAT), а сервер пересылает байты между сторонами.
TURN — реальные затраты. Каждый пакет видео должен пройти лишний сетевой переход. На региональном ретрансляторе TURN это добавляет около 30–80 миллисекунд кругового пробега. Между регионами — скажем, ретранслятор во Франкфурте для участника в Токио и участника в Сан-Паулу — это может быть от 80 до 200 миллисекунд. Оператор TURN также платит за трафик: каждый бит вашего потока идет через его каналы.
Поэтому хорошо спроектированное приложение использует TURN только тогда, когда пробивка заведомо не удалась. Это решение ICE принимает автоматически.
ICE: перебор всех кандидатов параллельно
Interactive Connectivity Establishment, RFC 8445, — это хореография, связывающая все это воедино. ICE не выбирает стратегию заранее. Он собирает все возможные адреса-кандидаты каждого участника, обменивается полным списком с другой стороной, а затем обе стороны параллельно проверяют каждую пару кандидатов — наперегонки, чтобы найти первую, которая работает.
Для каждого участника ICE обычно собирает:
- Кандидаты-хосты — каждый локальный IP-адрес на каждом сетевом интерфейсе (Ethernet, Wi-Fi, виртуальные интерфейсы, IPv4 и IPv6).
- Кандидаты, отраженные сервером — публичные адреса, полученные от серверов STUN.
- Кандидаты-ретрансляторы — адреса, выделенные на сервере TURN.
Два участника обмениваются этими списками через канал сигнализации — в Remio это небольшое соединение WebSocket с relay.remio.net, которое передает кандидатов ICE и описание сеанса WebRTC (SDP), а затем, когда пошли медиаданные, больше ничего не делает.
Когда оба списка на руках, ICE начинает проверки связности. Каждый участник отправляет пакет STUN-binding-request по каждой паре кандидатов в порядке приоритета. Приоритеты рассчитаны так, чтобы предпочесть путь с наименьшей задержкой:
- Хост — хост — оба участника в одной локальной сети. Идеальный случай: несколько сотен микросекунд задержки, роутер не участвует.
- Хост — отраженный сервером или отраженный — отраженный — участники в разных сетях, пробитые через свои NAT. Именно это обычно и означает «P2P через интернет» на практике.
- Все, что связано с ретранслятором — последняя мера, используется, только когда все пути с более высоким приоритетом не прошли проверки связности.
Первая пара кандидатов, где успешны оба направления, назначается победителем, и по этому пути начинают идти медиаданные. Весь процесс обычно завершается значительно быстрее секунды.
ICE также собирает кандидатов непрерывно. Если посреди сеанса появляется путь лучше — скажем, телефон выходит из мобильной сети и подключается к Wi-Fi, — ICE может переназначить новый путь, не обрывая звонок.
Почему Remio так настойчиво предпочитает P2P
Remio — приложение удаленного рабочего стола, а не видеозвонок. Бюджет задержки жесток. Чтобы сеанс ощущался как работа за хост-машиной, весь конвейер — захват, кодирование, сеть, декодирование, отрисовка — должен быть крошечным: в локальной сети он занимает около 8 мс, а остальное — собственная частота обновления вашего дисплея, 60 Гц (около 16,7 мс на кадр). Каждый лишний переход — грех.
В прямом P2P-соединении в локальной сети сетевая часть этого бюджета составляет около 1–5 миллисекунд кругового пробега. Ретранслятора нет; байты идут прямо с одного устройства на другое. С конвейером Remio это в сумме дает около 8 мс обработки в локальной сети (по нашим внутренним замерам; остальное — собственная частота обновления вашего дисплея, 60 Гц) — ваш ввод доходит раньше, чем рисуется следующий кадр. Удаленная машина неотличима от локальной.
В соединении через ретранслятор TURN — даже региональный — сетевая часть подскакивает до 30–80 миллисекунд. Полная воспринимаемая пользователем задержка теперь 40–100 мс. Для большинства задач все еще приемлемо, но чувствуется при быстром перетаскивании или быстрой серии щелчков. Трекпад уже не совсем ваш.
Эта разница и есть причина, по которой мы прилагаем столько усилий, чтобы удерживать сеансы на P2P. Стек WebRTC в Remio собирает кандидатов IPv4 и IPv6, параллельно обращается к нескольким серверам STUN и агрессивно предпочитает прямые пути при выборе пары кандидатов в ICE. Внутри мы даже используем измеренное время кругового пробега, чтобы классифицировать сеть: меньше 15 мс — значит LAN, кодировщик стартует высоко и ему разрешено использовать намного больше пропускной способности. Все, что медленнее, считается WAN и настраивается консервативнее.
И — об этом конкуренты часто умалчивают — соединение защищено сквозным шифрованием при любом пути. Ваш экран никогда не касается наших серверов, и даже ретранслятор TURN видит только шифртекст: ключи согласуются напрямую между двумя участниками во время рукопожатия, до того как сдвинется хоть один пиксель. Идут ли байты по P2P или через TURN, ни сервер сигнализации Remio, ни оператор TURN прочитать их не могут. P2P просто означает, что на пути данных нет третьей стороны вообще.
Когда ретранслятор неизбежен (и это нормально)
Иногда сетевые боги говорят «нет». Симметричный NAT с обеих сторон, двойной CGNAT у мобильного оператора со строгим провайдером, корпоративный межсетевой экран, разрешающий только исходящий TLS к известным облачным провайдерам — это реальные, распространенные конфигурации. В таких случаях сеанс должен идти через ретранслятор, иначе его не будет вообще.
Серверная часть TURN в Remio — Cloudflare Calls, что дает нам глобальную сеть ретрансляторов рядом с большинством пользователей. Когда ICE выбирает путь через ретранслятор, ощущения падают с «как локально» до «как в Splashtop» — пользоваться все еще очень можно, но разница заметна. Добавленная задержка составляет 30–80 мс для регионального ретранслятора; между регионами может доходить до 200 мс.
Главное: данные все равно защищены сквозным шифрованием. Cloudflare видит зашифрованные пакеты UDP в одну сторону и зашифрованные пакеты UDP в другую. Он может считать байты для выставления счетов. Он не видит ни ваш экран, ни нажатия клавиш, ни какое-либо содержимое сеанса. Точки расшифровки на стороне Remio тоже нет, потому что в конвейере нет облака Remio — мы используем службу TURN через Cloudflare и никогда не трогаем полезную нагрузку.
Именно эту архитектуру подробнее описывает наша техническая документация по безопасности. Коротко: P2P или ретранслятор, модель угроз одна и та же.
Запасной выход IPv6
В IPv6 340 ундециллионов адресов (3,4 × 1038) — достаточно, чтобы дать каждой песчинке на Земле собственный публичный IP и еще несколько триллионов в запасе. В мире только с IPv6 NAT в основном не нужен. Два устройства с поддержкой IPv6 могут просто слать пакеты на адреса друг друга, а единственное препятствие — межсетевой экран хоста на любом из концов.
Если у вас дома и у мобильного оператора есть IPv6, вы могли заметить, что некоторые приложения подключаются быстрее, когда оба конца используют IPv6: у всего танца «соберем кандидатов, проверим пары» меньше препятствий. Не нужно искать трансляцию NAT, не нужна поездка к STUN — только прямые адреса.
Но вот в чем загвоздка: в 2026 году глобальное внедрение все еще неполное. Многие домашние роутеры плохо справляются с IPv6 или не справляются вовсе. Многие корпоративные сети по умолчанию блокируют входящий IPv6. Некоторые операторы предлагают IPv6 на радиочасти, но выше по сети переходят на IPv4. Чисто IPv6-пути существуют, но полагаться на них как на единственный механизм нельзя.
Поэтому Remio — как и любой серьезный P2P-стек — собирает кандидатов IPv4 и IPv6 и позволяет ICE пустить их наперегонки. Если прямой путь по IPv6 существует и работает, он обычно выигрывает по задержке. Если нет, включается IPv4 с пробивкой. Если не получается и это — ретранслятор. Пользователь ничего из этого не видит; соединение просто устанавливается.
Как узнать, какой путь использует ваш сеанс
Интересно, по какому пути пошел ваш сеанс? Индикатор подключения Remio показывает тип простыми словами — «Напрямую» для P2P, «Ретранслятор» для TURN. Панель статистики для разработчиков показывает полное состояние WebRTC, включая типы кандидатов назначенной пары (host, srflx, relay) и измеренное время кругового пробега.
Несколько быстрых интерпретаций:
- Круговой пробег меньше 5 мс, напрямую — вы в той же локальной сети, что и хост. Лучший случай. Достижимы около 8 мс обработки (остальное — собственная частота обновления вашего дисплея, 60 Гц).
- Круговой пробег 5–15 мс, напрямую — та же сеть Wi-Fi, но с дополнительным переходом через точку доступа или mesh. Все равно отлично.
- Круговой пробег 15–80 мс, напрямую — вы в другой сети, чем хост, пробивка удалась. P2P через интернет работает.
- Круговой пробег 30–80 мс, ретранслятор (региональный) — симметричный NAT или carrier-grade NAT сорвал пробивку. Подхватил ближайший TURN Cloudflare.
- Круговой пробег 80–200 мс, ретранслятор — TURN на большем географическом расстоянии, либо вы и хост в очень разных регионах.
Если вы стабильно переходите на ретранслятор даже дома, обычные подозреваемые — модем провайдера с симметричным NAT, CGNAT IPv4 на вашем домашнем подключении (на перепродавцах оптики встречается чаще, чем вы думаете) или чересчур усердный межсетевой экран, блокирующий входящий UDP. В нашем руководстве по снижению задержки удаленного рабочего стола разобраны типичные виновники, а страница прямое подключение в локальной сети — быстрый путь, если оба устройства в вашей сети.
Реальные цифры производительности
Собирая все вместе, вот цифры задержки, которые мы измеряем в рабочей среде на разных путях, по которым может пойти сеанс Remio:
- Прямое P2P в локальной сети: 1–5 мс сетевого кругового пробега. Сквозная задержка (событие ввода — обновление пикселя): около 8 мс обработки (остальное — собственная частота обновления вашего дисплея, 60 Гц) при содействии остального конвейера.
- Wi-Fi в той же сети с дополнительными переходами: 5–10 мс сетевого кругового пробега.
- Ретранслятор TURN, региональный: 30–80 мс сетевого кругового пробега.
- Ретранслятор TURN, между регионами: 80–200 мс сетевого кругового пробега.
- Мобильная сеть 4G/5G, P2P с пробивкой: 40–100 мс сетевого кругового пробега.
Они соответствуют цифрам в результатах тестов Remio и объясняют, почему мы поставили границу между LAN и WAN на 15 мс кругового пробега: она четко отделяет прямые пути от любого ретранслятора (минимум 30 мс) или мобильного пути (минимум 40 мс) с очень малым числом ложных срабатываний.
Обход NAT — одна из тех тем, где протоколы по отдельности просты, а комбинаторика запутанна. Большинству пользователей никогда не понадобится знать о существовании ICE, STUN и TURN — они просто получат приложение, быстро подключающееся откуда угодно куда угодно. Протоколы хорошо делают свою работу, когда вы их не замечаете. А когда вы все же замечаете — сеанс устанавливается на мгновение дольше или «Напрямую» превращается в «Ретранслятор», — у вас теперь есть мысленная модель.
Подробнее о нативном конвейере Remio и решениях, превращающих 1–5 мс сетевой задержки в около 8 мс обработки (остальное — собственная частота обновления вашего дисплея, 60 Гц), — в статье почему важна нативность. О модели угроз для путей через ретранслятор — в технической документации по безопасности. Или просто посмотрите возможности и скачайте Remio, чтобы почувствовать, как это работает.