Бегунов ЕгорСистемный администратор, DevOps
  1. Главная
  2. Блог
  3. Сети

WireGuard на Windows Server: служба с автозапуском и трафик только к нужным адресам

Содержание

Windows Server подключается по WireGuard к серверу за пределами РФ. Через туннель идёт только трафик к адресам из AllowedIPs, а остальное, как и раньше, уходит напрямую через провайдера. Туннель поднимается сам при загрузке сервера, входить в систему для этого не нужно.

Как это работает

  • WireGuard for Windows запускает каждый туннель как обычную службу Windows WireGuardTunnel$<имя> с автоматическим запуском.
  • AllowedIPs на клиенте задаёт список сетей, для которых Windows добавляет маршрут в туннель. Адреса, которых нет в списке, туннель не затрагивает.

Что понадобится

  • Windows Server 2019, 2022 или 2025 и права администратора.
  • Работающий WireGuard-сервер и клиентский конфиг для него, например из wg-easy.
  • Список адресов и подсетей, трафик к которым должен идти через туннель.

На сервере должен быть включён NAT для клиентов, иначе их трафик не выйдет дальше сервера. В wg-easy NAT включён по умолчанию.

Все команды выполняются в PowerShell от имени администратора.

Шаг 1. Установите WireGuard

Скачайте установщик с wireguard.com/install и запустите его. GUI для дальнейшей работы не понадобится, его можно сразу закрыть.

Шаг 2. Подготовьте конфиг

Конфиг из wg-easy выглядит примерно так:

[Interface]
PrivateKey = <приватный ключ клиента>
Address = 10.8.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = <публичный ключ сервера>
PresharedKey = <общий ключ>
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
Endpoint = vpn.example.com:51820

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

  1. В AllowedIPs оставьте только нужные адреса.
  2. Удалите строку DNS, чтобы DNS-запросы шли на прежние серверы.
  3. В Endpoint вместо доменного имени укажите IP-адрес сервера. Служба разрешает имя только один раз, при запуске, и если сеть к этому моменту ещё не поднялась, туннель не стартует.

После правки получится такой конфиг:

[Interface]
PrivateKey = <приватный ключ клиента>
Address = 10.8.0.2/24

[Peer]
PublicKey = <публичный ключ сервера>
PresharedKey = <общий ключ>
Endpoint = 198.51.100.50:51820
AllowedIPs = 10.8.0.0/24, 203.0.113.0/24, 192.0.2.15/32
PersistentKeepalive = 25

Что означают записи в AllowedIPs:

ЗаписьЧто означает
10.8.0.0/24Сеть самого туннеля, чтобы можно было пинговать сервер по 10.8.0.1
203.0.113.0/24Целая подсеть
192.0.2.15/32Один адрес

Несколько правил для AllowedIPs:

  • Только IP-адреса и подсети. Доменные имена здесь не работают. Узнать адреса домена можно командой Resolve-DnsName example.com -Type A и добавить каждый как /32. У сервисов на CDN адреса меняются, поэтому для них лучше брать диапазоны, которые публикует сам сервис.
  • Никогда не указывайте 0.0.0.0/0. При одном пире такая запись включает в WireGuard для Windows блокировку всего трафика вне туннеля. На сервере это оборвёт RDP и всё остальное, что приходит на внешний адрес.

Шаг 3. Положите конфиг в защищённую папку

В конфиге лежит приватный ключ, поэтому доступ к файлу нужен только SYSTEM и администраторам. Сначала создайте папку и выставьте ей права:

New-Item -ItemType Directory -Path C:\WireGuard -Force | Out-Null
icacls C:\WireGuard /inheritance:r /grant:r "*S-1-5-18:(OI)(CI)F" "*S-1-5-32-544:(OI)(CI)F"

Затем скопируйте в неё конфиг под именем wg0.conf:

Copy-Item "$env:USERPROFILE\Downloads\client.conf" C:\WireGuard\wg0.conf

Имя файла становится именем туннеля. Используйте латиницу, цифры и символы _ - ., без пробелов.

Шаг 4. Установите туннель как службу

& "$env:ProgramFiles\WireGuard\wireguard.exe" /installtunnelservice C:\WireGuard\wg0.conf

Команда создаёт службу WireGuardTunnel$wg0 с автоматическим запуском и сразу её запускает. После перезагрузки туннель поднимется сам. Служба читает конфиг из C:\WireGuard при каждом старте, поэтому файл нельзя удалять или переносить.

Шаг 5. Включите перезапуск при сбоях

Без этой настройки служба, упавшая при старте, так и останется остановленной. Две команды ниже велят Windows перезапускать её: через 10 секунд, через 30 секунд, а дальше раз в минуту.

sc.exe failure 'WireGuardTunnel$wg0' reset= 86400 actions= restart/10000/restart/30000/restart/60000
sc.exe failureflag 'WireGuardTunnel$wg0' 1

Имя службы пишите в одинарных кавычках: в двойных кавычках PowerShell посчитает $wg0 переменной и подставит вместо неё пустую строку. Команду пишите как sc.exe, а не sc, потому что в PowerShell sc — это алиас Set-Content.

Проверка

Служба запущена, а у туннеля свежий хендшейк:

Get-Service 'WireGuardTunnel$wg0'
& "$env:ProgramFiles\WireGuard\wg.exe" show

В выводе Get-Service должно быть Running. В wg show поле latest handshake должно показывать секунды или минуты назад.

Маршруты из AllowedIPs появились на интерфейсе туннеля:

Get-NetRoute -InterfaceAlias wg0 -AddressFamily IPv4 | Select-Object DestinationPrefix

Трафик к нужному адресу идёт в туннель, а к остальным — напрямую:

tracert -d -h 3 203.0.113.10   # адрес из AllowedIPs: первый хоп 10.8.0.1
tracert -d -h 3 8.8.8.8        # адрес не из списка: первый хоп — шлюз провайдера

Последняя проверка — перезагрузка. Перезагрузите сервер, не входите в систему и через пару минут проверьте туннель с другой машины, например по latest handshake в панели wg-easy.

Как добавить или убрать адрес

  1. Откройте C:\WireGuard\wg0.conf в Блокноте, запущенном от имени администратора.
  2. Поправьте строку AllowedIPs и сохраните файл.
  3. Перезапустите службу, чтобы применить изменения:
Restart-Service 'WireGuardTunnel$wg0'

Как удалить туннель

& "$env:ProgramFiles\WireGuard\wireguard.exe" /uninstalltunnelservice wg0

Команда удаляет службу и сетевой адаптер туннеля. Файл конфига остаётся в C:\WireGuard.

Частые ошибки

СимптомПричинаРешение
Get-Service не находит службуИмя службы написано в двойных кавычкахВзять его в одинарные: 'WireGuardTunnel$wg0'
sc failure ничего не изменилВ PowerShell sc — это алиас Set-ContentПисать sc.exe
После запуска туннеля пропал RDPВ AllowedIPs указан 0.0.0.0/0Оставить в AllowedIPs только нужные адреса
Сайт открывается не через туннельДомен сейчас отдаёт IP, которого нет в AllowedIPsПроверить адреса через Resolve-DnsName и дополнить список
После перезагрузки служба остановленаВ Endpoint указано доменное имя, а сеть ещё не была готоваУказать IP в Endpoint и выполнить шаг 5
Хендшейк есть, но трафик не проходитНа сервере не настроен NAT или пакеты WireGuard теряются по путиПроверить NAT на сервере и подключение с другого канала связи

Итог

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