аутентификация wireguard через active directory

WireGuard + Active Directory: единый вход через wg-portal и LDAP

Аутентификация WireGuard через Active Directory — это метод управления доступом к VPN, при котором учётные записи сотрудников синхронизируются с корпоративным каталогом. Вместо ручной генерации ключей для каждого устройства система автоматически создаёт конфигурации на основе членства в группах домена.

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

Использование wg-portal с LDAP-провайдером устраняет этот разрыв. Блокировка пользователя в Active Directory автоматически приводит к деактивации его VPN-пира при следующей синхронизации, обеспечивая единый контур безопасности без вмешательства инженера.

WireGuard + Active Directory: единый вход через wg-portal и LDAP

Аутентификация WireGuard через Active Directory устраняет разрыв между учётными записями и VPN-доступом: блокировка сотрудника в домене автоматически отключает его туннель при следующей синхронизации wg-portal.

Содержание

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

Аутентификация WireGuard через Active Directory снимает главную боль классической схемы: ручную раздачу ключей и рассинхрон между VPN и корпоративными учётками. Сам WireGuard пользователей не знает — протокол оперирует парами ключей и списком allowed-ips, и если публичного ключа пира нет в конфиге сервера, туннель просто не поднимается (WireGuard: протокол на ключах). Учётных записей, паролей и групп на уровне протокола не существует, и это осознанное решение авторов, а не пробел, который можно закрыть флагом.

Пока в компании десять человек, ручная модель терпимая: сгенерировали ключ, вписали пир в wg0.conf, отправили профиль в мессенджер. На восьмидесяти пользователях всё разваливается. Каждый новый сотрудник — это ещё одна пара ключей, ещё одна строка в конфиге и ещё один файл, который живёт вне корпоративного каталога. Каждое увольнение превращается в квест «вспомнить, какой ключ чей».

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

Веб-панель wg-portal — это самодостаточный бинарник и docker-образ wgportal/wg-portal, который берёт на себя генерацию ключей, конфигураций клиентов и, главное, источник пользователей. В качестве источника мы подключаем ваш каталог: Active Directory по LDAP. Учётка одна — тот же логин, что для почты и входа в домен. Заводить и отключать людей вы продолжаете там, где привыкли, в оснастке AD, а VPN синхронизируется следом по расписанию.

Такую связку мы разворачивали в нашем кейсе на 80+ сотрудников: единый вход, один пароль, автоматический отзыв доступа при блокировке учётки — корпоративный VPN на wg-portal. Это тот случай, когда лишний слой (веб-панель поверх WireGuard) окупается уже на второй-третьей волне кадровых изменений.

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

Как настроить LDAP-провайдер в wg-portal для Active Directory

LDAP-провайдер в wg-portal для Active Directory описывается в секции auth.ldap файла config/config.yaml; путь к файлу переопределяется переменной окружения WG_PORTAL_CONFIG, если вы держите конфиг рядом с docker-compose (документация wg-portal). Секция auth содержит массивы oidc, oauth и ldap; в каждом элементе обязательно уникальное поле provider_name, по которому провайдер идентифицируется в логах и в интерфейсе.

Рабочий блок для AD, который мы раскатывали на боевом контуре, выглядит так — подставьте свои домен, OU и учётку сервисного пользователя:

Разберём поля по назначению. url указывает на контроллер домена, в примере это srv-ad1.company.local:389. bind_user и bind_pass — сервисная учётная запись, под которой wg-portal ходит в каталог: заводите её отдельной, только с правом чтения, и никогда не включайте в административные группы домена. base_dn задаёт корень поиска (DC=COMPANY,DC=LOCAL), а field_map сопоставляет атрибуты AD полям портала: sAMAccountName уходит в идентификатор пользователя, mail — в почту, givenName и sn — в имя и фамилию, memberOf — в список групп для последующего маппинга.

Два флага в примере отвечают за безопасность канала: start_tls: true поднимает TLS поверх подключения к контроллеру домена, а cert_validation: true включает проверку его сертификата. На современных контроллерах, в частности на Windows Server 2025, шифрование — уже не опция, а требование; почему и как выбрать между STARTTLS и LDAPS — в разделе про шифрование канала ниже.

sync_interval: 15m задаёт периодичность фоновой синхронизации: раз в пятнадцать минут wg-portal обходит каталог, обновляет список пользователей и применяет sync_filter. Флаг log_user_info: true расширяет запись в логе — полезно на этапе отладки, потом можно выключить.

