Настройка классических TURN серверов часто превращается в работу "вслепую" администратору приходится ставить сторонние пакеты, вручную проверять прохождение UDP пакетов через NAT и гадать, сколько одновременных видеозвонков выдержит виртуальная машина.
В бинарный файл Slyber Turn Server встроены два профессиональных CLI инструмента, которые закрывают все задачи по проверке и профилированию сервера без установки внешних зависимостей:
slyber_turn doctor- автоматический сканер конфигурации, сетевых портов, правил NAT и работоспособности TURN-аллокаций.slyber_turn bench(илиbenchmark) - многопоточный генератор WebRTC подобного медиа трафика с расчетом пропускной способности, потерь пакетов, круговой и односторонней задержки (RTT / One-Way Latency), а также медиа джиттера по стандарту RFC 3550.
1. Инструмент глубокой диагностики
Команда doctor выполняет комплексную проверку узла: от корректности синтаксиса .env и настройки CORS до реального тестового выделения релейного порта из пула.
Запуск диагностики
Для проверки сервера с использованием текущей конфигурации (/opt/slyber_turn/.env) выполните:
sudo slyber_turn doctor
При необходимости вы можете переопределить любой параметр конфигурации на лету с помощью флагов командной строки:
sudo slyber_turn doctor -public-ip 203.0.113.50 -udp-port 3478 -realm rtc.example.com
Что проверяет doctor шаг за шагом
Диагностика проходит в 4 последовательных этапа:
Этап 1. Валидация конфигурации и емкости пула портов
Утилита загружает настройки, проверяет длину секретного ключа (TURN_SECRET не менее 16 символов), отсутствие конфликтов между портами UDP, TCP, TLS и HTTP, а затем вычисляет максимальную емкость одновременных релейных сессий по формуле RELAY_MAX_PORT - RELAY_MIN_PORT + 1.
Этап 2. Аудит защиты HTTP API
Проверяется конфигурация безопасности эндпоинта выдачи временных учетных данных /api/turn-credentials:
- Если список
ALLOWED_ORIGINSпуст и при этом не включен строгий режимREQUIRE_SECRET=true, утилита выведет предупреждение[WARN], так как браузерные CORS-запросы будут отклоняться. - Если защита настроена корректно, выводится статус
[OK]с количеством разрешенных доменов и статусомrequire_secret.
Этап 3. Внешняя STUN проверка и сверка NAT
Утилита обращается к внешним STUN-серверам (stun.l.google.com:19302, stun.cloudflare.com:3478, stun1.l.google.com:19302) с таймаутом в 3 секунды, измеряет сетевой RTT и узнает реальный внешний IP-адрес, с которого ваш сервер выходит в интернет:
- Если обнаруженный внешний IP совпадает с настроенным
PUBLIC_IP, проверка проходит успешно ([OK]). - Если адреса различаются (например, сервер находится за облачным NAT 1:1 или указан неверный IP в
.env), выводится предупреждение[WARN] IP mismatch.
Защита от засорения аналитики: Для тестовых подключенийdoctorиbenchиспользуют зарезервированный системный идентификатор пользователяdoctor_probe. Ядро сервера и система телеметрии автоматически распознают это имя и не записывают диагностические проверки в счетчики пользовательских подключений, список активных сессий и журнал событийevents.jsonl. Вы можете запускатьslyber_turn doctorизcronили систем мониторинга каждую минуту без искажения бизнес-метрик.
Примеры вывода slyber_turn doctor
Успешная проверка работающего сервера:
[INFO] Running slyber_turn doctor diagnostics...
--------------------------------------------------
[OK] Configuration valid (realm: turn.local, relay port pool: 49152-65535, capacity: 16384 sessions)
[OK] HTTP API protection active (origins: 1, require_secret: false)
[OK] STUN check passed in 18ms: PUBLIC_IP (203.0.113.50) matches external IP
[INFO] UDP port 3478 is already in use - switching to running server verification (Live Probe)...
[OK] HTTP API (:8080/healthz) responded normally (200 OK)
[OK] TURN Allocate succeeded in 412µs (allocated relay address: 203.0.113.50:51024)
--------------------------------------------------
[OK] Diagnostics completed successfully. Server is ready.
Успешная проверка перед запуском сервиса (Режим Self-Test):
Plaintext
[INFO] Running slyber_turn doctor diagnostics...
--------------------------------------------------
[OK] Configuration valid (realm: turn.local, relay port pool: 49152-65535, capacity: 16384 sessions)
[OK] HTTP API protection active (origins: 1, require_secret: false)
[OK] STUN check passed in 21ms: PUBLIC_IP (203.0.113.50) matches external IP
[INFO] Ports UDP 3478 / TCP 3478 are free - starting isolated Self-Test...
[OK] TURN Allocate succeeded in 385µs (allocated relay address: 203.0.113.50:49152)
--------------------------------------------------
[OK] Diagnostics completed successfully. Server is ready.
Справочник диагностических сообщений и решение проблем
| Сообщение doctor | Причина возникновения | Как исправить |
[WARN] IP mismatch: configured PUBLIC_IP=..., but external STUN reported ... | В .env указан IP адрес, который не совпадает с реальным выходным IP сервера. | Установите PUBLIC_IP="auto" в /opt/slyber_turn/.env или укажите правильный публичный IPv4 адрес сервера и перезапустите службу. |
[FAIL] UDP port 3478 is free, but TCP port 3478 is already in use | На сервере остановлен TURN, но TCP-порт 3478 (или TLS_PORT 5349) занят другим сторонним процессом. | Проверьте, кто занимает порт (sudo ss -tulpn | grep 3478), остановите конфликтующий процесс или смените порт в .env. |
[WARN] HTTP API (:8080/healthz) is not responding | TURN-сервер запущен, но HTTP API не отвечает (или запущен с другими флагами/портом). | Проверьте статус службы (sudo systemctl status slyber_turn) и настройки HTTP_ENABLED / HTTP_PORT в .env. |
[FAIL] TURN Allocate failed on 127.0.0.1:3478 | Работающий сервер не ответил на запрос выделения порта или отклонил авторизацию. | Убедитесь, что порт 3478 не занят чужим STUN/TURN сервером (например, старым coturn), и что вы запускаете doctor с тем же .env, с которым запущен сервис. |
2. Нагрузочное тестирование и оценка качества медиа: slyber_turn bench
Команда slyber_turn bench (синоним: slyber_turn benchmark) создает реалистичную нагрузку на TURN сервер, имитируя десятки и сотни одновременных аудио и видеозвонков WebRTC.
Архитектура и алгоритм работы бенчмарка
Тестирование в bench выполняется в 5 фаз:
Определение режима тестирования (mode):
self-test: Если флаг-targetне указан и портUDP_PORTсвободен, утилита автоматически поднимает внутри себя изолированный TURN-сервер на127.0.0.1(с временным разрешением loopback-трафикаSetAllowLoopback(true)) и тестирует его.live-local: Если флаг-targetне указан, а портUDP_PORTуже занят работающим серверомslyber_turn, тест автоматически запускается против живого локального сервера (PUBLIC_IP:UDP_PORT).live-remote: Если явно передан флаг-target <host:port>, тест выполняется по сети против указанного удаленного TURN-сервера.
Массовая параллельная аллокация (Allocation Setup):
- Одновременно в отдельных горутинах запускается
Nклиентов (-clients), каждый из которых открывает UDP-сокет, проходит HMAC-SHA1 аутентификацию и запрашивает у сервера релейный порт (Allocate). - Для каждого клиента фиксируется точное время выделения порта, на основе чего рассчитываются метрики
avg,p95иmax.
Разбиение на пары и прогрев каналов (Warmup):
- Все успешно подключившиеся клиенты объединяются в пары (
Клиент А ↔ Клиент Б). - Каждая пара обменивается стартовым 24-байтным пакетом через выделенные релейные адреса и выдерживает паузу
80 мсдля создания TURN-разрешений (CreatePermission) в обоих направлениях.
Двусторонняя пересылка медиа-пакетов по бинарному протоколу SLYB:
- В течение заданного времени (
-duration) каждый клиент с заданной частотой (-pps) отправляет собеседнику через TURN-релей UDP-пакеты заданного размера (-size). - Первые 24 байта каждого пакета содержат специальный заголовок:
Байты 0..3: Магическая сигнатура протокола0x534C5942(ASCII:"SLYB").Байты 4..7: Флаг направления (0=PING,1=PONG).Байты 8..15: Порядковый номер пакета (seq,uint64).Байты 16..23: Точная метка времени отправки в наносекундах (UnixNano,uint64).- Когда Клиент Б получает пакет
PING, он вычисляет время прохождения в одну сторону, обновляет сглаженный показатель медиа-джиттера по формуле RFC 3550 ($J = J + (\vert{}D(i-1, i)\vert{} - J)/16$), меняет флаг пакета наPONG(1) и немедленно отправляет его обратно через TURN-релей Клиенту А. - Когда Клиент А получает вернувшийся
PONG(пакет прошел 4 плеча ретрансляции:A -> TURN -> B -> TURN -> A), он фиксирует доставку и вычисляет полный круговой RTT.
Ожидание пакетов в полете и сбор отчета:
- По окончании отправки
benchждет до1500 мс(waitForInFlightPackets), чтобы корректно принять последние пакеты, находящиеся в пути, после чего формирует текстовый или JSON-отчет.
Флаги запуска slyber_turn bench
Специальные флаги бенчмарка:
| Флаг CLI | По умолчанию | Описание |
-target | "" (автовыбор) | Адрес целевого TURN сервера в формате host:port. Если не указан, тестируется локальный сервер (live-local или self-test). |
-clients | 10 | Количество одновременных TURN клиентов (аллокаций). Если указано нечетное число, оно автоматически увеличивается на 1 для формирования полных пар собеседников. |
-duration | 5s | Длительность фазы активной генерации медиа-трафика (например, 5s, 30s, 1m). |
-size | 1200 | Размер каждого UDP пакета в байтах (минимум 24 байта; 1200 байт соответствует типичному размеру WebRTC видео-пакета VP8/VP9/H.264). |
-pps | 50 | Количество пакетов в секунду, отправляемых каждым клиентом (50 pps = 1 пакет каждые 20 мс, что точно соответствует аудио-потоку Opus в WebRTC). |
-json | false | Вывод итогового отчета в формате JSON (удобно для CI/CD-пайплайнов и автоматического мониторинга). |
Дополнительные флаги конфигурации (при удаленном или кастомном тестировании):
Команда bench также поддерживает все базовые флаги конфигурации: -secret (секретный ключ сервера), -realm (доменная область), -udp-port, -tcp-port, -public-ip и -max-kbps (проверка работы шейпера трафика под нагрузкой).
Примеры запуска
1. Быстрый локальный тест по умолчанию (10 клиентов, 5 секунд):
sudo slyber_turn bench
2. Стресс-тест высокой видео-нагрузки (100 клиентов / 50 пар, 30 секунд, 100 пакетов/сек по 1200 байт):
sudo slyber_turn bench -clients 100 -duration 30s -size 1200 -pps 100
3. Удаленное тестирование продакшен-сервера с другой машины с выводом в JSON:
slyber_turn bench \
-target 203.0.113.50:3478 \
-secret "your-production-turn-secret-key" \
-realm "turn.yourdomain.com" \
-clients 20 \
-duration 10s \
-json
Разбор результатов тестирования
1. Стандартный текстовый отчет:
[INFO] Starting Slyber Turn benchmark against 127.0.0.1:3478 (mode: live-local, clients: 20, duration: 5s, payload: 1200 B)...
----------------------------------------------------------------------
Allocation Setup : 20/20 succeeded | avg: 1.42 ms | p95: 2.15 ms | max: 2.40 ms
Relay Throughput : 19.20 Mbps (2000 packets/sec, 11.44 MB relayed)
Packet Delivery : 5000 sent | 5000 recv | 0.00% loss (0 dropped)
Relay Latency : ~0.35 ms one-way (4-leg loop RTT avg: 0.70 ms | p50: 0.65 ms | p95: 1.10 ms)
Media Jitter : 0.12 ms (RFC 3550)
Quality Verdict : [OK] EXCELLENT (Ready for low-latency HD Voice & Video)
----------------------------------------------------------------------
2. JSON-отчет (флаг -json):
При указании флага -json утилита выводит полную структуру метрик (включая дополнительные перцентили rtt_min_ms, rtt_p99_ms, rtt_max_ms и точное число переданных байт bytes_relayed):
{
"target": "127.0.0.1:3478",
"mode": "live-local",
"clients": 20,
"duration_sec": 5.0,
"alloc_success": 20,
"alloc_failed": 0,
"alloc_avg_ms": 1.42,
"alloc_p95_ms": 2.15,
"alloc_max_ms": 2.4,
"packets_sent": 5000,
"packets_received": 5000,
"packets_lost": 0,
"packet_loss_percent": 0.0,
"bytes_relayed": 12000000,
"throughput_mbps": 19.2,
"packets_per_sec": 2000.0,
"rtt_min_ms": 0.41,
"rtt_avg_ms": 0.7,
"rtt_p50_ms": 0.65,
"rtt_p95_ms": 1.1,
"rtt_p99_ms": 1.48,
"rtt_max_ms": 1.85,
"one_way_relay_avg_ms": 0.35,
"jitter_ms": 0.12,
"verdict": "[OK] EXCELLENT (Ready for low-latency HD Voice & Video)"
}
Что означает каждая метрика отчета:
Allocation Setup(alloc_avg_ms/alloc_p95_ms/alloc_max_ms): Скорость рукопожатия и выделения релейного порта под нагрузкой. Показывает, насколько быстро подключаются новые участники звонка.Relay Throughput(throughput_mbps/packets_per_sec/bytes_relayed): Суммарная скорость прокачки медиа-трафика через TURN-сервер в мегабитах в секунду и пакетах в секунду (учитываются как входящиеPING, так и ответныеPONGпакеты).Packet Delivery(packet_loss_percent/packets_lost): Процент потерянных UDP-пакетов. Для качественной связи на локальном сервере потери должны быть равны0.00%.Relay Latency(one_way_relay_avg_msиrtt_*):4-leg loop RTT— полное время прохождения пакета туда и обратно через два релейных порта (Клиент А -> TURN -> Клиент Б -> TURN -> Клиент А).one-way(RTT / 2) — чистая задержка ретрансляции в одну сторону (Клиент А -> TURN -> Клиент Б), которую реально ощущают собеседники в разговоре.Media Jitter(jitter_ms): Неравномерность интервалов доставки пакетов, рассчитанная по алгоритму RTP RFC 3550. Низкий джиттер гарантирует отсутствие «роботизированного» голоса и заиканий видео.
Особенность проверки с включенным лимитом скорости (MAX_KBPS_PER_SESSION): Если у вас в .env настроен шейпер трафика (например, MAX_KBPS_PER_SESSION=1000), а вы запустите bench с параметрами, превышающими этот лимит на одного клиента, ограничитель скорости bandwidthLimiter начнет штатно отбрасывать лишние UDP-пакеты. Чтобы протестировать максимальную физическую мощность самого сервера без искусственного шейпинга, передайте флаг -max-kbps 0:
sudo slyber_turn bench -clients 40 -duration 10s -max-kbps 0