Задача клиента
В марте 2026 года к нам в АйТи Фреш обратилась консалтинговая компания из Екатеринбурга — управленческий консалтинг для среднего бизнеса. Около 50 человек в штате, и 30 из них — консультанты, которые постоянно в разъездах: дом, клиенты, коворкинги, командировки.
Пришли с конкретными болями, не с абстрактными «хотим лучше»:
- Дорогое VPN-решение — сидели на Cisco AnyConnect за 180 000 рублей в год. При этом реально использовали процентов десять от всей функциональности. Классика.
- Жалобы сотрудников на скорость — пробовали OpenVPN как альтернативу, но при переключении с Wi-Fi на мобильную сеть туннель рвался, задержки были ощутимые. Консультанты жаловались.
- Отсутствие мобильного доступа — со смартфона безопасно зайти в корпоративную CRM было просто нельзя
- Безопасность — клиентские данные гоняются через публичные сети в кафе и аэропортах, шифрование обязательно
Мы предложили WireGuard VPN. Бесплатно, открытый исходный код, быстро работает. Задача была конкретная: безопасный удалённый доступ для 30+ человек с любых устройств, минимальные задержки и запас для роста.
Почему мы выбрали WireGuard вместо Cisco и OpenVPN
WireGuard появился как модуль ядра Linux в 2020 году — с версии 5.6 он прямо в ядре, ничего лишнего устанавливать не нужно. Для сравнения: кодовая база OpenVPN и IPsec — это сотни тысяч строк, которые никто не аудировал целиком никогда. WireGuard — около 4 000 строк. Реально читаемо одним человеком за разумное время. Криптография современная: Curve25519 для обмена ключами, ChaCha20 для шифрования, Poly1305 для аутентификации, BLAKE2s для хеширования, SipHash24 для хеш-таблиц.
Для этого клиента выбор был очевиден. Ноль рублей на лицензии, мгновенное переподключение, роуминг между сетями без разрыва туннеля — именно это и нужно человеку, который за день меняет три точки доступа.
Сравнительный анализ, который мы представили клиенту
| Параметр | WireGuard | OpenVPN | IPsec/IKEv2 |
|---|
| Кодовая база | ~4 000 строк | ~100 000 строк | ~400 000 строк |
| Шифрование | ChaCha20-Poly1305 | AES-256-GCM / CBC | AES-256-GCM |
| Пропускная способность | ~900 Мбит/с | ~500 Мбит/с | ~700 Мбит/с |
| Время установления соединения | <100 мс | ~5-10 сек | ~1-3 сек |
| Работа в пространстве | Ядро | Пользовательское | Ядро |
| Роуминг | Встроенный | Нет | С MOBIKE |
Мы гоняли тесты на сервере с Intel Xeon E-2236. WireGuard стабильно выдаёт на 30–50% большую пропускную способность, чем OpenVPN в сопоставимых условиях. Причина простая: работает прямо в пространстве ядра, без переключений в userspace, плюс криптопримитивы оптимизированы под современное железо.
Сценарии, под которые мы проектировали решение
Под задачи клиента мы выделили четыре сценария, под которые и проектировали всю конфигурацию:
- Удалённый доступ сотрудников — подключение за секунды, туннель держится при смене сети между Wi-Fi и мобильным интернетом
- Site-to-Site VPN — связь главного офиса с переговорной площадкой на стороне клиента
- Mesh-сети — серверы компании в разных дата-центрах должны видеть друг друга напрямую
- Мобильный доступ — нативные клиенты под iOS и Android, аккумулятор не съедают
Честно скажу про ограничение: если нужна обфускация трафика и обход DPI — WireGuard не лучший выбор, там лучше смотреть в сторону VLESS/XTLS или Shadowsocks. Но у этого клиента такой задачи не стояло, так что ограничение нас не касалось.
Установка WireGuard на сервер клиента
Разворачивали на выделенном сервере под Debian 12. На современных дистрибутивах установка WireGuard — это буквально несколько минут и пара команд.
Применённая конфигурация: установка на Debian 12
# Обновляем пакеты
sudo apt update && sudo apt upgrade -y
# Устанавливаем WireGuard
sudo apt install -y wireguard wireguard-tools
# Проверяем загрузку модуля ядра
sudo modprobe wireguard
lsmod | grep wireguard
# Убеждаемся, что модуль загрузился
# wireguard 81920 0
# curve25519_x86_64 36864 1 wireguard
# libchacha20poly1305 16384 1 wireguard
Если ядро старше, чем 5.6, — придётся доставить модуль из бэкпортов:
# Для Debian 10 (buster)
echo 'deb http://deb.debian.org/debian buster-backports main' | sudo tee /etc/apt/sources.list.d/buster-backports.list
sudo apt update
sudo apt install -y -t buster-backports wireguard
Установка на CentOS/RHEL 8/9 и Rocky Linux
# CentOS/RHEL 8
sudo dnf install -y epel-release elrepo-release
sudo dnf install -y kmod-wireguard wireguard-tools
# Rocky Linux 9 / AlmaLinux 9
sudo dnf install -y epel-release
sudo dnf install -y wireguard-tools
# Загружаем модуль
sudo modprobe wireguard
После установки проверили, что директория /etc/wireguard на месте и права доступа выставлены корректно:
sudo mkdir -p /etc/wireguard
sudo chmod 700 /etc/wireguard
Генерация ключей и настройка сервера
WireGuard строится на асимметричной криптографии — эллиптические кривые Curve25519, у каждого узла своя пара ключей. Для клиентских подключений мы дополнительно подняли preshared key (PSK) — это требование их собственной службы безопасности, защита от квантовых атак на будущее.
Вот как мы генерировали ключевые пары
# Генерация ключей для сервера
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
# Устанавливаем права доступа на приватный ключ
sudo chmod 600 /etc/wireguard/server_private.key
# Генерация ключей для первого клиента
wg genkey | sudo tee /etc/wireguard/client1_private.key | wg pubkey | sudo tee /etc/wireguard/client1_public.key
# Генерация Pre-Shared Key (дополнительная защита)
wg genpsk | sudo tee /etc/wireguard/client1_psk.key
sudo chmod 600 /etc/wireguard/client1_private.key /etc/wireguard/client1_psk.key
# Просмотр сгенерированных ключей
echo "Server Private: $(cat /etc/wireguard/server_private.key)"
echo "Server Public: $(cat /etc/wireguard/server_public.key)"
echo "Client1 Private: $(cat /etc/wireguard/client1_private.key)"
echo "Client1 Public: $(cat /etc/wireguard/client1_public.key)"
echo "Client1 PSK: $(cat /etc/wireguard/client1_psk.key)"
Важно: приватные ключи — это не то, что пересылают в Telegram или обычной почтой. Никогда. Для раздачи конфигураций сотрудникам мы использовали QR-коды и зашифрованную почту — быстро и без риска утечки.
Применённая конфигурация сервера wg0.conf
Вот конфигурационный файл сервера, который получился в итоге:
# /etc/wireguard/wg0.conf
[Interface]
# Приватный ключ сервера
PrivateKey = SERVER_PRIVATE_KEY_HERE
# IP-адрес сервера в VPN-сети
Address = 10.0.0.1/24
# Порт прослушивания (UDP)
ListenPort = 51820
# DNS-сервер для клиентов (опционально)
DNS = 1.1.1.1, 8.8.8.8
# Команды при поднятии интерфейса — включаем NAT и форвардинг
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT
PostUp = iptables -A FORWARD -o wg0 -j ACCEPT
PostUp = sysctl -w net.ipv4.ip_forward=1
# Команды при выключении интерфейса — убираем правила
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -A FORWARD -i wg0 -j ACCEPT
PostDown = iptables -A FORWARD -o wg0 -j ACCEPT
# === Клиент 1: Ноутбук администратора ===
[Peer]
PublicKey = CLIENT1_PUBLIC_KEY_HERE
PresharedKey = CLIENT1_PSK_HERE
AllowedIPs = 10.0.0.2/32
# === Клиент 2: Мобильное устройство ===
[Peer]
PublicKey = CLIENT2_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.3/32
# === Клиент 3: Офисный шлюз (Site-to-Site) ===
[Peer]
PublicKey = CLIENT3_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.4/32, 192.168.10.0/24
PersistentKeepalive = 25
Пара моментов, на которые стоит обратить внимание: в AllowedIPs для site-to-site соединения прописана подсеть удалённого офиса (192.168.10.0/24). А PersistentKeepalive = 25 нужен, когда клиент сидит за NAT — без него туннель будет рваться.
Включение IP-форвардинга на постоянной основе
# Включаем форвардинг пакетов
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
# Проверяем
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 1
Настройка клиентских устройств сотрудников
Нам нужно было охватить все рабочие сценарии сразу: 30 человек, три типа устройств — ноутбуки на Linux и Windows, смартфоны на iOS и Android. Структура клиентского конфига везде одинакова, разница только в том, как его загрузить в приложение.
Конфигурация для Linux-ноутбуков
# Устанавливаем WireGuard на клиенте
sudo apt install -y wireguard resolvconf
# Создаём конфигурацию клиента
sudo nano /etc/wireguard/wg0.conf
# /etc/wireguard/wg0.conf (клиент Linux)
[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY_HERE
Address = 10.0.0.2/24
DNS = 1.1.1.1, 8.8.8.8
# MTU — важен при проблемах с фрагментацией
# MTU = 1420
[Peer]
PublicKey = SERVER_PUBLIC_KEY_HERE
PresharedKey = CLIENT1_PSK_HERE
Endpoint = vpn.example.com:51820
# Для полного туннелирования (весь трафик через VPN)
AllowedIPs = 0.0.0.0/0, ::/0
# Для split-tunneling (только VPN-подсеть)
# AllowedIPs = 10.0.0.0/24
# Keepalive для работы за NAT
PersistentKeepalive = 25
# Поднимаем туннель
sudo wg-quick up wg0
# Проверяем статус
sudo wg show
# Автозапуск при загрузке
sudo systemctl enable wg-quick@wg0
# Проверяем подключение
ping 10.0.0.1
curl ifconfig.me # Должен показать IP VPN-сервера
Настройка для Windows-ноутбуков
Большинство консультантов сидели на Windows. Мы заранее подготовили готовые .conf-файлы — людям оставалось только импортировать. Клиент скачивается с wireguard.com/install, установка стандартная. Дальше всё просто:
- Открываете приложение WireGuard
- Жмёте «Add Tunnel» → «Add empty tunnel»
- Вставляете конфигурацию вручную — она идентична Linux-варианту
- Или просто импортируете готовый файл .conf — это быстрее
Конфиг для Windows ничем не отличается от Linux-клиента — один и тот же формат. Мы сгенерировали персональный client.conf для каждого из 30 сотрудников и передали по защищённому каналу. Никакой самодеятельности с настройками.
# Генерация QR-кода для мобильных клиентов
sudo apt install -y qrencode
qrencode -t ansiutf8 < /etc/wireguard/client1.conf
Мобильные клиенты: iOS и Android
Тем, кто работает с CRM прямо со смартфона, конфиг раздавали через QR-коды. Сканируешь — и готово, вводить ничего не нужно:
# На сервере — генерируем конфигурацию клиента
cat <<EOF > /tmp/mobile-client.conf
[Interface]
PrivateKey = MOBILE_PRIVATE_KEY
Address = 10.0.0.3/24
DNS = 1.1.1.1
[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF
# Генерируем QR-код
qrencode -t png -o /tmp/mobile-qr.png < /tmp/mobile-client.conf
# Или выводим в терминал
qrencode -t ansiutf8 < /tmp/mobile-client.conf
Сотрудник открывает приложение WireGuard, наводит камеру на QR — подключение поднимается за 5 секунд. После того как все отсканировали, временные файлы с QR-кодами мы сразу удалили:
sudo shred -u /tmp/mobile-client.conf /tmp/mobile-qr.png
Настройка NAT, firewall и DNS
Firewall — это то место, где у многих всё и ломается. Нам нужно было решить три задачи одновременно: пропустить UDP-трафик WireGuard, поднять NAT для выхода клиентов в интернет и не сломать DNS внутри VPN-сети. Если упустить хоть одно — туннель либо не поднимется, либо интернет через него работать не будет.
Правила iptables для WireGuard
# Разрешаем входящий UDP-трафик на порт WireGuard
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
# Разрешаем трафик на интерфейсе wg0
sudo iptables -A INPUT -i wg0 -j ACCEPT
sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT
# NAT — маскарадинг для выхода в интернет
# Замените eth0 на ваш реальный внешний интерфейс
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
# Сохраняем правила
sudo apt install -y iptables-persistent
sudo netfilter-persistent save
Настройка через nftables (современный подход)
# /etc/nftables.conf
table inet wireguard {
chain input {
type filter hook input priority 0; policy accept;
udp dport 51820 accept comment "WireGuard"
iifname "wg0" accept comment "WireGuard tunnel traffic"
}
chain forward {
type filter hook forward priority 0; policy drop;
iifname "wg0" accept comment "Forward from WG"
oifname "wg0" accept comment "Forward to WG"
ct state established,related accept
}
chain postrouting {
type nat hook postrouting priority 100;
ip saddr 10.0.0.0/24 oifname "eth0" masquerade
}
}
# Применяем конфигурацию
sudo nft -f /etc/nftables.conf
sudo systemctl enable nftables
DNS-сервер для VPN-клиентов
DNS-запросы сотрудников тоже должны ходить через зашифрованный туннель — иначе смысл VPN теряется наполовину. Для этого мы подняли локальный DNS-резолвер прямо на сервере:
# Устанавливаем Unbound
sudo apt install -y unbound
# Конфигурация /etc/unbound/unbound.conf.d/wireguard.conf
server:
interface: 10.0.0.1
access-control: 10.0.0.0/24 allow
do-ip6: no
hide-identity: yes
hide-version: yes
prefetch: yes
num-threads: 2
msg-cache-size: 16m
rrset-cache-size: 32m
forward-zone:
name: "."
forward-addr: 1.1.1.1
forward-addr: 8.8.8.8
sudo systemctl restart unbound
sudo systemctl enable unbound
В конфигурации каждого клиента прописали DNS = 10.0.0.1 — публичные DNS-серверы из этой схемы полностью исключены.
Автоматизация управления пользователями
30 человек — это уже не «настроить руками за вечер». Мы написали скрипт, который генерирует ключи, создаёт конфиг и добавляет нового пира на сервер в один прогон. Плюс настроили автозапуск через systemd — после перезагрузки сервера WireGuard поднимается сам.
Основные команды управления
# Запуск интерфейса
sudo wg-quick up wg0
# Остановка интерфейса
sudo wg-quick down wg0
# Автозапуск при загрузке
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
# Просмотр статуса подключений
sudo wg show
sudo wg show wg0
# Вывод статистики в формате JSON
sudo wg show all dump
# Добавление нового пира без перезагрузки
sudo wg set wg0 peer CLIENT_NEW_PUBLIC_KEY allowed-ips 10.0.0.10/32
# Удаление пира
sudo wg set wg0 peer CLIENT_PUBLIC_KEY remove
Скрипт автоматического добавления клиентов
Скрипт писался специально для IT-отдела заказчика. Задача была простая: человек без глубоких знаний Linux должен подключить нового сотрудника самостоятельно, не дёргая нас каждый раз:
#!/bin/bash
# /usr/local/bin/wg-add-client.sh
# Скрипт для добавления нового VPN-клиента
set -euo pipefail
SERVER_PUB_KEY=$(cat /etc/wireguard/server_public.key)
SERVER_ENDPOINT="vpn.example.com:51820"
VPN_SUBNET="10.0.0"
WG_CONF="/etc/wireguard/wg0.conf"
if [ -z "${1:-}" ]; then
echo "Использование: $0 <имя_клиента>"
exit 1
fi
CLIENT_NAME="$1"
# Определяем следующий свободный IP
LAST_IP=$(grep -oP 'AllowedIPs = 10\.0\.0\.\K[0-9]+' $WG_CONF | sort -n | tail -1)
NEXT_IP=$((LAST_IP + 1))
if [ $NEXT_IP -gt 254 ]; then
echo "Ошибка: пул IP-адресов исчерпан"
exit 1
fi
# Генерируем ключи
CLIENT_PRIV=$(wg genkey)
CLIENT_PUB=$(echo "$CLIENT_PRIV" | wg pubkey)
CLIENT_PSK=$(wg genpsk)
# Создаём конфиг клиента
CLIENT_CONF="/etc/wireguard/clients/${CLIENT_NAME}.conf"
mkdir -p /etc/wireguard/clients
cat > "$CLIENT_CONF" <<EOF
[Interface]
PrivateKey = ${CLIENT_PRIV}
Address = ${VPN_SUBNET}.${NEXT_IP}/24
DNS = 10.0.0.1
[Peer]
PublicKey = ${SERVER_PUB_KEY}
PresharedKey = ${CLIENT_PSK}
Endpoint = ${SERVER_ENDPOINT}
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF
# Добавляем пир на сервер
cat >> "$WG_CONF" <<EOF
# === ${CLIENT_NAME} ===
[Peer]
PublicKey = ${CLIENT_PUB}
PresharedKey = ${CLIENT_PSK}
AllowedIPs = ${VPN_SUBNET}.${NEXT_IP}/32
EOF
# Применяем без перезагрузки
wg set wg0 peer "${CLIENT_PUB}" preshared-key <(echo "${CLIENT_PSK}") allowed-ips "${VPN_SUBNET}.${NEXT_IP}/32"
echo "Клиент ${CLIENT_NAME} добавлен: ${VPN_SUBNET}.${NEXT_IP}"
echo "Конфигурация: ${CLIENT_CONF}"
echo ""
echo "QR-код для мобильного клиента:"
qrencode -t ansiutf8 < "$CLIENT_CONF"
chmod 600 "$CLIENT_CONF"
Мониторинг и устранение неполадок
После того как все 30 человек подключились, мы настроили мониторинг через Prometheus и Grafana и передали IT-отделу инструкцию по диагностике — чтобы они могли разбираться с типовыми проблемами сами, не ждя нашего ответа.
Диагностика проблем подключения
# Проверяем статус интерфейса
ip a show wg0
# Проверяем активных пиров и время последнего handshake
sudo wg show wg0
# Если latest handshake старше 2 минут — есть проблемы
# Проверяем маршруты
ip route show table all | grep wg0
# Проверяем доступность порта снаружи
nc -uzv vpn.example.com 51820
# Включаем динамическое логирование WireGuard
echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control
# Смотрим логи
sudo dmesg | grep wireguard
journalctl -u wg-quick@wg0 -f
# Тестируем MTU (часто причина проблем)
ping -M do -s 1400 10.0.0.1
# Уменьшайте размер пакета, пока ping не заработает
# Затем установите MTU = найденное значение + 28
Типичные проблемы, с которыми столкнулись сотрудники
- Handshake не устанавливается — первым делом проверяйте, открыт ли UDP-порт 51820 в firewall, правильно ли скопирован PublicKey и верный ли адрес в Endpoint
- Туннель поднялся, но интернета нет — смотрите ip_forward, правила NAT/MASQUERADE и имя сетевого интерфейса в PostUp: именно там чаще всего опечатка
- Низкая производительность — проверяйте MTU, для IPv4 оптимально 1420, и убедитесь, что процессор поддерживает аппаратное ускорение ChaCha20
- DNS не работает — проверьте, установлен ли resolvconf, и перечитайте конфиг клиента: DNS там должен быть прописан явно
- Потеря пакетов у клиентов за NAT — лечится просто: добавьте
PersistentKeepalive = 25 в конфиг клиента
Мониторинг через Prometheus и Grafana
# Устанавливаем Prometheus exporter для WireGuard
sudo apt install -y prometheus-node-exporter
# Или используем специализированный wireguard_exporter
wget https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/latest/download/prometheus_wireguard_exporter-linux-amd64
chmod +x prometheus_wireguard_exporter-linux-amd64
sudo mv prometheus_wireguard_exporter-linux-amd64 /usr/local/bin/prometheus_wireguard_exporter
# Создаём systemd unit
sudo cat > /etc/systemd/system/wireguard-exporter.service <<EOF
[Unit]
Description=Prometheus WireGuard Exporter
After=network.target
[Service]
ExecStart=/usr/local/bin/prometheus_wireguard_exporter -p 9586
Restart=always
User=root
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now wireguard-exporter
В Grafana мы собрали дашборд с тремя ключевыми метриками: число активных подключений прямо сейчас, объём трафика по каждому пиру и время последнего handshake. IT-отдел получил доступ и смотрит всё это в реальном времени — без необходимости лезть в консоль.
Результаты внедрения
Уложились в 3 рабочих дня. Первый день — сервер, конфиги, firewall, DNS. Ещё два дня — клиентские устройства, QR-коды для мобилок, обучение IT-отдела работе со скриптом. Вот что получили по факту:
- Экономия 180 000 руб./год — полностью отказались от лицензий Cisco AnyConnect, перешли на бесплатный WireGuard
- Подключение менее 100 мс — на OpenVPN уходило 5–10 секунд, здесь сотрудники этого просто не замечают
- Пропускная способность выросла на 40% — WireGuard стабильно даёт ~900 Мбит/с, OpenVPN на том же железе выдавал ~500 Мбит/с
- Ноль обрывов при роуминге — консультанты переключаются с Wi-Fi на мобильную сеть и обратно, VPN-соединение не падает
- 30 сотрудников подключены — из них 12 работают с мобильных устройств на iOS и Android
- Новый сотрудник подключается за 2 минуты — скрипт автоматизации делает всё сам, от генерации ключей до QR-кода
- Мониторинг 24/7 — дашборд в Grafana показывает статус каждого подключения, IT-отдел видит картину без лишних вопросов
Через неделю после запуска клиент полностью отключил Cisco. IT-отдел уже самостоятельно подключил троих новых сотрудников по нашей документации — нас не потревожили ни разу.