A typical scenario is bad or missing audio perceived on the client side. As I've done previously (here for Opus and here for SILK) I'd like to share some practical strategies to extract audio from a pcap trace (to verify the audio received/sent was "correct") and to "re-play" the call inside a test bed (to verify that the audio was good but also carried correctly by the RTP stream). Of course a lot can be inferred by indirect data, for example the summary of RTCP reports showing the number of packets exchanged, packets lost, the latency. But sometimes those metrics are perfect while the issue is still there.
Focusing in this case on Opus audio, and starting from a pcap file with the network traces for a call under investigation, let's see how to decode the Opus frames carried by the RTP packets into an audible WAV file.
You don't even need to have captured the signalling: it's sufficient to have the UDP packets carrying the RTP. If signalling is not visible by Wireshark it may not recognize that the UDP packets carry RTP, but you give it a hint by right-clicking on a frame and "Decode as..." and selecting "RTP".
It's typically easy to find the relevant RTP stream in Wireshark ("Telephony -> RTP -> RTP Streams"), select it, and prepare a filter. Then you can Export the packets belonging to that stream into a dedicated pcap file ("File --> Export Specified Packets...").
I've then modified opusrtp from a fork of opus-tools in order to be able to extract the payload from a given pcap, creating an Opus file. e.g.:
./opusrtp --extract trace.pcap
This will output a rtpdump.opus file, which can be converted into a WAV file directly with opusdec, still part of opus-tools:
./opusdec --rate 8000 rtpdump.opus audio.wav
You can listen to the wav file and verify whether at least the carried RTP payload was valid.
The network trace with the RTP can also be used to re-play the call, injecting the same RTP as in the call under investigation. With the help of sipp you can set up a rudimentary but very powerful test bed. Use the standard UAS scenario (e.g. in uas.xml), but with an additional part:
right after the ACK is received. If you launch sipp with a command like:
sipp -sf uas.xml -i MEDIA_IP_ADDRESS
you'll be able to call sipp. It will answer the call, as the scenario mandates, and will play the RTP contained in rtp_opus.pcap. The stream SSRC, timestamps, even Marker bits will be preserved. This will give you quite an accurate simulation of the stream received by the client in the original call.
It should be straightforward to reach all these components. For opus-tools, on a debian-based machine, you can just:
sudo apt-get install libogg-dev libpcap-dev
git clone https://github.com/giavac/opus-tools.git
cd opus-tools
./autogen.sh
./configure
make
For sipp:
sudo apt-get install sip-tester
I hope this will save the reader some time in future investigations.
UPDATE: The fork of opus-tools was merged into the original repo, so you don't need my repo.
UPDATE 2: This only works if the opus payload in the RTP is not encrypted. Also it may need a patch when the extension header for volume indications are used (e.g. 'urn:ietf:params:rtp-hdrext:
Hi,
ReplyDeleteI am trying to covert a pcap and I have the following error:
Got 132 byte packet (132 bytes captured)
skipping packet: unrecognized linktype 12
Got 127 byte packet (127 bytes captured)
skipping packet: unrecognized linktype 12
Here the capture:
https://drive.google.com/file/d/0BySOpdix-JH6b2Z2Q2xnbFVnOUk/view?usp=sharing
BR,
Martín.
Hi Martin,
ReplyDeletethe tool as is now expects data captured with ethernet (DLT_EN10MB) or null (DLT_NULL) type, while yours is a raw packet capture.
Is there any chance you can have a capture with the ethernet layer?
Otherwise the tool should be changed to support raw packet data (I don't think I'll be able to work on this any time soon).
Giacomo
HI Giacomo,
DeleteI am using rtpengine to save the videocall, and right I save the pcap with the eth header, and the .opus is generating but is no audible.
I am attaching the pcap here:
https://drive.google.com/file/d/0BySOpdix-JH6djB0T01ncVpEblE/view?usp=sharing
I think the log is ok:
Got 155 byte packet (155 bytes captured)
eth 0x0800 00:00:00:00:00:00 -> 00:00:00:00:00:00
ipv4 protocol 17 195.77.235.141 -> 195.77.235.141 header 20 bytes
udp 121 bytes 40268 -> 40282 crc 0x0000
rtp 0xfca33a6e 111 23426 985204741 v2 .X. CC 0 101 bytes
Got 157 byte packet (157 bytes captured)
eth 0x0800 00:00:00:00:00:00 -> 00:00:00:00:00:00
ipv4 protocol 17 195.77.235.141 -> 195.77.235.141 header 20 bytes
udp 123 bytes 40268 -> 40282 crc 0x0000
I don't know what I am doing wrong, maybe when I have exported from the original pcap to the only opus.pcap
After you have the .opus file, decode it into a wav file, e.g.:
Delete./opusdec --rate 8000 rtpdump.opus output.wav
also the wav file is not audible, has the following errors:
DeleteDecoding to 8000 Hz (2 channels)
Encoded with opus rtp packet dump
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding error: corrupted stream
Decoding complete.
Hi Giacomo,
DeleteCould you help me to see what happens? Do you need the capture?
Thanks,
Martín.
OK Martin, feel free to send me the capture (gmail email address).
DeleteThis comment has been removed by the author.
ReplyDeleteI have a pcap with 2 VoIP calls(the first is a 1-way audio call). Installed your fork opus-tools to make th eopus payload to listen if the sound got to the devices.
ReplyDeleteUnfortunately running into the issues below
Running Kali Linux after .\configure I get Type "make; make install" then after make I get the following errors:
/usr/bin/ld: src/opusenc-resample.o: undefined reference to symbol 'sin@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status.
Thanks
Hi Unknown, are you sure the configure command hasn't complained about missing libraries?
DeleteRegards,
Giacomo
It says is OK, log below. Thanks for the response:
ReplyDeleteroot@hostname:/home/git_repo/opus-tools# ./configure
checking whether make supports nested variables... yes
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether to enable maintainer-specific portions of Makefiles... yes
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking whether make supports the include directive... yes (GNU style)
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking dependency style of gcc... gcc3
checking for gcc option to accept ISO C99... none needed
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking whether byte ordering is bigendian... no
checking for an ANSI C-conforming const... yes
checking for inline... inline
checking for C/C++ restrict keyword... __restrict
checking for C99 variable-size arrays... yes
checking if gcc supports -O3 -g -ffast-math... yes
./configure: line 4992: LT_LIB_M: command not found
checking for main in -lwinmm... no
checking for pkg-config... yes
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for OGG... yes
checking for OPUS... yes
checking sys/soundcard.h usability... yes
checking sys/soundcard.h presence... yes
checking for sys/soundcard.h... yes
checking for sio_open in -lsndio... no
checking for FLAC... yes
checking for pcap_open_live in -lpcap... no
checking if gcc supports -fstack-protector-all... yes
checking for PIE support... yes
checking if gcc supports -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes... yes
checking for _LARGEFILE_SOURCE value needed for large files... no
checking for lrintf... no
checking for fminf... no
checking for fmaxf... no
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
configure:
------------------------------------------------------------------------
opus-tools 0.1.9-40-g64925e0: Automatic configuration OK.
Compiler support:
C99 var arrays: ................ yes
C99 lrintf: .................... no
Stack protector: ............... yes
PIE: ........................... yes
General configuration:
Assertion checking: ............ no
FLAC input: .................... yes
------------------------------------------------------------------------
Type "make; make install" to compile and install
I'm suspicious about
Delete> ./configure: line 4992: LT_LIB_M: command not found
Would you recommend a specific Linux Distro? I do not require to Kali Linux.
ReplyDeleteThanks
I'd recommend Debian or Ubuntu, just because that's where I was working on this project.
DeleteRegards,
Giacomo
Hi Giacomo
ReplyDeletehave you ever tried opusrtp with option --sniff ?
When I try : sudo ./opusrtp --sniff eth0 --port 10000 --type 96 --rate 8000 --channels 1 --output /tmp/ch1.opus then I get a sequence of few seconds of frames in /tmp/ch1.opus that I can play in VLC. But after a few seconds opusrtp stops.
For me that seems to be the ideal solution for a voice recorder that records RTP/Opus on disk, but unfortunately there is this limitation of only a few seconds.
Do you know why this is so?
I also noticed on the terminal screen that --port 10000 is not really filtering packets, instead it seems to accept all packets and skipping those who are not UDP/RTP
Nice to meet you.
ReplyDeleteopusrtp is wonder full tool. in fact, it can work perfectly with some pcap files but with some pcap files, it can extract opus but the output opus can not play ( or only noise).
Could you please help me to check.
Many thank for your support.
Please see one of these pcap at: https://drive.google.com/file/d/1Jkckhxal__pYbcZH70wONmnoRnvzHkcV/view?usp=sharing
Hi, i am looking for opusrtp.exe , i cannot find it in any of the compiled packages.
ReplyDeleteHi Milos, you need to build the opusrtp executable from source. It's mentioned in the article but this is the gist:
Deletesudo apt-get install libogg-dev libpcap-dev
git clone https://github.com/giavac/opus-tools.git
cd opus-tools
./autogen.sh
./configure
make
Thank you very much Giacomo, finally i have compiled it. But opusrtp extract only first channel/stream to the rtpdump.opus. It is possible to extract both streams ( VoIP call ) ?
DeleteHi Milos, I'd need to understand why it only extracts one stream. Would you be able to share somehow a pcap with both streams? A few packets for each stream would be sufficient.
Delete