VoIP Infrastructure
Asterisk 20 · WebRTC · PJSIP
VitalPBX · Debian 12
VoIP infrastructure: deploying corporate telephony with WebRTC
An international company, remote employees, calls through the browser. A critical DTLS/ECDSA incompatibility fixed through a non-standard transport configuration — properly, without workarounds.
DTLS
root cause — a handshake issue at the transport layer
RSA fix
self-signed instead of ECDSA, full compatibility
2 ext
SIP extensions, WebRTC through the browser
✓ live
two-way audio, system in production
Context
An international company: a corporate PBX with WebRTC calls through the browser, external DID numbers via voip.ms, support for remote employees. Stack: VitalPBX + Asterisk 20 on Debian 12, VitXi WebRTC client.
VitXi WebRTC
voip.ms DID
Remote workers
Problem
Asterisk 20 + ECDSA = no two-way audio. The connection establishes, the DTLS handshake completes, but the RTP stream drops. The standard documentation offered no solution.
ECDSA incompatible
No audio RTP
NAT traversal fail
;; /etc/asterisk/pjsip__20-transport.conf
[transport-wss]
type=transport
protocol=wss
cert_file=/etc/letsencrypt/live/
domain/fullchain.pem
priv_key_file=/etc/letsencrypt/
live/domain/privkey.pem
;; ❌ ECDSA — Asterisk 20 bug
;; no two-way audio
method=tlsv1_2
;; /etc/asterisk/pjsip__20-transport.conf
[transport-wss]
type=transport
protocol=wss
cert_file=/etc/asterisk/
dtls-cert.pem
priv_key_file=/etc/asterisk/
dtls-key.pem
;; ✓ RSA 2048 self-signed
;; fully compatible with Asterisk 20
method=tlsv1_2
# RSA 2048, valid 10 years, for DTLS in Asterisk
openssl req -x509 -newkey rsa:2048 \
-keyout /etc/asterisk/dtls-key.pem \
-out /etc/asterisk/dtls-cert.pem \
-days 3650 -nodes \
-subj "/CN=asterisk-dtls"
# permissions — only asterisk can read the key
chown asterisk:asterisk /etc/asterisk/dtls-*.pem
chmod 600 /etc/asterisk/dtls-key.pem
[global]
type=global
;; ❌ overwrites the default values
external_media_address=159.198.74.173
external_signaling_address=159.198.74.173
;; ❌ RTP is sent to the internal IP
;; SDP contains 192.168.x.x → audio fail
[global](+)
;; (+) = append to the existing section
external_media_address=159.198.74.173
external_signaling_address=159.198.74.173
;; ✓ SDP advertises the public IP
;; RTP reaches the browser without STUN
[transport-wss](+)
local_net=10.0.0.0/8
local_net=192.168.0.0/16
# WebSocket → Asterisk PJSIP WSS transport
location /ws {
proxy_pass https://127.0.0.1:8089;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_ssl_verify off; # self-signed DTLS cert
}
# SSL — Let's Encrypt (ECDSA) for the browser
# Asterisk only sees the RSA self-signed cert internally
ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
Issues resolved:
✓ DTLS/ECDSA fix
✓ NAT append
✓ nginx WSS
✓ two-way RTP