Repository navigation
Name rtpproxy Media with sipnab
Capture on a media relay and you get the audio of every call. But nothing in an RTP packet says which call it belongs to. The name is in the signaling. A relay on its own machine never sees the signaling.
sipnab can still name rtpproxy's media, from the relay's control traffic:
- For each call, your SIP proxy sends rtpproxy a command that carries the call's Call-ID.
- rtpproxy answers with the port it opened for it.
- With
--rtpproxy-control, sipnab reads both. It ties the media on that port to the call.
This guide sets that up against the stack from Add rtpproxy to your voice stack:
- first on the machine that runs the SIP proxy and rtpproxy together,
- then with rtpproxy on a machine of its own.
The proxy is one of these:
- OpenSIPS, from its packages or built from source,
- Kamailio, set up as that guide's With Kamailio section sets it up.
sipnab never talks to the proxy. So every step is the same for each proxy. The one exception is the line in the rtpproxy on its own machine step that edits the proxy's configuration.
Nothing.
- With
--rtpproxy-control, sipnab reads rtpproxy's control traffic from its capture. - It never sends rtpproxy a command. So it cannot make rtpproxy create, change or delete a call.
- That is also why it cannot name a call that was already up when it started.
- rtpproxy has no command that lists its calls.
- So there is nothing sipnab could ask.
- rtpengine has such a command. With rtpengine,
--rtpengine-controldoes ask, as Let sipnab name rtpengine's media shows.
Every block on this page ran as written, in order, on 2026-10-01, with sipnab 0.5.197 from its release package.
- The machines were clean x86_64 virtual machines with 2 cores and 3 GB of
memory:
- Debian 13 (kernel 6.12.63),
- Ubuntu 24.04.5 (kernel 6.8.0).
- sipnab ran in three setups:
- beside OpenSIPS built from source,
- beside the OpenSIPS packages with Kamailio on the same machine,
- on the relay's own machine with OpenSIPS on another.
- On both systems:
- Causing each fault under When something does not work produced what it describes.
- A capture with
--rtpproxy-controlsent nothing to rtpproxy's control port.
- arm64 was not tested.
The examples use 192.0.2.10 for the machine that runs the SIP proxy and
192.0.2.20 for the relay's own machine. Replace them with yours.
On the machine that runs rtpproxy:
# Run all of these, in order.
V=$(curl -fsSL https://api.github.com/repos/NormB/sipnab/releases/latest \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["tag_name"].lstrip("v"))')
curl -fsSLO https://github.com/NormB/sipnab/releases/download/v$V/sipnab_${V}_amd64.deb
curl -fsSL https://github.com/NormB/sipnab/releases/download/v$V/SHA256SUMS.txt \
| grep " sipnab_${V}_amd64.deb$" | sha256sum -c -
sudo apt-get install -y ./sipnab_${V}_amd64.deb
sipnab --version--rtpproxy-control, which this guide uses, arrived in sipnab 0.5.196.
Give sipnab a capture filter that admits three things:
- the SIP,
- rtpproxy's control socket,
- rtpproxy's media ports.
This guide uses the ones from the rtpproxy guide, UDP port 7722 and ports 50000-59999:
portrange 5060-5061 or udp port 7722 or udp portrange 50000-59999
sipnab takes the filter as its last argument, in the syntax tcpdump uses.
Check the port and the range against the -s, -m and -M options in
/etc/sysconfig/rtpproxy.
Name the control port, even though the media range sometimes lets the control traffic through without it.
- The proxy sends its commands from ports the system picks.
- On Debian and Ubuntu, some of those fall inside 50000-59999 and some do not.
With OpenSIPS and Kamailio on one machine, Kamailio on 5062, widen the
signaling range to portrange 5060-5062. With rtpengine on the same machine
as well, add its range, or udp portrange 30000-39999.
--rtpproxy-control takes the address and port of rtpproxy's UDP control
socket, the -s udp: option. Start sipnab. It captures for 25 seconds, then
prints its report:
sudo sipnab -N -d any --rtpproxy-control 127.0.0.1:7722 --duration 25 --report "portrange 5060-5061 or udp port 7722 or udp portrange 50000-59999"-d any captures on every interface, the loopback one included. The control
socket listens on 127.0.0.1. The test callee does too.
While it runs, place a test call from a second terminal:
# Run all of these, in order.
cd ~/sipp
sipp -sn uas -i 127.0.0.1 -p 5070 -rtp_echo -m 1 -bg
sudo sipp -sf uac_rr.xml 192.0.2.10:5060 -i 192.0.2.10 -p 5080 -s echo -m 1 -timeout 90sWhen the 25 seconds are up, sipnab's report lists the call:
- by its Call-ID,
- as
Completed, - with all its streams under
RTP Streams:, - with no
Orphaned Streams:section.
Call-ID From To State Code Duration Msgs
---------------------------------------------------------------------------------------------------
1-51936@192.0.2.10 sipp echo Completed 200 9s 13
RTP Streams:
SSRC PT Codec Clock Source Destination Pkts
--------------------------------------------------------------------------------------
0xdee0ee8f 8 PCMA 8000 192.0.2.10:6000 192.0.2.10:51292 236
0xdee0ee8f 8 PCMA 8000 192.0.2.10:58734 127.0.0.1:6000 236
0xdee0ee8f 8 PCMA 8000 127.0.0.1:6000 192.0.2.10:58734 236
0xdee0ee8f 8 PCMA 8000 192.0.2.10:51292 192.0.2.10:6000 236
This shows the report's first columns only. There are eight streams in all:
- the four audio streams above, from the caller to rtpproxy, rtpproxy to the callee and back,
- the same four again for the DTMF events the caller sends
(
telephone-event).
A call that was already up is not named. Start a call first, then sipnab. The caller plays about 8 seconds of audio. So start sipnab within a second or two:
# Run all of these, in order.
cd ~/sipp
sipp -sn uas -i 127.0.0.1 -p 5070 -rtp_echo -m 1 -bg
sudo sipp -sf uac_rr.xml 192.0.2.10:5060 -i 192.0.2.10 -p 5080 -s echo -m 1 -timeout 60s -bg
sleep 1
sudo sipnab -N -d any --rtpproxy-control 127.0.0.1:7722 --duration 6 --report "portrange 5060-5061 or udp port 7722 or udp portrange 50000-59999"The call's INVITE went by before sipnab started. So did the commands that
opened its ports. Its streams land under Orphaned Streams:, with no call to
name them.
Move rtpproxy to its own machine as described in Put rtpproxy on its own machine. The relay's machine now carries the control traffic and the media, and no SIP. Install sipnab there as in the Install sipnab step. Start it with the relay's control address:
sudo sipnab -N -d any --rtpproxy-control 192.0.2.20:7722 --duration 25 --report "udp port 7722 or udp portrange 50000-59999"While it runs, place a test call on the proxy's machine.
- The rtpproxy guide's callee listens on
127.0.0.1. The relay cannot reach that from its own machine. - So start the callee on the machine's address instead.
- Put its media on ports 7000-7100, so that it does not collide with the caller's 6000.
- Point the proxy at it.
The first line finds the proxy's configuration: the OpenSIPS packages', a source build's, or Kamailio's:
# Run all of these, in order.
for f in /etc/opensips/opensips.cfg /usr/local/etc/opensips/opensips.cfg /etc/kamailio/kamailio.cfg; do sudo test -f "$f" && C=$f && break; done
sudo sed -i 's|sip:127.0.0.1:5070|sip:192.0.2.10:5070|' "$C"
case "$C" in */kamailio/*) sudo systemctl restart kamailio;; *) sudo systemctl restart opensips;; esac
cd ~/sipp
sipp -sn uas -i 192.0.2.10 -p 5070 -min_rtp_port 7000 -max_rtp_port 7100 -rtp_echo -m 1 -bg
sudo sipp -sf uac_rr.xml 192.0.2.10:5060 -i 192.0.2.10 -p 5080 -s echo -m 1 -timeout 90sWhen the 25 seconds are up, sipnab's report on the relay's machine does two things:
- It lists the call's streams under
RTP Streams:. - Then it names the call from rtpproxy's control traffic, with no SIP in the capture:
Calls named by a media relay (no SIP for them in this capture):
Call-ID Streams
---------------------------------------------------------------------
1-15862@192.0.2.10 8
- The Call-ID is the one the SIP proxy gave rtpproxy. rtpproxy's own log shows it for the session too.
- There are eight streams again: the audio and the DTMF events on both sides of the relay.
- There is no SDP on this machine. So the report shows the DTMF streams' codec
as
?.
-
The report shows calls but
0 RTP packets. sipnab's filter admitted signaling only. Add the relay's control port and media range, as in the Let sipnab see the media and the control traffic step. -
Streams appear, but no call names them, on the relay's machine. sipnab
did not read the commands that opened their ports. Check three things:
-
--rtpproxy-controlnames exactly the address and port of rtpproxy's-s udp:option. - The filter admits that port.
- sipnab started before the calls you want named.
-
-
sipnab logs
could not be asked which calls are up: rtpengine reply is not bencode, and rtpproxy logsdelete command syntax error: invalid number of arguments (1). You pointed--rtpengine-controlat rtpproxy's control socket.- That flag sends rtpengine's commands.
- rtpproxy read the first one as a delete with the wrong number of arguments, and refused it.
- Use
--rtpproxy-controlfor rtpproxy.
Website · Repository · Issues · Generated from docs/ — edit there, not here.
Getting started
- Installation
- First CLI Triage
- Glossary
- Cookbook
- Runnable Examples
- Real World Captures
- Troubleshooting
- Tuning Capture
- Encapsulations
- Rtpengine Relays
- Backers
Using the TUI
CLI & automation
- CLI Reference
- Error Messages
- Filter DSL
- Output Formats
- SIP Response Codes
- SIP Methods
- SIP Header Fields
- SIP Parameters
- SIP Lint Rules
- MOS and Codecs
Configuration
Integrations (API & MCP)
- REST API
- Prometheus Metrics
- Authentication
- MCP
- MCP Deployment
- MCP Across an Estate
- MCP Tools
- MCP Tools Core
- MCP Tools Signaling
- MCP Tools Captures
- MCP Tools Security
- MCP Tools Media
- MCP Tools Relay
- MCP Tools TFPS
- MCP Tools Server
- MCP Tools vCon
- MCP Tools TLS
- MCP Protocol
- Uprobe Walkthrough
- Capture SIP over TLS
- WASM Plugins
- vCon Export
- vCon Capture Stack
- G729 Decoding
Your SIP server
- Use OpenSIPS as the SIP Server
- Run sipnab beside OpenSIPS
- Use Kamailio as the SIP Server
- Run sipnab beside Kamailio
- Use Asterisk as the PBX
- Run sipnab beside Asterisk
- Use FreeSWITCH in the Voice Stack
- Run sipnab beside FreeSWITCH
Add to your voice stack
- Add a vCon Server
- Send vCons to a vCon Server
- Send vCons to vcon store
- Add TFPS
- Control TFPS from sipnab
- Ban SIP Scanners with fail2ban
- Feed fail2ban from sipnab
- Add rtpengine
- Name rtpengine Media with sipnab
- Add rtpproxy
- Name rtpproxy Media with sipnab
- Add Homer
- Connect sipnab to Homer
- Add Prometheus and Grafana
- Add sipnab Metrics to Prometheus
Development & internals
- Internals Index
- Internals Subsystem Guide
- Internals Invariants
- Internals Testing
- Internals Walkthroughs
- Internals Build CI Release
- Internals Profiling
- Internals Domain Primer
- Library API
- Benchmarks
- Fault Model
- Threat Model
- Assurance Case
- Architecture
- Internals Threading
- Internals TUI Testing
- Internals Zero Copy Payloads
- Internals Uprobe Capture
- Internals Rtpengine Control Plane
- Internals Relay Control Decoding
- Internals vCon Exporter
- Internals Operator Guide Notes
- Internals Postmortems
- Internals Code Map
- Internals Lint Rules
- Internals Encapsulation Decoding
- Internals MCP Design Notes
- Internals Metrics And Output Notes