Установка и настройка TURN-сервера Coturn на VPS для WebRTC: TLS, WebSocket и безопасная авторизация
TL;DR
Coturn — это TURN/STUN-сервер для WebRTC, который передаёт аудио, видео и DataChannel-трафик между клиентами, когда прямое P2P-соединение блокируют NAT, CGNAT или корпоративные firewall. В этом руководстве настраивается Coturn на Ubuntu Server 24.04 LTS с TLS-сертификатом Let’s Encrypt, безопасной REST-аутентификацией и правилами firewall для UDP/TCP relay-портов.
- TURN нужен как резервный путь передачи медиатрафика для WebRTC, когда STUN не позволяет установить прямое соединение.
- Coturn будет слушать STUN/TURN на портах
3478и5349, а relay-трафик — в ограниченном диапазоне UDP-портов. - TLS включается напрямую в Coturn с сертификатами Let’s Encrypt; обратный прокси не должен терминировать TURN-TLS.
- WebSocket применяется для защищённого сигнального канала WebRTC через
wss://, но сам Coturn не превращает TURN в WebSocket-сервер. - Вместо постоянных логинов используются краткоживущие TURN credentials по механизму
use-auth-secret. - После настройки сервер проверяется через логи Coturn, утилиту
turnutils_uclientи браузерную диагностику WebRTC.
Что мы настраиваем и зачем
WebRTC позволяет браузерам, мобильным приложениям и desktop-клиентам передавать голос, видео, экран и произвольные данные в реальном времени. В идеальном случае два клиента устанавливают прямое P2P-соединение. На практике это регулярно не работает: пользователь находится за симметричным NAT, мобильным CGNAT, строгим офисным firewall, гостиничным Wi-Fi или сетью, где разрешён только HTTPS-трафик.
STUN-сервер помогает клиенту узнать публичный IP-адрес и тип NAT. Но STUN сам по себе не передаёт медиа. Если прямой маршрут недоступен, WebRTC-клиент использует TURN-сервер как relay: оба участника отправляют UDP-, TCP- или TLS-трафик на сервер, а Coturn пересылает пакеты между ними. Это повышает надёжность звонков, но означает, что медиатрафик проходит через ваш VPS.
В результате будет получена следующая схема:
- STUN/TURN по UDP и TCP на
turn.example.com:3478; - TURN over TLS на
turns:turn.example.com:5349; - relay-диапазон портов, например
49160-49200/udp; - краткоживущая аутентификация пользователей через общий серверный секрет;
- автоматическое обновление TLS-сертификата Let’s Encrypt;
- при необходимости — отдельный WebSocket-сигналинг по
wss://signal.example.com.
TURN, TLS и WebSocket: важное различие
WebRTC состоит из нескольких независимых частей. Сигналинг передаёт SDP offer/answer и ICE-кандидаты. Обычно это WebSocket, Socket.IO, HTTPS API, XMPP или другой прикладной канал. Для сигнального сервера используется wss://, то есть WebSocket поверх HTTPS.
TURN решает другую задачу: передаёт уже согласованный медиатрафик WebRTC. Coturn поддерживает TURN по UDP, TCP и TLS, однако обычная установка Coturn не является WebSocket TURN-сервером. Нельзя поставить Caddy или Nginx перед портом 3478 и ожидать, что TURN станет работать через WebSocket: это разные протоколы. Если ваша корпоративная сеть пропускает только TCP/443, используйте TURN over TLS на 5349, либо выделенный IP и порт 443 при отсутствии конфликта с HTTPS.
Self-hosted TURN или managed TURN
| Критерий | Managed TURN | Свой Coturn на VPS |
|---|---|---|
| Запуск | Быстро, без администрирования | Нужны DNS, firewall, TLS и мониторинг |
| Контроль данных | Трафик проходит через внешнего оператора | Маршрутизация и журналы под вашим контролем |
| Стоимость при росте трафика | Часто зависит от переданных ГБ | Главное ограничение — включённый трафик VPS |
| Настройка аутентификации | Ограничена API провайдера | Можно интегрировать с собственным backend |
| География | Зависит от доступных регионов | Можно выбрать VPS рядом с аудиторией |
Self-hosted Coturn рационален для собственного видеочата, SaaS-продукта, Mattermost Calls, Jitsi, LiveKit, Janus, mediasoup, мобильного приложения или внутренней корпоративной связи. Для небольшого продукта он даёт предсказуемую инфраструктуру. Однако нужно заранее оценить исходящий трафик: при relay-соединении сервер обычно получает поток от одного клиента и отправляет его второму, поэтому 1 ГБ переданного видео может потребовать примерно 2 ГБ сетевого трафика сервера.
Какой VPS-конфиг нужен под эту задачу
Coturn экономно расходует CPU и RAM, потому что не перекодирует видео и не анализирует медиапоток. Основная нагрузка — пропускная способность сети, число одновременных allocations и пакетов в секунду. При групповом звонке с SFU трафик TURN обычно меньше, чем при mesh-звонке, но это зависит от архитектуры приложения и поведения клиентов.
| Сценарий | CPU | RAM | Диск | Сеть |
|---|---|---|---|---|
| Тесты, 5–20 одновременных relay-пользователей | 1 vCPU | 1 ГБ | 10 ГБ SSD | 100 Мбит/с, публичный IPv4 |
| Небольшой продукт, 20–100 одновременных пользователей | 2 vCPU | 2 ГБ | 20 ГБ SSD | 1 Гбит/с, от 1 ТБ трафика |
| Постоянные видеозвонки, 100–500 relay-пользователей | 4 vCPU | 4–8 ГБ | 40 ГБ SSD | 1 Гбит/с, большой или безлимитный трафик |
Для первого production-запуска достаточно 2 vCPU, 2 ГБ RAM, 20 ГБ SSD, статического IPv4 и канала 1 Гбит/с. Такой вариант можно выбрать как VPS с указанными характеристиками. Важнее количества диска — гарантированная или понятная пропускная способность, отсутствие жёсткого лимита пакетов в секунду и достаточный месячный объём исходящего трафика.
Когда нужен dedicated, а не VPS
Выделенный сервер оправдан, когда relay-трафик стабильно занимает сотни мегабит или гигабиты в секунду, важны предсказуемые PPS, требуется несколько публичных IP, либо сервис обслуживает сотни и тысячи одновременных видеопотоков. Dedicated также полезен, если нужно разделить TURN на отдельные географические узлы и не зависеть от виртуализации соседних арендаторов.
Не следует переходить на dedicated только потому, что в конфиге есть TLS. Шифрование TURN требует CPU, но на современных процессорах несколько сотен умеренных соединений обычно не являются проблемой. Сначала измерьте фактические метрики: CPU, входящий и исходящий трафик, число allocations, packet loss и latency.
Как выбрать локацию
TURN добавляет задержку в путь медиапакетов, поэтому размещайте сервер ближе к большей части аудитории. Для пользователей из Германии, Польши и Нидерландов подойдёт центральноевропейская локация. Если участники разговора находятся в разных регионах, один TURN-сервер будет компромиссом: трафик обоих пойдёт к нему.
Для глобального продукта используют несколько Coturn-узлов и отдают клиенту региональный список ICE-серверов. Не выбирайте локацию только по цене: потеря пакетов, плохой peering и высокая задержка заметнее для звонков, чем для обычного веб-сайта.
Подготовка сервера
Ниже предполагается чистый Ubuntu Server 24.04 LTS с публичным IPv4-адресом. Выполняйте начальное подключение под root, затем создайте обычного администратора. Перед настройкой DNS создайте A-запись turn.example.com, указывающую на IP VPS. Для TLS-проверки запись должна уже распространяться в DNS.
Обновите систему и установите базовые утилиты
apt update && apt upgrade -y
apt install -y sudo curl ca-certificates gnupg ufw fail2ban dnsutils jq
reboot
Первая команда обновляет пакеты Ubuntu, устанавливает инструменты администрирования и перезагружает сервер, если ядро или системные библиотеки были обновлены.
Создайте пользователя для администрирования
adduser deploy
usermod -aG sudo deploy
install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
nano /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys
chown deploy:deploy /home/deploy/.ssh/authorized_keys
Вставьте в authorized_keys ваш публичный SSH-ключ одной строкой. До отключения входа root обязательно откройте вторую SSH-сессию и убедитесь, что вход под deploy действительно работает.
Отключите парольный SSH-вход
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
cat > /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
EOF
sshd -t && systemctl restart ssh
Файл в sshd_config.d переопределяет опасные значения без редактирования основного файла. Команда sshd -t проверяет синтаксис до перезапуска SSH.
Настройте UFW и Fail2ban
Для Coturn требуются UDP и TCP на порту 3478, TCP на 5349, UDP на 5349 для DTLS-вариантов, а также relay-диапазон. В примере используется ограниченный диапазон 49160:49200: 41 UDP-порт. Этого достаточно для тестового или небольшого сервиса. Чем больше одновременных relay-сессий, тем шире должен быть диапазон.
ufw default deny incoming
ufw default allow outgoing
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 3478/tcp
ufw allow 3478/udp
ufw allow 5349/tcp
ufw allow 5349/udp
ufw allow 49160:49200/udp
ufw enable
ufw status numbered
Порты 80/tcp и 443/tcp нужны для выпуска сертификата и будущего HTTPS/WSS-сигналинга. Если на сервере не будет сигнального приложения, после выпуска сертификата порт 80 можно закрыть при использовании DNS challenge, но для стандартного HTTP-01 renewal он должен оставаться доступным.
systemctl enable --now fail2ban
fail2ban-client status
timedatectl set-timezone UTC
timedatectl status
Fail2ban защищает прежде всего SSH. TURN-аутентификация будет защищена краткоживущими credential, поэтому блокировать отдельные TURN-ошибки через Fail2ban обычно менее полезно, чем ограничивать доступ firewall и следить за аномалиями трафика.
Установка ПО — пошагово
В Ubuntu 24.04 LTS доступен пакет Coturn ветки 4.6.x. Для production разумно использовать пакет дистрибутива: он получает обновления безопасности вместе с системой, корректно интегрирован с systemd и содержит утилиты диагностики. На момент планирования инфраструктуры в 2026 году ориентируйтесь на актуальный стабильный релиз ветки Coturn 4.6.x или новее, доступный в security-репозитории вашего дистрибутива.
Установите Coturn и Certbot
apt update
apt install -y coturn certbot
turnserver --version
certbot --version
Команда устанавливает TURN/STUN-сервер и ACME-клиент Let’s Encrypt. Проверьте версию Coturn: пакет не должен быть устаревшим или собранным из непроверенного стороннего репозитория.
Включите systemd-службу Coturn
systemctl unmask coturn
systemctl enable coturn
systemctl status coturn --no-pager
В некоторых сборках Ubuntu служба может быть замаскирована до первичной настройки. Пока конфиг не создан, служба может завершаться с ошибкой — это нормально. Запускать её окончательно будем после создания конфигурации.
Получите TLS-сертификат
Перед выполнением команды убедитесь, что turn.example.com разрешается в публичный IP этого сервера и порт 80/tcp доступен извне. На время проверки Certbot поднимет собственный временный HTTP-сервер.
systemctl stop coturn
certbot certonly --standalone \
--non-interactive \
--agree-tos \
--email [email protected] \
-d turn.example.com
Замените [email protected] и домен на реальные значения. Сертификаты появятся в каталоге /etc/letsencrypt/live/turn.example.com/. Не копируйте закрытый ключ в домашние каталоги и не добавляйте его в Git.
Создайте отдельную группу для чтения сертификата
Служба Coturn обычно запускается от системного пользователя turnserver. Доступ к privkey.pem должен быть предоставлен минимально необходимому пользователю через группу ssl-cert.
usermod -aG ssl-cert turnserver
chgrp ssl-cert /etc/letsencrypt/live/turn.example.com/privkey.pem
chmod 640 /etc/letsencrypt/live/turn.example.com/privkey.pem
namei -l /etc/letsencrypt/live/turn.example.com/privkey.pem
Символьные ссылки из live ведут в каталог archive, поэтому после обновления сертификата права могут изменяться. Далее будет добавлен deploy hook, который повторно задаёт права и перезапускает Coturn.
Сгенерируйте секрет для REST-аутентификации
install -d -m 750 /etc/coturn
umask 077
openssl rand -hex 32 > /etc/coturn/auth-secret
chown root:turnserver /etc/coturn/auth-secret
chmod 640 /etc/coturn/auth-secret
cat /etc/coturn/auth-secret
Эта команда создаёт 256-битный секрет. Сохраните его в защищённом хранилище секретов. Последняя команда выведет значение только для безопасного переноса в backend приложения; не запускайте её в терминале с логированием истории или демонстрацией экрана.
Конфигурация Coturn, TLS и WebSocket-сигналинга
В production не используйте lt-cred-mech с постоянными пользователями, если ваш backend способен выпускать временные credentials. Режим use-auth-secret позволяет приложению сформировать имя пользователя в виде Unix-времени истечения и идентификатора пользователя, а пароль вычислить как HMAC-SHA1 от имени пользователя с серверным секретом. Coturn проверяет credential локально, без базы данных.
Создайте основной конфиг Coturn
Замените IP, домен и адрес интерфейса на свои. Если у VPS один публичный IPv4 без внутреннего NAT, external-ip можно указать как публичный адрес. Если VPS находится за NAT, используйте формат PUBLIC_IP/PRIVATE_IP.
# /etc/turnserver.conf
listening-port=3478
tls-listening-port=5349
listening-ip=0.0.0.0
relay-ip=PUBLIC_IPV4
external-ip=PUBLIC_IPV4
realm=turn.example.com
server-name=turn.example.com
fingerprint
min-port=49160
max-port=49200
use-auth-secret
static-auth-secret=REPLACE_WITH_SECRET_FROM_AUTH_SECRET_FILE
no-multicast-peers
no-loopback-peers
stale-nonce=600
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
no-tlsv1
no-tlsv1_1
cipher-list=HIGH:!aNULL:!MD5:!RC4
no-cli
no-tcp-relay
log-file=/var/log/turnserver/turnserver.log
simple-log
syslog
Параметр no-tcp-relay отключает TCP relay allocations, но не отключает приём TURN по TCP или TLS. Для большинства WebRTC-сценариев relay по UDP предпочтительнее: ниже задержка и меньше head-of-line blocking. Если вашим клиентам действительно нужен relay через TCP, удалите эту строку и протестируйте нагрузку отдельно.
Опция fingerprint включает обязательный атрибут FINGERPRINT для совместимости и целостности STUN-сообщений. no-multicast-peers и no-loopback-peers не позволяют использовать TURN как прокси к multicast- или loopback-адресам. Ограничение портов делает firewall контролируемым и снижает поверхность злоупотреблений.
Подставьте секрет без хранения его в Git
Файл Coturn читается сервисом и содержит секрет, поэтому установите строгие права. Если конфигурация управляется Ansible, Terraform или другим IaC-инструментом, передавайте секрет через зашифрованные variables или secret manager, а не храните его в репозитории.
SECRET="$(cat /etc/coturn/auth-secret)"
sed -i "s/REPLACE_WITH_SECRET_FROM_AUTH_SECRET_FILE/${SECRET}/" /etc/turnserver.conf
chown root:turnserver /etc/turnserver.conf
chmod 640 /etc/turnserver.conf
install -d -m 750 -o turnserver -g turnserver /var/log/turnserver
turnserver -c /etc/turnserver.conf -o -v
Последняя команда запускает Coturn в foreground с подробным выводом. Если синтаксис, IP, сертификат или права на ключ неправильны, ошибка будет видна сразу. После проверки остановите тестовый процесс сочетанием Ctrl+C.
Запустите службу и проверьте слушающие порты
systemctl restart coturn
systemctl enable coturn
systemctl status coturn --no-pager
ss -lntup | grep -E ':(3478|5349)\b'
journalctl -u coturn -n 100 --no-pager
Ожидаются UDP и TCP на 3478, TCP на 5349 и, в зависимости от сборки и TLS/DTLS-настроек, UDP на 5349. Не публикуйте административный CLI Coturn в интернет: в конфиге он отключён директивой no-cli.
Настройте автоматическое обновление сертификата
cat > /etc/letsencrypt/renewal-hooks/deploy/reload-coturn.sh <<'EOF'
#!/bin/sh
chgrp ssl-cert /etc/letsencrypt/live/turn.example.com/privkey.pem
chmod 640 /etc/letsencrypt/live/turn.example.com/privkey.pem
systemctl restart coturn
EOF
chmod 750 /etc/letsencrypt/renewal-hooks/deploy/reload-coturn.sh
certbot renew --dry-run
systemctl list-timers | grep certbot
Deploy hook перезапускает Coturn только после успешного обновления сертификата. Команда --dry-run проверяет, что renewal пройдёт до истечения срока сертификата. Краткий перезапуск может сбросить активные allocations, поэтому проводите ручные изменения сертификатов в окно обслуживания.
Как backend формирует временные TURN credentials
Имя пользователя обычно имеет вид EXPIRES:USER_ID, где EXPIRES — Unix timestamp. Пароль — Base64-представление HMAC-SHA1 имени пользователя с общим секретом. Время жизни 1–24 часа выбирают по длительности сессий: для видеозвонка часто хватает 3600–7200 секунд. Не выдавайте credential на месяцы: утечка такого пароля позволит использовать ваш relay для чужого трафика.
import crypto from 'node:crypto';
const secret = process.env.TURN_AUTH_SECRET;
const ttlSeconds = 3600;
const expires = Math.floor(Date.now() / 1000) + ttlSeconds;
const username = ${expires}:user-12345;
const credential = crypto
.createHmac('sha1', secret)
.update(username)
.digest('base64');
const iceServers = [
{
urls: [
'turn:turn.example.com:3478?transport=udp',
'turn:turn.example.com:3478?transport=tcp',
'turns:turn.example.com:5349?transport=tcp'
],
username,
credential
}
];
Секрет передавайте приложению через переменную окружения, systemd credentials, Kubernetes Secret или vault. Не возвращайте TURN_AUTH_SECRET в браузер. Браузеру передаются только временные username и credential.
Пример переменных окружения backend
cat > /etc/myapp/turn.env <<'EOF'
TURN_HOST=turn.example.com
TURN_TLS_PORT=5349
TURN_AUTH_SECRET=replace-with-the-same-secret
TURN_CREDENTIAL_TTL=3600
EOF
chmod 600 /etc/myapp/turn.env
Файл /etc/myapp/turn.env является примером для вашего сигнального API. Сам Coturn не считывает этот файл: он использует значение static-auth-secret из своего конфига. Оба значения должны совпадать.
TLS-проверка и функциональный тест
openssl s_client -connect turn.example.com:5349 \
-servername turn.example.com -brief < /dev/null
turnutils_uclient -u "EXPIRES:user-12345" \
-w "GENERATED_PASSWORD" \
-p 3478 turn.example.com
tail -f /var/log/turnserver/turnserver.log
Первая команда проверяет сертификат и TLS-рукопожатие. Вторая входит в пакет Coturn и создаёт клиентский тест; подставьте свежую пару временных credentials. В логе ищите успешную аутентификацию и создание allocation. Для проверки из браузера используйте тестовую страницу вашего приложения, откройте chrome://webrtc-internals и убедитесь, что выбранный candidate pair имеет тип relay в сети, где P2P недоступен.
WebSocket-сигналинг через Caddy
Если у вас есть сигнальный сервер на локальном порту 3000, Caddy может автоматически обслуживать HTTPS и проксировать WebSocket-соединения. Это отдельный сервис и отдельный домен, например signal.example.com. Не направляйте через Caddy UDP-порты Coturn и не проксируйте TURN как HTTP.
signal.example.com {
reverse_proxy 127.0.0.1:3000
}
Caddy автоматически поддерживает upgrade до WebSocket и получает HTTPS-сертификат для домена сигналинга. На клиенте подключайтесь к wss://signal.example.com, а ICE-конфигурацию с TURN credentials получайте через авторизованный API или через этот же сигнальный канал. Если сигнальный сервер расположен на другом узле, это не мешает ему выдавать краткоживущие credentials для Coturn.
Бэкапы и обслуживание
Coturn в режиме use-auth-secret не хранит пользователей, записи звонков или медиаданные. Поэтому бэкапить нужно не relay-трафик, а конфигурацию, TLS-материалы, секреты, firewall-правила и инфраструктурные скрипты. Если ваш backend хранит пользователей, комнаты, историю или записи, его базу данных резервируйте отдельным процессом.
Что включить в резервную копию
/etc/turnserver.confи файл секрета/etc/coturn/auth-secret;/etc/letsencrypt, если требуется быстрое восстановление существующих сертификатов;- конфигурации Caddy и сигнального приложения;
- дампы PostgreSQL, MySQL или другой БД backend-приложения;
- список пакетов, правила UFW и документацию по DNS-записям;
- необязательно: журналы Coturn с коротким сроком хранения для расследования инцидентов.
Не храните единственную копию секрета на том же VPS. При потере секрета можно сгенерировать новый, но все действующие credentials немедленно перестанут работать. Это допустимый аварийный сценарий, однако его лучше выполнять контролируемо.
Пример резервного копирования через Restic
apt install -y restic
export RESTIC_REPOSITORY="s3:https://s3.example.net/turn-backups"
export RESTIC_PASSWORD_FILE="/root/.config/restic/password"
export AWS_ACCESS_KEY_ID="REPLACE_ME"
export AWS_SECRET_ACCESS_KEY="REPLACE_ME"
restic init
restic backup /etc/turnserver.conf /etc/coturn /etc/letsencrypt /etc/caddy
restic snapshots
Замените S3-адрес и учётные данные. В production передавайте переменные через защищённый root-only environment-файл или systemd unit, а не сохраняйте ключи в shell history. Альтернатива — отдельный backup VPS по SSH, BorgBackup или rsync поверх SSH с ключом, ограниченным только командой резервного копирования.
Скрипт и cron
cat > /usr/local/sbin/backup-coturn.sh <<'EOF'
#!/bin/sh
set -eu
. /root/.config/restic/env
restic backup /etc/turnserver.conf /etc/coturn /etc/letsencrypt /etc/caddy
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
EOF
chmod 700 /usr/local/sbin/backup-coturn.sh
cat > /etc/cron.d/backup-coturn <<'EOF'
17 3 * root /usr/local/sbin/backup-coturn.sh >> /var/log/backup-coturn.log 2>&1
EOF
Файл /root/.config/restic/env должен иметь права 600 и содержать переменные Restic. Раз в квартал выполняйте тест восстановления на отдельной машине: резервная копия без проверки восстановления не является надёжным бэкапом.
Обновления и окно обслуживания
Обновления безопасности Ubuntu можно устанавливать регулярно, но обновление Coturn, OpenSSL или перезапуск службы способны оборвать активные relay allocations. Для небольшого сервиса выберите короткое maintenance window, заранее предупредите пользователей и выполните:
apt update
apt list --upgradable
apt upgrade -y
systemctl restart coturn
systemctl status coturn --no-pager
journalctl -u coturn -n 50 --no-pager
Для высокой доступности используйте минимум два TURN-узла в разных зонах и возвращайте клиентам несколько URL в iceServers. Тогда обновления можно делать поочерёдно: снять узел с выдачи новых credentials, дождаться завершения звонков, обновить и вернуть его в пул.
Troubleshooting + FAQ
Почему браузер не использует relay-кандидат, хотя Coturn запущен?
Это не всегда ошибка. WebRTC предпочитает прямой host или server-reflexive маршрут, если он работает. Чтобы проверить TURN, протестируйте двух клиентов из разных сетей, например мобильного интернета и корпоративной сети. В chrome://webrtc-internals посмотрите выбранную пару кандидатов. Если relay-кандидаты вообще не появляются, проверьте правильность URL, временных credentials, DNS, доступность 3478/udp и строки логов Coturn с ошибками аутентификации.
Ошибка 401 Unauthorized или Wrong credentials при подключении к TURN: что делать?
Проверьте, что backend и Coturn используют один и тот же static-auth-secret. Имя пользователя должно содержать будущий Unix timestamp, а пароль должен быть Base64 от HMAC-SHA1 именно строки username. Частая ошибка — использовать HMAC-SHA256, hex-кодирование вместо Base64 или timestamp в миллисекундах. Также синхронизируйте время сервера через systemd-timesyncd или chrony: просроченный credential Coturn отвергнет.
Почему TURN по UDP работает, а turns:// на 5349 не подключается?
Сначала проверьте openssl s_client с параметром -servername. Если сертификат не читается, посмотрите права на privkey.pem, группу ssl-cert и журнал journalctl -u coturn. Затем убедитесь, что открыт 5349/tcp в UFW и во внешнем firewall панели провайдера. Проверьте, что DNS-имя в сертификате совпадает с именем в TURN URL, иначе браузер отклонит TLS-соединение.
Почему звонки работают дома, но не работают из мобильной или корпоративной сети?
Домашняя сеть может позволять P2P, поэтому TURN там не задействуется. В проблемной сети UDP часто заблокирован или NAT симметричный. Убедитесь, что вы отдаёте клиенту не только turn: с UDP, но и TCP-вариант на 3478, а также turns: на 5349. Проверьте, что не включён no-tcp-relay, если вашим клиентам требуется именно TCP relay, а не только TCP-подключение к серверу.
Что означает ошибка Allocate request timed out?
Обычно запрос дошёл до Coturn, но сервер не смог создать или использовать relay-сокет. Проверьте external-ip, relay-ip, диапазон min-port/max-port и разрешение этого диапазона в UFW и сетевом firewall. На VPS за приватным NAT обязательно укажите соответствие публичного и внутреннего IP в формате external-ip=PUBLIC/PRIVATE. Также проверьте, не исчерпан ли узкий relay-диапазон при большом числе звонков.
Какой VPS-конфиг минимально подойдёт?
Для разработки, тестов и десятков редких звонков достаточно 1 vCPU, 1 ГБ RAM, 10 ГБ SSD и публичного IPv4. Для небольшого production-сервиса разумный минимум — 2 vCPU, 2 ГБ RAM, 20 ГБ SSD и канал 1 Гбит/с. Оценивайте не только вычислительные ресурсы: TURN потребляет трафик в обе стороны, поэтому лимит включённых гигабайт и качество сети часто важнее RAM.
Что выбрать — VPS или dedicated для этой задачи?
VPS подходит большинству небольших и средних WebRTC-проектов: Coturn не требует много диска и легко масштабируется добавлением новых узлов. Dedicated выбирайте при стабильной высокой нагрузке, требованиях к предсказуемому packet rate, гигабитах relay-трафика или необходимости множества публичных IP. Начните с измеряемого VPS-узла, соберите метрики реальных звонков и переходите на dedicated только при подтверждённой сетевой или CPU-нагрузке.
Можно ли использовать порт 443 для TURN, если он уже занят HTTPS-сайтом?
На одном IP и одном TCP-порту нельзя одновременно напрямую слушать HTTPS-сайт и TURN-TLS без специального L4-мультиплексирования. Стандартный и простой вариант — HTTPS/WSS на 443, TURN-TLS на 5349. Если пользователи находятся за очень строгими firewall, используйте отдельный IP для TURN на 443 или отдельный TURN-узел. Не пытайтесь решить проблему обычным HTTP reverse proxy: TURN не является HTTP-протоколом.
Выводы и следующие шаги
Теперь у вас есть Coturn TURN/STUN-сервер с ограниченным relay-диапазоном, TLS-сертификатом, firewall-защитой и безопасной краткоживущей авторизацией. Такая схема позволяет WebRTC-клиентам надёжно переходить на relay-маршрут, когда прямое P2P-соединение невозможно.
- Интегрируйте генерацию REST credentials в авторизованный backend и выдавайте их только участникам активного звонка.
- Добавьте мониторинг доступности портов, срока TLS-сертификата, CPU, трафика и количества allocations.
- При росте аудитории разверните несколько региональных Coturn-узлов и постепенно обновляйте их без остановки всей сети.