8.7 Capturing SIP over TLS — siptrace and HEP¶
[!IMPORTANT] The moment you turn on TLS (
5061) or WebSocket-Secure,tcpdumpandsngrepon the wire go blind — they see TLS records, not SIP. The trick every operator eventually needs: stop capturing on the wire and capture inside Kamailio, where the message is already plaintext, streaming a copy out over HEP.siptracedoes exactly that, andsngreprenders it live.
Why wire capture fails on TLS¶
TLS is terminated at the transport layer — the tls module decrypts the byte stream during reception (3.1), before the parser and request_route ever see it. So the sip_msg Kamailio routes on is plaintext no matter the transport. On the NIC, a 5061 or WSS flow is an opaque TLS record stream: sngrep can't parse it, and pulling session keys off a busy proxy to decrypt offline is not a debugging workflow. For encrypted signalling, wire capture is dead — you have to tap a layer up.
siptrace — tap at the SIP layer¶
siptrace duplicates the message as Kamailio sees it: after decrypt, before re-encrypt, so the copy is always plaintext. Two ways to arm it — per-message sip_trace() in the route (selective: trace only what a condition matches) or trace_mode/trace_on for automatic global mirroring; sip_trace_mode() (or the mode arg) sets the scope to message, transaction, or dialog.
Where the copy goes is modparams:
trace_mode— bit-flags for the destination:1=HEP,2=database,4=SIP URI.duplicate_uri— the target as a SIP URI, e.g.sip:127.0.0.1:9060.hep_mode_on— wrap the copy in HEP;hep_version(1/2/3);hep_capture_idtags this agent.trace_to_database— also write to thesip_tracetable for offline/Homer storage.
HEP — why not just forward the SIP¶
HEP (Homer Encapsulation Protocol) wraps the original SIP payload plus metadata — source/destination IP:port, transport, timestamp, and a correlation/capture id — in a UDP envelope. The metadata is the whole point: the decrypted copy has lost its real transport identity (it now originates from Kamailio), so HEP carries the original 5-tuple alongside the payload, and the correlation id stitches both legs of a call together. Homer/sipcapture is the long-term store; for live debugging you don't need it — any HEP listener will do.
Viewing it live with sngrep¶
sngrep speaks HEP both ways. Point siptrace at a local port:
modparam("siptrace", "trace_mode", 1) # 1 = HEP
modparam("siptrace", "hep_mode_on", 1)
modparam("siptrace", "duplicate_uri", "sip:127.0.0.1:9060")
Then run sngrep as a HEP listener on that port and watch the decrypted dialogs — ladder diagram and full message bodies — even though the wire carried TLS:
-L (--eep-listen) starts the HEP server; -H udp:homer.example.net:9060 (--eep-send) re-emits the same stream onward to a Homer instance or a second sngrep (older builds spell these EEP options --eep / -E). One capture point, decrypted, forwardable.
When to reach for it¶
TLS/WSS is the obvious case, but tapping inside also wins where the wire lies in other ways: you see the message after your own lump edits (the final form actually sent), you see both sides of a topology-hidden call (siptrace sits inside, where topos hasn't masked anything yet), and the HEP correlation id lets you follow one call across a cluster. The cost is one duplicated UDP packet per traced message — cheap, but on heavy traffic keep sip_trace() behind a condition rather than mirroring everything.
← Table of contents · ← 8.6 Media — rtpengine · Next: 7.1 RPC architecture →