MAATRIX / Блог / Мониторинг доступности VPN-сервера через Uptime Kuma

Мониторинг доступности VPN-сервера через Uptime Kuma

MAATRIX

Сервер отвечает на ping, SSH пускает, а WireGuard или OpenVPN не поднимается — знакомая ситуация, если мониторите только «жив ли хост». VPN-сервис может упасть отдельно от сервера: демон вылетел по OOM, конфиг слетел после обновления пакета, iptables-правило потерялось после перезагрузки. Разберём, как в Uptime Kuma настроить проверку именно VPN-порта, почему для UDP-протоколов встроенный TCP-монитор врёт, и как развести алерты VPN отдельно от общего шума мониторинга.

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

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

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

Почему «сервер жив» не значит «VPN работает»

Ping и стандартный HTTP/TCP-монитор на 22-м порту проверяют, что хост в сети и SSH отвечает. Это никак не связано с состоянием VPN-демона: wg-quick, openvpn или softether — отдельный процесс со своим жизненным циклом, и он падает независимо от того, жив ли сервер в целом.

Типичные причины расхождения: демон убит OOM killer при нехватке памяти (сервер продолжает отвечать на всё остальное), конфиг с опечаткой не применился после systemctl restart и сервис остался в состоянии failed, правило iptables/nftables для форвардинга трафика потерялось после апдейта ядра и перезагрузки, а сам процесс WireGuard при этом жив и слушает порт — просто трафик никуда не идёт. Последний случай отдельно неприятен: порт открыт, а VPN не работает, и проверка «порт слушает» его не поймает в принципе — это уже вопрос сквозного теста, не мониторинга порта.

Отдельный монитор именно на VPN-порт нужен, чтобы падение демона попадало в Telegram раньше, чем об этом напишет пользователь. Общий мониторинг сервера (установка Uptime Kuma с нуля) для этого не рассчитан по построению — он смотрит на хост, а не на конкретный сервис внутри него.

TCP Port монитор: для каких VPN-протоколов он подходит напрямую

Если VPN работает поверх TCP, встроенный тип монитора TCP Port в Uptime Kuma подходит без хитростей — он делает обычный SYN/ACK-хендшейк и считает порт живым, если соединение установилось.

Подходит для:

Протокол/сервисПорт по умолчаниюЧто проверяет TCP Port
OpenVPN (режим proto tcp)1194/tcpДемон слушает и принимает TCP-соединения
SSTP443/tcpСлужба RRAS/SSTP отвечает на TLS-хендшейк
SoftEther (management/HTTPS)443 или 992/tcpВеб-консоль и протокол SoftEther на TCP
WireGuard через обёртку (udp2raw, stunnel в TCP-режиме)зависит от настройки обёрткиСлушает ли сам туннелирующий процесс

Настройка тривиальна: Add New Monitor → Monitor Type: TCP Port, указываете IP сервера и порт, интервал проверки и Retries. Для VPN-сервиса Retries стоит поднять до 2–3 — единичный сетевой чих на длинном маршруте не должен будить вас ночью, а два подряд провала уже повод разобраться.

Важная оговорка: успешный TCP-хендшейк подтверждает только то, что порт слушает. Он не проверяет, что аутентификация проходит и что через туннель реально идёт трафик — это уже задача сквозного теста, не порта.

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

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

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

Ловушка с UDP: почему TCP Port здесь не работает

WireGuard по умолчанию использует UDP на 51820, OpenVPN по умолчанию — тоже UDP, на 1194. И вот здесь встроенный монитор TCP Port в Uptime Kuma напрямую бесполезен: UDP — протокол без установления соединения, у него нет SYN/ACK, который можно проверить извне универсальным способом.

Хуже того, WireGuard спроектирован намеренно тихим: он не отвечает на «мусорные» пакеты вообще — ни отказом, ни любым откликом. Это защита от сканирования (порт не палится в обычном UDP-скане), но она же делает внешнюю проверку «порт открыт снаружи» неотличимой от «порта нет вовсе»: в обоих случаях в ответ тишина. Утилиты вроде nmap -sU в такой ситуации честно пишут open|filtered — то есть сами признают, что не могут различить эти два состояния без ответа от службы.

Следствие: если поставить в Uptime Kuma Ping-монитор на IP сервера и считать, что этого достаточно для VPN — он будет зелёным даже когда демон WireGuard упал, потому что ping проверяет ICMP до хоста, а не состояние UDP-порта. Нужен другой подход, работающий именно с тем, что происходит на самом VPN-сервисе.

Рабочий вариант для UDP: локальный скрипт-watchdog и Push-монитор

Раз внешне UDP-порт надёжно не продиагностировать без специфики протокола, проверку переносят на сам сервер — не «достучаться снаружи», а «убедиться, что служба реально слушает и работает», и сообщать об этом наружу через Push-монитор Uptime Kuma.

Push-монитор в Kuma устроен наоборот по сравнению с остальными: не Kuma стучится к вам, а ваш скрипт стучится к Kuma по расписанию. Если стука не было дольше заданного интервала — монитор считается упавшим. Заводится за минуту: Add New Monitor → Monitor Type: Push, интервал (например, 60 секунд) — Kuma выдаёт URL вида https://status.example.com/api/push/AbCdEf12345?status=up&msg=OK&ping=.

Скрипт-проверка для WireGuard, запускаемый по cron или через systemd-таймер на самом VPN-сервере:

#!/bin/bash
# /opt/vpn-check/wg-healthcheck.sh
IFACE="wg0"
PUSH_URL="https://status.example.com/api/push/AbCdEf12345"

# 1. Порт реально слушает
if ! ss -lun | grep -q ":51820\b"; then
    echo "wg0 не слушает 51820/udp" >&2
    exit 1
fi

