MAATRIX / Блог / Антипаттерн: один VPN-конфиг на всю команду

Антипаттерн: один VPN-конфиг на всю команду

MAATRIX

Команда из семи человек, один файл client.ovpn или wg0-client.conf, который передают новому сотруднику в мессенджере — знакомая картина почти в любой компании, где VPN настраивали «на скорую руку» и с тех пор не трогали. Это работает, пока никто не увольняется, ничего не утекает и никому не нужно понять, кто именно зашёл на сервер в три часа ночи. Как только одно из этих условий нарушается, общий конфиг превращается из удобства в дыру, которую закрывать уже поздно.

Как это выглядит на практике

Типичная история: администратор поднимает WireGuard или OpenVPN на сервере, генерирует один ключ, оборачивает его в .conf или .ovpn файл и рассылает всем, кому нужен доступ к внутренней сети — до базы данных, до админки, до тестового стенда. Файл лежит в общем Google Drive, в закреплённом сообщении в Telegram-чате разработки, иногда — в репозитории в папке infra/vpn/. Новый человек в команде получает ссылку на файл в день выхода на работу, и это выглядит как эффективный онбординг: пять минут — и доступ есть.

Проблема в том, что вся система доступа держится на одном секрете, который знают все. С точки зрения сервера это не команда из семи человек, а один анонимный пользователь, который иногда заходит с семи разных IP одновременно. WireGuard и OpenVPN прекрасно умеют разграничивать пользователей — но только если вы даёте им это делать.

Проблема 1: нельзя отозвать доступ одному человеку

Это главная причина, по которой общий конфиг рано или поздно аукается. У WireGuard нет полей username/password — идентичность пира определяется парой ключей. Если у всех семи членов команды один и тот же приватный ключ в конфиге, то у сервера в wg0.conf соответственно один и тот же PublicKey в секции [Peer]. Отозвать доступ одному человеку — значит физически невозможно сделать точечно: либо вы отзываете доступ всем, либо не отзываете никому.

На практике это означает, что при увольнении сотрудника происходит одно из двух:

  • Ничего не происходит. Доступ остаётся, потому что пересоздавать и раздавать заново конфиг всей команде — отдельная задача, которую откладывают «на потом», а потом забывают. Разбор похожего случая — в статье SSH-ключ уволенного сотрудника работал восемь месяцев: механизм тот же, просто вместо SSH-ключа — общий VPN-конфиг.
  • Все переделывается разом. Администратор генерирует новую пару ключей, обновляет wg0.conf на сервере, рассылает новый файл шести оставшимся людям — и на день-два часть команды сидит без доступа, потому что кто-то не успел переустановить конфиг на телефоне или ноутбуке.

Оба варианта — плохие. Первый оставляет открытую дверь, второй превращает рутинную кадровую процедуру в аврал для всей команды.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Проблема 2: нет аудита — кто и когда подключался

Даже если вы храните логи VPN-сервера, при общем ключе они бесполезны для расследования: в логах будет один и тот же PublicKey (для WireGuard) или один и тот же Common Name сертификата (для OpenVPN) с семью разными IP-адресами и случайным временем подключения. Понять, кто именно из команды заходил в сеть в конкретный момент, если у всех общий идентификатор — невозможно в принципе, никакие настройки логирования это не исправят задним числом.

Это становится критичным ровно в тот момент, когда что-то идёт не так: пропали данные из базы, кто-то случайно (или не случайно) удалил продакшн-таблицу, изменил конфиг файрвола не в тот момент. Первый вопрос в такой ситуации — «кто был подключён к сети в это время» — при общем конфиге остаётся без ответа. Как выглядит нормальный аудит подключений, когда у каждого свой ключ, разобрано в статье аудит доступов VPN — кто и когда подключался.

Отдельно это создаёт проблему для комплаенса: если у компании есть требования хранить логи доступа к инфраструктуре (для внутреннего аудита, для клиентских договоров, иногда — по требованиям регуляторов), общий VPN-конфиг делает эти логи формальностью без реального содержания.

Проблема 3: утечка конфига компрометирует всю сеть сразу

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

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

Стоит помнить и обратный сценарий: если общий приватный ключ WireGuard оказался в публичном репозитории или в логе CI/CD (такое встречается чаще, чем кажется — конфиги коммитят «временно» и забывают), под угрозой не аккаунт одного человека, а вся внутренняя сеть компании целиком, включая базы данных, админки и внутренние сервисы, до которых по VPN достаёт кто угодно из команды.

Как правильно: индивидуальный конфиг на каждого

И WireGuard, и OpenVPN изначально спроектированы для того, чтобы у каждого клиента был свой уникальный идентификатор — это не какая-то надстройка, а базовый режим работы протокола.

WireGuard. Каждый пир — это своя пара ключей (PrivateKey на клиенте, PublicKey на сервере) и свой AllowedIPs внутри VPN-подсети. Генерация занимает секунды:

wg genkey | tee client_ivan_private.key | wg pubkey > client_ivan_public.key

На сервере в /etc/wireguard/wg0.conf для каждого сотрудника — своя секция [Peer]:

[Peer]
# Иван, backend
PublicKey = <public_key_ivan>
AllowedIPs = 10.8.0.11/32

[Peer]
# Мария, DevOps
PublicKey = <public_key_maria>
AllowedIPs = 10.8.0.12/32

Отзыв доступа — это удаление одной секции [Peer] и wg syncconf wg0 <(wg-quick strip wg0) без разрыва соединений у остальных. Ни пересоздания ключей, ни рассылки новых конфигов другим членам команды.

