אפליקציית ה-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
תגובות
אין עדיין תגובות. היו הראשונים.