TURN Server زمانی وارد مسیر تماس میشود که WebRTC یا VoIP نتواند بین دو سمت یک مسیر مستقیم قابلاستفاده برای Media پیدا کند. در این حالت، Coturn میتواند صدای رمزنگاریشده را از یک نقطه عمومی روی اینترنت دریافت و به سمت مقابل Relay کند؛ کاری که مخصوصاً پشت CGNAT، NATهای سخت، شبکههای سازمانی محدود و بعضی VPNها حیاتی است.
در این راهنما Coturn را برای یک سناریوی واقعی VoIP راهاندازی میکنیم: دامنه turn.example.com به VPS اشاره میکند، کاربران با Credential معتبر به TURN وصل میشوند، UDP/TCP و TURN over TLS در دسترس هستند و Relay Port Range بهصورت کنترلشده در Firewall باز میشود. سپس NAT، TLS، Realm، احراز هویت، TURN REST API و ابزارهای تست را مرحلهبهمرحله بررسی میکنیم.
در زمان نگارش، Coturn 4.18.0 جدیدترین Release عمومی پروژه است و در ۸ سپتامبر ۲۰۲۶ منتشر شده است. در نسخههای جدید یک تغییر مهم وجود دارد: DTLS Listener دیگر بهصورت پیشفرض فعال نیست و اگر واقعاً TURN over DTLS لازم دارید باید آن را صریحاً فعال کنید. برای بیشتر سناریوهای WebRTC، UDP/TCP روی 3478 و TURN over TLS روی TCP/5349 مسیرهای اصلی هستند.
هدف این مقاله: ساخت TURN Server امن و قابلتست با Coturn، نه فقط بازکردن Port 3478. Realm، Authentication، TLS، Public/Private IP Mapping، Relay Range، Firewall و تست واقعی Allocation همگی باید با هم درست باشند.
TURN چه فرقی با STUN دارد؟
STUN و TURN هر دو بخشی از فرآیند عبور Media از NAT هستند، اما کار یکسانی انجام نمیدهند.
| سرویس | کار اصلی | آیا Media را Relay میکند؟ |
|---|---|---|
| STUN | Public Mapping و نوع اتصال را کشف میکند | خیر |
| TURN | برای Client یک Relay Allocation روی سرور عمومی میسازد | بله |
در WebRTC، ICE معمولاً ابتدا Candidate مستقیم را امتحان میکند. اگر مسیر مستقیم با Host یا Server Reflexive Candidate برقرار نشود، Relay Candidate حاصل از TURN میتواند Media را عبور دهد.
Direct path:
Browser A ---------------- Browser B
If direct path fails:
Browser A ---- TURN Server ---- Browser B
|
Coturn
به همین دلیل TURN باید در مسیر عمومی اینترنت قرار بگیرد و پهنای باند کافی داشته باشد؛ چون برخلاف STUN، ترافیک واقعی تماس از آن عبور میکند.
نسخه فعلی Coturn و نکته مهم ارتقا در ۲۰۲۶
آخرین Release عمومی Coturn در زمان بررسی این مقاله 4.18.0 است. این نسخه در ۸ سپتامبر ۲۰۲۶ منتشر شده است.
در شاخههای جدید چند تغییر مهم برای مدیر سرور وجود دارد:
🔹 DTLS Listener دیگر بهصورت پیشفرض بالا نمیآید و برای فعالکردن آن باید گزینه dtls را تنظیم کنید.
🔹 در تنظیمات فعلی پروژه، حداقل TLS پیشفرض TLS 1.2 است و فعالکردن TLS 1.0/1.1 نیازمند تنظیم صریح است؛ برای Production معمولاً دلیلی برای فعالکردن نسخههای قدیمی ندارید.
🔹 Stateless nonce در نسخههای جدید برای کاهش State و کمک به سناریوهای Load-balanced بهبود یافته است.
🔹 ابزارهای تست turnutils_* همچنان همراه پروژه ارائه میشوند و برای بررسی STUN، Allocation و TLS بسیار کاربردیاند.
نکته نسخه: اگر Coturn را از Repository خود Debian/Ubuntu نصب کنید، ممکن است نسخه Package از آخرین Upstream عقبتر باشد. همیشه بعد از نصب خروجی turnserver --version را ببینید و قبل از استفاده از Optionهای جدید، مستند همان نسخه را بررسی کنید.
پیشنیازهای یک TURN Server مناسب VoIP
🔹 VPS یا سرور با IP عمومی ثابت.
🔹 دامنهای مثل turn.example.com.
🔹 دسترسی Root یا sudo.
🔹 Certificate معتبر برای TURN over TLS.
🔹 Firewall با امکان بازکردن UDP/TCP Listener و Relay Range.
🔹 پهنای باند متناسب با تعداد تماسهایی که واقعاً از TURN Relay میشوند.
برای تماس صوتی، CPU معمولاً Bottleneck اول نیست؛ Bandwidth و تعداد Relay Allocationها مهمترند. اگر ۱۰۰ تماس همزمان مجبور شوند از TURN عبور کنند، سرور هم Traffic ورودی و هم Traffic خروجی آن Media را حمل میکند.
مرحله ۱: DNS را قبل از Coturn درست کنید
یک رکورد A برای دامنه TURN بسازید:
turn.example.com. 300 IN A 203.0.113.50
از روی خود VPS بررسی کنید:
dig +short turn.example.com
باید Public IP واقعی سرور را برگرداند.
مرحله ۲: Coturn را نصب کنید
روی Debian/Ubuntu:
apt update
apt install -y coturn
نسخه:
turnserver --version
و وضعیت سرویس:
systemctl status coturn
در بعضی Packageهای قدیمی Debian/Ubuntu ممکن است فعالسازی سرویس از طریق /etc/default/coturn هم لازم باشد. اگر سرویس عمداً Disabled شده بود، فایل Package همان Distribution را بررسی کنید.
مرحله ۳: Realm را درست انتخاب کنید
realm فقط یک Label ظاهری نیست. در Long-Term Credential Mechanism، Realm بخشی از محاسبه کلید احراز هویت است.
یک انتخاب ساده و پایدار:
realm=turn.example.com
server-name=turn.example.com
مستند Coturn صراحتاً اشاره میکند اگر Realm را بعداً تغییر دهید، کلیدهای Long-Term Credential کاربران باید دوباره ساخته شوند؛ چون Realm در تولید HMAC Key نقش دارد.
مرحله ۴: Listener و Relay Port Range را مشخص کنید
یک Config ساده و قابلکنترل در /etc/turnserver.conf:
listening-port=3478
tls-listening-port=5349
realm=turn.example.com
server-name=turn.example.com
min-port=49160
max-port=49260
fingerprint
stale-nonce=600
no-multicast-peers
پورتهای پیشفرض Coturn عبارتاند از:
| کاربرد | پورت | پروتکل |
|---|---|---|
| TURN/STUN Listener | 3478 | UDP و TCP |
| TURN over TLS | 5349 | TCP |
| TURN over DTLS در صورت فعالسازی | 5349 | UDP |
| Relay Allocation | 49160-49260 در این مثال | UDP |
محدوده پیشفرض Relay در Coturn بسیار بزرگتر است؛ از 49152 تا 65535. برای یک VPS کوچک میتوانید Range را محدود کنید، اما باید بدانید Range کوچکتر سقف Allocation را هم محدود میکند.
مرحله ۵: اگر سرور Public IP مستقیم دارد، NAT Mapping اضافه نکنید
اگر IP عمومی مستقیماً روی Interface سرور Bind شده است، معمولاً نیازی به external-ip ندارید.
اما اگر Coturn پشت NAT یا روی Private IP اجرا میشود:
listening-ip=10.0.0.20
relay-ip=10.0.0.20
external-ip=203.0.113.50/10.0.0.20
مستند Coturn تأکید میکند در این حالت NAT باید Relay Port را با همان شماره Port به Public Side نگاشت کند. یعنی اگر Allocation داخلی روی 49180 است، Mapping عمومی نیز باید همان 49180 را به همان Port داخلی برساند.
خطای رایج: فقط Forward کردن 3478 کافی نیست. TURN بعد از Authentication یک Relay Port از Range مشخصشده میسازد؛ اگر آن Range در Firewall/NAT عبور نکند، Allocation ساخته میشود اما Media ردوبدل نمیشود.
مرحله ۶: برای TLS یک Certificate معتبر تنظیم کنید
فرض کنیم Certificate معتبر برای turn.example.com دارید:
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
در Coturn فعلی، TLS 1.2 حداقل پیشفرض است و TLS 1.0/1.1 فقط با تنظیم صریح فعال میشوند. برای Production معمولاً همان Default امنتر را نگه دارید.
اگر به TURN over DTLS نیاز دارید و نسخه فعلی Coturn دارید:
dtls
DTLS را فقط زمانی فعال کنید که Client شما واقعاً از آن استفاده میکند. برای WebRTC معمولی، turn: روی UDP/TCP و turns: روی TLS/TCP اغلب کافیاند.
مرحله ۷: برای تست اولیه یک کاربر ثابت بسازید
برای Lab و تست، Long-Term Credential ساده است. ابتدا Config را طوری تنظیم کنید:
lt-cred-mech
realm=turn.example.com
کاربر تستی را با turnadmin اضافه کنید:
turnadmin -a \
-u voip-test \
-p 'CHANGE_TO_A_LONG_RANDOM_PASSWORD' \
-r turn.example.com
این روش برای تست مناسب است، اما قرار دادن Username/Password دائمی داخل JavaScript عمومی انتخاب خوبی برای Production نیست.
مرحله ۸: برای Production از Credential زماندار TURN REST API استفاده کنید
Coturn یک مدل مناسب WebRTC دارد که با use-auth-secret فعال میشود. در این مدل Browser Password دائمی ندارد. Backend شما Credential کوتاهعمر تولید میکند.
Config:
use-auth-secret
static-auth-secret=REPLACE_WITH_A_LONG_RANDOM_SECRET
realm=turn.example.com
Secret قوی بسازید:
openssl rand -hex 32
مستند رسمی Coturn الگوریتم Credential زماندار را اینطور تعریف میکند:
temporary_username = expiry_timestamp + ":" + user_id
temporary_password =
base64(
HMAC-SHA1(
temporary_username,
shared_secret
)
)
نمونه PHP سمت Backend:
<?php
$secret = getenv('TURN_SHARED_SECRET');
$userId = 'user-123';
$expiry = time() + 3600;
$username = $expiry . ':' . $userId;
$password = base64_encode(
hash_hmac('sha1', $username, $secret, true)
);
header('Content-Type: application/json');
echo json_encode([
'username' => $username,
'credential' => $password,
'ttl' => 3600,
]);
Shared Secret هیچوقت نباید وارد JavaScript عمومی شود. فقط Username و Credential موقت تولیدشده را به Client برگردانید.
مرحله ۹: Firewall را کامل و محدود باز کنید
اگر در Config همین Relay Range را دارید:
min-port=49160
max-port=49260
نمونه UFW:
ufw allow 3478/udp
ufw allow 3478/tcp
ufw allow 5349/tcp
ufw allow 49160:49260/udp
اگر dtls را فعال کردهاید و Client واقعاً از TURN over DTLS استفاده میکند:
ufw allow 5349/udp
در سناریوی TURN over TCP Relay یا Configهای خاص، Port Requirement میتواند متفاوت باشد. Firewall را با Transportهایی باز کنید که واقعاً در Client استفاده میکنید.
چرا no-auth برای TURN عمومی خطرناک است؟
بدون Authentication، هر کاربر اینترنت میتواند سرور شما را برای Relay Traffic مصرف کند. نتیجه میتواند مصرف Bandwidth، هزینه، Abuse و حتی استفاده از TURN بهعنوان مسیر دسترسی ناخواسته باشد.
برای WebRTC عمومی حداقل یکی از این دو مدل را داشته باشید:
🔹 Long-Term Credential با کاربرهای مشخص برای Lab/سیستم کنترلشده.
🔹 TURN REST API با Credential کوتاهعمر برای Web Application عمومی.
همچنین no-multicast-peers را فعال نگه دارید و فقط در محیط آزمایش گزینههایی مثل Allow Loopback Peer را بررسی کنید؛ مستند Coturn درباره بازکردن Loopback Peer در Production هشدار امنیتی داده است.
Quota و Bandwidth Limit را برای جلوگیری از Abuse تنظیم کنید
Coturn امکان محدودکردن Allocation و Bandwidth را دارد:
user-quota=8
total-quota=500
این اعداد فقط Example هستند. مقدار مناسب باید با تعداد Tab، Device و Call همزمان واقعی شما تعیین شود.
همچنین Optionهای max-bps و bps-capacity برای محدودکردن Bandwidth Session یا کل Server وجود دارند، اما محدودیت خیلی پایین میتواند کیفیت Audio/Video را خراب کند.
مرحله ۱۰: Coturn را Restart و Listenerها را بررسی کنید
systemctl restart coturn
systemctl status coturn
Listenerها:
ss -lntup | grep -E '3478|5349'
Log زنده:
journalctl -u coturn -f
تست ۱: STUN را با turnutils_stunclient بررسی کنید
این تست TURN Allocation را ثابت نمیکند؛ فقط STUN Binding را بررسی میکند:
turnutils_stunclient turn.example.com
برای تست پیوسته Latency و Loss در نسخههای جدید ابزار:
turnutils_stunclient -c turn.example.com
تست ۲: TURN Allocation را با turnutils_uclient بررسی کنید
برای User ثابت تستی:
turnutils_uclient \
-u voip-test \
-w 'YOUR_TEST_PASSWORD' \
-y \
-v \
turn.example.com
گزینه -y Client-to-client Test را فعال میکند و برای تست Relay نیازی به turnutils_peer جدا ندارد.
برای TCP/TLS:
turnutils_uclient \
-t \
-S \
-p 5349 \
-u voip-test \
-w 'YOUR_TEST_PASSWORD' \
-y \
-v \
turn.example.com
تست ۳: Certificate پورت 5349 را مستقیم ببینید
openssl s_client \
-connect turn.example.com:5349 \
-servername turn.example.com
نام دامنه، Chain Certificate و تاریخ اعتبار را بررسی کنید.
تست ۴: Browser را مجبور کنید فقط TURN استفاده کند
برای تشخیص اینکه TURN واقعاً کار میکند، موقتاً Direct Candidateها را کنار بگذارید:
const pc = new RTCPeerConnection({
iceTransportPolicy: 'relay',
iceServers: [
{
urls: [
'turn:turn.example.com:3478?transport=udp',
'turn:turn.example.com:3478?transport=tcp',
'turns:turn.example.com:5349?transport=tcp'
],
username: TURN_USERNAME,
credential: TURN_CREDENTIAL
}
]
});
MDN توضیح میدهد وقتی iceTransportPolicy روی relay باشد، فقط Candidateهای Relay مثل TURN در نظر گرفته میشوند. اگر در این حالت ICE Connected نمیشود، مشکل را مستقیماً روی TURN بررسی کنید.
Trickle ICE؛ تست ساده از خود مرورگر
صفحه Trickle ICE پروژه WebRTC یکی از سریعترین راهها برای دیدن Candidateهاست. TURN URL و Credential را وارد کنید و بررسی کنید آیا Candidate از نوع relay ساخته میشود یا نه.
اگر فقط host و srflx میبینید ولی relay ندارید، TURN Allocation موفق نشده است.
خطای 401 در TURN همیشه بد نیست
در Long-Term Credential، Challenge احراز هویت بخشی از فرآیند طبیعی است. مهم این است که Client بعد از دریافت Realm/Nonce با Credential درست Retry کند و Allocation نهایی موفق شود.
اما اگر Loop دائمی 401 دارید، این موارد را بررسی کنید:
🔹 Realm Client و Server با هم سازگار باشد.
🔹 Username/Password یا Credential زماندار درست باشد.
🔹 ساعت سرور برای Credentialهای Timestamp-based درست باشد.
🔹 Shared Secret سمت Backend و Coturn یکی باشد.
🔹 از دو Mechanism احراز هویت متضاد همزمان استفاده نکرده باشید.
خطای 438 Stale Nonce چیست؟
Nonce عمر محدود دارد. Coturn بهصورت پیشفرض میتواند بعد از زمان مشخص Client را مجبور به Authentication مجدد کند. در Config نمونه ما:
stale-nonce=600
یک Client استاندارد باید 438 را مدیریت و با Nonce جدید درخواست را تکرار کند. اگر Application دستساز دارید، این رفتار را تست کنید.
TURN روی 443؛ چه زمانی لازم میشود؟
بعضی شبکهها فقط Web Traffic را اجازه میدهند. Coturn میتواند Listener را روی Portهایی مثل 443 هم اجرا کند، اما این تصمیم باید با HTTPS Server، Reverse Proxy و سرویسهای دیگر همان IP هماهنگ شود.
اگر هدف شما عبور از Firewall سختگیر است، معمولاً TURN over TLS/TCP روی 443 گزینهای است که باید در Lab واقعی همان شبکه تست شود. فقط تغییر Port بدون Certificate، Auth و Relay Range درست، مشکل را حل نمیکند.
Monitoring و Capacity؛ TURN بیشتر از آنچه فکر میکنید Bandwidth میخورد
وقتی Media از TURN عبور میکند، Server در وسط مسیر است. برای هر Stream، Packet وارد سرور و دوباره خارج میشود. بنابراین در Capacity Planning فقط Bitrate Codec را یکبار حساب نکنید.
این شاخصها را مانیتور کنید:
🔹 Active Allocations.
🔹 Bandwidth ورودی/خروجی.
🔹 Packet Drop روی NIC.
🔹 Allocation Failure.
🔹 Authentication Failure.
🔹 تعداد Connectionهای TCP/TLS.
🔹 مصرف Relay Port Range.
Coturn Exporter داخلی Prometheus هم دارد، اما مستند فعلی پروژه اشاره میکند این قابلیت در Packageهای apt معمولاً در دسترس نیست و به Build مناسب نیاز دارد. Port پیشفرض Exporter برابر 9641 و مسیر پیشفرض Metrics برابر /metrics است.
یک Config جمعوجور برای Production کوچک
این نمونه برای VPS با Public IP مستقیم، TLS و TURN REST API نوشته شده است:
listening-port=3478
tls-listening-port=5349
realm=turn.example.com
server-name=turn.example.com
fingerprint
use-auth-secret
static-auth-secret=REPLACE_WITH_A_LONG_RANDOM_SECRET
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
min-port=49160
max-port=49260
stale-nonce=600
user-quota=8
total-quota=500
no-multicast-peers
اگر سرور پشت NAT است، external-ip را متناسب با Public/Private IP اضافه کنید. اگر DTLS Listener لازم دارید، dtls را هم اضافه کنید.
مطلب مرتبط: اگر میخواهید یک نمونه دیگر از کاربرد Coturn روی VPS ایران را ببینید، راهنمای PairDrop ایرانیکاسرور نیز از Coturn برای عبور ارتباط پشت NAT استفاده میکند.
اشتباههای رایج در Coturn
🔹 بازکردن فقط 3478 و فراموشکردن Relay Port Range.
🔹 تنظیم external-ip روی سروری که Public IP مستقیم دارد.
🔹 پشت NAT بودن Coturn بدون Port-preserving Mapping برای Relay Range.
🔹 استفاده از no-auth روی اینترنت عمومی.
🔹 قراردادن Shared Secret TURN REST API داخل JavaScript.
🔹 تغییر Realm بعد از ساخت User Key و فراموشکردن بازسازی Credentialها.
🔹 تصور اینکه STUN Test موفق یعنی TURN Relay هم سالم است.
🔹 باز بودن 5349 ولی Certificate اشتباه یا منقضی.
🔹 فعالکردن DTLS بر اساس آموزشهای قدیمی بدون بررسی نیاز واقعی Client.
برای راهاندازی Coturn روی VPS کمک میخواهید؟
اگر دامنه، Public IP، تعداد تماس همزمان و نوع Clientهای WebRTC مشخص باشند، میتوان Coturn را با TLS، Credential زماندار، Firewall و Relay Range مناسب آماده و با تست واقعی TURN Allocation اعتبارسنجی کرد.
ایرانیکاسرور میتواند برای تهیه VPS، نصب Coturn، تنظیم TLS، NAT، Firewall و تست TURN در کنار Asterisk یا WebRTC کمک کند.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467
پرسشهای رایج
Coturn چیست؟
Coturn یک پیادهسازی متنباز STUN/TURN Server است که برای ساخت Relay Media در WebRTC و ارتباطهای Real-time پشت NAT استفاده میشود.
STUN و TURN چه فرقی دارند؟
STUN Public Mapping را کشف میکند اما Media را Relay نمیکند. TURN روی سرور عمومی Allocation میسازد و Media را بین دو سمت عبور میدهد.
پورتهای اصلی Coturn کداماند؟
پورت پیشفرض TURN/STUN برابر 3478 برای UDP/TCP و پورت پیشفرض TLS برابر 5349 است. Relay Port Range نیز باید جداگانه در Firewall باز شود.
Realm در Coturn چه کاربردی دارد؟
Realm بخشی از Long-Term Credential Mechanism است و در تولید کلید احراز هویت نقش دارد. اگر Realm را تغییر دهید، Credential Keyهای وابسته به Realm باید دوباره تولید شوند.
برای WebRTC بهتر است User ثابت داشته باشیم یا Credential زماندار؟
برای تست User ثابت سادهتر است، اما برای Web Application عمومی Credential زماندار با TURN REST API امنتر است چون Password دائمی داخل Frontend قرار نمیگیرد.
چطور بفهمیم TURN واقعاً استفاده میشود؟
باید ICE Candidate از نوع relay ببینید. برای تست میتوانید موقتاً iceTransportPolicy را روی relay قرار دهید تا Browser فقط از TURN استفاده کند.
اگر Coturn پشت NAT باشد چه کنیم؟
Public/Private Mapping را با external-ip تعریف کنید و Listener و Relay Port Range را با همان شماره Port از NAT عبور دهید.
آیا DTLS در Coturn 4.18 بهصورت خودکار فعال است؟
خیر. در نسخههای جدید DTLS Listener بهصورت پیشفرض فعال نیست و اگر لازم باشد باید گزینه dtls را صریحاً فعال کنید.
جمعبندی
TURN Server زمانی لازم میشود که مسیر مستقیم WebRTC یا VoIP از NAT و Firewall عبور نکند. Coturn این مشکل را با ساخت Relay Allocation روی یک IP عمومی حل میکند، اما فقط زمانی درست کار میکند که Realm، Authentication، Listener، Relay Range و NAT Mapping همه با هم هماهنگ باشند.
برای شروع، UDP/TCP روی 3478 و TURN over TLS روی 5349 را راهاندازی کنید، Relay Range را محدود و در Firewall باز کنید و برای Production بهجای Password ثابت در Frontend از Credential زماندار TURN REST API استفاده کنید.
در پایان فقط STUN را تست نکنید. با turnutils_uclient Allocation واقعی بسازید و در Browser نیز با iceTransportPolicy: 'relay' مطمئن شوید Relay Candidate واقعاً قابلاستفاده است.
برای نصب Coturn روی VPS کمک میخواهید؟
اگر Public IP، دامنه و تعداد تماسهای همزمان مشخص باشند، میتوان Relay Range، TLS و Credential Policy را قبل از استفاده واقعی WebRTC تست کرد.
تماس با پشتیبانی ایرانیکاسرور: 021-91302467
”’
# Validate
scripts = re.findall(r’‘, html, flags=re.S)
assert len(scripts) == 1
json.loads(scripts[0])
for bad in (“<article”, ”
“, “<html”, “<body”, “<head”):
assert bad not in html.lower()
assert not re.search(r'<h[23][^>]*color\s*:’, html, re.I)
html_path = Path(“/mnt/data/coturn-voip-turn-server-nat-wordpress.html”)
html_path.write_text(html, encoding=”utf-8″)
info = “””کلیدواژه کانونی:
عنوان سئو:
نامک:
توضیح متا:
متن جایگزین:
عنوان:
عنوان تصویر:
توضیح:
عنوان نهایی مقاله:
راهاندازی TURN Server با Coturn برای VoIP پشت NAT؛ از TLS تا تست واقعی
برچسبها:






دیدگاهها (۰)