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

Устройство закрытой сети и подключение первых серверов

В основе лежит проверенный туннельный протокол ядра, но всё утомительное вокруг него взяла на себя служба координации: обмен ключами между узлами, поиск пути через преобразования адресов и поддержка карты сети. Каждый узел устанавливает прямые соединения с теми узлами, с которыми ему разрешено общаться, и трафик идёт напрямую между машинами, минуя центральные серверы. Координатор участвует только в знакомстве узлов и раздаче ключей, поэтому даже его недоступность на короткое время не рвёт уже установленные связи.

Адреса в закрытой сети выдаются из частного диапазона и закрепляются за узлом, а связи строятся точка-точка, что даёт малую задержку между машинами разных провайдеров. Установившееся соединение переживает смену адреса любой из сторон: ноутбук разработчика, переехавший из офиса в домашнюю сеть, продолжает общаться с серверами без переподключения. Для инфраструктуры это означает, что география перестаёт иметь значение: машины в разных облаках и дома образуют одну плоскую сеть с прозрачной адресацией.

Подключение сервера сводится к установке пакета и одной команде входа. Для машин с человеком за клавиатурой команда открывает страницу входа, но на серверах интерактивный вход неуместен, поэтому используется ключ доступа: долговременный токен, который узел предъявляет при подключении:

curl -fsSL https://tailscale.com/install.sh | sh
tailscale up --authkey=tskey-auth-xxxxx --hostname=prod-web-1
tailscale status

Ключи доступа создаются в панели сети и настраиваются: срок жизни, разрешённые ярлыки, повторяемость. Сервер с таким ключом появляется в сети под заданным именем, и уже через несколько секунд с него можно пинговать другие узлы по их именам. Список узлов с адресами и версиями показывает команда состояния, и по ней же удобно сверять, все ли машины хозяйства присутствуют в сети.

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

Правила доступа и разметка узлов тегами

Политика доступа описывается одним файлом в формате JSON, и это главный инструмент дисциплины в сети. Узлы размечаются ярлыками: серверы получают ярлык службы, автоматические исполнители свой, рабочие ноутбуки раздаются пользователям. Правила ссылаются на ярлыки, а не на отдельные машины, поэтому добавление нового сервера не требует правки политики:

{
  "tagOwners": {
    "tag:prod": ["autogroup:admin"],
    "tag:ci": ["autogroup:admin"]
  },
  "acls": [
    {
      "action": "accept",
      "src": ["tag:ci"],
      "dst": ["tag:prod:22, 80, 443"]
    },
    {
      "action": "accept",
      "src": ["autogroup:member"],
      "dst": ["tag:prod:22"]
    }
  ]
}

В примере автоматические исполнители могут заходить на боевые машины только по служебным портам, а люди по административному порту. Всё прочее запрещено по умолчанию: политика работает как белый список, и незаписанное соединение не установится. Такой рисунок правил убирает вечный вопрос закрытой сети о том, кто кому что может, и заменяет его коротким файлом, который читается за минуту и хранится в репозитории рядом с остальным кодом инфраструктуры.

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

Связка с системами доставки кода

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

Порядок настройки такой связки укладывается в несколько шагов:

  1. в панели сети создаётся одноразовый ключ доступа с ярлыком автоматического исполнителя;
  2. ключ передаётся в систему доставки как защищённая переменная окружения;
  3. на этапе запуска исполнитель устанавливает пакет и подключается к сети под этим ключом;
  4. доставка идёт по адресам закрытой сети напрямую на боевые машины;
  5. после работы узел исполнителя исчезает из сети, потому что ключ был одноразовым, а узел помечен как временный.

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

Маршруты в подсети и адресация по именам внутри сети

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

tailscale up --advertise-routes=10.20.0.0/24
tailscale up --accept-routes

Первая команда объявляет маршруты на узле площадке, вторая разрешает машинам принимать чужие маршруты. Такой рисунок закрывает типовую задачу смешанного хозяйства: новые машины живут в закрытой сети напрямую, а унаследованное оборудование достижимо через узлы своих площадок. Отдельный плюс в том, что правила доступа применяются и к маршрутизированным подсетям, поэтому ограничение прав действует на старые машины так же, как на новые.

Собственный сервер координации для придирчивых хозяйств

Служба координации у провайдера удобна, но некоторые хозяйства хотят держать её у себя: требования к размещению данных, полная независимость от внешних служб или принципиальная позиция по поводу третьих сторон в инфраструктуре. Для таких случаев существует открытая реализация координатора, которая поддерживает те же клиентские программы и поднимается на собственном сервере из одного контейнера.

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

Служба имён закрытой сети решает вечную проблему инфраструктуры: запоминать адреса машин не нужно. Каждый узел получает человекочитаемое имя по имени машины, и эти имена разрешаются внутри сети автоматически. Вместо адресов в конфигурациях и скриптах пишутся имена, и переезд машины к другому провайдеру не ломает ни одной строки конфигурации, потому что имя сохранилось.

Имена поддерживают и области: машина с именем из нескольких частей адресуется с уточнением, что позволяет держать в сети одинаковые имена для разных сред. Для скриптов это значит, что адресация перестаёт быть хрупкой частью автоматизации: путь до машины описывается именем роли, а не адресом, который изменится при следующем пересоздании. Дополнительно сеть раздаёт и обратную разрешаемость, поэтому журналы служб показывают понятные имена вместо адресов, что упрощает разбор инцидентов.

Административный доступ, передача файлов и жизнь узлов

Отдельной главой заслуживает административный вход. Клиентская программа умеет встроенный терминальный режим: узел принимает подключения не от системной службы ssh, а от самой сети, и право входа определяется политикой, а не ключами на каждой машине. Команда входа на узел из другого узла сети остаётся привычной, но ключи и аккаунты выдаются политикой в одном месте, и вход стажёра, присоединённый к команде на неделю, создаётся и отзывается правкой правил доступа, без обхода машин и правок авторизованных ключей.

Для передачи файлов между машинами работает встроенный механизм: файл отправляется одной командой с указания имени узла, получение на той стороне происходит интерактивно или в настраиваемый каталог. Это решает повседневную задачу обмена скриптами, конфигурациями и конфигурационными файлами без поднятия общего хранилища и без открытия дополнительных служб. Между узлами сети копия идёт напрямую и шифрована, как и любой другой трафик этой сети.

Для сборочных и доставочных сценариев та же связка облегчает отладку: владелец запуска заходит по терминалу прямо со своего ноутбука и смотрит журналы на живой машине исполнителя, не выставляя её наружу. По окончании сеанса доступ стажёра отзывается уборкой ярлыка из правил или удалением узла из панели, и в сети не остаётся ни одной лишней записи.

У каждого узла в сети есть срок действия регистрации, по истечении которого узел требует повторного входа. Для серверов период продлевается и настраивается на весь узел целиком, а для временных машин время жизни ограничено самим режимом работы. Порядок ротации стоит завести простой: срок действия ключей доступа короткий, перевыпуск автоматический, а узлы с истёкшей регистрацией видны в панели отдельно и либо продлеваются, либо выводятся из хозяйства.

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

Наблюдение за сетью и типовые операции

Состояние сети проверяется с любого узла: команда состояния перечисляет узлы, адреса и качество соединений, а проверка достижимости измеряет путь до конкретной машины и показывает, идёт ли трафик напрямую или через ретрансляцию. Прямые соединения между машинами разных провайдеров устанавливаются в большинстве случаев, и ретрансляция остаётся запасным режимом для самых строгих сетей.

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