
AppSecFest — это ежегодное событие, где вы можете познакомиться с миром кибербезопасности и узнать больше о событиях и решениях используемых многими компаниями уже сейчас.
На данном мероприятии наша команда mimicats выступала в роли организаторов и мы решили разбавить выступления спикеров и презентации решений более практическими и интересными заданиями.
Нами было сделано Play Zone, где участвуя в интерактивных играх и квизах связанных с кибербезопасностью вы могли заработать коины для покупки эксклюзивного мерча.
А также мы решили простроить целую инфраструктуру для данного мероприятия и проведения локального соревнования, где приняли участие как и уже бывалые ИБ-шники, так и совсем зеленные новички.
Дальше уже пойдет больше про то, что было сделано, а также вектор в котором мы двигались при построении данной инфраструктуры.
План статьи:
1) Архитектура проекта и немного воды
2) Настройка OpenVPN
3) Телеграм ботыы
4) CTFd
5) Wazuh
6) Zabbix
Архитектура проекта:

Основной идеей у нас было создать безопасную систему, в который участники могли бы комфортно решать задания и мы видели если бы они совали носы куда не стоит)
И стоит заметить, что тут скорее не про то как НУЖНО делать, а про то как видели и хотели сделать мы.
OpenVPN
Важная часть инфры, так как нам надо было ограничить доступ к нашим заданиям как можно сильнее и контролировать как можно больше.
Было поднято 2 Openvpn
1) Для обычных юзеров без авторизации - доступ к веб таскам и CTFd
2) Для админов с авторизацей - доступ к SIEM(Wazuh), Zabbix, веб таскам и CTFd по ssh
sudo apt update sudo apt install openvpn easy-rsa make-cadir ~/openvpn-ca cd ~/openvpn-ca ./easyrsa init-pki ./easyrsa build-ca # задайте имя и пароль CA ./easyrsa gen-req server_non_auth nopass ./easyrsa sign-req server server_non_auth ./easyrsa gen-req server_auth nopass ./easyrsa sign-req server server_auth ./easyrsa gen-dh openvpn --genkey secret ta.key
Затем настройка конфигов
для юзеров:
nano /etc/openvpn/server/server_non_auth.conf port 1194 proto udp dev tun topology subnet ; Пути к сертификатам и ключам ca /etc/openvpn/ca.crt cert /etc/openvpn/server_non_auth.crt key /etc/openvpn/server_non_auth.key dh /etc/openvpn/dh.pem ; tls-auth /etc/openvpn/ta.key 0 # Разрешаем запуск скриптов script-security 3 # Подключаем скрипт, который будет вызываться при каждом входящем подключении client-connect /etc/openvpn/scripts/
client-connect.sh
; Задаём основной пул IP (например, 10.10.10.0/24) server 10.10.10.0 255.255.255.0 ifconfig-pool-persist /etc/openvpn/ipp_non_auth.txt ; Раздача маршрута для доступа к сети 192.168.52.0/24 push "route 192.168.52.0 255.255.255.0" keepalive 10 120 cipher AES-256-CBC persist-key persist-tun status /var/log/openvpn_non_auth_status.log verb 3
client-connect /etc/openvpn/scripts/
client-connect.sh
- данная часть кода нужна для того чтобы выполнялся скрипт
client-connect.sh
при каждом подключении клиента #!/bin/bash # /etc/openvpn/scripts/
client-connect.sh
LOGFILE="/var/log/openvpn-client-connect.json" # Получаем метку времени timestamp=$(date '+%Y-%m-%dT%H:%M:%S%z') # Формируем JSON-строку json="{\"timestamp\":\"${timestamp}\",\ \"event\":\"client-connect\",\ \"common_name\":\"${common_name}\",\ \"untrusted_ip\":\"${untrusted_ip}\",\ \"untrusted_port\":\"${untrusted_port}\",\ \"vpn_ip\":\"${ifconfig_pool_remote_ip}\"}" echo "${json}" >> "${LOGFILE}" exit 0
Данный скрипт нужен для логирования подключении пользователей для передачи их в нашу SIEM.
Это позволяло нам удобно следить за тем, кто и когда подключался.
В итоге получаем логи в формате json для удобной передачи в Wazuh
[root@vpn-rocky openvpn]# cat /var/log/openvpn-client-connect.json
{"timestamp":"2025-04-22T19:21:21+0000","event":"client-connect","common_name":"client1","untrusted_ip":"176.64.21.98","untrusted_port":"27086","vpn_ip":"10.10.10.4"}
{"timestamp":"2025-04-23T00:25:10+0500","event":"client-connect","common_name":"client1","untrusted_ip":"176.64.21.98","untrusted_port":"29515","vpn_ip":"10.10.10.4"}
для админов
Такая же конфигурации но только выдача админам IP из подсети 10.69.69.0/24 для доступа к админской подсети 192.168.69.0/24
Также добавили авторизацию. Авторизация происходить через проверку логина/пароля через PAM.

