TURN
Протокол TURN для видеокоммуникаций
TURN (Traversal Using Relays around NAT) – это сетевой протокол, который используется для обеспечения связи между устройствами через NAT (Network Address Translation), особенно в случаях, когда прямое соединение невозможно. Этот протокол широко применяется в системах видеоконференцсвязи и VoIP (Voice over IP).
Основы работы протокола TURN
Протокол TURN позволяет устройству, находящемуся за NAT, установить TCP/UDP-соединение с сервером TURN, который затем будет пересылать данные от этого устройства к другим участникам сессии. Таким образом, даже если два устройства находятся за разными NAT, они могут обмениваться данными через посредника – TURN-сервер.
Основные компоненты системы:
- Клиент: устройство, которое хочет установить соединение.
- Сервер TURN: посредник, который помогает устройствам обходить ограничения NAT.
- Пир (Peer): другое устройство, с которым клиент хочет установить соединение.
Процесс взаимодействия выглядит следующим образом:
- Клиент отправляет запрос на сервер TURN с указанием типа соединения (TCP или UDP) и желаемого адреса назначения.
- Сервер TURN выделяет клиенту публичный адрес и порт, а также устанавливает туннель для пересылки данных.
- Когда другой пир отправляет данные на этот публичный адрес, сервер TURN перенаправляет их обратно клиенту.
- В случае двусторонней связи оба клиента могут использовать свои выделенные адреса и порты для обмена данными.
Формат сообщений TURN
Сообщения TURN передаются в формате STUN (Session Traversal Utilities for NAT), но имеют дополнительные поля для управления соединением. Основные типы сообщений включают:
- Allocate: Запрос выделения ресурсов на сервере TURN.
- CreatePermission: Создание разрешения для конкретного IP-адреса.
- ChannelBind: Установка канала для передачи данных без использования дополнительных заголовков.
- Send: Отправка данных через сервер TURN.
- Data: Передача данных от сервера TURN клиенту.
Пример сообщения Allocate:
{
"magic": "0x2112A442",
"transactionID": "0x9cbe67a7b5e6d18f",
"messageType": "Allocate",
"length": 20,
"attributes": [
{
"type": "LIFETIME",
"value": 600
},
{
"type": "REQUESTED-TRANSPORT",
"value": "UDP"
}
]
}
Применение TURN в видеозвонках
Рассмотрим пример использования TURN в системе видеоконференцсвязи. Предположим, у нас есть два участника, каждый из которых находится за своим NAT. Прямое соединение между ними невозможно, поэтому они используют сервер TURN для установления связи.
- Оба участника отправляют запросы на выделение ресурсов на сервере TURN.
- Сервер TURN возвращает каждому участнику публичный IP-адрес и порт.
- Участники обмениваются этими адресами через сигнализационный сервер (например, SIP или WebRTC).
- Теперь участники могут отправлять данные друг другу через сервер TURN.
Пример реализации клиента TURN на Python с использованием библиотеки aioturn:
import asyncio
from aioturn import TurnClient
async def main():
client = await TurnClient.create('turn.example.com', 'username', 'password')
# Выделяем ресурсы на сервере TURN
allocation = await client.allocate()
# Получаем публичный IP-адрес и порт
public_ip, public_port = allocation.relayed_address
print(f'Public IP: {public_ip}, Public Port: {public_port}')
# Создаем разрешение для другого участника
peer_ip = '192.168.1.100'
await client.create_permission(peer_ip)
# Отправляем данные другому участнику
data = b'Hello, World!'
await client.send(data, peer_ip, 5000)
# Ожидаем получения данных от другого участника
received_data = await client.recv()
print(received_data)
# Освобождаем ресурсы
await client.close()
asyncio.run(main())
В этом примере мы создаем клиента TURN, выделяем ресурсы на сервере, получаем публичный IP-адрес и порт, создаем разрешение для другого участника и отправляем ему данные. Затем мы ожидаем получения данных от другого участника и освобождаем ресурсы после завершения работы.