После правки конфигурации перезапустите сервис: systemctl restart wg-portal для бинарной установки или docker compose restart wg-portal для контейнерной. Убедитесь, что в логах появилась строка о старте провайдера с вашим provider_name и что первый цикл синхронизации завершился без ошибок bind.

Как настроить LDAP-провайдер в wg-portal для Active Directory
				
					auth:
  ldap:
    - provider_name: ad_company
      url: ldap://srv-ad1.company.local:389
      start_tls: true
      cert_validation: true
      bind_user: ldap_wireguard@company.local
      bind_pass: ВАШ_ПАРОЛЬ
      base_dn: DC=COMPANY,DC=LOCAL
      login_filter: (&(objectClass=user)(mail={{login_identifier}})(!userAccountControl:1.2.840.113556.1.4.803:=2))
      sync_filter: (&(objectClass=user)(mail=*)(!userAccountControl:1.2.840.113556.1.4.803:=2))
      sync_interval: 15m
      admin_group: CN=WireGuardAdmins,OU=Some-OU,DC=COMPANY,DC=LOCAL
      registration_enabled: true
      disable_missing: true
      log_user_info: true
      field_map:
        user_identifier: sAMAccountName
        email: mail
        firstname: givenName
        lastname: sn
        memberof: memberOf
				
			

Маппинг групп AD на VPN-пиры и автосоздание конфигов WireGuard

Маппинг групп AD на VPN-пиры в wg-portal держится на двух полях конфигурации: admin_group и interface_filter. Первое отвечает за административные права в самой панели, второе — за то, к какому WireGuard-интерфейсу пользователь получит доступ.

admin_group принимает DN группы AD целиком: admin_group: CN=WireGuardAdmins,OU=Some-OU,DC=COMPANY,DC=LOCAL. Все, кто входит в эту группу, при входе через LDAP становятся администраторами портала: видят чужие профили, могут править интерфейсы, скачивать любые конфиги. Остальные пользователи — обычные, они видят только свои пиры и свою QR-раздачу для мобильного клиента. Мы держим отдельную группу вида WireGuardAdmins и не смешиваем её с Domain Admins: доступ к VPN-панели и доступ к контроллерам домена — это разные роли, и лишние права в AD сюда лучше не тянуть.

interface_filter привязывает интерфейс WireGuard к группе AD через LDAP-фильтр. В нашем боевом конфиге к интерфейсу wg0 пускаются только члены группы VPNUsers:

Логика простая. Кадровик добавил нового аналитика в VPNUsers — на следующем цикле sync_interval wg-portal заводит ему пир на интерфейсе wg0, генерирует ключевую пару и клиентский конфиг, пользователь заходит в портал под доменным логином и забирает свой профиль (файл .conf или QR-код). Отдельно вручную ничего не трогается: WireGuard-конфиг перечитывается порталом сам.

Разделение по интерфейсам мы используем, чтобы разграничить сегменты сети без ACL на маршрутизаторе. wg0 уходит в подсеть офиса (файлы, 1С, внутренние веб-сервисы), wg1 — в изолированный сегмент подрядчиков (только веб-таск-трекер и один RDP). Пользователь, состоящий в обеих группах, получает два разных пира на двух интерфейсах — портал не «схлопывает» их в один.

Флаг registration_enabled: true разрешает создавать учётку в самом портале при первом успешном входе доменного пользователя, прошедшего login_filter. Без него пользователю пришлось бы сначала завестись руками — с флагом всё происходит автоматически на первом логине.

				
					interfaces:
 - name: wg0
 interface_filter: (memberOf=CN=VPNUsers,OU=Groups,DC=COMPANY,DC=LOCAL)
 - name: wg1
 interface_filter: (memberOf=CN=Contractors,OU=Groups,DC=COMPANY,DC=LOCAL)
				
			

Что происходит с доступом при блокировке или удалении пользователя в AD

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

Механизм спрятан в LDAP-фильтрах. И login_filter, и sync_filter содержат условие (!userAccountControl:1.2.840.113556.1.4.803:=2). Строка 1.2.840.113556.1.4.803 — это OID правила сравнения LDAP_MATCHING_RULE_BIT_AND в Active Directory, а число 2 — бит ADS_UF_ACCOUNTDISABLE в атрибуте userAccountControl (userAccountControl, Microsoft Learn). Условие с отрицанием читается как «аккаунт НЕ отключён». Отключили учётку в AD — пользователь перестаёт проходить фильтр, и на следующей синхронизации wg-portal переводит его пир в состояние disabled.

