Вашето WebRTC приложение работи на вашия Wi-Fi и не работи при онзи единствен клиент, който звъни от хотел. Медията точка-точка има нужда от път между двете страни; когато и двете са зад строг NAT или защитна стена реже UDP, път няма и обаждането просто не се свързва. Никой не вижда грешка — само безкрайно „свързване…“.
TURN сървърът е резервният вариант точно за такива обаждания: двете страни пращат медията си към него, а той я ретранслира. Ако вграждате видео или глас в приложение, поддържате Matrix или Jitsi за екип или правите гласов чат за игра — трябва ви. coturn е стандартната отворена реализация, и е лека.
Кой план
TURN почти не натоварва CPU и памет. Той харчи трафик: всеки ретранслиран поток минава през сървъра два пъти, на вход и на изход. Трафикът на нашите планове е без лимит при 1 Gbit/s, така че въпросът е колко ретранслирани обаждания вървят едновременно, а не колко ще ви таксуват.
| Едновременно ретранслирани обаждания | План |
|---|---|
| Няколко — екип, малко приложение | Nano-IP: 2 vCPU, 1 GB, 15 GB ($8/месец) |
| Десетки | Micro-IP: 2 vCPU, 2 GB, 25 GB ($10/месец) |
| Повече, или TURN до сървъра на приложението | Small-IP: 4 vCPU, 4 GB, 35 GB ($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
Коментари
Още няма коментари. Бъди първият.