sngrep
is a tool for displaying SIP calls message flows from the terminal of your server. It can be used to display real-time SIP traffic and to process PCAP files (packet captures). Think of it as a specialized tcpdump
tool designed for VoIP. It's open-source and it's available here.
Step-by-step guide
Here are the steps to take if you want to install sngrep
on your VoipNow server.
- If VoipNow is not installed, perform the installation using the command line installer as instructed here.
Install the required software packages so that you can download and compile sngrep
by running:
# yum -y install git libpcap openssl-devel gnutls pcre-devel libpcap-devel ncurses-devel autoconf automake gcc make
Download the sngrep
files.
# cd ~
# git clone https://github.com/irontec/sngrep.git
Cloning into 'sngrep'...
remote: Counting objects: 4878, done.
remote: Total 4878 (delta 0), reused 0 (delta 0), pack-reused 4878
Receiving objects: 100% (4878/4878), 4.06 MiB | 1.98 MiB/s, done.
Resolving deltas: 100% (3864/3864), done.
Checking connectivity... done.
A new folder named sngrep
containing the source code will be created. Go to that folder.
Run the bootstrap.sh
script.
# ./bootstrap.sh
Generating the configure script ...
Run the configure
script.
./configure
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 make supports nested variables... yes
checking whether make supports nested variables... (cached) yes
checking for style of include used by make... GNU
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 dependency style of gcc... gcc3
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 minix/config.h usability... no
checking minix/config.h presence... no
checking for minix/config.h... no
checking whether it is safe to define __EXTENSIONS__... yes
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking for g++... no
checking for c++... no
checking for gpp... no
checking for aCC... no
checking for CC... no
checking for cxx... no
checking for cc++... no
checking for cl.exe... no
checking for FCC... no
checking for KCC... no
checking for RCC... no
checking for xlC_r... no
checking for xlC... no
checking whether we are using the GNU C++ compiler... no
checking whether g++ accepts -g... no
checking dependency style of g++... none
checking whether ln -s works... yes
checking for egrep... (cached) /usr/bin/grep -E
checking for pthread_create in -lpthread... yes
checking for pcap_open_offline in -lpcap... yes
checking pcap.h usability... yes
checking pcap.h presence... yes
checking for pcap.h... yes
checking ncurses.h usability... yes
checking ncurses.h presence... yes
checking for ncurses.h... yes
checking for initscr in -lncurses... yes
checking for new_panel in -lpanel... yes
checking for new_form in -lform... yes
checking for new_item in -lmenu... yes
██╗██████╗ ██████╗ ███╗ ██╗████████╗███████╗ ██████╗
██║██╔══██╗██╔═══██╗████╗ ██║╚══██╔══╝██╔════╝██╔════╝
██║██████╔╝██║ ██║██╔██╗ ██║ ██║ █████╗ ██║
██║██╔══██╗██║ ██║██║╚██╗██║ ██║ ██╔══╝ ██║
██║██║ ██║╚██████╔╝██║ ╚████║ ██║ ███████╗╚██████╗
╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝ ╚═════╝
configure:
configure: sngrep configure finished
configure: ======================================================
configure: GnuTLS Support : no
configure: OpenSSL Support : no
configure: Unicode Support : no
configure: Perl Expressions Support : no
configure: IPv6 Support : no
configure: EEP Support : no
configure: ======================================================
configure:
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config/Makefile
config.status: creating doc/Makefile
config.status: creating tests/Makefile
config.status: creating src/config.h
config.status: executing depfiles commands
Compile sngrep
with the make
command.
# make
Making all in src
make[1]: Entering directory `/root/sngrep/src'
make all-am
make[2]: Entering directory `/root/sngrep/src'
CC capture.o
CC address.o
CC packet.o
CC sip.o
CC sip_call.o
CC sip_msg.o
CC sip_attr.o
CC main.o
CC option.o
CC group.o
CC filter.o
CC keybinding.o
CC media.o
CC setting.o
CC rtp.o
CC util.o
CC vector.o
CC ui_panel.o
CC scrollbar.o
CC ui_manager.o
CC ui_call_list.o
CC ui_call_flow.o
CC ui_call_raw.o
CC ui_stats.o
CC ui_filter.o
CC ui_save.o
CC ui_msg_diff.o
CC ui_column_select.o
CC ui_settings.o
CCLD sngrep
make[2]: Leaving directory `/root/sngrep/src'
make[1]: Leaving directory `/root/sngrep/src'
Making all in config
make[1]: Entering directory `/root/sngrep/config'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/root/sngrep/config'
Making all in doc
make[1]: Entering directory `/root/sngrep/doc'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/root/sngrep/doc'
Making all in tests
make[1]: Entering directory `/root/sngrep/tests'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/root/sngrep/tests'
make[1]: Entering directory `/root/sngrep'
make[1]: Nothing to be done for `all-am'.
make[1]: Leaving directory `/root/sngrep'
Install sngrep
with the make install
command.
# make install
Making install in src
make[1]: Entering directory `/root/sngrep/src'
make[2]: Entering directory `/root/sngrep/src'
/usr/bin/mkdir -p '/usr/local/bin'
/usr/bin/install -c sngrep '/usr/local/bin'
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/root/sngrep/src'
make[1]: Leaving directory `/root/sngrep/src'
Making install in config
make[1]: Entering directory `/root/sngrep/config'
make[2]: Entering directory `/root/sngrep/config'
/usr/bin/mkdir -p '/usr/local/etc'
/usr/bin/install -c -m 644 sngreprc '/usr/local/etc'
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/root/sngrep/config'
make[1]: Leaving directory `/root/sngrep/config'
Making install in doc
make[1]: Entering directory `/root/sngrep/doc'
make[2]: Entering directory `/root/sngrep/doc'
make[2]: Nothing to be done for `install-exec-am'.
/usr/bin/mkdir -p '/usr/local/share/man/man8'
/usr/bin/install -c -m 644 sngrep.8 '/usr/local/share/man/man8'
make[2]: Leaving directory `/root/sngrep/doc'
make[1]: Leaving directory `/root/sngrep/doc'
Making install in tests
make[1]: Entering directory `/root/sngrep/tests'
make[2]: Entering directory `/root/sngrep/tests'
make[2]: Nothing to be done for `install-exec-am'.
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/root/sngrep/tests'
make[1]: Leaving directory `/root/sngrep/tests'
make[1]: Entering directory `/root/sngrep'
make[2]: Entering directory `/root/sngrep'
make[2]: Nothing to be done for `install-exec-am'.
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/root/sngrep'
make[1]: Leaving directory `/root/sngrep'
sngrep
is now installed into /usr/local/bin/sngrep
which should be already in your path. You may launch it with the sngrep
command:
After starting sngrep
, you'll be presented with a text-mode, interactive interface which can be navigated with the arrow keys and quit with the Esc key.
How to make the most of SNGREP
Initialize a softphone which registers to your VoipNow server, and the REGISTER
and the SUBSCRIBE
methods sent by the phone will appear in the console right away. You can clear the list of captured messages by pressing the F5 key, as indicated in the legend at the bottom of the screen.
You can move the cursor between the displayed packets using the arrow keys. For details about a specific SIP method, press ENTER. You'll get a graphical flow of the packets exchanged between your phone and the VoipNow server. You may navigate through the flow using the same arrow keys - the selected message details will be displayed on the right of the window.
Pressing ENTER again will show the packet in raw mode.
Here are the 4 stages of a SIP registration:
- The initial REGISTER sent by the phone (informing the server of his presence).
- The 401 Unauthorized sent by the server to the phone (containing the challenge to which the phone has to reply).
- The second REGISTER message sent by the phone (with the valid credentials, user ID and password).
- The 200 OK confirming the phone has registered correctly with the server.
Place a call to *52
(the echo test) and you'll see the call appear in the list.
Pressing ENTER will open a call flow diagram illustrating the communication between the phone and the SIP/PBX components of VoipNow.
More great SNGREP features
For example, you can compare two SIP packets by checking them with the Space key. Once the second packet is checked, the differences between the two packets will be automatically shown in a separate window.
If you press F2 and F3 in a call flow, you will be able to see SDP and RTP information.
There are more options and features in sngrep, so feel free to explore further. While a bit more cumbersome to use than Wireshark, sngrep can help you quickly debug SIP problems on your server.
Related articles
-
Page:
-
Page:
-
Page:
-
Page:
-
Page:
#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))