Какой из десяти файлов отключать?
Допустим, из десяти филиальных роутеров один пропал: его забыли в такси, украли со склада или он уехал вместе с арендатором, съехавшим из офиса. Ночью вы открываете папку с конфигурациями и видите десять файлов с почти одинаковыми именами: wg0.conf, wg0-new.conf, wg0-final.conf, wg0-final2.conf. Вопрос простой: какой из них нужно отключить, чтобы потерянная железка больше не попадала в сеть, а остальные девять не заметили ничего?
Если ответ приходится искать по содержимому файлов, система уже устроена неудачно. Хорошая схема на десять роутеров отвечает на этот вопрос за одну команду поиска по таблице, а не за час археологии. Для этого нужно решить три вещи заранее: у каждого роутера собственная идентичность, у каждой идентичности есть понятное имя, а имя однозначно связано с адресом в туннеле и открытым ключом.
Эта статья про такое устройство. Без общего профиля «на всех», без толстого паспорта сервера, без десятка бумаг. Нужны одна небольшая таблица, правильно выбранные адреса и привычка проверять оставшиеся девять после того, как убран один.
Один сервер, десять разных собеседников
Начнём с модели. В WireGuard нет «пользователей» и «учётных записей» в привычном смысле. Каждый участник — это peer, а peer, как сказано в описании wg(8), определяется своим открытым ключом. Закрытый ключ остаётся на самом устройстве, а сервер хранит только открытую половину пары. У каждого роутера, таким образом, пара ключей, и краткое руководство WireGuard показывает именно такую картину: у peer есть закрытый и открытый ключ, а состояние можно посмотреть через wg show.
Отсюда вытекает архитектура. На центральном сервере поднят один интерфейс, допустим wg0. В нём одна секция [Interface] с собственным закрытым ключом сервера и десять секций [Peer], по одной на роутер. На каждом роутере лежит свой короткий конфиг: его собственный закрытый ключ, один [Peer] с сервером, адрес в туннеле и список сетей, которые нужно отправлять через сервер.
Важно, что «десять профилей» — это не десять серверов и не десять интерфейсов. Сервер один, и он знает десять разных собеседников. Так проще и в обслуживании, и в диагностике: одна точка входа, один порт, одно место, где видно всех.
Соблазн сделать иначе понятен. Конфиг набрали один раз, проверили, что он работает, и размножили на все десять роутеров, поменяв лишь адрес. Работать будет, пока всё спокойно. Но в таком устройстве исчезает само понятие «один роутер»: у десяти устройств одна и та же идентичность, и отключить можно либо всех, либо никого. Поэтому дальше речь пойдёт только о схеме, где каждому роутеру выдан собственный ключ.
Как выглядит секция одного роутера на сервере
Пример условный: адреса и сети выбраны для иллюстрации. Секция для филиала «Север» на сервере:
[Peer]
# filial-nord | 10.60.0.11 | владелец: Ирина, офис-менеджер
PublicKey = (открытый ключ роутера filial-nord)
AllowedIPs = 10.60.0.11/32, 192.168.10.0/24В AllowedIPs собрано всё, что относится к этому роутеру: его адрес внутри туннеля и локальная сеть филиала. Как поясняет wg(8), этот параметр работает в двух направлениях: он ограничивает, с каких адресов от peer принимаются пакеты, и одновременно подсказывает, каким адресам назначения этот peer подходит для отправки. Для IPv4 и IPv6 префиксы перечисляются отдельно, поэтому если филиалы получат ещё и IPv6-сети, их нужно будет вписать явно, а не надеяться, что они подтянутся сами.
Обратите внимание на строку-комментарий. В ней имя профиля, адрес в туннеле и владелец. Это самая дешёвая страховка: человек, открывший файл через полгода, сразу поймёт, что перед ним, а поиск по имени или адресу найдёт нужную секцию без разбора ключей.
Имена для людей, ключи для машины
Открытый ключ в WireGuard — это строка из сорока четырёх символов в кодировке base64. Для человека она бесполезна: два ключа различаются где-то посередине, а при переписывании в чат легко потерять символ. Поэтому профиль нужен с именем, которое произносится вслух и не меняется.
Работает простое правило: имя описывает место и роль, а не человека и не дату. filial-nord, sklad-2, pvz-01 переживут увольнение сотрудника и переезд. Имя вида router-ivan-2024 устареет, как только Иван уйдёт, а год перестанет что-либо значить после первой замены железа. Фамилию или должность держите отдельным полем: она описывает ответственного, а не устройство.
Имя профиля стоит использовать везде одинаково:
- в комментарии в секции
[Peer]на сервере; - в имени файла на самом роутере и в архиве, если конфиг где-то хранится;
- в первой колонке реестра, о котором пойдёт речь дальше;
- в названии узла в системе мониторинга, если она есть.
Чего не стоит делать: писать в реестре и комментариях закрытые ключи. Закрытому ключу вообще незачем попадать в таблицу, переписку или тикет. Он нужен одному устройству. Открытый ключ в реестре тоже лучше сокращать до первых шести-восьми символов: для поиска и сверки этого хватает, а полная строка лежит там, где ей и положено лежать, в конфиге сервера.
Осторожно с выводом команд
Есть одна ловушка, о которой легко забыть, когда хочется быстро «скопировать состояние сервера в тикет». По описанию wg(8), вывод wg showconf и машинный формат dump могут содержать секреты. На сервере в них попадёт закрытый ключ интерфейса. Поэтому для переписки с коллегами и поддержкой берите обычный wg show и вырезайте из него то, что нужно, а полные выгрузки не отправляйте никуда и не кладите в общие папки.
Три поля, которые держат всё вместе
Теперь про реестр. Он нужен ровно для того, чтобы на вопрос «какой из десяти?» отвечать мгновенно. Лишнего в нём быть не должно: в нём три смысловых поля и пара вспомогательных.
- Владелец — кто физически отвечает за устройство и кому звонить, если оно пропало.
- Адрес в туннеле — уникальный адрес роутера внутри сети WireGuard.
- Открытый ключ — то, чем peer однозначно определяется на сервере.
Эти три поля связывают человека, сеть и криптографию. Когда пропал роутер, вы идёте от человека (звонок или сообщение), находите адрес (по нему видно, что говорит wg show) и ключ (по нему убираете peer). Если одного из звеньев нет, цепочка рвётся: без владельца не у кого спросить, без адреса непонятно, что смотреть в мониторинге, без ключа непонятно, что удалять.
Вот небольшой условный пример для шести из десяти роутеров. Ключи показаны только началом, остальное скрыто.
| Профиль | Владелец | Адрес в туннеле | Сеть за роутером | Открытый ключ | Статус |
|---|---|---|---|---|---|
| filial-nord | Ирина | 10.60.0.11 | 192.168.10.0/24 | q7Hd… (скрыт) | активен |
| filial-yug | Олег | 10.60.0.12 | 192.168.20.0/24 | Zm3c… (скрыт) | активен |
| filial-vostok | Марина | 10.60.0.13 | 192.168.30.0/24 | b9Lw… (скрыт) | активен |
| sklad-1 | Павел | 10.60.0.14 | 192.168.40.0/24 | T2yR… (скрыт) | активен |
| sklad-2 | Павел | 10.60.0.15 | 192.168.41.0/24 | x5Vn… (скрыт) | отозван |
| pvz-01 | Светлана | 10.60.0.16 | 192.168.50.0/24 | Ke8o… (скрыт) | активен |
Таблица не обязана жить в специальной системе. Подойдёт обычный файл в закрытом репозитории или страница во внутренней вики. Важно, чтобы её можно было искать по любому из трёх полей и чтобы изменение сервера и изменение записи происходили в один и тот же момент. Реестр, который отстаёт от реальности на месяц, хуже его отсутствия: он создаёт уверенность там, где её нет.
Статус «отозван» стоит оставлять, а не стирать строку. Причина практическая: адрес в туннеле и сеть за роутером нельзя случайно отдать следующему устройству, пока вы не убедились, что старое действительно выведено из обращения. Запись об отозванном роутере напоминает и о том, какой ключ больше не должен появиться на сервере.
Два филиала с одним префиксом
Самое неприятное место при сборке десяти профилей — не ключи, а адресация. Филиалы заводили в разное время разные люди, и роутеры из коробки привычно раздают 192.168.1.0/24 или 192.168.10.0/24. Рано или поздно два филиала оказываются с одинаковой локальной сетью.
Представим условный случай: «Север» и «Юг» оба живут в 192.168.10.0/24. Если вписать этот префикс в AllowedIPs обоим peer на сервере, получится противоречие. AllowedIPs, как описано в wg(8), служит и фильтром входящего трафика, и указателем маршрута для исходящего. Пакет для 192.168.10.25 нужно отправить какому-то одному peer. Двум сразу его отправить нельзя, а выбрать между ними сервер не сможет по осмысленному признаку. В итоге один из филиалов будет недоступен или, ещё хуже, трафик для юга окажется у севера.
Есть три рабочих способа развести такие сети. Какой выбрать, зависит от того, насколько больно менять адреса.
Перенумеровать один филиал
Самый чистый вариант: «Югу» назначается новая локальная сеть, скажем 192.168.20.0/24, и на роутере переписывается раздача адресов. Дальше в AllowedIPs у «Юга» стоит новый префикс, у «Севера» остаётся прежний, и конфликта нет вообще. Цена вопроса — работа на месте: принтеры, камеры и кассы со статическими адресами придётся пройти руками. Если в филиале два десятка устройств, которые получают адрес автоматически, это час работы. Если там десятки устройств с вбитыми адресами, придётся запланировать окно.
Транзитный префикс с трансляцией адресов
Если менять сеть нельзя (например, в ней крутится оборудование, которое никто не решается трогать), на роутере «Юга» можно сделать трансляцию: для остальных участников его сеть выглядит как отдельный префикс, например 10.77.2.0/24, а роутер сам переписывает адреса на границе. Тогда в AllowedIPs на сервере для «Юга» записывается именно 10.77.2.0/24, а реальный 192.168.10.0/24 остаётся за кулисами. Минус очевиден: придётся обслуживать правила трансляции, а в журналах и мониторинге адреса «снаружи» и «внутри» будут различаться. Зато сеть в филиале остаётся нетронутой.
Точечные адреса вместо всей сети
Иногда достаточно доступа не ко всей подсети филиала, а к нескольким устройствам, например к одному серверу или к кассовому узлу. Тогда в AllowedIPs вписываются отдельные адреса с маской /32. Конфликта по префиксу нет, если хосты в этих двух сетях различаются по адресам, но схема хрупкая: стоит кому-то в «Юге» поставить новое устройство на адрес, который уже занят в «Севере», и вы получите ту же путаницу в миниатюре.
Для небольшого числа роутеров обычно выигрывает первый путь. Он дороже один раз и ничего не стоит потом. Остальные два имеет смысл оставлять для случаев, когда сеть филиала чужая или когда менять адреса физически невозможно.
Как конфликт отражается в реестре
Реестр делает конфликт видимым до того, как он стал аварией. Колонка «Сеть за роутером» в таблице выше нужна именно для этого: перед добавлением нового филиала достаточно пробежать по ней глазами. Если новая строка повторяет префикс, вы увидите проблему на бумаге, а не в виде жалобы, что у «Юга» вдруг открывается чужой принтер. Для пары «Север» и «Юг» в реестре будет сначала 192.168.10.0/24 дважды, и именно повтор заставит принять решение: перенумеровать, транслировать или сузить доступ.
Заодно проверьте и адреса самого туннеля. В примере они выданы подряд из 10.60.0.0/24, начиная с .11, а .1 занят сервером. Свободные адреса .2–.10 оставлены про запас, а в конце диапазона места хватит ещё на сотню роутеров. Туннельную сеть не стоит делать ни пересекающейся с локальными сетями филиалов, ни совпадающей с домашними диапазонами сотрудников, которые заходят в ту же сеть с ноутбуков. Для этого в примере выбран отдельный диапазон 10.60.0.0/24, не похожий на типичные 192.168.x.x.
Если эта тема вам близка и хочется строить доступ не на «весь филиал видит весь офис», а на точечных правилах, посмотрите разбор Zero Trust-доступа через WireGuard без классического VPN: там та же механика AllowedIPs используется для ограничения, кто и куда может ходить.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Что случится, если один профиль раздать двум роутерам
Теперь вернёмся к соблазну «размножить один конфиг». Он возникает не только при первоначальной настройке. Он возникает и при замене: роутер сломался, привезли новый, и проще всего скопировать на него файл со старого. Или в двух филиалах быстро «поднимают связь на время», используя один и тот же профиль. Посмотрим, что делает с этим WireGuard.
Идентичность peer — это его открытый ключ. Два роутера с одним закрытым ключом для сервера выглядят как один peer, который то и дело меняет адрес. Сервер запоминает, откуда пришёл последний корректно аутентифицированный пакет: wg(8) описывает, что endpoint обновляется именно по таким пакетам. Значит, если оба устройства шлют трафик, адрес, на который сервер отвечает, будет перескакивать с одного на другой. Ответы то приходят «своему» роутеру, то «чужому», то никому, пока не прилетит следующий пакет. Снаружи это выглядит как обрывы, зависающие сессии и плавающие задержки, и найти причину по симптомам трудно: каждый роутер по отдельности работает исправно.
К этому добавляется вторая проблема, уже не техническая, а управленческая. Если один из двух роутеров потерян, убрать его из системы можно только вместе со вторым: ключ общий. А значит, на вопрос «какой файл отключать» ответ один: «все, у кого этот ключ». Дублирование профиля стирает именно то различие, ради которого мы вводили десять отдельных peer.
Есть и тонкость с адресами. Если у двух роутеров один и тот же туннельный адрес, то даже при разных ключах часть трафика уйдёт не туда. Поэтому правило звучит так: один роутер, один ключ, один адрес, один peer на сервере. Даже временная связь «на недельку» получает собственный профиль. Создать новую пару ключей и строку в реестре дешевле, чем потом разбирать, кто на самом деле говорил с сервером.
Отключаем один, проверяем девять
Вернёмся к потерянному роутеру. Допустим, это sklad-2 из таблицы. Что нужно сделать, по шагам?
- Найти строку. По имени профиля в реестре видим: адрес
10.60.0.15, сеть192.168.41.0/24, ключ начинается сx5Vn…, владелец — Павел. - Сверить с сервером. В выводе
wg showнаходим peer по началу ключа. Убеждаемся, что это тот самый и что у него именно тот разрешённый адрес. - Убрать peer из работающего интерфейса. Согласно wg(8), peer удаляется через
wg setс указанием интерфейса, ключа и словаremove:wg set wg0 peer ОТКРЫТЫЙ_КЛЮЧ remove. С этого момента сервер перестаёт принимать трафик от этого ключа. - Убрать секцию из файла конфигурации. Это отдельное действие, и забывать о нём нельзя.
- Обновить реестр. Статус «отозван», дата, причина.
- Проверить остальные девять.
Четвёртый шаг заслуживает внимания. По описанию в wg(8), изменение работающего интерфейса и изменение конфигурационного файла — разные операции. Команда wg set меняет текущее состояние, но файл на диске остаётся прежним. Если вы удалили peer только командой, то при следующей перезагрузке сервера или перезапуске интерфейса потерянный роутер вернётся: секция-то всё ещё в файле. Поэтому порядок такой: либо сначала правим файл, а потом применяем изменения, либо делаем обе вещи подряд и сразу.
Применение различий без перезапуска
Если править файл и затем перезапускать весь интерфейс, пострадают все девять оставшихся: интерфейс поднимается заново, туннели пересогласуются, на секунды пропадёт связь. Для такого случая в wg(8) предусмотрена команда syncconf: она применяет разницу между файлом и работающим интерфейсом и не пересоздаёт всех peer. Для отзыва одного из десяти это то, что нужно: убрали секцию из файла, применили различия, остальные девять продолжили работать как работали.
Как именно подать на вход syncconf конфигурацию, если она написана в расширенном формате с адресами и маршрутами, зависит от того, чем вы поднимаете интерфейс. Это стоит отработать один раз на тестовой машине, а не на боевом сервере в момент, когда пропал роутер. Проверка на стенде с двумя-тремя peer занимает несколько минут и снимает главный страх: что ответ на отзыв окажется перезапуском для всех.
Как убедиться, что остальные не пострадали
После отзыва нужны два вида проверки. Первая: потерянного роутера на сервере больше нет. wg show не должен содержать его ключ, а в реестре статус стоит «отозван». Вторая, и о ней забывают чаще, — остальные девять живы.
Практичный способ: заранее знать, как выглядит нормальное состояние. Для каждого peer wg show показывает время последнего рукопожатия. У роутеров, которые передают трафик или поддерживают связь, оно свежее. Если сразу после отзыва у кого-то из девяти время рукопожатия не обновляется, это сигнал: возможно, правка файла зацепила чужую секцию, или в AllowedIPs потерялась строка. Проверяйте не только факт «сервер видит peer», но и реальный путь: пинг до адреса внутри филиала, до какого-нибудь устройства за роутером.
Если на роутере филиала установлен PersistentKeepalive, помните, что он нужен для поддержания состояния NAT. По умолчанию, как отмечено в кратком руководстве, функция выключена и подходит не каждой конфигурации. Для роутеров за NAT, к которым сервер должен иметь возможность обратиться первым, эту настройку обычно включают на стороне самого роутера. Для роутеров, которые всегда говорят первыми и редко молчат, она может быть лишней. Поэтому, если после отзыва один из оставшихся роутеров «затих» в выводе wg show, посмотрите, не от одного ли он типа: за NAT и без поддержания соединения.
Замена роутера: новый секрет вместо копии старого
Потерянный sklad-2 нужно чем-то заменить. И здесь легко совершить ту же ошибку, что и с дубликатом: взять сохранённый файл и положить на новую железку. Чем это плохо? Секрет, один раз побывавший в потерянном устройстве, нельзя считать безопасным. Если файл есть на утерянном роутере, значит, он есть у того, кто этот роутер нашёл. Возвращать его в работу на новом устройстве означает вручную отменить собственный отзыв.
Правильный порядок обратный:
- Новый роутер сам создаёт пару ключей. Закрытый ключ рождается на устройстве и никуда с него не уходит.
- Администратору передаётся только открытый ключ. Его безопасно отправить даже обычным сообщением: подделать по нему доступ нельзя, а ошибка в одном символе обнаружится сразу.
- В реестре появляется новая строка с новым ключом. Имя профиля можно оставить прежним по роли (
sklad-2) или сделать с суффиксом, но ключ в новой строке уже другой. - На сервере добавляется новая секция
[Peer], и конфигурация применяется без пересоздания остальных.
А вот с адресом можно поступить по-разному. Старый туннельный адрес 10.60.0.15 можно выдать новому роутеру, если вы уверены, что старого peer на сервере уже нет, а в реестре строка прежнего ключа помечена «отозван». Новый адрес безопаснее, если важно, чтобы любые следы старого устройства (правила межсетевого экрана, исключения в мониторинге, закладки в чужих скриптах) не оказались унаследованы новым. Для десяти роутеров свободных адресов хватает с запасом, поэтому лучше выдать свежий и не гадать.
Та же логика работает при плановой замене, не только при потере. Если роутер старый и его меняют на новый, это повод сменить ключ, а не переносить. Привычка «ключ живёт у устройства, пока живо устройство» убирает целый класс вопросов вроде «а где ещё мог остаться этот файл».
Сервер под десять туннелей: с чего начинать
Десять постоянных туннелей — нагрузка небольшая сама по себе, но на ней стоит остановиться в двух местах: что именно ходит через сервер и где он расположен. Если через него идёт только управление, мониторинг и доступ к паре внутренних сервисов, потребности скромные. Если же весь филиальный трафик, включая видео и резервные копии, заворачивается в центр, картина меняется, и мерить придётся на реальных потоках.
Для такой задачи подходит обычный VPS MAATRIX с root-доступом: интерфейс WireGuard, правила пересылки и сетевые настройки требуют полного контроля над системой. В публичном предложении указаны NVMe-диски, процессоры AMD EPYC и расположение в UK, US, RU и FR. Для десяти роутеров разумно начать с самой небольшой конфигурации, Ba с 1 vCPU, 2 ГБ памяти и 40 ГБ NVMe, и посмотреть, как ведёт себя сервер под вашим реальным трафиком. Если упираетесь в процессор или канал, следующие ступени (Uab с 2 vCPU и 4 ГБ, Heka с 4 vCPU и 8 ГБ и так далее) дают запас. Ресурсы в плане — отправная точка для теста, а не обещание, сколько трафика потянет конкретная конфигурация: это показывают замеры на ваших потоках.
Локацию выбирайте по тому, где сидит большинство филиалов и сервисов. Для сети, где десять роутеров расположены в одной стране, ближайшая точка обычно даёт меньшую задержку на туннеле. Если часть филиалов за рубежом, имеет смысл посмотреть на время отклика в обе стороны, прежде чем фиксировать выбор.
Строка, которая находится сразу
Вернёмся к началу, к ночному звонку про пропавший роутер. Теперь он выглядит иначе. Вы открываете реестр и ищете имя: sklad-2. Одна строка: владелец Павел, адрес 10.60.0.15, сеть 192.168.41.0/24, ключ с началом x5Vn…. Находите этот ключ в wg show, убираете peer, правите файл, применяете различия без перезапуска остальных, проверяете, что у девяти оставшихся свежие рукопожатия, и меняете статус в реестре.
Никто не открывает десять файлов, не сверяет ключи по памяти и не отключает всех сразу «на всякий случай». Каждый роутер существует отдельно: у него своё имя, свой секрет, свой адрес и своя строка. А когда на склад приедет новое устройство, оно привезёт с собой собственный закрытый ключ, и от потерянного у него не останется ничего, кроме названия.