Docs Let sipnab name rtpproxy's media
Let sipnab name rtpproxy's media
On this page
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,
and 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, and rtpproxy
answers with the port it opened for it. With --rtpproxy-control, sipnab
reads both and 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 OpenSIPS, from its packages or built from source, or 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, apart from the one line in step 4 that edits the proxy’s configuration.
What sipnab sends rtpproxy
Nothing. With --rtpproxy-control, sipnab reads rtpproxy’s control traffic
from its capture and 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. With rtpengine, which has one, --rtpengine-control does
ask, as Let sipnab name rtpengine’s media shows.
Tested on
Every block on this page ran as written, in order, on 2026-10-01, with sipnab
0.5.197 from its release package, on clean x86_64 virtual machines with 2 cores
and 3 GB of memory, Debian 13 (kernel 6.12.63) and Ubuntu 24.04.5 (kernel
6.8.0): beside OpenSIPS built from source, beside the OpenSIPS packages with
Kamailio on the same machine, and 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, and a capture with --rtpproxy-control sent 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.
1. Install sipnab
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.
2. Let sipnab see the media and the control traffic
Give sipnab a capture filter that admits three things: the SIP, rtpproxy’s control socket, and 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, and 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.
3. Name the calls on the proxy’s machine
--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, and 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 90s
When the 25 seconds are up, sipnab’s report lists the call by its Call-ID,
Completed, with all its streams under RTP Streams: and 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. Eight streams in all: the four
audio streams above, from the caller to rtpproxy, rtpproxy to the callee and
back, and 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 and the commands that opened its ports went by before
sipnab started. Its streams land under Orphaned Streams:, with no call to
name them.
4. rtpproxy on its own machine
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 step 1, and 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, which the relay cannot reach from its own
machine, so start the callee on the machine’s address instead, with its media
on ports 7000-7100 so that it does not collide with the caller’s 6000, and
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 90s
When the 25 seconds are up, sipnab’s report on the relay’s machine lists the
call’s streams under RTP Streams:, and then 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, which rtpproxy’s own log
shows for the session too. Eight streams again, the audio and the DTMF events
on both sides of the relay. With no SDP on this machine, the report shows the
DTMF streams’ codec as ?.
When something does not work
- 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 step 2. - Streams appear, but no call names them, on the relay’s machine. sipnab
did not read the commands that opened their ports. Check that
--rtpproxy-controlnames exactly the address and port of rtpproxy’s-s udp:option, that the filter admits that port, and that 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, and rtpproxy read the first one as a delete with the wrong number of arguments and refused it. Use--rtpproxy-controlfor rtpproxy.