VPN и SIEM: интеграция логирования для комплаенса
Аудитор или служба безопасности рано или поздно задаёт один и тот же вопрос: «покажите, кто подключался к VPN за последние три месяца и с каких адресов». Если ответ — «сейчас погрепаю файл на сервере, если его не успели ротировать» — это провал по любому чек-листу комплаенса, от внутреннего до PCI DSS. Разберём, как выгружать события VPN-подключений во внешнюю систему сбора логов (SIEM), чтобы они переживали компрометацию сервера, были доступны для расследования и не терялись при ротации.
Содержание
- Зачем логам VPN отдельный дом за пределами сервера
- Что отправлять в SIEM: набор событий, а не всё подряд
- Транспорт: rsyslog по TLS вместо plaintext UDP
- WireGuard: событий подключения нет, их нужно собрать самостоятельно
- Приём и разбор событий на стороне SIEM
- Алерты: что должно поднимать тревогу, а не просто попадать в архив
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Зачем логам VPN отдельный дом за пределами сервера
Локальный лог решает задачу диагностики: разработчик смотрит tail -f, находит ошибку, чинит конфиг. Для комплаенса и расследований этого недостаточно по трём причинам.
Во-первых, целостность: если сервер скомпрометирован, первое, что делает атакующий с минимальной квалификацией, — чистит локальные логи. Файл на диске сервера — не доказательство, если у того же процесса, который скомпрометирован, есть права на него переписать.
Во-вторых, срок жизни: logrotate с rotate 30 — это разумная гигиена для диагностики (см. статью про ротацию логов, чтобы не забивался диск), но для расследования инцидента, который вскрылся через два месяца, тридцати дней уже не хватит.
В-третьих, корреляция: событие «странное подключение к VPN в 3 ночи» само по себе ничего не значит. Оно значит много, если рядом на временной шкале видно попытку логина на файловый сервер с того же адреса. Такую корреляцию можно построить только в системе, которая видит логи со всех источников сразу, а не по одному серверу за раз.
SIEM (Wazuh, ELK/Elastic, Graylog, Splunk) закрывает все три пункта: логи копируются в момент события на отдельный хост, хранятся с заданной ретенцией независимо от локальной ротации, и по ним можно строить правила и алерты поперёк всей инфраструктуры.
Что отправлять в SIEM: набор событий, а не всё подряд
Для комплаенса нужен не полный дамп трафика, а конкретный набор событий подключения — тот же принцип минимизации, что описан в статье про логи VPN-подключений и что хранить по закону, просто теперь эти поля улетают не в локальный файл, а во внешнюю систему:
- время и факт установки/разрыва сессии;
- идентификатор клиента (CN сертификата, публичный ключ WireGuard, логин);
- исходный IP и порт;
- код результата — успех, TLS handshake failed, auth failure, истёкший или отозванный сертификат;
- объём трафика по сессии (агрегированно, не построчный дамп пакетов);
- используемый протокол/профиль (например, «менеджеры» vs «разработчики», если у вас разделение по OU в сертификатах).
Осознанно не включайте DNS-запросы клиентов и список посещённых через туннель адресов в SIEM-поток — это не событие подключения, а история поведения пользователя, и в общей системе, к которой имеет доступ вся команда безопасности, такие данные создают риск больше, чем пользу. Если для конкретного расследования нужна именно эта детализация — включайте её точечно и на ограниченный срок.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверТранспорт: rsyslog по TLS вместо plaintext UDP
Для OpenVPN самый надёжный способ не потерять события — не парсить лог-файл, а поручить пересылку rsyslog, который уже установлен почти на любом Linux-сервере. Сначала переключаем OpenVPN на системный syslog вместо отдельного файла:
# server.conf
# вместо log-append /var/log/openvpn/server.log
syslog openvpn-server
verb 3
Дальше в rsyslog фильтруем сообщения от этого тега и пересылаем их на SIEM отдельным правилом, не трогая остальной системный лог:
# /etc/rsyslog.d/30-openvpn-siem.conf
if $programname == 'openvpn-server' then {
action(
type="omfwd"
target="siem.internal.example"
port="6514"
protocol="tcp"
StreamDriver="gtls"
StreamDriverMode="1"
StreamDriverAuthMode="x509/name"
StreamDriverPermittedPeers="siem.internal.example"
queue.type="linkedList"
queue.filename="openvpn_siem_fwd"
queue.saveOnShutdown="on"
action.resumeRetryCount="-1"
)
stop
}
Порт 6514 и StreamDriver="gtls" — это RFC 5425 (syslog по TLS): события идут не открытым текстом по UDP 514, а по зашифрованному TCP-соединению с проверкой сертификата приёмника. Для комплаенс-требований почти всегда важно именно это — не только *что* логируется, но и что лог нельзя перехватить или подменить по дороге. Директивы queue.* спасают от потери событий, если SIEM временно недоступен: rsyslog буферизует их на диске и дошлёт после восстановления связи, вместо того чтобы тихо их выбросить, как это делает plaintext UDP по умолчанию.
WireGuard: событий подключения нет, их нужно собрать самостоятельно
WireGuard принципиально не пишет журнал сессий — это осознанное решение авторов протокола, минимизирующее логирование по умолчанию. Для комплаенса это означает, что события нужно генерировать самим, сравнивая состояние интерфейса во времени. Разберитесь сначала, зачем это вообще нужно на Windows-хостах — там та же проблема решена в статье про мониторинг VPN-подключений на Windows Server; на Linux принцип аналогичный, но реализация через cron и wg show:
#!/bin/bash
# /usr/local/bin/wg-session-log.sh
set -euo pipefail
INTERFACE=wg0
LOGFILE=/var/log/wireguard/sessions.log
STATE_DIR=/var/lib/wireguard-log
mkdir -p "$STATE_DIR"
wg show "$INTERFACE" dump | tail -n +2 | while read -r pubkey _psk endpoint _allowed latest_hs rx tx _keepalive; do
state_file="$STATE_DIR/${pubkey//\//_}"
prev_hs=$(cat "$state_file" 2>/dev/null || echo 0)
if [ "$latest_hs" != "0" ] && [ "$latest_hs" != "$prev_hs" ]; then
printf '{"ts":"%s","event":"handshake","interface":"%s","peer":"%s","endpoint":"%s","rx":%s,"tx":%s}\n' \
"$(date -Iseconds)" "$INTERFACE" "$pubkey" "$endpoint" "$rx" "$tx" >> "$LOGFILE"
echo "$latest_hs" > "$state_file"
fi
done
Ставим в cron раз в минуту (* * * * * /usr/local/bin/wg-session-log.sh), получаем построчный JSON-лог событий handshake, который дальше отправляем в SIEM тем же способом, что и файл OpenVPN — через imfile в rsyslog или через отдельный шиппер вроде Vector/Filebeat, если вы уже используете его для остальной инфраструктуры (например, для метрик, как в статье про Grafana Loki на VPS). Разрешение в минуту — компромисс: точнее секундного handshake WireGuard не отдаёт сам по себе, а более грубый интервал уже теряет короткие сессии.
Приём и разбор событий на стороне SIEM
Сама пересылка — половина дела; вторая половина — чтобы SIEM понимал, что за событие пришло, а не складывал его в общий текстовый мусор. В Wazuh это делается через localfile в ossec.conf на агенте плюс декодер/правило на менеджере:
<!-- /var/ossec/etc/ossec.conf на агенте -->
<localfile>
<log_format>syslog</log_format>
<location>/var/log/openvpn/server.log</location>
</localfile>
<localfile>
<log_format>json</log_format>
<location>/var/log/wireguard/sessions.log</location>
</localfile>
JSON-формат для WireGuard разбирается «из коробки» без написания декодера — поля peer, endpoint, event сразу становятся полями события в Wazuh. Для OpenVPN потребуется декодер под конкретный формат строки (в сообществе Wazuh такие уже есть, писать с нуля обычно не нужно, но проверьте версии — синтаксис строк OpenVPN немного отличается между релизами).
Если у вас Graylog, тот же путь — вход через GELF или Syslog input на порту 6514 с TLS-транспортом, а извлечение полей делается через встроенный Grok-экстрактор или через pipeline rules на Graylog Query Language. Для ELK/Elastic — аналогично через Filebeat с модулем или через Logstash grok-фильтр перед индексацией в Elasticsearch.
Краткое сравнение трёх типичных вариантов для небольшой/средней инфраструктуры:
| SIEM | Стоимость | Порог входа | Когда имеет смысл |
|---|---|---|---|
| Wazuh | Open source, self-hosted | Средний | Уже есть XDR-задачи (файловая целостность, уязвимости), логи VPN — часть общей картины |
| Graylog | Open source (community) / платная Enterprise | Низкий-средний | Нужен именно сбор и поиск по логам без лишней функциональности |
| ELK/Elastic | Open source ядро, платные фичи в X-Pack | Средний-высокий | Уже есть Elasticsearch в инфраструктуре, большие объёмы |
Все три варианта разворачиваются на отдельном VPS — держать SIEM на том же сервере, что и сам VPN, бессмысленно: при компрометации VPN-хоста атакующий получит доступ и к приёмнику логов.
Алерты: что должно поднимать тревогу, а не просто попадать в архив
Собранные логи бесполезны, если на них никто не смотрит до момента расследования постфактум. Минимальный набор правил, который стоит завести поверх потока событий VPN:
- Всплеск auth failure с одного IP или сертификата — признак перебора или неправильно сконфигурированного клиента, который долбит сервер повторными попытками.
- Подключение сертификата, помеченного как отозванный (
CRLreject в логе) — либо забыли отозвать клиента у уволенного сотрудника на роутере, либо кто-то использует старую копию ключа. - «Невозможное перемещение»: один и тот же идентификатор подключается с двух географически далёких IP в пределах короткого окна — либо ключ скомпрометирован и используется параллельно, либо это одновременная сессия с VPN и без него, что тоже стоит проверить.
- Подключения вне рабочего окна, если профиль клиента подразумевает работу по расписанию (например, подрядчик с доступом только по будням).
- Долгое отсутствие handshake у ожидаемо активного peer'а WireGuard — это не угроза безопасности, а сигнал о том, что сам сбор логов, возможно, сломался, и стоит проверить cron-задачу из предыдущего раздела.
В Wazuh такие правила описываются XML-блоком с условием на frequency и timeframe поверх уже разобранных событий; в Graylog — через Alert Conditions на сохранённом поиске. Не пытайтесь сразу покрыть все пять пунктов — начните с всплеска ошибок аутентификации и невозможного перемещения, это два правила, которые чаще всего реально ловят что-то полезное, а не просто генерируют шум.
Арендуйте сервер под свои задачи!
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Обязательно ли использовать именно SIEM, или достаточно центрального лог-сервера вроде Loki?
Для чистого мониторинга доступности и агрегированных метрик Loki вполне достаточно и заметно легче в эксплуатации. SIEM нужен, когда требуется корреляция между источниками, готовые правила детекции и хранение с контролем целостности именно под задачи безопасности и аудита — это разные инструменты для разных вопросов.
Что если SIEM временно недоступен — теряются ли события за это время?
При корректной настройке queue.* в rsyslog (пример выше) события буферизуются на диске отправителя и досылаются после восстановления связи. Проверьте на тесте: остановите SIEM-приёмник на пару минут, сгенерируйте тестовые подключения, поднимите приёмник обратно и убедитесь, что события дошли, а не потерялись молча.
Нужно ли хранить логи в SIEM бессрочно ради комплаенса?
Нет — ретенция задаётся политикой хранения, а не техническим ограничением SIEM. Разумная практика — синхронизировать срок хранения в SIEM с тем, что вы определили для локальных логов (см. статью про логи VPN и хранение по закону), а не оставлять «навсегда по умолчанию», просто потому что диска хватает.
Как быть с сертификатами клиентов при многопользовательской конфигурации Easy-RSA — их тоже видно в SIEM?
Да, CN сертификата из связки Easy-RSA попадает в событие как идентификатор клиента — это нужно для того самого «кто подключался», ради которого всё затевалось. Если сертификаты выданы по отделам или ролям, стоит сразу завести это как отдельное поле при парсинге, а не доставать регуляркой из свободного текста при каждом расследовании.
Реально ли всё это поднять на одном небольшом VPS для маленькой команды?
Да — Graylog или Wazuh в минимальной конфигурации спокойно работают на отдельном сервере с несколькими гигабайтами памяти при потоке в десятки-сотни событий VPN в день; для такого объёма это не про масштаб Splunk-инсталляции в крупной компании, а про дисциплину «логи живут не там же, где сервис».
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →