Production и облако · Production and cloud · урок 9 · 14 мин

Сети: WireGuard, Tailscale, NAT и ретрансляторы DERP

Networking: WireGuard, Tailscale, NAT traversal and DERP relays

ТемыСетиTailscaleWireGuard

Зачем

После урока ты объяснишь, как две машины за разными NAT находят друг друга и шифруют трафик: WireGuard, что поверх него делает Tailscale, когда пакеты идут напрямую, а когда через ретранслятор DERP, и кому при этом приходится доверять. Это нужно, когда GPU-машины стоят в разных местах, и на собеседовании в вопросах «how would you connect these boxes securely?» и «why is this link slow?».

Задача: машины за NAT не видят друг друга

У каждой машины дома адрес вида 192.168.1.x. Это private address (частный адрес): таких адресов в мире миллионы, и снаружи до него не дойти. Наружу весь дом выходит под одним public address (публичным адресом) от провайдера. Подмену делает маршрутизатор, это NAT (Network Address Translation, трансляция адресов): он переписывает обратный адрес исходящего пакета на внешний адрес и свой порт и запоминает соответствие, чтобы вернуть ответ нужной машине.

Главное свойство NAT для нас: маршрутизатор впускает пакет снаружи, только если изнутри перед этим ушёл пакет туда же. Незваный пакет он выбрасывает. Поэтому ноутбук дома и GPU-машина в офисе, каждая за своим NAT, сами друг до друга не достучатся: первый пакет каждой упрётся в чужой маршрутизатор. Классический ответ — открыть порт на маршрутизаторе (port forwarding). Он требует доступа к чужому маршрутизатору и оставляет порт открытым всему интернету.

WireGuard: туннель из пары ключей

WireGuard — протокол VPN (зашифрованного соединения), с 2020 года встроенный в ядро Linux 5.6. У каждой машины пара ключей: private key (закрытый) никогда не покидает машину, public key (открытый) можно раздавать кому угодно. Всё идёт по UDP, поэтому зашифрованный пакет для маршрутизатора — обычный UDP-пакет.

Конфигурация WireGuard — список соседей. Для каждого: его public key, endpoint (адрес и порт, где его искать) и AllowedIPs — какие адреса живут за ним. Пакет на адрес из AllowedIPs шифруется ключом этого соседа; пакет от соседа принимается, только если его адрес из того же списка. Шифры фиксированы: Curve25519 для обмена ключами, ChaCha20-Poly1305 для трафика, BLAKE2s для хеша, рукопожатие по схеме Noise. Выбирать нечего, поэтому и ошибиться в настройке негде.

Чего WireGuard не делает сам: не раздаёт ключи (их переписывают на каждую машину вручную), не знает, где сосед сейчас, и не проходит NAT. Для двух серверов с постоянными публичными адресами это не проблема. Для дюжины устройств за NAT, которые меняют сети, это работа на полный день.

Tailscale: control plane и data plane

Tailscale берёт WireGuard для самих пакетов и делит работу на две части.

Сервер координации public keys, адреса, правила control plane — только ключи Ноутбук Сервер GPU data plane: напрямую, WireGuard
Сервер координации раздаёт только открытые ключи; данные идут напрямую между машинами

Сверху Tailscale даёт постоянные адреса из диапазона 100.64/10 (RFC 6598, он почти никогда не пересекается с домашними сетями), имена через MagicDNS (<машина>.<сеть>.ts.net) и правила доступа (ACL). Правила пишутся в одном месте, а проверяет их каждая машина сама, когда расшифровывает входящий пакет.

Hole punching и DERP: напрямую или через ретранслятор

Как пройти NAT без открытых портов? Через правило «впускаю ответ на свой пакет».

  1. Каждая машина спрашивает сервер STUN: «с какого адреса и порта ты меня видишь?».
  2. Машины обмениваются этими адресами через координацию.
  3. Обе одновременно шлют пакеты друг другу. Пакет ноутбука открывает «дырку» в домашнем NAT, пакет GPU-машины — в офисном. Следующие пакеты каждый NAT принимает как ответ. Это hole punching (пробивка NAT).

Работает это, если NAT даёт машине один и тот же внешний порт для всех адресатов — endpoint-independent mapping, «простой» NAT. «Трудный» NAT выдаёт новый порт на каждого адресата, и адрес из STUN другому соседу не подходит. Против одного трудного NAT есть перебор портов; против двух трудных сразу пробивка почти безнадёжна.

На этот случай есть DERP (Designated Encrypted Relay for Packets) — ретрансляторы Tailscale в разных городах. Через DERP устройства обмениваются служебными пакетами для пробивки, а когда прямой путь не нашёлся, DERP пересылает уже зашифрованные пакеты WireGuard. Прочитать их он не может: ключей у него нет. Соединение обычно начинается через DERP и, если пробивка удалась, переходит на прямой путь.

Ноутбук · дом NAT дома один внешний адрес DERP Варшава сначала: ≈ 200 мс через Европу потом напрямую: ≈ 3 мс NAT офиса три машины, один адрес GPU-машина · офис
Первые пакеты идут через DERP, около 200 мс, потом напрямую, около 3 мс

Пример с числами, Алматы. Ближайшие ретрансляторы в Европе: до Франкфурта 94 мс, до Варшавы 120 мс. Ноутбук дома и GPU-машина в другом здании того же города: первые ответы tailscale ping идут через DERP в Варшаве за 180–240 мс, после пробивки — напрямую за 3–5 мс. Это в 40–80 раз быстрее. Для SSH разница заметна, а для копирования весов модели на 15 ГБ решающая. Поэтому вопрос «напрямую или через relay» — первый, когда связь между своими машинами медленная: tailscale status пишет direct или relay "waw" у каждого соседа.

