server_maul_hard: TURN и WireGuard¶
Эта страница описывает фактически развёрнутые сетевые сервисы
server_maul_hard: TURN для WebRTC и центральный Linux WireGuard-хаб для связи
бортового и операторского MikroTik.
Текущее состояние
На 30 октября 2026 года TURN работает в Docker. Интерфейс WireGuard
поднят и слушает публичный UDP-порт. Добавлен первый клиент с адресом
10.77.0.10/32; peers бортового и операторского MikroTik ещё не
добавлены: для этого нужны их публичные ключи и точные маршрутизируемые
подсети.
Роль сервера¶
server_maul_hard — публичный узел в дата-центре Hetzner. Он решает две разные
задачи:
| Сервис | Назначение |
|---|---|
| WireGuard | Соединяет сети НРК и оператора, даже если обе стороны находятся за Starlink/LTE CGNAT |
| TURN | Ретранслирует WebRTC-медиатрафик, когда браузер и видеоисточник не могут установить прямое соединение |
TURN и WireGuard независимы. Отказ или отсутствие TURN не разрывает VPN, а наличие TURN не создаёт маршрута к локальным сетям НРК.
Основные параметры сервера:
| Параметр | Значение |
|---|---|
| Публичный IPv4 | 136.243.89.142 |
| ОС | Ubuntu Server 26.04 LTS, x86-64 |
| TURN DNS | turn.136-243-89-142.sslip.io |
| WireGuard endpoint | 136.243.89.142:13231/udp |
| WireGuard VPN-сеть | 10.77.0.0/24 |
Карта файловой системы¶
Ниже перечислены основные каталоги server_maul_hard, относящиеся к Maul,
документации, WireGuard, TURN и публикации сервисов. Это не полный список
файлов Ubuntu, а эксплуатационная карта проекта.
server_maul_hard
├── /srv/maul/ исходники Maul и документации
│ ├── docs/ исходные Markdown-страницы MkDocs
│ ├── mkdocs.yml навигация и настройки MkDocs
│ ├── requirements-docs.txt зафиксированные зависимости документации
│ ├── .mkdocs-venv/ Python-окружение MkDocs
│ ├── site/ сгенерированный публичный сайт
│ ├── cfmoto-pixhawk-dashboard/ исходники и venv панели управления
│ ├── ardupilot/ отдельный репозиторий ArduPilot
│ ├── cfmoto-gearbox-telemetry/ отдельный репозиторий телеметрии КПП
│ ├── cfmoto-steering-controller/ отдельный репозиторий рулевого контроллера
│ └── backups/ резервные параметры и результаты проверок
│
├── /opt/borsuk-turn/ управляемый проект TURN
│ ├── compose.yaml описание контейнера Coturn
│ ├── runtime/turnserver.conf активная конфигурация внутри контейнера
│ ├── configure.py подготовка runtime-конфигурации
│ ├── probe.py проверка TURN
│ └── renew-cert.sh обновление файлов сертификата
│
├── /etc/borsuk-turn/ защищённые runtime-файлы TURN
│ ├── auth-secret общий секрет аутентификации
│ ├── fullchain.pem цепочка TLS-сертификата
│ └── privkey.pem закрытый TLS-ключ
│
├── /etc/systemd/network/ постоянная конфигурация WireGuard
│ ├── 70-wg-maul.netdev интерфейс, порт, ключ и peers
│ └── 70-wg-maul.network VPN-адрес и IP forwarding интерфейса
├── /etc/wireguard/ ключи WireGuard-сервера
│ ├── maul-server.key закрытый ключ
│ └── maul-server.pub публичный ключ
├── /etc/sysctl.d/
│ └── 90-maul-wireguard.conf постоянный IPv4 forwarding
│
├── /etc/nginx/ публикация MkDocs, dashboard и TURN TLS
│ ├── sites-available/ конфигурации виртуальных хостов
│ ├── sites-enabled/ ссылки на активные сайты
│ └── stream-borsuk.conf SNI-маршрутизация TCP/443
├── /etc/letsencrypt/ сертификаты и правила Certbot
│ ├── live/ стабильные ссылки на актуальные сертификаты
│ ├── archive/ версии сертификатов
│ ├── renewal/ параметры продления
│ └── renewal-hooks/deploy/
│ └── borsuk-turn обновление сертификата Coturn после renew
├── /etc/systemd/system/
│ └── maul-dashboard.service запуск dashboard на 127.0.0.1:8766
├── /etc/ufw/ постоянные правила firewall
├── /var/lib/docker/ внутренние данные Docker — вручную не править
└── systemd journal рабочие журналы сервисов
/srv/maul: рабочее дерево проекта¶
/srv/maul — канонический каталог Maul. Основные правила работы:
- страницы редактируются в
/srv/maul/docs, а навигация — в/srv/maul/mkdocs.yml; /srv/maul/siteявляется результатом сборки, поэтому вручную его не редактируют;- строгая проверка выполняется из
/srv/maulкомандой.mkdocs-venv/bin/mkdocs build --strict; - nginx публикует именно
/srv/maul/site; - каталоги
ardupilot,cfmoto-gearbox-telemetryиcfmoto-steering-controller— самостоятельные репозитории: изменения в одном из них не следует смешивать с документацией; - временные каталоги и файлы с
backupв имени являются снимками перед изменениями, но не заменяют внешнюю резервную копию сервера.
Dashboard запускается unit-файлом
/etc/systemd/system/maul-dashboard.service от непривилегированного
пользователя maul-dashboard. Его рабочий каталог —
/srv/maul/cfmoto-pixhawk-dashboard, а listener доступен только локально на
127.0.0.1:8766; наружу запросы пропускает nginx.
/opt/borsuk-turn: управляемый TURN-проект¶
Контейнер borsuk-turn-coturn-1 создаётся из
/opt/borsuk-turn/compose.yaml. Каталог
/opt/borsuk-turn/runtime монтируется в контейнер как /etc/coturn только
для чтения. Защищённые файлы из /etc/borsuk-turn также передаются в
контейнер read-only.
Файлы /etc/turnserver.conf и /etc/default/coturn относятся к старому
host-варианту Coturn. Активный TURN работает в Docker, поэтому эти файлы не
следует принимать за текущую конфигурацию или запускать параллельно с
контейнером.
Секретные файлы
Нельзя выводить, копировать в документацию или коммитить содержимое
/etc/borsuk-turn/auth-secret, /etc/borsuk-turn/privkey.pem,
/etc/wireguard/maul-server.key, /opt/borsuk-turn/.env и закрытые
ключи из других конфигураций. Для диагностики обычно достаточно имён,
владельцев, прав доступа и публичных ключей.
/etc: конфигурация хоста¶
Конфигурация WireGuard разделена по назначению:
| Путь | Что хранится | Чем применяется |
|---|---|---|
/etc/systemd/network/70-wg-maul.netdev |
параметры wg-maul и peers |
systemd-networkd |
/etc/systemd/network/70-wg-maul.network |
адрес 10.77.0.1/24 и forwarding |
systemd-networkd |
/etc/wireguard/maul-server.key |
приватный ключ сервера | WireGuard через .netdev |
/etc/wireguard/maul-server.pub |
публичный ключ сервера | выдаётся клиентам |
/etc/sysctl.d/90-maul-wireguard.conf |
глобальный IPv4 forwarding | systemd-sysctl |
/etc/ufw/user.rules |
скомпилированные IPv4-правила UFW | UFW |
Nginx использует схему sites-available → sites-enabled. Включены сайты
документации, dashboard и ACME challenge. Отдельный
/etc/nginx/stream-borsuk.conf распределяет TLS-соединения на порту 443 по
SNI между HTTPS и TURN.
Где смотреть журналы¶
Основные сервисы пишут в systemd journal или Docker logging driver:
# WireGuard и создание интерфейса
journalctl -u systemd-networkd --since today
# Dashboard
journalctl -u maul-dashboard --since today
# Nginx
journalctl -u nginx --since today
# TURN
cd /opt/borsuk-turn
docker compose logs --tail=100 coturn
Для текущего состояния журнала не требуется искать отдельный
wireguard.log: handshake и счётчики проверяются командой
wg show wg-maul. TURN-логи могут содержать клиентские IP и идентификаторы, поэтому
перед передачей их нужно маскировать.
Что резервировать¶
Минимальный набор для восстановления инфраструктуры:
/srv/maul/docs,/srv/maul/mkdocs.ymlи/srv/maul/requirements-docs.txt;/opt/borsuk-turn, кроме временных runtime-артефактов, с отдельной защищённой копией секретов;/etc/borsuk-turn,/etc/systemd/network/70-wg-maul.*,/etc/wireguardи/etc/sysctl.d/90-maul-wireguard.conf;- активные nginx-, UFW- и systemd-конфигурации;
- репозитории и необходимые параметры оборудования из
/srv/maul/backups.
Секреты в резервной копии должны быть зашифрованы. Каталоги
/srv/maul/site, .mkdocs-venv и /var/lib/docker можно восстановить из
исходников и декларативных конфигураций, поэтому они не являются главным
источником истины.
Общая схема¶
СЕТЕВОЙ КОНТУР
Бортовой RB5009UPr ── исходящий WireGuard ──┐
│
server_maul_hard
10.77.0.1
│
Операторский RB5009UG ─ исходящий WireGuard ┘
МЕДИАКОНТУР WEBRTC
видеоисточник / MediaMTX ───── прямое соединение ───── браузер
│ │
└──── TURN fallback через server_maul_hard ──────┘
WireGuard¶
Зачем нужен центральный хаб¶
Обычные тарифы Starlink и многие мобильные операторы используют CGNAT. Входящее соединение к операторскому или бортовому MikroTik в этом случае невозможно. Центральный сервер имеет публичный адрес, а оба MikroTik сами подключаются к нему исходящими UDP-соединениями.
борт → интернет → server_maul_hard ← интернет ← оператор
Развёрнутые параметры¶
| Параметр | Значение |
|---|---|
| Linux-интерфейс | wg-maul |
| Endpoint | 136.243.89.142:13231 |
| Протокол | WireGuard, UDP |
| Адрес сервера в VPN | 10.77.0.1/24 |
| Public key сервера | 08WVMsOYsbIclgxlHcb71ZJV49+G8oLiz7MAbYG9kkQ= |
| Peers | один клиент: 10.77.0.10/32; MikroTik ещё не добавлены |
Планируемая адресация пилота:
| Участник | VPN-адрес |
|---|---|
server_maul_hard |
10.77.0.1 |
| MikroTik оператора | 10.77.0.2 |
| MikroTik НРК Maul 94 | 10.77.0.94 |
Адреса бортовых VLAN, например 192.168.94.0/24, добавляются в
AllowedIPs соответствующего peer только после подтверждения фактической
адресации. Одинаковые подсети разных НРК использовать нельзя.
Как проходит пакет¶
Пример обращения оператора к бортовой камере:
ПК оператора
│
RB5009UG
│ WireGuard
▼
server_maul_hard
│ маршрутизация по AllowedIPs
▼
RB5009UPr
│ Camera VLAN
▼
камера
На server_maul_hard не выполняется NAT между WireGuard peers. Сервер
маршрутизирует пакеты, а обратные маршруты должны быть известны обоим
MikroTik.
Конфигурация на сервере¶
WireGuard управляется systemd-networkd:
| Файл | Назначение |
|---|---|
/etc/systemd/network/70-wg-maul.netdev |
создание интерфейса и UDP listener |
/etc/systemd/network/70-wg-maul.network |
адрес 10.77.0.1/24 и forwarding |
/etc/sysctl.d/90-maul-wireguard.conf |
системное разрешение IPv4 forwarding |
/etc/wireguard/maul-server.key |
закрытый ключ сервера, защищённый файл |
/etc/wireguard/maul-server.pub |
публичный ключ сервера |
Закрытые ключи
Приватный ключ сервера и приватные ключи MikroTik нельзя добавлять в MkDocs, Git, экспорт для пересылки или сообщения. Для регистрации peer используется только его публичный ключ.
Добавление peer¶
Для каждого MikroTik необходимо:
- создать новый WireGuard-интерфейс и уникальную пару ключей;
- получить только публичный ключ MikroTik;
- добавить публичный ключ и уникальные
AllowedIPsнаserver_maul_hard; - добавить public key сервера и endpoint
136.243.89.142:13231на MikroTik; - установить
persistent-keepalive=25sдля работы через CGNAT; - проверить handshake, VPN-адреса и маршруты до нужных VLAN;
- только после этого разрешать прикладной трафик firewall-правилами.
Firewall¶
На публичном интерфейсе открыт только WireGuard-порт 13231/udp. UFW
разрешает пересылку трафика wg-maul → wg-maul; доступ определяется
криптографическими peer-ключами и AllowedIPs.
Нельзя добавлять общий peer с AllowedIPs=0.0.0.0/0 на сервере: он
перехватит маршруты других НРК. Каждому peer назначаются только его VPN-адрес
и принадлежащие ему LAN/VLAN-подсети.
TURN¶
Что делает TURN¶
TURN используется как fallback для WebRTC. Если прямой UDP-путь между видеоисточником и браузером не создаётся из-за NAT или firewall, оба клиента соединяются с TURN, а сервер ретранслирует медиапакеты.
видеоисточник → TURN → браузер оператора
TURN:
- не преобразует RTSP в WebRTC;
- не захватывает видео с камеры;
- не заменяет MediaMTX/Janus или другой медиашлюз;
- не заменяет WireGuard;
- расходует серверный трафик на каждый ретранслируемый поток.
Реализация¶
Фактический TURN работает в Docker Compose:
| Параметр | Значение |
|---|---|
| Каталог | /opt/borsuk-turn |
| Compose-файл | /opt/borsuk-turn/compose.yaml |
| Контейнер | borsuk-turn-coturn-1 |
| Образ | coturn/coturn:4.18.0-r0-debian |
| Сеть контейнера | host network |
| Restart policy | unless-stopped |
| TURN realm | turn.136-243-89-142.sslip.io |
| Relay ports | UDP 49160–49260 |
Контейнер работает с read-only filesystem, без дополнительных Linux
capabilities кроме NET_BIND_SERVICE, с no-new-privileges. Конфигурация и
TLS-файлы монтируются внутрь контейнера только для чтения.
Стандартный host-unit coturn.service выключен. Это ожидаемо: нельзя
одновременно запускать host Coturn и Docker Coturn на одних портах.
Аутентификация¶
Coturn использует long-term credentials на основе общего auth secret. Клиент получает короткоживущие TURN credentials от доверенного аутентифицированного API. Общий secret хранится в защищённой runtime- конфигурации и не публикуется.
Нельзя прописывать общий TURN secret в браузерный JavaScript, мобильное приложение или публичный репозиторий.
Порты TURN¶
| Порт | Протокол | Назначение |
|---|---|---|
3478 |
UDP/TCP | STUN/TURN listener |
443 |
TCP/TLS | рекомендуемый TURN TLS через nginx stream/SNI |
5349 |
TCP/TLS | прямой TURN TLS listener |
49160–49260 |
UDP | relay-порты медиатрафика |
80 |
TCP | только ACME HTTP challenge для сертификата |
В конфигурации включён no-tcp-relay: клиент может подключиться к TURN по
TCP/TLS, но медиатрафик от TURN к peer ретранслируется по UDP.
TLS на порту 443¶
Порт 443/tcp принимает nginx stream с ssl_preread. По SNI nginx
разделяет соединения:
docs.136-243-89-142.sslip.ioиdashboard.136-243-89-142.sslip.ioнаправляются на внутренний HTTPS;- TURN TLS направляется на Coturn
127.0.0.1:5349; - TLS завершается в Coturn, nginx передаёт TCP без расшифровки.
Сертификат Let's Encrypt выпущен для
turn.136-243-89-142.sslip.io. certbot.timer проверяет обновление, а deploy
hook копирует обновлённые файлы в /etc/borsuk-turn и перезапускает только
Coturn-контейнер.
TURN и WireGuard: когда что используется¶
| Ситуация | WireGuard | TURN |
|---|---|---|
| Управление MikroTik | да | нет |
| Доступ к камере по её VPN/LAN-адресу | да | нет |
| Телеметрия и команды НРК | да | нет |
| Прямой WebRTC работает | возможно | нет |
| WebRTC не проходит NAT/firewall | возможно | да |
| RTSP необходимо преобразовать в WebRTC | нет | нет — нужен медиашлюз |
Предпочтительный порядок для видео:
- прямой WebRTC-путь;
- прямой медиапуть через WireGuard;
- TURN только как fallback.
Это уменьшает задержку и не пропускает каждый видеопоток через публичный сервер без необходимости.
Диагностика¶
WireGuard¶
wg show wg-maul
networkctl status wg-maul
ss -lunp | grep 13231
Рабочий peer должен показывать свежий latest handshake и растущие счётчики
transfer. Наличие listener само по себе не подтверждает связь с MikroTik.
TURN¶
cd /opt/borsuk-turn
docker compose ps
docker compose logs --tail=50 coturn
Проверка открытого порта или TLS-сертификата недостаточна. Полная проверка TURN должна создать аутентифицированную allocation и передать тестовые пакеты через relay-порт.
Журналы
TURN-логи могут содержать IP-адреса клиентов и идентификаторы временных credentials. Их нельзя публиковать целиком без маскировки.
Текущее ограничение и развитие¶
Сейчас server_maul_hard является единственной публичной точкой WireGuard и
TURN. Для пилота это допустимо, но сервер остаётся единой точкой отказа.
Перед production необходимо:
- развернуть второй WireGuard-хаб в другом дата-центре;
- настроить два endpoint на каждом MikroTik;
- проверить переключение Starlink/LTE и основного/резервного VPN-хаба;
- добавить мониторинг handshake age, packet loss и трафика;
- контролировать суммарную полосу TURN при нескольких видеопотоках;
- выполнять тест восстановления из защищённой резервной копии.