Ваш WebRTC-застосунок працює на вашому Wi-Fi і не працює в того самого клієнта, що дзвонить із готелю. Медіа «точка-точка» потрібен шлях між двома сторонами; коли обидві за суворим NAT або файрвол ріже UDP, шляху немає, і дзвінок просто не з'єднується. Помилки ніхто не бачить — лише нескінченне «з'єднання…».
TURN-сервер — запасний варіант саме для таких дзвінків: обидві сторони надсилають медіа на нього, а він ретранслює. Якщо ви вбудовуєте відео чи голос у застосунок, тримаєте Matrix або Jitsi для команди чи робите голосовий чат для гри — він вам потрібен. coturn — стандартна відкрита реалізація, і вона легка.
Який тариф
TURN майже не навантажує CPU й пам'ять. Він витрачає трафік: кожен ретрансльований потік проходить через сервер двічі, на вхід і на вихід. Трафік на наших тарифах безлімітний на 1 Гбіт/с, тож питання в тому, скільки ретрансльованих дзвінків іде одночасно, а не в тому, скільки вам виставлять.
| Ретрансльованих дзвінків одночасно | Тариф |
|---|---|
| Кілька — команда, невеликий застосунок | Nano-IP — 2 vCPU, 1 ГБ, 15 ГБ ($8/міс) |
| Десятки | Micro-IP — 2 vCPU, 2 ГБ, 25 ГБ ($10/міс) |
| Більше, або TURN поруч із сервером застосунку | Small-IP — 4 vCPU, 4 ГБ, 35 ГБ ($16/міс) |
Тариф має бути зі своєю IPv4 — TURN цілком про вхідні з'єднання на багато портів, а тарифи NAT ззовні приймають тільки SSH. На наших тарифах з виділеною IP публічна адреса стоїть просто на інтерфейсі сервера, тож coturn знаходить її без рядка external-ip. Ставте сервер ближче до користувачів: Німеччина чи Фінляндія, доступність видно під час замовлення. Оплата криптою, без KYC, якщо це для вас важливо.
Які порти відкрити: 3478 UDP і TCP, 49152–65535 UDP для ретрансльованих медіа і 5349 TCP, якщо додаєте TLS.
Встановлення й налаштування
Від root на Ubuntu 24.04 або Debian 12:
apt install -y coturn
ip -4 addr # публічна IP-адреса має бути в списку на інтерфейсі
Запишіть конфіг зі свіжим спільним секретом:
SECRET=$(openssl rand -hex 32)
cat > /etc/turnserver.conf <<EOF
listening-port=3478
fingerprint
use-auth-secret
static-auth-secret=$SECRET
realm=turn.example.com
min-port=49152
max-port=65535
no-cli
no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
EOF
echo "$SECRET" # це значення потрібне вашому бекенду
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable
Не пропускайте рядки denied-peer-ip. Без них будь-хто з дійсними обліковими даними може через ваш ретранслятор дістатися приватних адрес — зокрема сервісів із внутрішнього боку самого сервера. Ми перевірили: з цими рядками ретрансляцію на приватну адресу відхиляють з «403 Forbidden IP».
Облікові дані з терміном дії
З use-auth-secret coturn приймає ім'я користувача, що містить час закінчення дії, і пароль, який є його HMAC. Генерує їх ваш бекенд; секрет ніколи не залишає серверної сторони. На Node.js:
const crypto = require("crypto");
// Тимчасові логін/пароль для TURN (схема TURN REST API, яку coturn розуміє через use-auth-secret).
function turnCredentials(secret, user, ttlSeconds = 3600) {
const username = `${Math.floor(Date.now() / 1000) + ttlSeconds}:${user}`;
const credential = crypto.createHmac("sha1", secret).update(username).digest("base64");
return { username, credential };
}
console.log(JSON.stringify(turnCredentials(process.env.TURN_SECRET, "alice")));
У браузері запитайте в бекенда свіжу пару й передайте її в RTCPeerConnection:
const { username, credential } = await fetch("/api/turn-credentials").then((r) => r.json());
const pc = new RTCPeerConnection({
iceServers: [
{ urls: "stun:turn.example.com:3478" },
{
urls: ["turn:turn.example.com:3478?transport=udp", "turn:turn.example.com:3478?transport=tcp"],
username,
credential,
},
],
});
Перевірка
На самому сервері, за тією самою схемою через openssl (вона видає рівно той самий пароль, що й код на Node.js, — ми звірили):
U="$(( $(date +%s) + 3600 )):test"
P=$(echo -n "$U" | openssl dgst -binary -sha1 -hmac "$SECRET" | base64)
turnutils_uclient -y -n 10 -u "$U" -w "$P" YOUR_SERVER_IP
Наприкінці має бути «Total lost packets 0». З неправильним паролем клієнт зупиняється на «Cannot complete Allocation» — це сервер робить свою справу.
Ми також перевірили зі справжнього Chromium: з iceTransportPolicy: "relay" і свіжими обліковими даними браузер отримав relay-кандидатів від сервера; з поганим паролем — жодного. Якщо хочете перевірити свою схему так само, увімкніть цю опцію на хвилину — вона змушує кожен дзвінок іти через TURN.
TLS, якщо потрібен
Деякі мережі блокують UDP і прискіпливі до звичайного TCP; TURN поверх TLS проходить крізь більше з них. Отримайте сертифікат на turn.example.com (certbot підійде). Його файли читає лише root, а coturn працює від користувача turnserver, тож дайте coturn власну копію:
mkdir -p /etc/coturn
cp /etc/letsencrypt/live/turn.example.com/fullchain.pem /etc/letsencrypt/live/turn.example.com/privkey.pem /etc/coturn/
chown turnserver: /etc/coturn/*.pem && chmod 640 /etc/coturn/privkey.pem
cat >> /etc/turnserver.conf <<'EOF'
tls-listening-port=5349
cert=/etc/coturn/fullchain.pem
pkey=/etc/coturn/privkey.pem
EOF
systemctl restart coturn && ufw allow 5349/tcp
Додайте turns:turn.example.com:5349?transport=tcp у список urls. Сертифікати короткоживучі, тож покладіть копіювання в deploy hook certbot — інакше TLS тихо зламається на першому ж оновленні.
Корисно знати
- TURN не робить погане з'єднання добрим. Він додає один перехід, тож ставте сервер ближче до тих, кому він потрібен.
- Якщо у вас є SFU — наприклад, videobridge у Jitsi, — це окрема частина. TURN допомагає клієнтам, які не можуть дістатися до нього напряму.
- Уся модель безпеки тримається на секреті. Не пускайте його у фронтенд і змініть, якщо він колись витече.
За темою
- VPS для Jitsi Meet — відеодзвінки на своєму сервері
- Свій Matrix Synapse — дзвінкам у Matrix теж потрібен TURN-сервер
- VPS для сайту на власній IP — застосунок, що видає облікові дані
- Як налаштувати файрвол ufw
Коментарі
Поки немає коментарів. Будьте першим.