Кому мы доверяем: Tailnet Lock и Headscale

Ключи раздаёт сервер координации, и машины ему верят. Если его взломают, он может подсунуть public key чужой машины, и наши машины примут её как свою.

Tailnet Lock закрывает эту дыру: новая машина входит в сеть, только если её ключ подписан одной из доверенных машин сети, и подпись проверяет каждая машина сама. Цена (документация Tailscale, 12.10.2026): нужно минимум две подписывающие машины, Android подписывать не может; при включении выдают 10 секретов отключения, и если потерять все, сеть не восстановить; Lock несовместим с device approval.

Headscale — открытый сервер координации, который ставят у себя вместо сервера Tailscale. Клиенты те же, меняется только адрес управления. По списку возможностей на 12.10.2026 есть MagicDNS, ACL, tags, exit nodes, subnet routers, Taildrop, Tailscale SSH и встроенный DERP. Funnel и Serve пока открытые задачи, Tailnet Lock в списке нет. Одна сеть, для себя или маленькой команды.

Решение инженера здесь — про доверие и эксплуатацию, а не про скорость: данные в обоих случаях идут напрямую. С Tailscale ты доверяешь компании и можешь закрыть риск через Tailnet Lock. С Headscale доверяешь своему серверу, а его обновления, резервные копии и доступность становятся твоей работой.

Схема

Термины · Key terms

WireGuard
протокол VPN: пара ключей у каждой машины, UDP, фиксированные шифры
NAT
подмена внутреннего адреса на внешний адрес маршрутизатора
endpoint-independent mapping
«простой» NAT: один внешний порт для всех адресатов
STUN
сервер, который говорит машине её внешний адрес и порт
hole punching
одновременная отправка пакетов, чтобы оба NAT приняли их как ответ
control plane / data plane
управление (ключи, правила) / сами пакеты
coordination server
сервер Tailscale, который раздаёт public keys и правила
DERP
ретранслятор Tailscale; помогает пробивке и возит шифр, если прямого пути нет
MagicDNS
имена машин внутри сети вида <машина>.<сеть>.ts.net
subnet router
машина, которая открывает в сеть всю свою локальную подсеть
Tailnet Lock
вход новой машины только по подписи доверенной машины сети
Headscale
свой открытый сервер координации вместо сервера Tailscale

Сделай сам

На Mac в терминале выполни tailscale status, потом tailscale ping к трём машинам (только чтение, настройки не меняются) и tailscale netcheck. Запиши таблицу из трёх строк: машина → первый ответ (через DERP или напрямую, мс) → итоговый путь и мс. Ниже добавь две строки из netcheck: MappingVariesByDestIP (простой ли у тебя NAT) и ближайший DERP с задержкой.

Обсуди с тьютором: покажи таблицу и спроси, что изменилось бы для каждой машины, если бы офисный NAT стал «трудным», и что тогда проверять первым.

Проверь себя · ответ под вопросом

1Сервер координации Tailscale видит наш трафик? А DERP?
Нет. Через сервер координации идут только public keys, адреса и правила, данные идут напрямую между машинами. DERP пересылает уже зашифрованные пакеты WireGuard; private keys есть только на машинах, поэтому прочитать их он не может, видит лишь, кто кому и сколько шлёт.
2Первые ответы от машины пришли за 200 мс, следующие за 3 мс. Что произошло между ними?
Сначала пакеты шли через DERP в Европе. Параллельно машины узнали внешние адреса друг друга через STUN и пробили NAT, одновременно отправив друг другу пакеты. Когда прямой путь заработал, Tailscale переключился на него.
3От какой угрозы защищает Tailnet Lock и чем это решение отличается от перехода на Headscale?
Tailnet Lock не даёт взломанному серверу координации добавить в сеть чужую машину: новый ключ должен быть подписан нашей доверенной машиной. Headscale убирает компанию Tailscale из доверия совсем, но сервер, его обновления и защита становятся нашей работой, а Tailnet Lock в нём нет.

Interview questions · US / UK

1You have GPU boxes in two offices, both behind NAT, and no open inbound ports. How would you connect them securely, and what happens on the wire?
Strong answer: WireGuard tunnel with per-node key pairs over UDP; a coordination server (Tailscale or self-hosted Headscale) distributes public keys and ACLs, private keys never leave the node; NAT traversal via STUN plus simultaneous sends (hole punching); encrypted relay (DERP) as fallback; ACLs enforced on each node; no port forwarding.
2In a Tailscale-style mesh, what can a compromised coordination server do, and how do you limit it?
Strong answer: it cannot read traffic, but it can push a rogue node's key so peers accept it; Tailnet Lock requires new node keys to be signed by trusted nodes and verified by every peer; store disablement secrets safely; or self-host the control plane with Headscale and own its security; tight ACLs and audit of device list either way.
3Two nodes in the same city see 200 ms latency over the VPN. How do you debug it?
Strong answer: check tailscale status and tailscale ping for relay versus direct; tailscale netcheck for UDP, NAT type and nearest DERP; suspect a hard NAT on both sides, blocked UDP or a firewall; fixes: allow UDP out, port mapping (UPnP, NAT-PMP, PCP) or one open port, a peer relay close by; confirm the path flips to direct.

Ключевые фразы · Say it aloud

Материалы