Флаг disable_missing: true закрывает второй сценарий: если пользователь исчез из результатов sync_filter целиком (удалили из AD, вывели за пределы base_dn или переместили в OU, не попадающую под фильтр), портал считает его отсутствующим и тоже гасит пир. Отдельно вспоминать про VPN при увольнении и подчищать список ключей руками не нужно — этим занимается фоновая синхронизация.

Важная оговорка про задержку. Синхронизация идёт по расписанию sync_interval; в нашем примере это 15m, значит между блокировкой учётки в AD и деактивацией пира проходит от нуля до пятнадцати минут. Для абсолютного большинства сценариев (сотрудник ушёл, роль сменилась, подрядчик закончил проект) это приемлемо. Если доступ нужно закрыть немедленно — в момент инцидента, при подозрении на компрометацию — заходите в интерфейс wg-portal под администратором и деактивируйте пользователя вручную. Это разорвёт активные сессии и снимет пир сразу, не дожидаясь следующего цикла.

На наших проектах мы дополнительно снижаем sync_interval до 5m на серверах с высокой чувствительностью данных: цена — чуть больший фон LDAP-запросов на контроллер домена, но окно неотозванного доступа сокращается втрое.

Отзыв доступа при увольнении — отдельный сценарий с активными сессиями, принудительным kick и аудитом факта отзыва: его пошагово мы разбираем в статье отзыв доступа к VPN у уволенного.

Чем аутентификация через AD отличается от локальных пользователей wg-portal

Аутентификация WireGuard через Active Directory отличается от локальных пользователей wg-portal единственным принципиальным моментом — источником истины. При локальных учётках источник истины — сама база портала: логин, пароль и признак «активен» лежат в SQLite или PostgreSQL wg-portal, и жизненным циклом каждой учётки надо управлять руками через веб-интерфейс. При LDAP-провайдере источник истины — контроллер домена: пароль, признак блокировки, членство в группах читаются оттуда, и портал только следует за состоянием AD.

Локальные пользователи удобны в двух ситуациях. Первая — маленькая команда до десяти человек, где заводить AD ради VPN избыточно, а поставить docker compose up и создать пять учёток руками получается за час. Вторая — единичные внешние доступы: подрядчик на две недели, аудитор, тестовая учётка для проверки конфигурации. Заводить их в корпоративном каталоге не хочется, а обеспечить доступ к VPN нужно. Мы такие учётки помечаем префиксом ext- и ведём отдельный список, у кого какая на руках.

Доменные пользователи, наоборот, полностью следуют за AD. Заблокировали в оснастке — пир погас на следующем цикле. Убрали из группы VPNUsers — доступ к интерфейсу wg0 пропал. Сменили пароль в домене — новый пароль сразу работает и для входа в портал. Ничего повторно вводить или синхронизировать руками не нужно; всё вводится однократно на стороне AD.

На практике мы совмещаем модели в одной установке wg-portal. Основной провайдер в секции auth — доменный LDAP, через который логинится вся штатная команда. Локальные учётки лежат рядом и используются точечно для внешних доступов. Портал не запрещает держать несколько провайдеров одновременно: у каждого свой provider_name, и на форме логина пользователь выбирает, каким способом входить.

Ещё одно важное отличие — поведение при недоступности источника. Если ляжет контроллер домена, LDAP-логин перестанет работать до его возвращения; локальные учётки при этом продолжают заходить, потому что их база — сам портал. Мы держим одну резервную локальную учётку администратора с длинным случайным паролем в менеджере секретов именно на этот случай: чтобы попасть в панель и разобраться, если домен временно недоступен.

Типовые ошибки подключения к LDAP и как их читать в логах wg-portal

Типовые ошибки подключения к LDAP в wg-portal сводятся к трём областям: bind сервисной учётки, шифрование канала и синтаксис фильтра поиска. Все три читаются в логах портала, если предварительно включили log_user_info: true: расширенный вывод показывает, с какими атрибутами пришёл пользователь и на каком шаге его отсекло.

