Траблшутинг SIP over TCP и WebSockets: фрагментация, MTU и Keepalive
- SIP-сообщения INVITE с длинным SDP (множество кодеков, видео, ICE-кандидаты) отбрасываются при работе по UDP.
- Разрыв соединений WebRTC / SIP over WebSockets через 30-60 секунд после установления вызова.
- Ошибка
400 Bad Request (Message too large)или500 Server Internal Errorна софтфонах и в веб-клиентах. - Nginx / Reverse Proxy обрывает соединения
WebSocket connection closed prematurely.
1. Проблема фрагментации UDP и принудительный переход на TCP/TLS
Если размер SIP-сообщения превышает Path MTU (стандартно 1500 байт, за вычетом заголовков — 1300 байт), пакет фрагментируется на сетевом уровне. Роутеры с NAT часто отбрасывают фрагментированные UDP-пакеты. Решение — использование TCP/TLS:
# Включение TCP/TLS транспорта в Asterisk (pjsip.conf)
[transport-tcp]
type=transport
protocol=tcp
bind=0.0.0.0:5060
[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/asterisk.crt
priv_key_file=/etc/asterisk/keys/asterisk.key
method=tlsv1_22. Настройка WebRTC SIP over Secure WebSockets (WSS) в PJSIP
Добавьте WSS транспорт в /etc/asterisk/pjsip.conf:
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0:8089
[webrtc_endpoint]
type=endpoint
transport=transport-wss
context=from-internal
disallow=all
allow=opus,ulaw,alaw
dtmf_mode=rfc4733
use_avpf=yes
media_encryption=dtls
dtls_verify=fingerprint
dtls_cert_file=/etc/asterisk/keys/asterisk.crt
dtls_private_key=/etc/asterisk/keys/asterisk.key
dtls_setup=actpass
ice_support=yes
media_use_received_transport=yes
rtcp_mux=yes3. Конфигурация Nginx в качестве WSS Reverse Proxy для SIP-клиентов
Чтобы избежать прямого подключения веб-сокетов к PBX, проксируйте трафик через Nginx:
upstream asterisk_wss {
server 127.0.0.1:8089;
}
server {
listen 443 ssl;
server_name sip.company.com;
ssl_certificate /etc/letsencrypt/live/sip.company.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sip.company.com/privkey.pem;
location /ws {
proxy_pass http://asterisk_wss;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Предотвращение обрыва Keepalive сессии прокси
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}4. Настройка интервалов SIP Keepalive
Для предотвращения закрытия состояния трансляции в NAT-таблицах промежуточных межсетевых экранов настройте постоянную отправку CRLF или OPTION пингов каждые 15-25 секунд на стороне клиента и сервера.
Частые вопросы (FAQ)
Почему SIP over UDP часто сбоит при наличии видеокодеков H.264 / VP8?
SDP-описание видеосессии содержит огромное количество криптографических атрибутов (SRTP crypto), ICE кандидатов и параметров кодека. Размер пакета превышает MTU (1500 байт), вызывая фрагментацию IP, которую большинство недорогих NAT-маршрутизаторов корректно собрать не могут.
Зачем нужен rtcp_mux=yes при работе через WebSockets?
Опция rtcp-mux мультиплексирует потоки RTP (голос/видео) и RTCP (статистика качества) на один и тот же UDP-порт, снижая требования к количеству открываемых портов на NAT и ускоряя процедуру согласования ICE.
Как решить проблему закрытия WSS-соединений через 60 секунд простоя?
Это происходит из-за дефолтных таймаутов прокси-сервера (Nginx/HAProxy) или закрытия NAT. Включите отправку WebSocket Ping/Pong фреймов в софтфоне каждые 15-20 секунд и увеличьте proxy_read_timeout в Nginx.
Чем отличается обработка SIP сообщений в TCP от UDP на уровне парсера?
В UDP одно сообщение гарантированно умещается в один датаграммный пакет. В потоковом TCP SIP-парсер должен строго отслеживать границы сообщений по заголовку Content-Length, иначе склеенные (streamed) сообщения вызовут синтаксический сбой парсера.