−25%

на річну оплату Windows, до 31.10. До тарифів

EQVPS
Почати

VPS для TURN-сервера (coturn) під WebRTC

Дзвінки, що не проходять крізь суворий NAT, рятує TURN-ретранслятор. coturn на сервері зі своєю IPv4: порти, тимчасові облікові дані, перевірений конфіг.

Ваш 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 допомагає клієнтам, які не можуть дістатися до нього напряму.
  • Уся модель безпеки тримається на секреті. Не пускайте його у фронтенд і змініть, якщо він колись витече.

За темою

Готові розгорнути? Оплата криптою, без KYC — сервер за хвилину.

Розгорнути →

Часті питання

Навіщо WebRTC-дзвінкам взагалі TURN-сервер?

WebRTC намагається з'єднати учасників напряму, і зазвичай це вдається. Коли обидві сторони за симетричним NAT або файрволом, що ріже UDP, — готельний Wi-Fi, офісні мережі, деякі мобільні оператори, — прямого шляху немає, і дзвінок мовчки не встановлюється. TURN-сервер ретранслює медіа саме для таких дзвінків; зазвичай називають частку десь близько одного дзвінка з десяти.

Чи може TURN працювати на тарифі NAT?

Ні. Клієнти підключаються на UDP і TCP 3478 та на діапазон портів ретрансляції, а тариф NAT ззовні приймає тільки ваш SSH-порт. Потрібен тариф зі своєю IPv4.

Скільки трафіку він споживає?

Кожен ретрансльований потік проходить через сервер двічі — від однієї сторони всередину й назовні до іншої. Відеодзвінок один на один по 1–2 Мбіт/с у кожен бік — це кілька Мбіт/с на сервері. CPU й RAM цього майже не помічають; справжня стеля — порт 1 Гбіт/с.

Чому б просто не прописати в застосунку постійні логін і пароль?

Бо все, що лежить у JavaScript браузера, публічне, а TURN-сервер з відомим паролем — безкоштовний ретранслятор для всього інтернету. З use-auth-secret ваш бекенд видає облікові дані з терміном дії, підписані секретом, якого браузер ніколи не бачить.

Чи потрібен TLS на порту 5349?

Він допомагає в мережах, що блокують UDP і прискіпливі до звичайного TCP. Додавайте його, коли звичайний TURN уже працює: дайте coturn сертифікат на ім'я TURN-сервера й відкрийте 5349/tcp. Ретрансляцію через TLS ми теж перевірили.

Коментарі

Поки немає коментарів. Будьте першим.

Залишити коментар

Коментарі проходять модерацію перед публікацією.