Bind не проходит. В логе строка вида LDAP bind failed: invalid credentials или LDAP result code 49. Возможные причины: опечатка в bind_pass, неверный формат bind_user, заблокированная в AD служебная учётка. В Active Directory bind_user указывают либо в UPN-формате (ldap_wireguard@company.local), либо полным DN (CN=LDAP WireGuard,OU=Service,DC=COMPANY,DC=LOCAL). Быстро проверить связку помогает ldapsearch с теми же параметрами:

Пользователи не находятся. В логе no entries returned при попытке логина. Причин две. Первая — ошибка в base_dn: ищем в ветке, где нужных пользователей физически нет. Проверьте, что все VPN-пользователи лежат ниже указанной точки в дереве AD. Вторая — рассогласование login_filter и того, что пользователь вводит на форме. В login_filter подстановка {{login_identifier}} уходит в атрибут, указанный в фильтре: если у вас (mail={{login_identifier}}), а пользователь вводит логин формата sAMAccountName, поиск не найдёт никого.

Шифрование канала — теперь обязательно. Обычный ldap:// на порту 389 без TLS передаёт логин и пароль bind-пользователя в открытом виде, и современные контроллеры такой bind отклоняют. В Windows Server 2025 подпись LDAP (LDAP signing) включена по умолчанию для всех новых развёртываний AD, а шифрование клиентских LDAP-подключений выбрано как предпочтительное (LDAP signing, Microsoft Learn). Практический вывод: простой bind wg-portal обязан идти по защищённому каналу. В wg-portal за это отвечают флаги start_tls: true и cert_validation: true из примера выше. Важный нюанс: требование WS2025 — это именно защищённый канал, а не порт 636 сам по себе. STARTTLS на 389 (соединение стартует на 389 и апгрейдится до TLS) и классический LDAPS на 636 (implicit TLS, шифрование сразу при подключении) удовлетворяют его одинаково; многие в AD стандартизируются на 636. Что бы вы ни выбрали, сертификат контроллера домена должен быть доверен на сервере с wg-portal: ошибка x509: certificate signed by unknown authority в логах означает, что корневой сертификат вашего CA нужно положить в системный доверенный store и перезапустить портал.

Все пользователи «пропали» после включения синхронизации. Частая причина — слишком строгий sync_filter. Условие (mail=*) отсекает всех, у кого не заполнен атрибут mail. Так из синхронизации может внезапно выпасть часть пиров — например, если почта хостится в отдельном тенанте и атрибут mail в AD не заполнен. Проверьте атрибуты у эталонного пользователя через ldapsearch или через ADSI Edit и, если поле пустое, либо заполните его в AD, либо ослабьте фильтр.

				
					ldapsearch -H ldap://srv-ad1.company.local:389 \
 -D "ldap_wireguard@company.local" -W \
 -b "DC=COMPANY,DC=LOCAL" "(sAMAccountName=test.user)"
				
			

Когда добавить 2FA поверх связки WireGuard + AD

Добавлять 2FA поверх связки WireGuard и Active Directory стоит там, где цена компрометации доменного пароля выше стоимости настройки внешнего IdP: доступ к финансовым системам, персональным данным, ключевой инфраструктуре, где одного украденного пароля хватает для критичного ущерба. Сама LDAP-аутентификация в wg-portal — это проверка доменного пароля, не более. Второго фактора она не даёт: подобранный или сфишенный пароль открывает вход в портал и выдачу нового профиля WireGuard.

Второй фактор в wg-portal ставится не на LDAP, а через OIDC. Портал поддерживает провайдеры типа oidc в той же секции auth, наравне с ldap. Схема простая: перед wg-portal встаёт корпоративный Identity Provider (мы разворачивали Keycloak и Authentik), который федерирует ту же Active Directory через LDAP-коннектор, а поверх пароля включает TOTP или WebAuthn как обязательный второй шаг. Пароль остаётся доменным, но вход подтверждается ещё и одноразовым кодом из приложения-аутентификатора или касанием аппаратного ключа. Для пользователя это плюс один экран после логина; для администратора — один узел (IdP), который логирует все попытки входа и позволяет крутить политики 2FA, не трогая ни AD, ни WireGuard.

Когда 2FA не нужна. Для рядового доступа сотрудника к внутреннему таск-трекеру, вики и файловому серверу через VPN доменной связки LDAP обычно достаточно: доменные пароли у вас и так под политикой (длина, срок жизни, блокировка после N попыток), а компрометация одной учётки открывает не больше, чем компрометация её же в почте. Ставить IdP только ради VPN в такой ситуации — это лишний узел, за которым надо следить и который сам становится точкой отказа.