OpenVPN. Механизм — PKI на базе Easy-RSA: у каждого клиента свой сертификат, подписанный общим CA сервера. Выдача нового клиента:

./easyrsa build-client-full ivan nopass

Отзыв — через CRL (Certificate Revocation List):

./easyrsa revoke ivan
./easyrsa gen-crl
cp pki/crl.pem /etc/openvpn/server/

Сервер подтягивает обновлённый CRL и перестаёт принимать сертификат Ивана, при этом остальные клиенты продолжают работать без изменений на своей стороне. Подробный разбор multi-user схемы с сертификатами — в статье OpenVPN multi-user: сертификаты и Easy-RSA.

Общий конфиг на командуИндивидуальный конфиг на пользователя
Отзыв доступа одному человекуНевозможен без переделки для всехОдна команда, без влияния на остальных
Аудит подключенийБессмысленен — все выглядят одинаковоТочный: видно, кто и когда подключался
Площадь поражения при утечкеВся сеть, все пользователиТолько доступ конкретного человека
Онбординг нового сотрудникаБыстро (передать файл)Чуть дольше (сгенерировать ключ/сертификат)
Ротация без даунтайма для командыСложно — меняются все конфиги разомПросто — меняется только один пир/сертификат

Единственный аргумент в пользу общего конфига — скорость онбординга. Но разница между «переслать файл» и «сгенерировать ключ по готовому скрипту» — это разница в одну-две минуты, если процесс автоматизирован.

Масштабирование: когда людей больше пяти

На команде из трёх-четырёх человек ручная генерация индивидуальных конфигов не создаёт нагрузки — вы просто заводите отдельную секцию [Peer] при найме. Но когда людей десять и больше, а тем более если состав часто меняется (подрядчики, стажёры, временный доступ на проект), ручное управление начинает буксовать: конфиги теряются, кто-то забывает отозвать доступ у контрактора, закончившего работу три месяца назад.

Здесь на помощь приходит автоматизация выдачи и учёта ключей:

  • Скрипт массовой генерации. Обёртка вокруг wg genkey/easyrsa build-client-full, которая по имени сотрудника создаёт ключ, добавляет пира на сервере и формирует QR-код или файл конфига для клиента. Пример такого подхода — в статье bash-скрипт массовой генерации WireGuard-клиентов.
  • Веб-панель управления. Инструменты вроде wg-easy или Outline Manager дают интерфейс, где новый пир создаётся кликом, а отозванный — исчезает из списка активных без ручного редактирования конфигов. Разбор распределения доступа через панель — в статье Outline Manager: раздача доступа команде.
  • Централизованная аутентификация. Для более зрелых команд имеет смысл завести единую точку управления доступом — например, через Keycloak или Active Directory, интегрированные с VPN-сервером, чтобы блокировка сотрудника в HR-системе автоматически отключала и его VPN-доступ. Это отдельная и не самая тривиальная настройка, но она снимает человеческий фактор из процесса отзыва доступа.

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

Что делать, если общий конфиг уже используется

Если у вас в команде сейчас именно такая ситуация — один файл на всех, — переход на индивидуальные конфиги можно сделать без простоя для команды:

  1. Не отключайте существующий общий пир сразу. Оставьте его работающим на время миграции.
  2. Сгенерируйте индивидуальные ключи/сертификаты для каждого действующего сотрудника, добавьте их как новых пиров на сервере.
  3. Разошлите новые конфиги, попросите каждого переключиться и подтвердить, что новое подключение работает.
  4. Через оговорённый срок (например, неделю) удалите старого общего пира из конфига сервера и перезапустите интерфейс.
  5. Задокументируйте процесс выдачи и отзыва — кто отвечает за добавление нового сотрудника, кто и как быстро отзывает доступ при увольнении. Без письменного процесса схема откатится к «одному файлу на всех» при первой же спешке.

Разбор организации доступа команды без раздачи избыточных прав каждому — в статье как раздать доступ команде без выдачи root: те же принципы применимы и к VPN-доступу, а не только к SSH и правам на сервере.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Насколько сложнее администрировать индивидуальные конфиги по сравнению с общим?

Для команды до 10-15 человек разница минимальна, особенно если один раз настроить скрипт генерации — тогда добавление нового сотрудника занимает те же одну-две минуты, что и рассылка общего файла, но без потери контроля.

Можно ли использовать общий конфиг временно, например, для разового доступа подрядчику на один день?

Лучше не привыкать к этому даже для разовых случаев — выдайте отдельный пир с ограниченным AllowedIPs и удалите его сразу после того, как задача выполнена. Это исключает риск, что временный доступ забудут отозвать.

WireGuard тяжелее в администрировании индивидуальных ключей, чем OpenVPN?

Нет, скорее наоборот — у WireGuard короче конфиг и проще ключевая пара (Curve25519 без промежуточного CA), а вот PKI в OpenVPN требует поддержки CA, что добавляет шаг с генерацией и хранением корневого сертификата.

Что делать, если сотрудников слишком много для ручного управления, а денег на enterprise-решение вроде Tailscale с SSO нет?

Опенсорсные панели вроде wg-easy или Netbird закрывают средний сегмент — не такие гибкие, как коммерческие ACL-системы, но полностью решают проблему индивидуальных ключей и точечного отзыва без подписки.

Нужно ли хранить логи подключений VPN, если в компании нет формальных требований комплаенса?

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

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →