MAATRIX / Блог / Мониторинг VPN через Prometheus и Grafana

Мониторинг VPN через Prometheus и Grafana

MAATRIX

WireGuard не пишет логи подключений и не хранит историю трафика — wg show покажет только текущее состояние, и то придётся смотреть руками через SSH. Если на сервере десяток пиров и вы хотите видеть, кто активен, сколько трафика прошло за сутки и не отвалился ли чей-то туннель — нужен отдельный сборщик метрик. Разберём связку с экспортёром WireGuard: что он умеет, как построить дашборд по трафику и пирам и как настроить алерт на «протухший» handshake.

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

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

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

Почему WireGuard не годится для мониторинга «из коробки»

WireGuard спроектирован предельно просто и без лишнего: никакого встроенного веб-интерфейса, статистики за период или уведомлений. Всё, что он отдаёт — это моментальный снимок через wg show wg0 dump: список пиров, время последнего handshake, счётчики принятых и переданных байт с момента запуска интерфейса.

Этого достаточно для разовой диагностики, но не для наблюдения за трендом. Счётчики трафика обнуляются при перезапуске интерфейса, история не хранится нигде, а узнать «в 3 ночи у клиента отвалился туннель на 40 минут» постфактум невозможно — данные просто не сохраняются. Если вы уже настраивали общий стек мониторинга сервера, помните: node_exporter из статьи про установку Grafana и Prometheus на VPS видит CPU, память и диск, но ничего не знает про пиры WireGuard — это отдельная метрика, для которой нужен свой экспортёр.

Решение — прогонять сырой вывод wg show через специализированный экспортёр, который превращает его в метрики формата Prometheus, а дальше складывать историю в базу временных рядов и строить дашборд поверх неё.

Экспортёр метрик WireGuard: какой выбрать

Готовых экспортёров для WireGuard несколько, и они отличаются подходом:

ЭкспортёрКак работаетПлюсыМинусы
prometheus-wireguard-exporter (MindFlavor)Бинарник на Rust, парсит wg show dumpЛёгкий, не требует root напрямую (нужен wg с CAP_NET_ADMIN)Нет истории имён пиров без правки конфига
wireguard_exporter (mdlayher)Читает состояние через netlink, без вызова wgНе зависит от утилиты wg, быстрееНужен Go-тулчейн для сборки из исходников
Самописный скрипт + node_exporter textfileCron-скрипт парсит wg show, пишет .prom-файлМаксимальный контроль, ничего лишнегоОбновление раз в интервал cron, а не в реальном времени

Для большинства серверов проще всего взять prometheus-wireguard-exporter — он активно поддерживается и отдаёт метрики сразу в удобном виде. Установка на Ubuntu 24.04/Debian 12:

cd /tmp
wget https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/download/5.0.5/prometheus_wireguard_exporter-linux-amd64
chmod +x prometheus_wireguard_exporter-linux-amd64
mv prometheus_wireguard_exporter-linux-amd64 /usr/local/bin/wireguard_exporter

Экспортёру нужны права на выполнение wg show — либо запускайте его от root (проще, но грубее), либо выдайте бинарнику точечную возможность через setcap:

setcap cap_net_admin+ep /usr/local/bin/wg

Арендуйте сервер под свои задачи!

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

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

systemd-юнит и первая проверка

Заведите отдельный юнит /etc/systemd/system/wireguard-exporter.service:

[Unit]
Description=Prometheus WireGuard Exporter
After=network.target wg-quick@wg0.service

[Service]
ExecStart=/usr/local/bin/wireguard_exporter -a -p 9586
Restart=on-failure

[Install]
WantedBy=multi-user.target

Флаг -a включает вывод расширенных метрик по каждому пиру (allowed-ips, handshake, трафик), -p 9586 — стандартный порт экспортёра. Запустите и проверьте:

systemctl daemon-reload
systemctl enable --now wireguard-exporter
curl localhost:9586/metrics

В выводе должны появиться строки вида wireguard_sent_bytes_total, wireguard_received_bytes_total, wireguard_latest_handshake_seconds — по одной группе на каждый публичный ключ пира. Если curl вернул пустой список или ошибку доступа — вероятнее всего, экспортёр не смог выполнить wg show: проверьте права через setcap --v /usr/local/bin/wg или временно запустите юнит от root, чтобы исключить проблему с правами.

Подключение к Prometheus

Если Prometheus уже развёрнут (см. статью про установку связки Prometheus и Grafana), добавьте новый job в /etc/prometheus/prometheus.yml:

scrape_configs:
  - job_name: 'wireguard'
    scrape_interval: 30s
    static_configs:
      - targets: ['localhost:9586']

Интервал в 30 секунд для VPN — разумный компромисс: чаще есть смысл только если вы отлаживаете конкретную проблему прямо сейчас, реже — начнёте терять короткие обрывы связи. Перезапустите Prometheus и проверьте на странице http://IP_СЕРВЕРА:9090/targets, что job wireguard в статусе UP.

