Как iPhone достаёт до вашего Mac откуда угодно
Ваш Mac стоит за роутером, а iPhone сидит в мобильной сети. Ни один не может позвонить другому. Вот последовательность, которая заставляет их заговорить, в том порядке, в каком всё происходит.
В одной сети: Bonjour и один порт
Приложение на Mac слушает TCP-порт 51515 и объявляет о себе через Bonjour как
_remotedesktop._tcp, прикладывая три небольших сведения: ID устройства, имя Mac и
версию протокола. iPhone ищет эту службу, поэтому Mac в той же сети Wi-Fi появляется в разделе
«Рядом» без ввода адреса.
Объявление это лишь подсказка. Ничего, что касается безопасности, по нему не решается, потому что в сети любой может объявить что угодно. Важно то, что происходит дальше: iPhone открывает соединение TLS 1.3, обе стороны предъявляют сертификат, и каждая сверяет открытый ключ другой с тем, который сохранила при связывании. Как устроено это связывание, рассказано в отдельной статье.
В домашней сети iPhone открывает два соединения: одно для управления (ввод, настройки, список окон) и одно только для картинки. Если видео не идёт по управляющему потоку, тяжёлый ключевой кадр никогда не заставит клик ждать своей очереди.
Вне сети: релей, который только знакомит
Когда вы уходите из дома, iPhone не может достучаться до частного адреса за вашим роутером, а роутер не принимает соединение, о котором его никто не просил. Поэтому Mac делает первый шаг, заранее. Пока он работает, он держит один исходящий WebSocket к релею Peering и каждые 25 секунд отправляет короткий пинг. Этот открытый сокет и есть присутствие Mac: так релей узнаёт, что Mac существует и не спит.
Когда вы касаетесь своего Mac на iPhone, происходит следующее:
- iPhone просит релей соединить его с ID устройства вашего Mac.
- Релей отвечает обоим концам адресом и парой случайных 16-байтных токенов: один для управления, другой для видео.
- Оба устройства открывают исходящее TCP-соединение к релею и первым записывают свой токен.
- Релей сопоставляет два токена и соединяет сокеты, копируя байты из одного в другой.
Затем iPhone начинает то же рукопожатие TLS, что и в домашней сети, и оно проходит прямо через релей к Mac. Релей это труба, а не участник разговора. У него никогда нет ключа. Подробнее о том, что он может и чего не может узнать, читайте в статье что видит релей.
Картинка идёт короткой дорогой
Пропускать всё через релей можно, но это самый медленный и самый дорогой путь. Поэтому картинка не остаётся в TCP-соединении. Она переходит на UDP, который лучше подходит для видео: опоздавший кадр ничего не стоит, а его повторная отправка только задерживает следующий.
Каждый конец также задаёт релею вопрос: с какого адреса подключается другая сторона? Релей отвечает адресом, который он наблюдал, и оба устройства начинают слать друг другу небольшие запечатанные пробные пакеты каждые 250 миллисекунд. Каждый пробный пакет пробивает отверстие в роутере отправителя, и когда два отверстия совпадают, пакет проходит и проходит проверку подлинности. С этого момента картинка идёт напрямую с Mac на iPhone, а релей выпадает из пути видео.
Этот приём обычно называют пробиванием NAT (hole punching). Он работает с большинством домашних роутеров и не работает с некоторыми строгими мобильными и корпоративными, и тогда картинка просто продолжает идти через релей. В любом случае ничего настраивать и открывать порты не нужно.
Если UDP заблокирован
Некоторые сети вообще отбрасывают UDP. Если картинки нет уже три секунды, а управляющее соединение всё ещё отвечает, iPhone просит Mac отправлять видео по управляющему потоку, нарезав его на куски. Битрейт при этом ограничен, поэтому картинка мягче, но мягкая картинка лучше замершей. Mac продолжает отправлять ключевой кадр по быстрому пути каждые несколько секунд, и когда iPhone видит, что этот путь ожил, он переключается обратно.
Почему всё устроено именно так
- Никаких входящих портов. Все соединения исходящие, поэтому не нужно менять настройки роутера, и ничего не торчит в интернет.
- Никакого аккаунта. Устройства определяются по ключам, которые они создают сами, а не по логину. См. связывание без аккаунта.
- Сначала дешёвый путь. Та же сеть бесплатна и не ограничена. Релей несёт только то, что не может пройти напрямую.
Версию для пользователей, с настройками, которые держат Mac доступным, пока вас нет, смотрите в материалах доступ к Mac откуда угодно и как не давать Mac засыпать при удалённом доступе.
Вопросы
Нужно ли открывать порты на роутере, чтобы пользоваться Peering вне дома?
Нет. Все соединения исходящие. Mac держит одно соединение с релеем, и оба устройства подключаются к нему сами, поэтому ничего пробрасывать не нужно.
Использует ли Peering релей на протяжении всего сеанса?
Релей соединяет устройства в начале. Затем картинка пытается пойти напрямую между Mac и iPhone и возвращается на релей, если ваша сеть не допускает прямого пути.