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-control names 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 logs delete command syntax error: invalid number of arguments (1). You pointed --rtpengine-control at 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-control for rtpproxy.