Asterisk WebRTC Setup Guide

Enable browser-based voice and video calls with Asterisk using WebSocket, DTLS-SRTP, ICE, and STUN/TURN

What is WebRTC with Asterisk?

WebRTC (Web Real-Time Communication) allows voice and video calls directly in a web browser without any plugins. When combined with Asterisk, users can make and receive phone calls from a webpage, softphone app, or mobile web app.

Required Components:

ComponentPurposeAsterisk Requirement
WebSocket (WSS)SIP signaling transport (replaces UDP/TCP)PJSIP with protocol=wss
DTLS-SRTPMedia encryption (browsers require it)media_encryption=dtls
ICE / STUN / TURNNAT traversal for mediaSTUN/TURN server addresses
Opus CodecAudio codec (required by browsers)allow=opus
Valid TLS CertificateBrowsers reject self-signed certs for WSSLet's Encrypt or commercial cert
Critical: WebRTC requires encryption. Browsers will not allow unencrypted WebSocket (ws://) or unencrypted media. You must use WSS (WebSocket Secure) with valid TLS certificates and DTLS-SRTP for media.

Step 1: PJSIP WebSocket Transport

; pjsip.conf - WebSocket Secure (WSS) transport

; Standard UDP transport (keep for non-WebRTC endpoints)
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060

; WebSocket Secure transport (for WebRTC)
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0:8089
; Use valid TLS certificates (Let's Encrypt recommended)
cert_file=/etc/asterisk/keys/fullchain.pem
priv_key_file=/etc/asterisk/keys/privkey.pem
; For self-signed (development only - browsers will reject):
; cert_file=/etc/asterisk/keys/asterisk.crt
; priv_key_file=/etc/asterisk/keys/asterisk.key
method=tlsv1_2

Enable HTTP Server (http.conf):

; /etc/asterisk/http.conf
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088        ; HTTP port
tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/keys/fullchain.pem
tlsprivatekey=/etc/asterisk/keys/privkey.pem

Step 2: WebRTC Endpoint Configuration

; pjsip.conf - WebRTC endpoint

[webrtc-user]
type=endpoint
transport=transport-wss
context=internal
disallow=all
allow=opus           ; Required: browsers prefer Opus
allow=ulaw           ; Fallback
allow=vp8            ; Video codec (optional)
allow=vp9            ; Video codec (optional)

; WebRTC-specific settings (shorthand)
webrtc=yes
; The "webrtc=yes" shorthand sets all of these:
;   use_avpf=yes
;   media_encryption=dtls
;   dtls_auto_generate_cert=yes
;   dtls_verify=fingerprint
;   dtls_setup=actpass
;   ice_support=yes
;   media_use_received_transport=yes
;   rtcp_mux=yes

; Audio settings
max_audio_streams=1
max_video_streams=1

; NAT settings
direct_media=no
force_rport=yes
rewrite_contact=yes
rtp_symmetric=yes

; Authentication
auth=webrtc-user-auth
aors=webrtc-user-aor

[webrtc-user-auth]
type=auth
auth_type=userpass
username=webrtc-user
password=SecurePassword123

[webrtc-user-aor]
type=aor
max_contacts=5
remove_existing=yes
Tip: The webrtc=yes shorthand (available in Asterisk 16.3+) automatically configures all required WebRTC settings. For older versions, you must set each option individually.

Step 3: ICE, STUN & TURN Configuration

ICE (Interactive Connectivity Establishment) uses STUN and TURN servers to discover the best media path through NAT. This is essential for WebRTC.

Asterisk RTP Configuration (rtp.conf):

; /etc/asterisk/rtp.conf
[general]
rtpstart=10000
rtpend=20000

; STUN server for ICE (Asterisk uses this for its own NAT detection)
stunaddr=stun.l.google.com:19302

; ICE support
icesupport=yes

; TURN server (if you run your own)
; turnaddr=turn.example.com
; turnusername=asterisk
; turnpassword=secret

Browser-Side STUN/TURN Configuration:

// In your JavaScript WebRTC client (SIP.js / JsSIP):
const configuration = {
  uri: 'sip:webrtc-user@pbx.example.com',
  transportOptions: {
    wsServers: ['wss://pbx.example.com:8089/ws']
  },
  authorizationUsername: 'webrtc-user',
  authorizationPassword: 'SecurePassword123',
  sessionDescriptionHandlerFactoryOptions: {
    peerConnectionConfiguration: {
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        // TURN server (essential for symmetric NAT):
        {
          urls: 'turn:turn.example.com:3478',
          username: 'turnuser',
          credential: 'turnpassword'
        }
      ]
    }
  }
};

Self-Hosted TURN Server (coturn):

# Install coturn
apt-get install coturn

# /etc/turnserver.conf:
listening-port=3478
tls-listening-port=5349
external-ip=203.0.113.50
realm=pbx.example.com
server-name=turn.example.com
lt-cred-mech
user=turnuser:turnpassword
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem

# Start coturn
systemctl enable coturn
systemctl start coturn

# Open firewall ports for TURN
iptables -A INPUT -p udp --dport 3478 -j ACCEPT
iptables -A INPUT -p tcp --dport 3478 -j ACCEPT
iptables -A INPUT -p udp --dport 5349 -j ACCEPT
iptables -A INPUT -p tcp --dport 5349 -j ACCEPT
# TURN relay ports
iptables -A INPUT -p udp --dport 49152:65535 -j ACCEPT

Step 4: Browser Client (SIP.js)

The most popular JavaScript SIP library for WebRTC is SIP.js. Here is a minimal example:

<!-- Include SIP.js -->
<script src="https://unpkg.com/sip.js@0.21.2/lib/platform/web/index.js"></script>
<script>
const { UserAgent, Registerer, Inviter, SessionState } = SIP;

const userAgent = new UserAgent({
  uri: UserAgent.makeURI('sip:webrtc-user@pbx.example.com'),
  transportOptions: {
    server: 'wss://pbx.example.com:8089/ws'
  },
  authorizationUsername: 'webrtc-user',
  authorizationPassword: 'SecurePassword123',
  sessionDescriptionHandlerFactoryOptions: {
    iceGatheringTimeout: 5000,
    peerConnectionConfiguration: {
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' }
      ]
    }
  }
});