Далее идет настройка сети для того чтобы юзеры могли получить доступ к внутренней сети с помощью ВПН.
Телеграм боты
Надо было как можно лучше автоматизировать все возможные процессы, так как количество людей у нас было ограничено и для каждого действия выделять людей нам не хотелось.
Автоматизировать мы решили следующие процессы:
1. Выдача доступов.
2. Поддержка
3. Озвучка First Blood'ов
Бот для раздачи данных, кредов и openvpn файлов для доступа к CTFd и таскам
Сделать так чтобы одной командой участник мог получить все доступы, было легко.
Однако, надо было сделать так, чтобы этот же пользователь не мог получить доступы для еще одной учетки, для этого мы решили чтобы бот собирал user_id
и приписывал их для каждой пары логин, пароль+vpn конфиг.
По итогу простенький бот, но который сильно помог нам с выдачей доступов, ведь поток людей был на протяжении всего соревнования.
Пример работы:

2. Support bot
Обработка запросов участников это одна из неотъемлемых частей любой СТФки, поэтому тут я решил просто облегчить работу админам, человек создавал запросы через телеграм:

А мы обрабатывали их в отдельном мессенджере:


3. First Blood
Вот тут было сложно придумать как реализовать автоматическую озвучку всех First Blood-ов
Так как у нас был отдельный VPN, я решил со своего ноута подключить SSH тунель до сервера с CTFd.
Таким образом, чтобы при обращении на сервере CTFd на localhost:6000 этот запрос обращался на localhost:5000 моего ноута.
Команда для подключения(с моего ноута):ssh -4 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -R 127.0.0.1:6000:127.0.0.1:5000 user@{ctfd_ip}

Как происходит озвучка First Blood:
https://drive.google.com/drive/folders/1qaVZQR3AvCD5d4CztWlri06cCkHjBixr?usp=sharing
CTFd
Разворачивание CTFd было стандартное с контейнера, но решили сделать свой дизайн под эту сореву.