# 2. Интерфейс поднят и есть хотя бы один живой пир
if ! wg show "$IFACE" latest-handshakes | awk '{print $2}' | grep -qv '^0$'; then
    echo "нет ни одного успешного хендшейка" >&2
    exit 1
fi

curl -fsS -m 10 "${PUSH_URL}?status=up&msg=OK&ping=" >/dev/null

Второй блок проверяет не только сам факт прослушивания порта, а результат wg show <интерфейс> latest-handshakes — если хотя бы у одного пира последний хендшейк не нулевой (не «никогда»), значит туннель реально согласовывает ключи, а не просто открыл сокет. Для пустого сервера без активных клиентов это условие нужно ослабить или убрать — там нормально, что хендшейков нет.

Для OpenVPN на UDP аналог проще, потому что демон пишет статус в файл:

#!/bin/bash
PUSH_URL="https://status.example.com/api/push/XyZ98765"
if systemctl is-active --quiet openvpn-server@server && \
   ss -lun | grep -q ":1194\b"; then
    curl -fsS -m 10 "${PUSH_URL}?status=up&msg=OK&ping=" >/dev/null
fi

Ставите в cron с интервалом заметно короче, чем интервал Push-монитора в Kuma — например, скрипт раз в минуту, а Push-монитор ждёт сигнал 3 минуты, чтобы одиночный сбой cron (диск занят, обновление пакетов) не поднимал ложную тревогу:

* * * * * /opt/vpn-check/wg-healthcheck.sh >> /var/log/vpn-healthcheck.log 2>&1

Честное ограничение этого подхода: он подтверждает, что служба жива и хендшейки идут *на момент последнего успешного пира*, но не гарантирует, что порт доступен именно с той сети, откуда подключаются ваши клиенты — блокировка провайдером конкретного региона таким скриптом не поймается. Для полного end-to-end теста нужен отдельный клиент-пробник с реальным VPN-подключением из внешней сети, который тоже периодически стучится в свой Push-монитор — это уже отдельная, более тяжёлая настройка, оправданная только для критичных по доступности узлов.

Разделение мониторинга VPN и общего мониторинга сервера

Смешивать монитор VPN-порта с монитором сайта или базы данных в одном списке — плохая идея: при разборе алерта в 3 часа ночи вы должны сразу видеть, что упало именно VPN, а не гадать по названию.

В Uptime Kuma для этого есть группы (Add Group) — создаёте группу «VPN», внутрь кладёте все связанные мониторы: TCP/Push-проверку самого протокола, отдельный монитор на management-порт (если есть панель SoftEther или веб-интерфейс), монитор на сам факт доступности сервера по SSH. Группа сворачивается на дашборде и не мешает общей картине.

Второй уровень разделения — Tags (Settings → Tags или прямо в настройках монитора): вешаете тег vpn с одним цветом и site/db с другими, фильтруете статус-страницу по тегу. Если у вас несколько VPN-серверов в разных локациях — RU, US, UK — тегом можно закодировать и регион, чтобы на публичной статус-странице (если она у вас есть) сразу было видно, какой узел недоступен.

Отдельный канал алертов в Telegram для VPN

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

Заводите отдельного Telegram-бота через @BotFather (/newbot, получаете токен вида 123456789:AAH...), создаёте отдельную группу или используете личный чат, добавляете бота туда и получаете chat_id:

curl -s "https://api.telegram.org/bot<ТОКЕН>/getUpdates" | grep -o '"chat":{"id":[0-9-]*'

В Uptime Kuma: Settings → Notifications → Setup Notification, тип Telegram, вставляете Bot Token и Chat ID, жмёте Test — должно прилететь тестовое сообщение. Дальше ключевой момент: не ставьте галочку «Apply on all existing monitors» — это разошлёт канал на всё подряд, включая мониторы сайта. Привязывайте новый Telegram-канал точечно, вручную открыв каждый VPN-монитор и включив нужное уведомление в его настройках.

Если Telegram-уведомления не приходят вовсе — это отдельная и частая проблема, разбор причин и решений в статье Uptime Kuma не шлёт уведомления. Общие ошибки конфигурации самой Kuma на сервере — в статье частые ошибки Uptime Kuma. А если ещё не решили, WireGuard или OpenVPN ставить на сервер — сравнение в статье WireGuard или OpenVPN: что выбрать.

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

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

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

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

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

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

Можно ли проверить UDP-порт VPN напрямую через Uptime Kuma, без своего скрипта?

Нет, в стабильной ветке Uptime Kuma нет отдельного типа монитора «UDP Port», а TCP-хендшейк к UDP-сервису не применим в принципе. Единственный встроенный способ довести UDP-проверку до Kuma — через Push-монитор, куда стучится ваш скрипт с локальной проверкой службы.

Ping-монитор на IP сервера разве не покажет, что VPN упал?

Нет. Ping проверяет ICMP-доступность хоста целиком, а не состояние конкретного демона на нём. Сервер может отвечать на ping и при этом иметь упавший WireGuard — ping этого не увидит.

Стоит ли ставить мониторинг VPN на том же сервере, где стоит сам VPN?

Нет, это касается и самой Uptime Kuma: если сервер ляжет целиком, упадёт и мониторинг вместе с VPN, и алерт просто не придёт. Панель Uptime Kuma должна стоять на отдельном сервере, а на VPN-сервере — только маленький скрипт-агент, который туда стучится.

Как часто запускать скрипт-проверку для Push-монитора?

Разумная отправная точка — раз в 1–2 минуты для скрипта и интервал Push-монитора в Kuma в 2–3 раза больше периода скрипта, чтобы один пропущенный запуск cron не превращался в ложную тревогу. Точные цифры зависят от того, насколько критична задержка обнаружения падения именно у вас.

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

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

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