Практическое правило, которое мы применяем на наших проектах: 2FA включаем точечно на группах, а не на всех подряд. В interface_filter для wg-critical (интерфейс с доступом к финансовым системам) прописываем группу, куда добавляем только тех, кому этот сегмент нужен, и требуем от них вход через OIDC с обязательным вторым фактором. Обычные сотрудники продолжают ходить в офисный сегмент через wg0 с доменным паролем без 2FA. Так безопасность оказывается там, где она действительно нужна, а не как формальная галочка на весь периметр.

Развернуть такую связку под ключ на вашем сервере — корпоративный VPN под ключ: подберём протокол, настроим wg-portal с Active Directory и, где нужно, добавим 2FA через отдельный IdP.

Итог

Часто задаваемые вопросы

Ответы на часто задаваемые вопросы по теме статьи.

Сам по себе WireGuard не знает понятий «логин» или «пароль», он проверяет только соответствие публичного ключа. Аутентификация WireGuard через Active Directory реализуется посредником — в нашем случае wg-portal. Портал хранит базу пользователей, синхронизируемую из AD по LDAP. Когда сотрудник входит в веб-интерфейс портала, система проверяет его доменные учётные данные. После успешного входа wg-portal автоматически генерирует пару ключей WireGuard, создаёт конфигурационный файл и добавляет пир в настройки сервера. Таким образом, доступ к VPN жёстко привязан к статусу учётной записи в домене.
Доступ будет отключён автоматически после следующего цикла синхронизации. В конфигурации wg-portal используются фильтры login_filter и sync_filter, которые исключают учётные записи с установленным флагом ADS_UF_ACCOUNTDISABLE (бит 2 атрибута userAccountControl). Если администратор блокирует сотрудника в AD, при очередной проверке (по умолчанию каждые 15 минут) wg-portal обнаружит, что пользователь не проходит фильтр, и деактивирует его пир. Туннель перестанет подниматься. Для мгновенного отзыва доступа можно деактивировать пользователя вручную в интерфейсе портала, не дожидаясь синхронизации.
Да, это одна из ключевых возможностей связки. В конфигурации wg-portal параметр interface_filter позволяет привязать конкретный WireGuard-интерфейс к группе безопасности AD. Например, члены группы CN=VPNUsers,OU=Groups,DC=COMPANY,DC=LOCAL получат доступ к интерфейсу wg0 с офисной подсетью, а члены другой группы — к изолированному интерфейсу wg1. Добавление сотрудника в нужную группу в AD автоматически приводит к созданию для него соответствующего профиля VPN при следующей синхронизации. Это позволяет гибко управлять сегментацией сети без правки конфигов сервера вручную.
Без шифрования — недопустимо, а на современных контроллерах ещё и не заработает. Обычный LDAP на порту 389 передаёт учётные данные bind-пользователя в открытом виде. В Windows Server 2025 подпись LDAP включена по умолчанию для новых развёртываний AD, поэтому простой bind без шифрования контроллер отклонит. В wg-portal защита включается флагами start_tls: true (STARTTLS поверх 389) и cert_validation: true. Важно: требование — именно защищённый канал, а не конкретный порт: STARTTLS на 389 и классический LDAPS на 636 подходят одинаково. При любом варианте сертификат контроллера домена должен быть доверен на сервере с wg-portal, иначе TLS-рукопожатие завершится ошибкой.
LDAP-провайдер в wg-portal проверяет только пароль домена. Для внедрения второго фактора необходимо использовать OIDC-провайдер. Схема работы выглядит так: разворачивается Identity Provider (например, Keycloak или Authentik), который настраивается на федерацию с Active Directory и требует второй фактор (TOTP или WebAuthn). Затем wg-portal настраивается на аутентификацию через этот OIDC-провайдер. В этом случае вход в портал и получение конфигурации WireGuard возможны только после прохождения полной проверки, включая ввод одноразового кода.

Константин Тютюнник — инженер IT For Prof. Специализируется на построении безопасных сетевых контуров и интеграции Linux-решений с корпоративными каталогами. Внедряет wg-portal с аутентификацией через Active Directory для компаний, которым нужен единый контур доступа и учёт подключений.

Внедрим централизованное управление доступом и настроим корпоративный VPN под ключ с интеграцией в вашу инфраструктуру Active Directory.

Поделиться: