Ứng dụng WebRTC của bạn chạy trên Wi-Fi của bạn và thất bại với đúng vị khách gọi từ khách sạn. Âm thanh và hình ảnh peer-to-peer cần một đường đi giữa hai phía; khi cả hai nằm sau NAT khắt khe, hoặc tường lửa chặn UDP, không có đường và cuộc gọi đơn giản là không kết nối. Không ai thấy lỗi — chỉ thấy “đang kết nối…” mãi không dứt.
Máy chủ TURN là phương án dự phòng cho đúng những cuộc gọi đó: cả hai phía gửi dữ liệu tới nó, và nó chuyển tiếp. Nếu bạn đang đưa video hay giọng nói vào ứng dụng, chạy Matrix hay Jitsi cho một nhóm, hoặc làm voice chat cho game, bạn cần một máy chủ như vậy. coturn là bản cài đặt mã nguồn mở tiêu chuẩn, và nó nhẹ.
Chọn gói nào
TURN tốn rất ít CPU và bộ nhớ. Thứ nó dùng là băng thông: mỗi luồng được chuyển tiếp đi qua máy chủ hai lần, vào và ra. Lưu lượng trên các gói của chúng tôi không giới hạn ở 1 Gbit/s, nên câu hỏi là có bao nhiêu cuộc gọi chuyển tiếp chạy cùng lúc, chứ không phải bạn bị tính bao nhiêu tiền.
| Số cuộc gọi chuyển tiếp cùng lúc | Gói |
|---|---|
| Vài cuộc — một nhóm, một ứng dụng nhỏ | Nano-IP: 2 vCPU, 1 GB, 15 GB ($8/tháng) |
| Vài chục | Micro-IP: 2 vCPU, 2 GB, 25 GB ($10/tháng) |
| Nhiều hơn, hoặc TURN cạnh máy chủ ứng dụng | Small-IP: 4 vCPU, 4 GB, 35 GB ($16/tháng) |
Phải là gói có IPv4 riêng — TURN hoàn toàn dựa vào kết nối đi vào trên nhiều cổng, còn gói NAT chỉ nhận SSH từ bên ngoài. Trên các gói có IP riêng của chúng tôi, địa chỉ công khai nằm ngay trên giao diện mạng của máy chủ, nên coturn tự tìm thấy mà không cần dòng external-ip. Đặt máy chủ gần người dùng: Đức hoặc Phần Lan, tình trạng còn chỗ hiển thị khi đặt hàng. Thanh toán bằng crypto, không cần KYC, nếu điều đó quan trọng với bạn.
Các cổng cần mở: 3478 UDP và TCP, 49152–65535 UDP cho dữ liệu chuyển tiếp, và 5349 TCP nếu bạn thêm TLS.
Cài đặt và cấu hình
Với quyền root trên Ubuntu 24.04 hoặc Debian 12:
apt install -y coturn
ip -4 addr # IP công khai của bạn phải có trên interface
Ghi cấu hình với một bí mật dùng chung mới:
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" # backend của bạn cần giá trị này
systemctl restart coturn
ufw allow 22/tcp && ufw allow 3478 && ufw allow 49152:65535/udp && ufw enable
Đừng bỏ các dòng denied-peer-ip. Thiếu chúng, bất kỳ ai có thông tin đăng nhập hợp lệ cũng có thể dùng relay của bạn để tới các địa chỉ riêng — kể cả dịch vụ ở phía nội bộ của chính máy chủ. Chúng tôi đã kiểm tra: có các dòng này, relay tới địa chỉ riêng bị từ chối với “403 Forbidden IP”.
Thông tin đăng nhập có hạn
Với use-auth-secret, coturn chấp nhận tên người dùng chứa thời điểm hết hạn và mật khẩu là HMAC của tên đó. Backend của bạn tạo ra chúng; bí mật không bao giờ rời phía máy chủ. Bằng Node.js:
const crypto = require("crypto");
// Tên người dùng/mật khẩu TURN tạm thời (lược đồ TURN REST API mà coturn hiểu qua 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")));
Trong trình duyệt, hãy xin backend một cặp mới và đưa nó cho 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,
},
],
});
Kiểm tra
Từ máy chủ, theo cùng sơ đồ bằng openssl (nó cho ra đúng mật khẩu như mã Node.js — chúng tôi đã so):
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
Cuối cùng bạn muốn thấy “Total lost packets 0”. Với mật khẩu sai, client dừng ở “Cannot complete Allocation” — đó là máy chủ đang làm đúng việc.
Chúng tôi cũng đã kiểm tra từ một Chromium thật: với iceTransportPolicy: "relay" và thông tin đăng nhập mới, trình duyệt nhận được relay candidate từ máy chủ; với mật khẩu sai thì không có cái nào. Nếu muốn thử cấu hình của bạn theo cách tương tự, hãy bật tùy chọn đó một lúc — nó buộc mọi cuộc gọi đi qua TURN.
TLS, nếu cần
Một số mạng chặn UDP và khó tính với TCP thường; TURN qua TLS đi lọt được nhiều mạng hơn. Lấy chứng chỉ cho turn.example.com (certbot là được). Tệp của nó chỉ root đọc được, trong khi coturn chạy dưới người dùng turnserver, nên hãy cho coturn một bản sao riêng:
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
Thêm turns:turn.example.com:5349?transport=tcp vào danh sách urls. Chứng chỉ có thời hạn ngắn, nên hãy đưa bước sao chép vào deploy hook của certbot — nếu không, TLS sẽ âm thầm hỏng ở lần gia hạn đầu tiên.
Nên biết
- TURN không biến kết nối kém thành kết nối tốt. Nó thêm một chặng, nên hãy đặt máy chủ gần những người cần nó.
- Nếu bạn chạy SFU — ví dụ videobridge của Jitsi — đó là một thành phần riêng. TURN giúp các client không tới được nó trực tiếp.
- Toàn bộ mô hình bảo mật nằm ở bí mật. Giữ nó ngoài frontend, và đổi nó nếu có lúc bị lộ.
Liên quan
- VPS cho Jitsi Meet: gọi video trên máy chủ của riêng bạn
- Tự host Matrix Synapse: cuộc gọi trong Matrix cũng cần máy chủ TURN
- VPS cho website trên IP riêng: ứng dụng cấp thông tin đăng nhập
- Cách cấu hình tường lửa ufw
Bình luận
Chưa có bình luận nào. Hãy là người đầu tiên.