-
Notifications
You must be signed in to change notification settings - Fork 2
WebRTC
GABPBX 1.1.2 makes chan_sofia a WebRTC endpoint. A browser running a
SIP-over-WebSocket library (for example SIP.js or JsSIP) can register, place a
call and receive a call, with two-way audio and two-way video, secured by
DTLS-SRTP. The implementation is self-contained: there is no pjproject and
no libnice in the tree. The same forked RTP engine that carries plain SIP
calls carries WebRTC, so non-WebRTC media is unchanged.
This page covers how it fits together and how to turn it on. The per-feature catalogue is Features; the security model is Security.
- Two WSS browsers can hold a real two-way audio call end to end.
- Two-way video (VP8 or H.264) rides on top of the audio call.
- Opus passes through both-Opus calls without transcoding.
- Setup, teardown and NAT survival all route correctly back over the accepted WebSocket.
| Concern | Mechanism | RFC | Where |
|---|---|---|---|
| SIP transport | SIP over secure WebSocket | RFC 7118 | channels/chan_sofia.c:11568-11660 |
| Media keying | DTLS-SRTP | RFC 5763/5764 | res/res_rtp_gabpbx.c:1001 |
| Connectivity | ICE-lite STUN responder | RFC 8445 | res/res_rtp_gabpbx.c:1265 |
| One socket per stream | rtcp-mux | RFC 5761 | channels/sofia/sofia_sdp.c:268 |
| Multiplexed media | BUNDLE + a=mid | RFC 8843 | channels/sofia/sofia_sdp.c:359 |
| Packet demux | STUN / DTLS / SRTP by first byte | RFC 7983 | res/res_rtp_gabpbx.c:1732 |
| Audio codec | Opus | RFC 7587 | channels/sofia/sofia_sdp.c:172 |
The browser registers and signals over a secure WebSocket. chan_sofia opens a
dedicated WSS listener from wssbindport, and auto-creates the WSS-named
certificate files sofia-sip's WebSocket transport expects (wss.pem from
agent.pem, ca-bundle.crt from cafile.pem) by hard-link or symlink, so the
operator manages only the standard agent.pem/cafile.pem
(channels/chan_sofia.c:11611-11632).
A browser's Contact host is always a placeholder, so in-dialog ACK/BYE
are routed back over the exact accepted WebSocket connection rather than to the
Contact (channels/chan_sofia.c:542-589), and ;transport=wss is appended to
the request-URI (mandatory for WSS per RFC 7118).
A WebRTC offer/answer uses the UDP/TLS/RTP/SAVPF media transport
(channels/sofia/sofia_sdp.c:380) instead of plain RTP/AVP. The SDP carries
a=ice-lite, ICE ufrag/pwd/candidate, a=fingerprint:sha-256, a=setup,
a=rtcp-mux, a=mid, and a session-level a=group:BUNDLE.
GABPBX is permanently the controlled, lite ICE agent
(res/res_rtp_gabpbx.c:1265, role AST_RTP_ICE_ROLE_CONTROLLED). It does not
gather candidates or send checks; it answers the browser's STUN binding
requests, learns the peer transport address from the first authenticated check,
and latches the nominated pair on USE-CANDIDATE. The STUN responder is armed in
sofia_webrtc_provision_offer before the offer leaves the wire, so the
browser's earliest connectivity checks are never dropped into a dead window.
Keys are not in the SDP. After ICE connectivity, a DTLS handshake runs over the
media path; SRTP keys are exported from it. The cert is ephemeral, self-signed,
EC P-256, CN gabpbx. a=setup advertises the engine's real negotiated role so
the two sides never both try to be the DTLS client. A dedicated retransmit
scheduler honors DTLS exponential backoff. gabpbx_dtls engine at
res/res_rtp_gabpbx.c:1001; key install at :1015-1071.
The trust anchor is the SDP a=fingerprint (RFC 8827/5763): the
self-signed cert cannot chain-verify, so on handshake completion the engine
demands a peer cert, requires a stored remote fingerprint, and does a
hash-matched X509_digest + memcmp against the SDP fingerprint. Any absence
or mismatch fails the call closed as a possible MITM
(res/res_rtp_gabpbx.c:1097-1120).
With rtcp-mux, a single socket per stream carries STUN, DTLS and
(S)RTP/RTCP interleaved. __rtp_recvfrom demuxes by the first byte
(res/res_rtp_gabpbx.c:1732-1786): STUN to the ICE responder, DTLS records to
the handshake, RTP to SRTP-unprotect, with muxed SRTCP dropped and a flood
guard. This path is dormant unless DTLS is active, so plain RTP is untouched.
Audio is the tagged BUNDLE transport. A browser typically offers audio + video
(+ datachannel); unsupported offered m-lines are reflected back as port-0
rejections in order (RFC 3264 §6) rather than 488-ing the whole session
(channels/sofia/sofia_sdp.c:501-527). This is what lets a browser's
audio+video+datachannel offer be answered instead of bounced.
Video does not ride the audio BUNDLE. The accepted/offered m=video is
emitted on its own port with its own ICE/fingerprint/setup/candidate,
a=rtcp-mux, and a distinct a=mid — a separate DTLS association from the
audio (channels/sofia/sofia_sdp.c:386-491). GABPBX both accepts a browser's
offered video (answerer) and offers video itself (offerer), so two browsers can
see each other.
A both-Opus call passes through with no transcoding. The three fixes that made browser-to-browser Opus clean:
- codec selection now knows Opus,
- the format rate returns 48 kHz, so the RTP TX timestamp advances +960 per 20 ms frame (not +160),
- the RTP smoother no longer re-chunks Opus's variable-size frames
(
res/res_rtp_gabpbx.c:2840-2845).
Opus is offered with useinbandfec=1;usedtx=0 and channels=2
(channels/sofia/sofia_sdp.c:172-174).
WebRTC is opt-in per peer with webrtc=yes, which is inherited from
[general] and can be overridden per peer
(channels/chan_sofia.c:2181, :2591, :13173).
[general]
; standard TLS material; WSS reuses agent.pem / cafile.pem
tlscertfile=/etc/gabpbx/keys/agent.pem
tlscafile=/etc/gabpbx/keys/cafile.pem
; secure WebSocket listener for browsers
wssbindaddr=0.0.0.0
wssbindport=8089
; default new peers to WebRTC (or set per peer)
webrtc=yes
[browser-200]
type=peer
host=dynamic
defaultuser=browser-200
secret=change-this-secret
context=internal
webrtc=yes
disallow=all
allow=opus
allow=ulawA webrtc=yes peer fails the call rather than ever falling back to insecure
media, and direct media is force-disabled on any DTLS/SRTP leg so keys are
never bridged or disclosed (channels/chan_sofia.c:3129-3134).
-
sip show peer <name>andsip show settingsreport the WebRTC state of a peer and the global default. - A reverse proxy (for example nginx) terminating browser HTTPS/WSS in front of
chan_sofiais a common deployment; route the WebSocket to thewssbindportlistener. When debugging the WSS leg, capture on the loopback the proxy forwards to. - After editing
sofia.confas root, restore ownership so GABPBX can read it (chown gabpbx:gabpbx /etc/gabpbx/sofia.conf).
- DataChannel (SCTP-over-DTLS) media — offered datachannel m-lines are port-0 rejected, not carried.
- Full (non-lite) ICE with candidate gathering and TURN — GABPBX is the ICE-lite controlled agent by design.
SIP — chan_sofia
Subsystems
Realtime & data
Operations