SIEM Wazuh: Логирование, трафик и безопасность
В дополнение к всей системе мы приняли решение развернуть SIEM-решение для централизованного сбора логов, анализа сетевого трафика и контроля VPN-соединений. В качестве основы был выбран open-source стек Wazuh, обладающий широкими возможностями по корреляции событий и интеграции с Elastic Stack.
Компоненты и архитектура
Wazuh agent — установлен на всех целевых серверах для сбора системных логов и событий безопасности.
Packetbeat — отвечает за сбор сетевого трафика, включая протоколы уровня приложений.
Filebeat — используется для отправки нестандартных и кастомных логов, в основном с VPN-сервера.
Logstash — принимает, обрабатывает и передаёт данные в OpenSearch (или Elasticsearch).
? Мониторинг VPN-трафика через Packetbeat
На хосте с VPN-сервером был установлен Packetbeat. Конфигурация направлена на отслеживание ключевых протоколов (HTTP, TLS, DNS, PostgreSQL, MongoDB и др.) и фильтрацию по внутренним IP-диапазонам.
Фрагмент packetbeat.yml
:
packetbeat.interfaces.device: any packetbeat.interfaces.poll_default_route: 1m packetbeat.interfaces.internal_networks:
- private
packetbeat.flows:
timeout: 30s
period: 10s
packetbeat.protocols:
- type: icmp
enabled: true
- type: http
include_body_for: ["application/json", "text/html", "application/xml"]
ports: [80, 8080, 8000, 5000, 8002,8088]
send_headers: true
send_all_headers: true
send_request: true
send_response: true
- type: tls
ports:
- 443
- 993
- 995
- 5223
- 8443
- 8883
- 9243
- type: dns
ports: [53]
- type: mysql
ports: [3306, 3307]
- type: pgsql
ports: [5432]
- type: redis
ports: [6379]
- type: mongodb
ports: [27017]
- type: memcache
ports: [11211]
- type: thrift
ports: [9090]
- type: nfs
ports: [2049]
- type: cassandra
ports: [9042]
- type: amqp
ports: [5672]
- type: dhcpv4
ports: [67, 68]
- type: sip
ports: [5060]
setup.template.settings:
index.number_of_shards: 1
processors:
- drop_event.when.not.or:
- network.source.ip: "10.69.69.0/24"
- network.source.ip: "10.10.10.0/24"
- drop_fields:
fields:
- host.hostname
- host.name - host.architecture - host.os.* - host.containerized - cloud - ecs - agent - docker - container - related - tags - input - service - event.dataset - event.kind - user_agent.device - url.query - status - status_phrase - http.request.headers - http.response.headers output.logstash: hosts: ["192.168.69.140:5000"]
? Сбор логов OpenVPN через Filebeat
Для мониторинга активности OpenVPN были настроены отдельные inputs в filebeat.yml
, включая статус-подключения, аутентификацию и клиентские события.
Пример конфигурации:
[rockylinux@vpn-rocky filebeat]$ sudo cat filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/openvpn.log fields: category: openvpn log_type: main - type: log enabled: true paths: - /var/log/openvpn_auth_status.log fields: category: openvpn log_type: auth - type: log enabled: true paths: - /var/log/openvpn_non_auth.log fields: category: openvpn log_type: non_auth - type: log enabled: true paths: - /var/log/openvpn-client-connect.log fields: category: openvpn log_type: connect - type: log enabled: true paths: - /var/log/openvpn_non_auth_status.log fields: category: openvpn log_type: non_auth_status - type: log enabled: true paths: - /var/log/openvpn-client-connect.json json.keys_under_root: true json.add_error_key: true fields: category: openvpn log_type: client_connect output.logstash: hosts: ["192.168.69.140:5000"]
? Обработка и маршрутизация логов в Logstash
Logstash принимает данные от Beat-агентов, фильтрует их, парсит JSON (если требуется) и перенаправляет в нужные индексы OpenSearch.
Основные моменты:
Разделение логов по категориям (openvpn, packetbeat и пр.).
Создание индексов по шаблону:
openvpn-auth-2025.05.13
,packetbeat-logs-2025.05.13
и т.п.Частичная очистка полей (mutate/remove_field) для упрощения структуры документа.
Фрагмент output-конфига:
root@wazuh-zabbix:/etc/logstash/conf.d# cat wazuh-opensearch.conf input { beats { port => 5000 ssl => false } } filter { if [fields][log_type] == "json_connect" { json { source => "message" skip_on_invalid_json => true } date { match => ["timestamp", "ISO8601"] target => "@timestamp" timezone => "UTC" } } if [@metadata][beat] == "filebeat" { mutate { remove_field => [ "@version", "[agent]", "ecs.version", "[host][name]", "[input][type]", "[log]", "tags" ] } } } output { if [@metadata][beat] == "filebeat" and [fields][category] == "openvpn" { opensearch { hosts => ["
https://localhost:9200
"] index => "openvpn-%{[fields][log_type]}-%{+
YYYY.MM
.dd}" user => "admin" password => "wazuhpassword" ssl => true ssl_certificate_verification => false } } else if [@metadata][beat] == "filebeat" { opensearch { hosts => ["
https://localhost:9200
"] index => "submissions" user => "admin" password => "wazuhpassword" ssl => true ssl_certificate_verification => false } } else if [@metadata][beat] == "packetbeat" { opensearch { hosts => ["
https://localhost:9200
"] index => "packetbeat-logs-%{+
YYYY.MM
.dd}" user => "admin" password => "R.z9oDh6j9paU5UYlYtH*MKQ+IoUMUWR" ssl => true ssl_certificate_verification => false } } }
Создание кастомных правил и декодеров в Wazuh для анализа специфических форматов логов (в т.ч. OpenVPN).

Создание кастомных индексов в OpenSearch для изоляции логов по источнику и типу события.


Разработка простых дашбордов в Wazuh Dashboards для визуального анализа активности.




Zabbix + Grafana: Контроль нагрузки на сеть и серверы
Последним этапом нашей работы стал контроль за нагрузкой на сеть и серверы. Для сбора метрик использовалась система мониторинга Zabbix, а визуализация данных осуществлялась с помощью Grafana.

Особое внимание было уделено параметрам сетевого трафика. Для предотвращения перегрузки сети мы ограничили скорость каждого клиента. Это позволило избежать узких мест и обеспечить стабильную работу всей системы при высоких нагрузках.

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

По итогу хотелось бы еще раз подчеркнуть, что это всё это наш опыт в построении и администрировании инфраструктуры.
Мы надеемся, что наш подход и решения окажутся полезными для тех, кто также работает над созданием устойчивой и прозрачной системы мониторинга.
YX1978
Вот это совпадение, случаянно наткнулся) Классная статья, интересно кто же из команды её написал? Жаль не удалось поучавствовать в этот раз)