Если сервер мониторинга и VPN-сервер — разные машины (что и правильно: точку сбора данных не стоит держать на том же узле, который может отвалиться первым), укажите вместо localhost реальный адрес VPN-сервера и откройте порт 9586 в firewall только для IP Prometheus:

ufw allow from IP_ПРОМЕТЕУСА to any port 9586 proto tcp

Дашборд: трафик и активные пиры

Готового «official» дашборда для этого экспортёра в галерее Grafana меньше, чем для node_exporter, поэтому проще собрать несколько панелей вручную — это займёт 15–20 минут. Ключевые панели:

Трафик по пирам (Graph, за период). Запрос через irate показывает не абсолютные счётчики, а скорость передачи в реальном времени:

irate(wireguard_sent_bytes_total[5m])
irate(wireguard_received_bytes_total[5m])

Добавьте легенду по лейблу public_key (или замените его на понятные имена — см. ниже), и панель покажет, кто из пиров сейчас качает трафик, а кто простаивает.

Активные пиры (Stat/Table). Метрика wireguard_latest_handshake_seconds отдаёт unix-время последнего рукопожатия. Чтобы получить «сколько секунд назад был последний handshake», используйте:

time() - wireguard_latest_handshake_seconds

Значение до 180 секунд — пир активен и туннель жив (WireGuard пересогласовывает ключи примерно раз в 2 минуты при наличии трафика). Значение, которое растёт часами — пир отключился или трафик через него не идёт. Добавьте на панель пороговые цвета: зелёный до 180 секунд, жёлтый до 600, красный дальше.

Суммарный трафик за сутки (Stat). Через increase() за 24 часа:

increase(wireguard_sent_bytes_total[24h]) + increase(wireguard_received_bytes_total[24h])

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

Публичные ключи в лейблах нечитаемы, поэтому имеет смысл держать соответствие «ключ → имя клиента» в отдельной таблице (текстовый файл или переменная Grafana) и подставлять его вручную при разборе инцидентов — сам экспортёр имён клиентов не знает, WireGuard их не хранит.

Алерты на отвалившийся туннель

Самый полезный алерт для VPN — не про CPU или диск, а про то, что конкретный клиент замолчал. В Grafana (Alerting → Alert rules) создайте правило на основе того же запроса про handshake:

time() - wireguard_latest_handshake_seconds > 600

Условие «истина дольше 5 минут» отсекает случайные короткие просадки сети и не будет спамить нотификациями на каждый недолгий пинг-таймаут. При срабатывании отправьте уведомление в Telegram или на почту — в разделе Contact points настраивается один раз, дальше работает на все правила.

Второй полезный алерт — резкий скачок входящего трафика с одного пира сверх обычного, что иногда сигнализирует не о легитимной нагрузке, а о скомпрометированном ключе клиента:

irate(wireguard_received_bytes_total[5m]) > 50000000

Порог (в примере — 50 МБ/с) подбирайте под свою нагрузку: для домашнего VPN на несколько устройств это уже подозрительно много, для сервера с активными бэкапами — норма. Здесь нет универсального числа, отталкивайтесь от собственного базового уровня трафика за неделю наблюдений.

Ограничения подхода и на что ещё обратить внимание

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

Также помните про дисковое пространство: чем больше пиров и чем чаще опрос, тем быстрее растёт база временных рядов Prometheus. Для VPN-сервера с несколькими десятками клиентов и интервалом 30 секунд типичный расход — несколько сотен мегабайт в месяц на саму эту метрику, но точную цифру у себя лучше проверить через du -sh /var/lib/prometheus спустя пару недель работы, а не полагаться на ориентир.

Если у вас не WireGuard, а OpenVPN, готовых экспортёров меньше и стабильных официальных нет — там чаще собирают метрики через парсинг status.log в textfile-коллектор node_exporter, это отдельная и менее прямолинейная задача.

Арендуйте сервер под свои задачи!

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

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

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

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

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

Экспортёр показывает 0 метрик, хотя wg show работает.

Обычно дело в правах: бинарник экспортёра запущен не от root и не получил cap_net_admin через setcap. Проверьте права на /usr/local/bin/wg и перезапустите юнит.

Можно ли мониторить несколько VPN-серверов одним Prometheus?

Да, это стандартный сценарий — добавьте в scrape_configs по одному target на каждый сервер с портом 9586, а в дашборде фильтруйте по лейблу instance.

Handshake «протух», но интернет у клиента работает.

WireGuard пересогласовывает ключи только при наличии исходящего трафика от клиента к серверу. Если устройство просто ничего не отправляет (спящий телефон, простаивающий сервер), время с последнего handshake будет расти — это не всегда авария, но стоит учитывать при настройке порога алерта.

Нужен ли отдельный VPS под мониторинг или хватит того же сервера, где стоит WireGuard?

Для одного сервера можно держать Prometheus и Grafana локально, но если серверов несколько или вы хотите видеть падение основного узла — вынесите мониторинг на отдельную машину, желательно в другой локации.

Как назвать пиров по-человечески, а не по публичному ключу?

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

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

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

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