// Start and register
await userAgent.start();
const registerer = new Registerer(userAgent);
await registerer.register();

// Make a call
const target = UserAgent.makeURI('sip:100@pbx.example.com');
const inviter = new Inviter(userAgent, target);
inviter.stateChange.addListener((state) => {
  if (state === SessionState.Established) {
    console.log('Call connected!');
  }
});
await inviter.invite();
</script>

Troubleshooting WebRTC

ProblemCauseSolution
WebSocket connection refusedHTTP server not enabled or wrong portCheck http.conf, ensure tlsenable=yes and port 8089 is open
WSS certificate error in browserSelf-signed or expired certificateUse Let's Encrypt for a valid certificate
Registration succeeds but no audioMissing DTLS-SRTP or ICE configSet webrtc=yes on endpoint; configure STUN server
ICE connection failedSymmetric NAT blocking STUNDeploy a TURN server (coturn); STUN alone is not enough
Opus codec not availableAsterisk compiled without OpusInstall codec_opus module: apt install asterisk-codec-opus
403 Forbidden on INVITEEndpoint not matching transportEnsure endpoint uses transport=transport-wss
Audio works one way onlyICE candidates not exchanged properlyCheck firewall for STUN/TURN ports; increase iceGatheringTimeout
# Debug WebRTC in Asterisk console
asterisk -rx "pjsip set logger on"
asterisk -rx "rtp set debug on"
asterisk -rx "core set verbose 5"

# Check WebSocket connections
asterisk -rx "http show status"

# Verify Opus codec is loaded
asterisk -rx "core show codecs" | grep opus

# Browser debugging:
# Open Chrome DevTools > Console for JavaScript errors
# chrome://webrtc-internals/ for detailed WebRTC stats
← Back to All Asterisk Solutions|Asterisk Complete Guide →