Category Archives: Session Initiation Prot. (SIP)

Asterisk

Asterisk is a framework or toolkit designed for VOIP systems . It can support Enterprise communication systems like PBXs, call distributors, VoIP gateways , conference bridges etc . It is open source and free to use . It is developed in C and runs in linux .

Technically , Asterisk has protocol support for many telephony technologies and protocols such as SIP , H323 .
It can connect old PSTN or copper line and VOIP .

Asterisk is a framework for building multi-protocol, real-time communications applications and solutions. Asterisk is to realtime voice and video applications as what Apache is to web applications

– asterisk.org

Combine the SIP channel, the PSTN interface channel and some Dialplan script and you have a gateway.
Change the Dialplan to drop calls into a ConfBridge session and you have a conference server.
Alter it once more to route calls into voice mailboxes and you have a voicemail server.
Tie it all together and you have an amazingly powerful phone system.

– asterisk.org

Installation

goto /usr/src and download the preferred the version of asterisk code from
http://downloads.asterisk.org/pub/telephony/asterisk/

I am using the latest release candidate at the time writing this article
asterisk-16.2.0-rc1-patch.tar.gz

Some external Dependencies
apt-get install subversion

Then install the source dependencies

 sudo su
contrib/scripts/get_mp3_source.sh

This will install mp3 related programs such as


A addons/mp3
A addons/mp3/decode_ntom.c
A addons/mp3/interface.c
A addons/mp3/MPGLIB_README
A addons/mp3/common.c
A addons/mp3/huffman.h
A addons/mp3/tabinit.c
A addons/mp3/Makefile
A addons/mp3/README
A addons/mp3/decode_i386.c
A addons/mp3/dct64_i386.c
A addons/mp3/MPGLIB_TODO
A addons/mp3/mpg123.h
A addons/mp3/layer3.c
A addons/mp3/mpglib.h
Exported revision 202.

Actual dependencies will be installed via install_prereq script

contrib/scripts/install_prereq install

Output snippet

The following NEW packages will be installed:
autoconf{a} automake{a} autopoint{a} autotools-dev{a} binutils{a} binutils-common{a} binutils-dev binutils-x86-64-linux-gnu{a} bison build-essential comerr-dev{a} cpp{a} cpp-7{a} debhelper{a}
dh-autoreconf{a} dh-strip-nondeterminism{a} doxygen dpkg-dev{a} fakeroot{a} flex fontconfig{a} fontconfig-config{a} fonts-dejavu-core{a} fonts-liberation{a} freetds-common{a} freetds-dev g++{a}
g++-7{a} gcc{a} gcc-7{a} gcc-7-base{a} gettext{a} gir1.2-gmime-2.6{a} gir1.2-harfbuzz-0.0{a} graphviz icu-devtools{a} intltool-debian{a} krb5-multidev{a} libalgorithm-diff-perl{a}
libalgorithm-diff-xs-perl{a} libalgorithm-merge-perl{a} libann0{a} libarchive-cpio-perl{a} libarchive-zip-perl{a} libasan4{a} libasound2{a} libasound2-data{a} libasound2-dev libatomic1{a}
libbinutils{a} libbison-dev{a} libbluetooth-dev libbluetooth3{a} libbsd-dev{a} libc-client2007e{a} libc-client2007e-dev libc-dev-bin{a} libc6-dev{a} libcairo2{a} libcc1-0{a} libcdt5{a} libcfg-dev
libcfg6{a} libcgraph6{a} libcilkrts5{a} libclang1-6.0{a} libcodec2-0.7{a} libcodec2-dev libcorosync-common-dev libcorosync-common4{a} libcpg-dev libcpg4{a} libcroco3{a} libct4{a}
libcurl4-openssl-dev libdatrie1{a} libdb-dev{a} libdb5.3-dev{a} libdpkg-perl{a} libedit-dev libexpat1-dev{a} libfakeroot{a} libfftw3-bin{a} libfftw3-dev libfftw3-double3{a} libfftw3-long3{a}
libfftw3-quad3{a} libfftw3-single3{a} libfile-fcntllock-perl{a} libfile-stripnondeterminism-perl{a} libfl-dev{a} libfl2{a} libflac-dev{a} libflac8{a} libfontconfig1{a} libgcc-7-dev{a} libgd3{a}
libglib2.0-bin{a} libglib2.0-dev{a} libglib2.0-dev-bin{a} libgmime-2.6-0{a} libgmime-2.6-dev libgomp1{a} libgpgme11{a} libgraphite2-3{a} libgraphite2-dev{a} libgsm1{a} libgsm1-dev libgssrpc4{a}
libgts-0.7-5{a} libgts-bin{a} libgvc6{a} libgvpr2{a} libharfbuzz-dev{a} libharfbuzz-gobject0{a} libharfbuzz-icu0{a} libharfbuzz0b{a} libical-dev libical3{a} libice6{a} libicu-dev{a}
libicu-le-hb-dev{a} libicu-le-hb0{a} libiculx60{a} libiksemel-dev libiksemel3{a} libisl19{a} libitm1{a} libjack-jackd2-0{a} libjack-jackd2-dev libjansson-dev libjansson4{a} libjbig-dev{a}
libjbig0{a} libjpeg-dev{a} libjpeg-turbo8{a} libjpeg-turbo8-dev{a} libjpeg8{a} libjpeg8-dev{a} libkadm5clnt-mit11{a} libkadm5srv-mit11{a} libkdb5-9{a} liblab-gamut1{a} libldap2-dev libllvm6.0{a}
liblsan0{a} libltdl-dev{a} libltdl7{a} liblua5.2-0{a} liblua5.2-dev liblzma-dev{a} libmail-sendmail-perl{a} libmpc3{a} libmpx2{a} libmysqlclient-dev libmysqlclient20{a} libncurses5-dev{a}
libneon27{a} libneon27-dev libnewt-dev libodbc1{a} libogg-dev libogg0{a} libosptk-dev libosptk4{a} libpam0g-dev{a} libpango-1.0-0{a} libpangocairo-1.0-0{a} libpangoft2-1.0-0{a} libpathplan4{a}
libpcap0.8-dev{a} libpci-dev{a} libpcre16-3{a} libpcre3-dev{a} libpcre32-3{a} libpcrecpp0v5{a} libpixman-1-0{a} libpng-dev{a} libpng-tools{a} libpopt-dev libportaudio2{a} libportaudiocpp0{a}
libpq-dev libpq5{a} libpython-dev{a} libpython-stdlib{a} libpython2.7{a} libpython2.7-dev{a} libpython2.7-minimal{a} libpython2.7-stdlib{a} libqb-dev{a} libqb0{a} libquadmath0{a} libradcli-dev
libradcli4{a} libreadline-dev{a} libresample1{a} libresample1-dev libsamplerate0{a} libsensors4{a} libsensors4-dev{a} libslang2-dev{a} libsm6{a} libsndfile1{a} libsndfile1-dev libsnmp-base{a}
libsnmp-dev libsnmp30{a} libspandsp-dev libspandsp2{a} libspeex-dev libspeex1{a} libspeexdsp-dev libspeexdsp1{a} libsqlite3-dev libsrtp0{a} libsrtp0-dev libsrtp2-1{a} libsrtp2-dev libssl-dev
libssl-doc{a} libstdc++-7-dev{a} libsybdb5{a} libsys-hostname-long-perl{a} libthai-data{a} libthai0{a} libtiff-dev{a} libtiff5{a} libtiff5-dev{a} libtiffxx5{a} libtinfo-dev{a} libtool{a}
libtool-bin{a} libtsan0{a} libubsan0{a} libudev-dev{a} libunbound-dev libunbound2{a} liburiparser-dev liburiparser1{a} libvorbis-dev libvorbis0a{a} libvorbisenc2{a} libvorbisfile3{a} libvpb-dev
libvpb1{a} libwebp6{a} libwrap0-dev{a} libxaw7{a} libxcb-render0{a} libxcb-shm0{a} libxml2-dev libxmu6{a} libxpm4{a} libxrender1{a} libxslt1-dev libxt6{a} linux-libc-dev{a} m4{a} make{a}
manpages-dev{a} mlock{a} module-assistant{a} mysql-common{a} odbcinst{a} odbcinst1debian2{a} pkg-config pkgconf{b} po-debconf{a} portaudio19-dev python{a} python-dev python-minimal{a} python2.7{a}
python2.7-dev{a} python2.7-minimal{a} python3-distutils{a} python3-lib2to3{a} unixodbc-dev uuid-dev vpb-driver-source{a} x11-common{a} xmlstarlet zlib1g-dev
The following packages will be upgraded:
gcc-8-base libcom-err2 libcurl4 libglib2.0-0 libgssapi-krb5-2 libk5crypto3 libkrb5-3 libkrb5support0 libldap-2.4-2 libldap-common libpython3-stdlib libpython3.6-minimal libpython3.6-stdlib
libssl1.1 libudev1 libuuid1 python3 python3-minimal python3.6 python3.6-minimal
.....

Current status: 127 (-25) upgradable.
# ###########################
install completed successfully
# ############################

Run configure which will create scripts for next processes

 ./configure

Build third party scripts

make -j2

After build , to run the installation

make install

Asterisk PBX setup

make basic-pbx

The output should be

Installing basic-pbx config files…
Installing file configs/basic-pbx/README
Installing file configs/basic-pbx/asterisk.conf
Installing file configs/basic-pbx/cdr.conf
Installing file configs/basic-pbx/cdr_custom.conf
Installing file configs/basic-pbx/confbridge.conf
Installing file configs/basic-pbx/extensions.conf
Installing file configs/basic-pbx/indications.conf
Installing file configs/basic-pbx/logger.conf
Installing file configs/basic-pbx/modules.conf
Installing file configs/basic-pbx/musiconhold.conf
Installing file configs/basic-pbx/pjsip.conf
Installing file configs/basic-pbx/voicemail.conf
Updating asterisk.conf

Also run make config to make pbx configs

make config 
ldconfig

















start asterisk

systemctl start asterisk

connect to asterisk tool for cli

asterisk -vvvr
Asterisk 16.2.0-rc1, Copyright (C) 1999 - 2018, Digium, Inc. and others.
Created by Mark Spencer markster@digium.com
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under

certain conditions. Type 'core show license' for details.

Connected to Asterisk 16.2.0-rc1 currently running on ip-172-31-45-26 (pid = 13388)
ip-172-31-45-26*CLI>

SIP and PJSIP modules

module show like sip
Module Description Use Count Status Support Level
chan_pjsip.so PJSIP Channel Driver 0 Running core
func_pjsip_endpoint.so Get information about a PJSIP endpoint 0 Running core
res_pjsip.so Basic SIP resource 38 Running core
res_pjsip_acl.so PJSIP ACL Resource 0 Running core
res_pjsip_authenticator_digest.so PJSIP authentication resource 0 Running core
res_pjsip_caller_id.so PJSIP Caller ID Support 1 Running core
res_pjsip_dialog_info_body_generator.so PJSIP Extension State Dialog Info+XML Pr 0 Running core
res_pjsip_diversion.so PJSIP Add Diversion Header Support 0 Running core
res_pjsip_dtmf_info.so PJSIP DTMF INFO Support 0 Running core
res_pjsip_endpoint_identifier_anonymous.so PJSIP Anonymous endpoint identifier 0 Running core
res_pjsip_endpoint_identifier_ip.so PJSIP IP endpoint identifier 0 Running core
res_pjsip_endpoint_identifier_user.so PJSIP username endpoint identifier 0 Running core
res_pjsip_exten_state.so PJSIP Extension State Notifications 0 Running core
res_pjsip_header_funcs.so PJSIP Header Functions 0 Running core
res_pjsip_logger.so PJSIP Packet Logger 0 Running core
res_pjsip_messaging.so PJSIP Messaging Support 0 Running core
res_pjsip_mwi.so PJSIP MWI resource 0 Running core
res_pjsip_mwi_body_generator.so PJSIP MWI resource 0 Running core
res_pjsip_nat.so PJSIP NAT Support 0 Running core
res_pjsip_notify.so CLI/AMI PJSIP NOTIFY Support 0 Not Running core
res_pjsip_one_touch_record_info.so PJSIP INFO One Touch Recording Support 0 Running core
res_pjsip_outbound_authenticator_digest.so PJSIP authentication resource 0 Running core
res_pjsip_outbound_publish.so PJSIP Outbound Publish Support 2 Running core
res_pjsip_outbound_registration.so PJSIP Outbound Registration Support 0 Running core
res_pjsip_path.so PJSIP Path Header Support 0 Running core
res_pjsip_pidf_body_generator.so PJSIP Extension State PIDF Provider 0 Running core
res_pjsip_pidf_digium_body_supplement.so PJSIP PIDF Digium presence supplement 0 Running core
res_pjsip_pidf_eyebeam_body_supplement.so PJSIP PIDF Eyebeam supplement 0 Running core
res_pjsip_publish_asterisk.so PJSIP Asterisk Event PUBLISH Support 0 Running core
res_pjsip_pubsub.so PJSIP event resource 11 Running core
res_pjsip_refer.so PJSIP Blind and Attended Transfer Suppor 1 Running core
res_pjsip_registrar.so PJSIP Registrar Support 0 Running core
res_pjsip_rfc3326.so PJSIP RFC3326 Support 0 Running core
res_pjsip_sdp_rtp.so PJSIP SDP RTP/AVP stream handler 0 Running core
res_pjsip_send_to_voicemail.so PJSIP REFER Send to Voicemail Support 0 Running core
res_pjsip_session.so PJSIP Session resource 14 Running core
res_pjsip_t38.so PJSIP T.38 UDPTL Support 0 Running core
res_pjsip_transport_websocket.so PJSIP WebSocket Transport Support 0 Not Running core
res_pjsip_xpidf_body_generator.so PJSIP Extension State PIDF Provider 0 Running core
39 modules loaded

Register sip phones with asterisk PBX and make / receive calls

To make calls among users, we need to configure channel driver with sip support . Using the sip protcol the phones within the enterprise will be able to send call signals out to one another. Open pjsip.conf

Take any endpoint from template , such as

;================================
;Laverne Roberts
;Software Engineer
[1113 (endpoint-internal-d70)
auth = 1113
aors = 1113
callerid = Laverne Roberts <1113>
[1113 (auth-userpass)
password = xxxxxxxx
username = xxxxxxxx
[1113 (aor-single-reg)
mailboxes = 1113@example

and set the values in sip softphone like zoiper , register with provided creds

registering sip phone zoiper with newly created asterisk PBX

If the registration creds used are not matching with the ones defines in pjsip.conf then REGISTER request failed message is displayed

Request 'REGISTER' from '' failed for 'x.x.x.x:18475' (callid: hp8iN6oWLRdER4zvEBdiUg..) - No matching endpoint found

On correct creds used the server prints traces such as

-- Added contact 'sip:1113@x.x.x.x:44312;transport=UDP;rinstance=b8aceff08623b51e' to AOR '1113' with expiration of 60 seconds
== Endpoint 1113 is now Reachable
-- Removed contact 'sip:1113@x.x.x.x:44312;transport=UDP;rinstance=b8aceff08623b51e' from AOR '1113' due to request
== Contact 1113/sip:1113@x.x.x.x:44312;transport=UDP;rinstance=b8aceff08623b51e has been deleted
== Endpoint 1113 is now Unreachable
-- Added contact 'sip:1113@x.x.x.x:18475;transport=UDP;rinstance=5af431512ae0af3a' to AOR '1113' with expiration of 60 seconds
== Endpoint 1113 is now Reachable

Alternatively one can also create new sip endpoints

-tbd


core show help
! -- Execute a shell command
acl show -- Show a named ACL or list all named ACLs
aoc set debug -- enable cli debugging of AOC messages
bridge kick -- Kick a channel from a bridge
bridge show all -- List all bridges
bridge show -- Show information about a bridge
bridge technology show -- List registered bridge technologies
bridge technology {suspend|unsuspend} -- Suspend/unsuspend a bridge technology
cc cancel [core|all] -- Kill a CC transaction
cc report status -- Reports CC stats
cdr set debug [on|off] -- Enable debugging in the CDR engine
cdr show active -- Display active CDRs for channels
cdr show status -- Display the CDR status
cdr submit -- Posts all pending batched CDR data
cel show status -- Display the CEL status
channel request hangup -- Request a hangup on a given channel
cli check permissions -- Try a permissions config for a user
cli reload permissions -- Reload CLI permissions config
cli show permissions -- Show CLI permissions
confbridge kick -- Kick participants out of conference bridges.
confbridge list -- List conference bridges and participants.
confbridge lock -- Lock a conference.
confbridge mute -- Mute participants.
confbridge record start -- Start recording a conference
confbridge record stop -- Stop recording a conference.
confbridge show menu -- Show a conference menu
confbridge show menus -- Show a list of conference menus
confbridge show profile bridge -- Show a conference bridge profile.
confbridge show profile bridges -- Show a list of conference bridge profiles.
confbridge show profile user -- Show a conference user profile.
confbridge show profile users -- Show a list of conference user profiles.
confbridge unlock -- Unlock a conference.
confbridge unmute -- Unmute participants.
config list -- Show all files that have loaded a configuration file
config reload -- Force a reload on modules using a particular configuration file
config show help -- Show configuration help for a module
core abort shutdown -- Cancel a running shutdown
core clear profile -- Clear profiling info
core ping taskprocessor -- Ping a named task processor
core reload -- Global reload
core restart gracefully -- Restart Asterisk gracefully
core restart now -- Restart Asterisk immediately
core restart when convenient -- Restart Asterisk at empty call volume
core set debug channel -- Enable/disable debugging on a channel
core set debug -- Set level of debug chattiness
core set verbose -- Set level of verbose chattiness
core show applications [like|describing] -- Shows registered dialplan applications
core show application -- Describe a specific dialplan application
core show calls [uptime] -- Display information on calls
core show channels [concise|verbose|count] -- Display information on channels
core show channel -- Display information on a specific channel
core show channeltypes -- List available channel types
core show channeltype -- Give more details on that channel type
core show codecs [audio|video|image|text] -- Displays a list of registered codecs
core show codec -- Shows a specific codec
core show config mappings -- Display config mappings (file names to config engines)
core show file formats -- Displays file formats
core show functions [like] -- Shows registered dialplan functions
core show function -- Describe a specific dialplan function
core show hanguphandlers all -- Show hangup handlers of all channels
core show hanguphandlers -- Show hangup handlers of a specified channel
core show help -- Display help list, or specific help on a command
core show hints -- Show dialplan hints
core show hint -- Show dialplan hint
core show image formats -- Displays image formats
core show license -- Show the license(s) for this copy of Asterisk
core show profile -- Display profiling info
core show settings -- Show some core settings
core show sounds -- Shows available sounds
core show sound -- Shows details about a specific sound
core show switches -- Show alternative switches
core show sysinfo -- Show System Information
core show taskprocessors -- List instantiated task processors and statistics
core show threads -- Show running threads
core show translation -- Display translation matrix
core show uptime [seconds] -- Show uptime information
core show version -- Display version info
core show warranty -- Show the warranty (if any) for this copy of Asterisk
core stop gracefully -- Gracefully shut down Asterisk
core stop now -- Shut down Asterisk immediately
core stop when convenient -- Shut down Asterisk at empty call volume
core waitfullybooted -- Wait for Asterisk to be fully booted
database del -- Removes database key/value
database deltree -- Removes database keytree/values
database get -- Gets database value
database put -- Adds/updates database value
database query -- Run a user-specified query on the astdb
database show -- Shows database contents
database showkey -- Shows database contents
devstate change -- Change a custom device state
devstate list -- List currently known custom device states
dialplan add extension -- Add new extension into context
dialplan add ignorepat -- Add new ignore pattern
dialplan add include -- Include context in other context
dialplan debug -- Show fast extension pattern matching data structures
dialplan reload -- Reload extensions and only extensions
dialplan remove context -- Remove a specified context
dialplan remove extension -- Remove a specified extension
dialplan remove ignorepat -- Remove ignore pattern from context
dialplan remove include -- Remove a specified include from context
dialplan set chanvar -- Set a channel variable
dialplan set extenpatternmatchnew false -- Use the Old extension pattern matching algorithm.
dialplan set extenpatternmatchnew true -- Use the New extension pattern matching algorithm.
dialplan set global -- Set global dialplan variable
dialplan show -- Show dialplan
dialplan show chanvar -- Show channel variables
dialplan show globals -- Show global dialplan variables
dnsmgr refresh -- Performs an immediate refresh
dnsmgr reload -- Reloads the DNS manager configuration
dnsmgr status -- Display the DNS manager status
features show -- Lists configured features
group show channels -- Display active channels with group(s)
http show status -- Display HTTP server status
indication add -- Add the given indication to the country
indication remove -- Remove the given indication from the country
indication show -- Display a list of all countries/indications
local show channels -- List status of local channels
logger add channel -- Adds a new logging channel
logger mute -- Toggle logging output to a console
logger reload -- Reopens the log files
logger remove channel -- Removes a logging channel
logger rotate -- Rotates and reopens the log files
logger set level {DEBUG|NOTICE|WARNING|ERROR|VERBOSE|DTMF} {on|off} -- Enables/Disables a specific logging level for this console
logger show channels -- List configured log channels
malloc trim -- Return excess memory to the OS
manager reload -- Reload manager configurations
manager set debug [on|off] -- Show, enable, disable debugging of the manager code
manager show command -- Show a manager interface command
manager show commands -- List manager interface commands
manager show connected -- List connected manager interface users
manager show eventq -- List manager interface queued events
manager show events -- List manager interface events
manager show event -- Show a manager interface event
manager show settings -- Show manager global settings
manager show users -- List configured manager users
manager show user -- Display information on a specific manager user
media cache create -- Create an item in the media cache
media cache delete -- Remove an item from the media cache
media cache refresh -- Refresh an item in the media cache
media cache show all -- Show all items in the media cache
media cache show -- Show a single item in the media cache
module load -- Load a module by name
module reload -- Reload configuration for a module
module show [like] -- List modules and info
module unload -- Unload a module by name
moh reload -- Reload MusicOnHold
moh show classes -- List MusicOnHold classes
moh show files -- List MusicOnHold file-based classes
no debug channel -- Disable debugging on channel(s)
pjproject set log level {default|0|1|2|3|4|5|6} -- Set the maximum active pjproject logging level
pjproject show buildopts -- Show the compiled config of the pjproject in use
pjproject show log level -- Show the maximum active pjproject logging level
pjproject show log mappings -- Show pjproject to Asterisk log mappings
pjsip dump endpt -- Dump the res_pjsip endpt internals
pjsip list aors -- List PJSIP Aors
pjsip list auths -- List PJSIP Auths
pjsip list channels -- List PJSIP Channels
pjsip list ciphers -- List available OpenSSL cipher names
pjsip list contacts -- List PJSIP Contacts
pjsip list endpoints -- List PJSIP Endpoints
pjsip list identifies -- List PJSIP Identifies
pjsip list registrations -- List PJSIP Registrations
pjsip list subscriptions {inbound|outbound} [like] -- List active inbound/outbound subscriptions
pjsip list transports -- List PJSIP Transports
pjsip qualify -- Send an OPTIONS request to a PJSIP endpoint
pjsip reload qualify aor -- Synchronize the PJSIP Aor qualify options
pjsip reload qualify endpoint -- Synchronize the qualify options for all Aors on the PJSIP endpoint
pjsip send register -- Registers an outbound registration target
pjsip send unregister -- Unregisters outbound registration target
pjsip set logger {on|off|host} -- Enable/Disable PJSIP Logger Output
pjsip show aors -- Show PJSIP Aors
pjsip show aor -- Show PJSIP Aor
pjsip show auths -- Show PJSIP Auths
pjsip show auth -- Show PJSIP Auth
pjsip show channels -- Show PJSIP Channels
pjsip show channel -- Show PJSIP Channel
pjsip show channelstats -- Show PJSIP Channel Stats
pjsip show contacts -- Show PJSIP Contacts
pjsip show contact -- Show PJSIP Contact
pjsip show endpoints -- Show PJSIP Endpoints
pjsip show endpoint -- Show PJSIP Endpoint
pjsip show identifiers -- List registered endpoint identifiers
pjsip show identifies -- Show PJSIP Identifies
pjsip show identify -- Show PJSIP Identify
pjsip show qualify aor -- Show the PJSIP Aor current qualify options
pjsip show qualify endpoint -- Show the current qualify options for all Aors on the PJSIP endpoint
pjsip show registrations -- Show PJSIP Registrations
pjsip show registration -- Show PJSIP Registration
pjsip show scheduled_tasks -- Show all scheduled tasks
pjsip show settings -- Show global and system configuration options
pjsip show subscription {inbound|outbound} -- Show active subscription details
pjsip show subscriptions {inbound|outbound} [like] -- Show active inbound/outbound subscriptions
pjsip show transports -- Show PJSIP Transports
pjsip show transport -- Show PJSIP Transport
pjsip show unidentified_requests -- Show PJSIP Unidentified Requests
pjsip show version -- Show the version of pjproject in use
rtcp set debug {on|off|ip} -- Enable/Disable RTCP debugging
rtcp set stats {on|off} -- Enable/Disable RTCP stats
rtp set debug {on|off|ip} -- Enable/Disable RTP debugging
say load [new|old] -- Set or show the say mode
stun set debug {on|off} -- Enable/Disable STUN debugging
timing test -- Run a timing test
udptl set debug {on|off|ip} -- Enable/Disable UDPTL debugging
udptl show config -- Show UDPTL config options
voicemail reload -- Reload voicemail configuration
voicemail show aliases -- List mailbox aliases
voicemail show users [for] -- List defined voicemail boxes
voicemail show zones -- List zone message formats
xmldoc dump -- Dump the XML docs to the specified file

*CLI> core show settings

PBX cores settings 
Version: 16.2.0-rc1
Build Options: BUILD_NATIVE, OPTIONAL_API
Maximum calls: Not set
Maximum open file handles: 1024
Root console verbosity: 5
Current console verbosity: 5
Debug level: 0
Maximum load average: 0.000000
Minimum free memory: 0 MB
Startup time: 10:27:35
Last reload time: 10:27:35
System: Linux/4.15.0-1021-aws built by root on x86_64 2019-02-11 11:48:29 UTC
System name:
Entity ID: 0e:28:c0:44:39:5e
PBX UUID: a2df96bb-6d1a-4f64-a953-cf02030e9851
Default language: en
Language prefix: Enabled
User name and group: /
Executable includes: Disabled
Transcode via SLIN: Enabled
Transmit silence during rec: Disabled
Generic PLC: Disabled
Generic PLC on equal codecs: Disabled
Min DTMF duration:: 80
Cache media frames: Enabled
RTP use dynamic payloads: 1
RTP dynamic payload types: 35-63,96-127

Subsystems
Manager (AMI): Disabled
Web Manager (AMI/HTTP): Disabled
Call data records: Enabled
Realtime Architecture (ARA): Disabled

Directories
Configuration file: /etc/asterisk/asterisk.conf
Configuration directory: /etc/asterisk
Module directory: /usr/lib/asterisk/modules
Spool directory: /var/spool/asterisk
Log directory: /var/log/asterisk
Run/Sockets directory: /var/run/asterisk
PID file: /var/run/asterisk/asterisk.pid
VarLib directory: /var/lib/asterisk
Data directory: /var/lib/asterisk
ASTDB: /var/lib/asterisk/astdb
IAX2 Keys directory: /var/lib/asterisk/keys
AGI Scripts directory: /var/lib/asterisk/agi-bin


Advertisements

Kamailio WebRTC SIP Server

The purpose of this article if to demo the process of using Kamailio + RTP Engine to enable SIP based WebRTC call to a traditional SIP UA like Xlite. Kamailio Will thus provide not only call routing but also NATing , TLS and websocket support for webrtc endpoints.

For this bridging of SRTP from WebRTC endpoint like JSSIP to RTP for SIP UA like Xlite , we will use RTP engine .

Kamailio

Kamailio with modules like websocket , TLS , NATHelper which help it to support websocket based SIP which default kamailio configuration doesn’t.

Snippets from kamailio config to support webrtc endpoints is below . the detailed explanation is at kamailio config for webrtc

loadmodule "tm.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tls.so"
loadmodule "xhttp.so"
loadmodule "websocket.so"
loadmodule "nathelper.so"

Configuration of some important modules

TLS module

To provide the SSL support which webrtc endpoints require Certificate Authority CA and provate certs signed by it

creating file paths

mkdir certs
mkdir certs/private
mkdir certs/newcerts
touch certs/index.txt
echo 01 >certs/serial
echo 01 >certs/crlnumber

list the files

/home/ubuntu/certs# ls
crlnumber  index.txt  newcerts  private  serial

create ca private key

openssl genrsa -out certs/private/cakey.pem 2048
chmod 600 certs/private/cakey.pem

create ca self signed certificate

openssl req -out certs/cacert.pem -x509 -new -key certs/private/cakey.pem

create server / client certificate, a private key (by name privkey.pem)

openssl req -out kamailio1_cert_req.pem -new -nodes
openssl ca -in kamailio1_cert_req.pem -out kamailio1_cert.pem

output should be like

Certificate is to be certified until Jun 25 11:02:41 2020 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

and files genrated shoudl look like

/home/ubuntu# ls 
 certs  kamailio1_cert.pem kamailio1_cert_req.pem privkey.pem

copy the newly created certs to their respective paths

mkdir /etc/pki/CA/
cp kamailio1_cert.pem /etc/pki/CA/
cp privkey.pem /etc/pki/CA/

make list of ca certs by finidng all cacerts accross root firectory and appending them to a catlist pem

find / -name cacert.pem
cat /usr/share/doc/libssl-doc/demos/cms/cacert.pem >> /home/ubuntu/catlist.pem
cat /usr/share/doc/libssl-doc/demos/smime/cacert.pem >> /home/ubuntu/catlist.pem
cat /home/ubuntu/kamailio_source_code/misc/tls-ca/rootCA/cacert.pem >> /home/ubuntu/catlist.pem
...
cp /home/ubuntu/catlist.pem /etc/pki/CA/

update kamailio.cfg

#!ifdef WITH_TLS
enable_tls=1
#!endif
...
modparam("tls", "tls_method", "SSLv23")
modparam("tls", "certificate", "/etc/pki/CA/kamailio1_cert.pem")
modparam("tls", "private_key", "/etc/pki/CA/privkey.pem")
modparam("tls", "ca_list", "/etc/pki/CA/calist.pem")

Websocket module

Websocket is considered a transport option just as TCP or UDP in kamailio config , hence just as one defines IP addr and ports for TCP, UDP protocol , we need to define the same for WS or WSS

#!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
#!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"
...
listen=MY_IP_ADDR
#!ifdef WITH_WEBSOCKETS
listen=MY_WS_ADDR
#!ifdef WITH_TLS
listen=MY_WSS_ADDR
#!endif
#!endif

check if port in R-URI meant for ws or wss, did not receive websocket or secure websocket

if (($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT) && !(proto == WS || proto == WSS)) {
    xlog("L_WARN", "SIP request received on $Rp\n");
    sl_send_reply("403", "Forbidden");
    exit;
}

request_route for websocket , included checking is client is behind NAT using nat_uac_test methods from NAThelper. If it is then for REGISTER methods do fix_nated_register and for other add_contact_alias

#!ifdef WITH_WEBSOCKETS
if (nat_uac_test(64)) {
	# NAT traversal  WebSocket
	force_rport();
	if (is_method("REGISTER")) {
		fix_nated_register();
	} else {
		if (!add_contact_alias()) {
		xlog("L_ERR", "Error aliasing contact <$ct&gt;\n");
		sl_send_reply("400", "Bad Request");
		exit;
		}
	}
}
#!endif

RTP engine

RTP relay and NAT helps with RTP packets

For detailed steps goto https://telecom.altanai.com/2018/04/03/rtp-engine-on-kamailio-sip-server/

dependencies

apt-get remove rtpproxy
sudo apt install debhelper iptables-dev libcurl4-openssl-dev libglib2.0-dev libxmlrpc-core-c3-dev libhiredis-dev markdown build-essential:native

source

git clone https://github.com/sipwise/rtpengine.git
cd rtpengine
 ./debian/flavors/no_ngcp

run

rtpengine --interface=54.86.35.95 --listen-ng=25061 --listen-cli=25062 --foreground --log-stderr --listen-udp=2222 --listen-tcp=25060

integrate with kamailio using

loadmodule "rtpengine.so"
...
modparam("rtpengine", "rtpengine_sock", "udp:localhost:7722")
modparam("nathelper", "received_avp", "$avp(s:rcv)")
...
tbd

JSSIP

Like most other WebRTC libraries , JSSIP is event driven and provides provide core WEBRTC API like getUserMedia and RTP PeerConnection providing STUN,ICE,DTLS, SRTP features. It also integrated with rtcninja to provide cross browser accessibility. The differentiators with JSSIP lies in the fact that it supports SIP stack over websockets

Building JSSIP client for kamailio

Can use CDN based https://cdnjs.cloudflare.com/ajax/libs/jssip/3.1.2/jssip.min.js

or can take a pull from JSSIP repo and build urself using gulp https://github.com/versatica/JsSIP

instantiate JSSIP websocket interface with kamailio IP

var socket = new JsSIP.WebSocketInterface('wss://<kamailio_ip>:443');

Add configuration for registeration . Note if not using kamailio as proxy to SBC, it is recommended to add regiseteration features to provide user reachability for incoming calls and NAT pings

var configuration = {
sockets : socket,
uri : 'sip:username@example.com',
password : 'password'
};

create UA and start

var ua = new JsSIP.UA(configuration);
ua.start();

SIP over WEBSOCKET messages and kamailio processing

REGISTER sip JSSIP UA with user altanai , domina voiptelcom.com

REGISTER sip:voiptelco.com SIP/2.0
Via: SIP/2.0/WSS 830p2l39g8bg.invalid;branch=z9hG4bK242397
Max-Forwards: 69
To: 
From: ;tag=3jaad0q8l8
Call-ID: fvn2cd1b9gqh6kd7nqdpj5
CSeq: 1 REGISTER
Contact: ;+sip.ice;reg-id=1;+sip.instance="";expires=600
Expires: 600
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO
Supported: path,gruu,outbound
User-Agent: JsSIP 3.1.2
Content-Length: 0

Processed by kamailio using REGISTRAR route block

route(REGISTRAR);
..
route[REGISTRAR] {
	if (is_method("REGISTER")) {
		if (!save("location")) {
			sl_reply_error();
		}
		exit;
	}
}
SIP/2.0 200 OK
Via: SIP/2.0/WSS 830p2l39g8bg.invalid;branch=z9hG4bK242397;rport=19035;received=x.x.x.x
To: ;tag=4dad943d40a0a309c33d64467664aa30.f6d3
From: ;tag=3jaad0q8l8
Call-ID: fvn2cd1b9gqh6kd7nqdpj5
CSeq: 1 REGISTER
Contact: ;expires=600;received="sip:x.x.x.x:19035;transport=ws";pub-gruu="sip:altanai@voiptelco.com;gr=urn:uuid:80fa65e7-1cd7-4e40-bbee-c07f7a1ae9a5";temp-gruu="sip:uloc-5d260578-4b58-c-eeac6bd6@voiptelco.com;gr";+sip.instance="";reg-id=1
Server: kamailio (5.2.3 (x86_64/linux))
Content-Length: 0

INVITE from user1 altanai to john , notice that TO header doesnt have tag . this will handy for recognizing whether it is first message of dialog of=r and indialog message such as ACK , RE-INVITE , BYE etc

INVITE sip:john@voiptelco.com SIP/2.0
Via: SIP/2.0/WSS ipoct61ao12v.invalid;branch=z9hG4bK4220209
Max-Forwards: 69
To: sip:john@voiptelco.com
From: sip:altanai@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Contact: 
Content-Type: application/sdp
Session-Expires: 90
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO
Supported: timer,gruu,ice,replaces,outbound
User-Agent: JsSIP 3.1.2
Content-Length: 1823

with SDP containing codecs and ICE details. Supporting audio over UDP/ TLS/RTL /SAVPF . Codecs beings

  • 111 OPUS
  • 103 ISAC/16000
  • 104 ISAC/32000
  • 9 G722
  • 0 PCMU / G.711u narrowband
  • 8 PCMA / G.711
  • 106 , 105 , 13 – CN / comfort noise
  • 110 , 112 , 113 , 126 – telephone-event / DTMF
v=0
o=- 4779000713447952953 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb
m=audio 55839 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 192.168.0.3
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:3802297132 1 udp 2122260223 192.168.0.3 55839 typ host generation 0 network-id 1 network-cost 10
a=candidate:2887880668 1 tcp 1518280447 192.168.0.3 9 typ host tcptype active generation 0 network-id 1 network-cost 10
a=ice-ufrag:0PIq
a=ice-pwd:i7ccvGPXLDO5JqMwbCUqMcyN
a=ice-options:trickle
a=fingerprint:sha-256 AB:50:70:E3:57:E3:0C:7B:61:3B:03:5B:0F:54:14:14:9C:49:50:16:07:DC:E7:09:3E:4D:B5:A0:2B:EC:84:A1
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb e803836d-249a-4b81-b73f-17e0f08dde5a
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:2800821831 cname:kLWViBLDLVfCXY8x
a=ssrc:2800821831 msid:SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb e803836d-249a-4b81-b73f-17e0f08dde5a
a=ssrc:2800821831 mslabel:SFIXFrpsOUskJ5JQhp1mIARlDk6S3hVFTOBb
a=ssrc:2800821831 label:e803836d-249a-4b81-b73f-17e0f08dde5a

100 trying from callee . Note the to and from headers remain same for request or responses . This is send automatically by kamailio for INVITE.

SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/WSS ipoct61ao12v.invalid;branch=z9hG4bK4220209;rport=17502;received=x.x.x.x
To: sip:john@voiptelco.com
From: sip:altanai@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Server: kamailio (5.2.3 (x86_64/linux))
Content-Length: 0

180 ringing from Callee , note the addition of contact header

SIP/2.0 180 Ringing
Record-Route: 
Via: SIP/2.0/WSS ipoct61ao12v.invalid;rport=17502;received=x.x.x.x;branch=z9hG4bK4220209
To: sip:john@voiptelco.com;tag=pvm73e3t89
From: sip:altanai@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Contact: sip:john@voiptelco.com;alias=x.x.x.x~17510~6;gr=urn:uuid:2e560b36-3ea8-41fd-80e3-ede66babb8a7
Supported: timer,gruu,ice,replaces,outbound
Content-Length: 0

200 OK with SDP

SIP/2.0 200 OK
Record-Route: 
Via: SIP/2.0/WSS ipoct61ao12v.invalid;rport=17502;received=x.x.x.x;branch=z9hG4bK4220209
To: sip:altanai@voiptelco.com;tag=pvm73e3t89
From: sip:john@voiptelco.com ;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 INVITE
Contact: sip:john@voiptelco.com;alias=x.x.x.x~17510~6;gr=urn:uuid:2e560b36-3ea8-41fd-80e3-ede66babb8a7
Session-Expires: 90;refresher=uas
Supported: timer,gruu,ice,replaces,outbound
Content-Type: application/sdp
Content-Length: 1477
v=0
o=- 4562215268128860297 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic: WMS oxU77z9z9RfNL4CayvM1cMJKI0r7u6ZdqLBd
m=audio 55380 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 192.168.0.3
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:3802297132 1 udp 2122260223 192.168.0.3 55380 typ host generation 0 network-id 1 network-cost 10
a=ice-ufrag:40h+
a=ice-pwd:6zJo50N7Bb2mqnrHq+jniukk
a=ice-options:trickle
a=fingerprint:sha-256 8A:F9:BE:8D:8A:80:FF:8C:89:3D:3A:D2:A1:36:B2:EC:11:53:81:7E:F4:53:E7:40:1E:B9:1E:A2:0F:D4:EA:2E
a=setup:active
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:oxU77z9z9RfNL4CayvM1cMJKI0r7u6ZdqLBd cb6da6b5-d5b8-460e-88bc-1458ebc718e6
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:3489110087 cname:oZ2LjwJD385qPHHH

Kamailio handling replies using reply_route

onreply_route {
     if (nat_uac_test(64)) {
         add_contact_alias();
     }
 }

Sending ACK .

ACK sip:john@voiptelco.com;alias=x.x.x.x~17510~6;gr=urn:uuid:2e560b36-3ea8-41fd-80e3-ede66babb8a7 SIP/2.0

Route: 
Via: SIP/2.0/WSS ipoct61ao12v.invalid;branch=z9hG4bK1876245
Max-Forwards: 69
To: sip:altanai@voiptelco.com ;tag=pvm73e3t89
From: sip:john@voiptelco.com;tag=2q0lecmbsn
Call-ID: s8bnv5869fp68d1ju8c1
CSeq: 1799 ACK
Allow: INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO
Supported: outbound
User-Agent: JsSIP 3.1.2
Content-Length: 0

since ACK is a Within dialog message and sequential request withing a dialog should take the path determined by record-routing , we first check if it has to tag. Having a to tag validates that it is a in-dialog request .

After this validate if is loose_route() and has no destination URI $du , then try to add rui alias using handle_ruri_alias() , if that fails , reject the request .

If it is not loose_route() and method is ACK then check if the ACK matches a transaction t_check_trans() ie is stateful . If it is then relay otherwise reject.

route(WITHINDLG);
...
route[WITHINDLG] {
	if (has_totag()) {
		if (loose_route()) {
			if ($du == "") {
				if (!handle_ruri_alias()) {
				xlog("L_ERR", "Bad alias <$ru&gt;\n");
				sl_send_reply("400", "Bad Request");
				exit;
				}
			}
			route(RELAY);
		} else {
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
				t_relay();
				exit;
				} else {
				exit;
				}
			}
			sl_send_reply("404", "Not Found");
		}
		exit;
	}
}

Also required to convert ICE packet fromWebRTC to non ICE for Xlite.

Kamailio Transaction management

Kamailio is basically only a transaction stateful proxy, without any dialog support build in. Here the TM module enables stateful processing of SIP transactions. State is a requirement for many complex logic such as accounting, forking , DNS resolution .

Branches – A single SIP INVITE request may be forked to multiple destinations , all of which together is called destination sets and Individual elements within the destination sets are called branches. A transaction can have more than one branch.
For example, during DNA failover, each failed DNS SRV destination can introduce a new branch.

Serial, Parallel and Combined Forking – By default kamailio performs parallel forking sending msg to all destinations and waiting for response , however it can also do serial ie send request one by one and wait for response /timeout before sending next . By use of priorities ( q valaue 0 – 1.0) , Kamailio can also intermix the forking technique ie describing priority oder for serial and same level for parallel . The destination uri are loaded using unctions t_load_contacts() and t_next_contacts().

parallel forking exmaple

request_route {
  seturi("sip:a@example.com");
  append_branch("sip:b@example.com");
  append_branch("sip:c@example.com");
  append_branch("sip:d@example.com");

  t_relay();
  break;
}

mixed forking exmaple

modparam("tm", "contacts_avp", "tm_contacts");
modparam("tm", "contact_flows_avp", "tm_contact_flows");

request_route {
  seturi("sip:a@example.com"); // lowest 0 
  append_branch("sip:b@example.com", "0.5"); // shoudl be in parallel with C
  append_branch("sip:c@example.com", "0.5"); // shoudl be in parallel with B
  append_branch("sip:d@example.com", "1.0"); // highest priority , should be tried first

  t_load_contacts();   // load all branches as per q values, store them in AVP configured in modparam 
  t_next_contacts();   // takes AVP and extracts higher q value branch

  t_relay();
  break;
}

Code to terminate when no more branches are found ( -1 returned) and return the message upstream

failure_route["serial"]
{
  if (!t_next_contacts()) {
    exit;
  }
  t_on_failure("serial");
  t_relay();
}

TM Module

t_relay, t_relay_to_udp and t_relay_to_tcp are main functions to setup transaction state, absorb retransmissions from upstream, generate downstream retransmissions and correlate replies to requests.

Memeory

TM copies clones of received SIP messages in shared memory. non-TM functions operate over the received message in private memory. Therefore core operations ( like record_route) should ne called before settings the trasnaction state ( t_realy ) for statefully processing a message.

An INVITE transaction will be kept in memory for maximum: max_inv_lifetime + fr_timer + wt_timer.
While A non-INVITE transaction will be kept in memory for a maximum: max_noninv_lifetime + wt_timer.

Parameters :

various parameters are used to fine tune how trsnactions are handled and timedout in kamailio. Note all timers are set in miliseconds notation.

fr_timer (integer) – timer hit when no final reply for a request or ACK for a negative INVITE reply arrives. Default 30000 ms (30 seconds).

fr_inv_timer (integer) – timer hit when no final reply for an INVITE arrives after a provisional message was received on branch. Default 120000 ms (120 seconds).

restart_fr_on_each_reply (integer) – restart fr_inv_timer fir INVITE transaction for each provisional reply. Otherwise it will be sreatred only for fisrt and then increasing provisonal replies. Turn it off in cases when dealing with bad UAs that continuously retransmit 180s, not allowing the transaction to timeout.

max_inv_lifetime (integer) – Maximum time an INVITE transaction is allowed to be active in a tansaction. It starts from the time trnsaction was created and after this timer is hit , transaction is moved to either wait state or in the final response retransmission state. Default 180000 ms (180 seconds )

max_noninv_lifetime (integer) – Maximum time a non-INVITE transaction is allowed to be active. default 32000 ms (32 seconds )

wt_timer (integer) – Time for which a transaction stays in memory to absorb delayed messages after it completed.

delete_timer (integer) – Time after which a to-be-deleted transaction currently ref-ed by a process will be tried to be deleted again. This is now obsolte and now transaction is deleted the moment it’s not referenced anymore.

retr_timer1 (integer) – Initial retransmission period

retr_timer2 (integer) – Maximum retransmission period started increasingly from starts with retr_timer1 and stays constant after this

noisy_ctimer (integer) – if set, INVITE transactions that time-out (FR INV timer) will be always replied. Otherwise they will be quitely dropped without any 408 branch timeout resposne

auto_inv_100 (integer) – automatically send and 100 reply to INVITEs.

auto_inv_100_reason (string) – Set reason text of the automatically sent 100 to an INVITE.

unix_tx_timeout (integer) – nix socket transmission timeout,

aggregate_challenges (integer) – if more than one branch received a 401 or 407 as final response, then all the WWW-Authenticate and Proxy-Authenticate headers from all the 401 and 407 replies will be aggregated in a new final response.

blst_503 (integer) – reparse_invite=1.

blst_503_def_timeout (integer) – blacklist interval if no “Retry-After” header is present

blst_503_min_timeout / blst_503_max_timeout (integer) – minimum and maximun blacklist interval respectively

blst_methods_add (unsigned integer) – Bitmap of method types that trigger blacklisting on transaction timeouts and by default INVITE triggers blacklisting only

blst_methods_lookup (unsigned integer) – Bitmap of method types that are looked-up in the blacklist before being forwarded statefully. For default only applied to BYE.

reparse_invite (integer) – set if CANCEL and negative ACK requests are to be constructed from the INVITE message ( same record-set etc as INVITE ) which was sent out instead of building them from the received request.

ac_extra_hdrs (string) – Header fields prefixed by this parameter value are included in the CANCEL and negative ACK messages if they were present in the outgoing INVITE. Can be only used with reparse_invite=1.

reparse_on_dns_failover (integer) – SIP message after a DNS failover is constructed from the outgoing message buffer of the failed branch instead of from the received request.

on_sl_reply (string) – Sets reply route block, to which control is passed when a reply is received that has no associated transaction.

modparam("tm", "on_sl_reply", "stateless_replies")
...
onreply_route["stateless_replies"] {
    // return 0 if do not allow stateless replies to be forwarded
    return 1; // will pass to core for stateless forwading
}

xavp_contact (string) – name of XAVP storing the attributes per contact.

contacts_avp (string) – name of an XAVP that stores names of destination sets. Used by t_load_contacts() and t_next_contacts() for forking branches

contact_flows_avp (string) – name of an XAVP that were skipped

fr_timer_avp (string) – override teh value of fr_timer on per transactio basis , outdated

fr_inv_timer_avp (string) – same as abovel , outdated

cancel_b_method (integer) – method to CANCEL an unreplied transaction branch. Params :
0 will immediately stop the request (INVITE) retransmission on the branch so that unrpelied branches will be terminated
1 will keep retransmitting the request on unreplied branches.
2 end and retransmit CANCEL even on unreplied branches, stopping the request retransmissions.

unmatched_cancel (string) – sets how to forward CANCELs that do not match any transaction. Params :
0 statefully
1 statelessly
2 dropping them

ruri_matching (integer) – try to match the request URI when doing SIP 1.0 transaction matching as older SIP didnt have via cookies as in RFC 3261

via1_matching (integer) – match the topmost “Via” header when doing SIP 1.0 transaction matching

callid_matching (integer) – match the callid when doing transaction matching.

pass_provisional_replies (integer)

default_code (integer) – Default response code sent by t_reply() ( 500 )

default_reason (string) – Default SIP reason phrase sent by t_reply() ( “Server Internal Error” )

disable_6xx_block (integer)- treat all the 6xx replies like normal replies. However according to RFC receiving a 6xx will cancel all the running parallel branches, will stop DNS failover and forking.

local_ack_mode (integer) – where locally generated ACKs for 2xx replies to local transactions are sent. Params :
0 – the ACK destination is choosen according next hop in contact and the route set and then DNS resolution is used on it
1 – the ACK is sent to the same address as the corresponding INVITE branch
2 – the ACK is sent to the source of the 2xx reply.

failure_reply_mode (integer) – how branches are managed and replies are selected for failure_route handling. Params :
0 – all branches are kept
1 – all branches are discarded
2 – only the branches of previous leg of serial forking are discarded
3 – all previous branches are discarded
if you dont want to drop all branches then use t_drop_replies() to sleectively drop

faked_reply_prio (integer) – how branch selection is done.

local_cancel_reason (boolean) – add reason headers for CANCELs generated due to receiving a final reply.

e2e_cancel_reason (boolean) – add reason headers for CANCELs generated due to receiving a CANCEL

remap_503_500 (boolean) – conversion of 503 response code to 500. RFC requirnment.

failure_exec_mode (boolean) – Add local failed branches in timer to be considered for failure routing blocks.

dns_reuse_rcv_socket (boolean) – reuse of the receive socket for additional branches added by DNS failover.

event_callback (str) – function in the kemi configuration file (embedded scripting language such as Lua, Python, …) to be executed instead of event_route[tm:local-request] block. The function recives a string param with name of the event

modparam("tm", "event_callback", "ksr_tm_event")
...
function ksr_tm_event(evname)
    KSR.info("===== TM module triggered event: " .. evname .. "\n");
    return 1;
end

relay_100 (str) – whether or not a SIP 100 response is proxied. not valid behavior when operating in stateful mode and only useful when in stateless mode

rich_redirect (int) – to add branch info in 3xx class reply. Params :
0 – no extra info is added (default)
1 – include branch flags as contact header parameter
2 – include path as contact uri Route header

Functions

These functions are operational blocks and route handlers for trsnactions handling in kamailio

t_relay([host, port]) – Relay a message statefully.
Exmaple to show if t_relay fails , atleast send a reply to UAC statelessly to not keep it waiting

if (!t_relay()) 
{ 
    sl_reply_error(); 
    break; 
};

t_relay_to_udp([ip, port]) / t_relay_to_tcp([ip, port]) – same as above but using specific protocol

if (some_conditon)
    t_relay_to_udp("1.2.3.4", "5060"); # sent to 1.2.3.4:5060 over udp
else
    t_relay_to_tcp(); # relay to msg. uri, but over tcp

t_relay_to_tls([ip, port])

t_relay_to_sctp([ip, port])

t_on_failure(failure_route) – on route block for failure management on a branch when a negative reply is recived to transaction. here uri is reset to value which it had on relaying.

t_on_branch_failure(branch_failure_route) – controls when negative response come for a transacion. here uri is reset to value which it had on relaying.

t_on_reply(onreply_route) – gets control when a reply from transaction is received

t_on_branch(branch_route) – control is passed after forking (when a new branch is created)

t_newtran() – Creates a new transaction

t_reply(code, reason_phrase) – Sends a stateful reply after a transaction has been established.

t_send_reply(code, reason)

t_lookup_request() – Checks if a transaction exists

t_retransmit_reply()

t_release() – Remove transaction from memory

t_forward_nonack([ip, port]) – forward a non-ACK request statefully

t_forward_nonack_udp(ip, port) / t_forward_nonack_tcp(ip, port)

t_forward_nonack_tls(ip, port)

t_forward_nonack_sctp(ip, port)

t_set_fr(fr_inv_timeout [, fr_timeout]) – Sets the fr_inv_timeout

t_reset_fr()

t_set_max_lifetime(inv_lifetime, noninv_lifetime) – Sets the maximum lifetime for the current INVITE or non-INVITE transaction, or for transactions created during the same script invocation

t_reset_max_lifetime()

t_set_retr(retr_t1_interval, retr_t2_interval) – Sets the retr_t1_interval and retr_t2_interval for the current transaction

t_reset_retr()

t_set_auto_inv_100(0|1) – switch automatically sending 100 replies to INVITEs on/off on a per transaction basis

t_branch_timeout() – Returns true if the failure route is executed for a branch that did timeout.

t_branch_replied()

t_any_timeout()

t_any_replied()

t_grep_status(“code”)

t_is_canceled()

t_is_expired()

t_relay_cancel()

t_lookup_cancel([1])
t_drop_replies([mode])
t_save_lumps()
t_load_contacts()
t_next_contacts()
t_next_contact_flow()
t_check_status(re)

t_check_trans() – check if a message belongs or is related to a transaction.

t_set_disable_6xx(0|1)
t_set_disable_failover(0|1)
t_set_disable_internal_reply(0|1)

t_replicate([params]) – Replicate the SIP request to a specific address.

t_relay_to(proxy, flags) – KSR.tm.t_relay()

t_set_no_e2e_cancel_reason(0|1)

t_is_set(target) – KEMI – KSR.tm.t_is_set() Return true if the attribute specified by ‘target’ is set for transaction. Target can be branch_route , failure_route and onreply_route

if not(KSR.tm.t_is_set("branch_route")>0) then
    core.set_branch_route("ksr_branch_manage");
end
if not(KSR.tm.t_is_set("onreply_route")>0) then
    core.set_reply_route("ksr_onreply_manage");
end
if not(KSR.tm.t_is_set("failure_route")>0) and (req_method == "INVITE") then
   core.set_failure_route("ksr_failure_manage");
end

t_use_uac_headers()

t_is_retr_async_reply()

t_uac_send(method, ruri, nexthop, socket, headers, body)

t_get_status_code() – Return the status code for transaction or -1 in case of error or no status code was set.

raw RPC cmds

kamctl rpc tm.list

{  

   "jsonrpc":"2.0",
   "result":[  
      {  
         "cell":"0x7f0698d06488",
         "tindex":50969,
         "tlabel":163886326,
         "method":"INVITE",
         "from":"From: ;tag=dddab54e\r\n",
         "to":"To: \r\n",
         "callid":"Call-ID: NjkyYjJlNzJkNzQ1OTYyZjE2MDM2NjFlYWZkNjY4OWE\r\n",
         "cseq":"CSeq: 1",
         "uas_request":"yes",
         "tflags":65,
         "outgoings":2,
         "ref_count":1,
         "lifetime":29578635
      }
   ],
   "id":3922
}

kamctl rpc tm.stats

before call

{  
   "jsonrpc":"2.0",
   "result":{  
      "current":0,
      "waiting":0,
      "total":3,
      "total_local":0,
      "rpl_received":6,
      "rpl_generated":6,
      "rpl_sent":6,
      "6xx":0,
      "5xx":3,
      "4xx":0,
      "3xx":0,
      "2xx":0,
      "created":3,
      "freed":3,
      "delayed_free":0
   },
   "id":4119
}

during call

{  

   "jsonrpc":"2.0",
   "result":{  
      "current":1,
      "waiting":0,
      "total":4,
      "total_local":0,
      "rpl_received":7,
      "rpl_generated":7,
      "rpl_sent":7,
      "6xx":0,
      "5xx":3,
      "4xx":0,
      "3xx":0,
      "2xx":0,
      "created":4,
      "freed":3,
      "delayed_free":0
   },
   "id":4217
}

during call wait

{  
   "jsonrpc":"2.0",
   "result":{  
      "current":1,
      "waiting":1,
      "total":4,
      "total_local":0,
      "rpl_received":8,
      "rpl_generated":8,
      "rpl_sent":8,
      "6xx":0,
      "5xx":4,
      "4xx":0,
      "3xx":0,
      "2xx":0,
      "created":4,
      "freed":3,
      "delayed_free":0
   },
   "id":4275
}

after call is completed

{  
   "jsonrpc":"2.0",
   "result":{  
      "current":0,
      "waiting":0,
      "total":4,
      "total_local":0,
      "rpl_received":8,
      "rpl_generated":8,
      "rpl_sent":8,
      "6xx":0,
      "5xx":4,
      "4xx":0,
      "3xx":0,
      "2xx":0,
      "created":4,
      "freed":4,
      "delayed_free":0
   },
   "id":4333
}

Opensips

It is an multi-functional, multi-purpose SIP server especially used in VoIP landscape as standalone SIP server or SBC ( Session Border Controller ) for inbound and outbound traffic by carriers, telecoms backend layers or ITSPs for call routing and trunking solutions. It can be deployed with Class4/5 Platforms, SIP Trunking , hosted or IP PBX setup , existing gateways/ Session Border Controllers, Application Servers, proxy server, Front-End Load Balancers, IMS Platforms, Call Center etc.

Combination of opensips working scenarios scripts with code is at https://github.com/altanai/opensipsexamples.

Features

Due to its very flexible and customisable routing engine it can be used in number of scenarios such as an SIP proxy or a  router and due to its high throughput it is widely recommended as an enterprise grade inbound/outbound proxy server.

  • Registrar
  • Router / proxy (lcr, dynamic routing, dialplan features)
  • Redirect server
  • Presence agent
  • Back-to-back User Agent
  • IM server
  • SIP to SMS gateway (bidirectional)
  • SIP to XMPP gateway for presence and IM (bidirectional)
  • Load-balancer or dispatcher
  • Inbound/front end for gateways/asterisk
  • SIP NAT traversal unit
  • Application server with custom logic

Since Opensips has emerged as a resilent SIP server , it is also used in specific usecases such as
– DID ( Direct Inward dialling ) for SIP trunking solutions ,
– Local Number Portability (LNP) providers,
– Canonical Name (CNAME) providers etc

It can act as Registrar with NAT traversal abilities (STUN, TURN, SIP pinging)

UDP , TCP , TLS , SCTP and WS transports over both IPv4 and IPv6
Additionally it can be connected to multiple networks ( Multihomed ) and do IP authentication or IP blacklisting

Class 4 routing capabilities in opensips include SIP aliases, Direct Inward Dialing , Speed dial, CPL,vDialplan , dispatcher with various algorithms, prefix-based routing to multiple carriers , failover support,
Load balancing , ENUM-based or Geolocation-based routing etc.
Some of the Class 5 capabilities in opensips are B2B , call queuing
UAC registration , authentication, mangling, White/Black list

SIP SIMPLE features as messaging , Presence , Busy Lamp Field (BLF), Shared Call/Line Appearance (SCA) , Bridged Line Appearance (BLA) , Message Waiting notifications (MWI), XCAP , Resource List Server ( RLS ) , XMPP , SMS gateway (AT and SMPP)

Although opensips has no built-in media capabilities, but it modules for external media engines for Media relaying (RTPProxy, MediaProxy, RTPEngine), Media transcoding (Sangoma D1 cards) , Codec manipulation.

I have explained the usage of these server components in my previous article on  SIP entities and Server here https://telecom.altanai.com/2013/07/13/sip-entities/

Modular Arhitecture

Opensips has majorly 2 parts core and addon-modules.

Opensips Core part is only a proxy stateless SIP server . It contains

  • SIP transport layer which supports UDP, TCP, TLS and WS for SIP. As per the listener in routing script transport protocols is selected .
  • SIP factory — the message parser and builder which can be used to add new headers or remove existing ones.
  • Routing script parser and interpreter for the routing script which loads it to the memory at the startup time. To load a new script server restart is required.
  • Memory and locking manager for the memory allocation and locking to prevent deadlocks and starvation. Although these arn’t accesible by route scripting, it can be configured at compile time.
  • Core script functions and variables which can be used in routing scripts in addition to the functions exported by add-on modules.

Interfaces

Events Interface

Used to notify external applications about events triggered internal to OpenSIPS such as
core events – E_CORE_THRESHOLD ,E_CORE_PKG_THRESHOLD , E_CORE_SHM_THRESHOLD , modules events , or even a custom event using raise_event() command

Statistics Interface

Provide insights to statistics of opensips in numerical results which could be used for services like  monitoring, load evaluation, realtime integration etc. The statictsics can be of two kinds :
1. counter like – variables that keep counting things that happened in OpenSIPS, like received requests, processed dialogs, failed DB queries, etc
2. computed values – variables that are calculated in realtime, like how much memory is used, the current load, active dialogs, active transactions, etc

These variable would reset form 0 at start sometimes even during runtime.

Binary Internal Interface

Provider communication between individual OpenSIPS instances. Used in cases such as failovers where dialogs needs to persist for service continuity. Hence with this interface one can replicate all the events related to the runtime data (creation / updating / deletion) to a backup OpenSIPS instance.

SQL interface and NoSQL interface

SQL interfaces provides interaction with Sql DB drivers and services such as MySQL, Postgres, Oracle, Berkeley, unixODBC etc , while NoSQL interface provides access to Redis, CouchBase, Cassandra, MongoDB, Memcached, and other databases which are more frequently implemented as external caches.

AAA interface definition

Currently, OpenSIPS supports the RADIUS driver for the AAA interface with upcoming support for DIAMETER.

Management interface

Allows the external applications to trigger predefined commands
Push data like setting a debug level, registering a contact etc
Fetch data like registered users, ongoing calls, get statistics etc
Trigger an internal action as reloading the data, sending a message so on

1. Functional SIP modules

SIP signalling modules such as B2B_ENTITIES , B2B_LOGIC , CALL CENTER ( for Inbound call center system ) , DIALOG , NAT_TRAVERSAL , NATHELPER
OPTIONS , REGISTRAR ,SIGNALING , UAC_REGISTRANT
TM (Transaction/stateful module) , SL (Stateless replier ) , SMS (SIP-to-SMS IM gateway)

SIP Routing modules such as CARRIERROUTE ( routing extension suitable for carriers) , CPL_C ( Call Processing Langugage interpreter ) ,
DISPATCHER , DROUTING ( Dynamic Routing / LCR ) , EMERGENCY ,ENUM ,
JABBER (JABBER IM and PRESENCE interconnection ) , IMC ( Instant Messaging Conferencing ),
LOAD_BALANCER , MSILO (SIP message silo) , RR ( Record-Route) , SCRIPT_HELPER ( Embedded SIP routing logic and dialog management) , OSP ( Open Settlement Protocol )

SIP messaging related , COMPRESSION , DIVERSION , IDENTITY ,MAXFWD , MANGLER
PATH , SIPMSGOPS ( SIP operations ) , TOPOLOGY_HIDING ,
UAC , UAC_AUTH , UAC_REDIRECT
URI , SST ( SIP Session Timer support )

Presence Modules like PRESENCE , PRESENCE_CALLINFO , PRESENCE_DIALOGINFO, PRESENCE_MWI (for Message Waiting Indication ) , PRESENCE_XCAPDIFF (for XCAP-DIFF event) , PRESENCE_XML
PUA , PUA_BLA , PUA_DIALOGINFO , PUA_MI , PUA_USRLOC , PUA_XMPP
B2B_SCA ( Back-to-Back Shared Call ), RLS ( Resource List Server )
XCAP , XCAP_CLIENT

2. Scripting modules

Script helper modules such as JSON , CFGUTILS , EXEC , TEXTOPS , AVPOPS , REGEX, MATHOPS , BENCHMARK ,
CARRIERROUTE , GFLAGS (Global shared flags )
PYTHON , LUA ,PERL , MMGEOIP ( MaxMind GeoIP )

Auth modules such as AUTH , AUTH_AAA ,AUTH_DB , PERMISSIONS

Accounting & Billing modules aas ACC ,CALL CONTROL

Dialplan Modules like ALIAS_DB , DIALPLAN , DOMAIN ( Multi-domain support ) , DOMAINPOLICY ,
GROUP , USERBLACKLIST , SPEEDDIAL ,PEERING ( Radius peering )

Data caching as DNS_CACHE , USRLOC ,SQL_CACHER

Traffic shaping module as PIKE ( Flood detector module ), QOS ,RATELIMIT ,FRAUD_DETECTION

3. Database modules

For SQL – DB_BERKELEY , DB_CACHEDB , DB_FLATSTORE , DB_HTTP , DB_MYSQL , DB_ORACLE ,DB_PERLVDB , DB_POSTGRES , DB_SQLITE
DB_TEXT , DB_UNIXODBC , DB_VIRTUAL

For noSQL – CACHEDB_CASSANDRA ,CACHEDB_COUCHBASE ,CACHEDB_LOCAL ,CACHEDB_MEMCACHED , CACHEDB_MONGODB , CACHEDB_REDIS , CACHEDB_SQL

4. External Integration modules

OpenSIPS API as EVENT_DATAGRAM , EVENT_FLATSTORE ( Text/File backend for events ), EVENT_ROUTE ,EVENT_RABBITMQ
EVENT_VIRTUAL ( Aggregator of event backends failover & balancing), EVENT_XMLRPC
MI_DATAGRAM ( DATAGRAM unix and network support for Management Interface )
MI_FIFO , MI_HTTP , MI_JSON , MI_XMLRPC_NG
HTTPD , PI_HTTP ( Provisioning Interface ) , STATISTICS

Media Relays
MEDIAPROXY – NAT traversal module
RTPENGINE – Connector to RTPengine external RTP relay
RTPPROXY – Connector to RTPproxy external RTP relay

non-SIP protocols modules such as AAA_RADIUS , H350 , LDAP – LDAP connector , stable
REST_CLIENT , SEAS ( Sip Express Application Server interface module), SIPCAPTURE , SIPTRACE ,
SNGTC ( Voice Transcoding in OpenSIPS using Sangoma hardware ),
SNMPStats , STUN , XMPP ( SIP-to-XMPP Gateway )

5. OpenSIPS protocols and infrastructure

CLUSTERER , TLS_MGM , PROTO_BIN ( Binary INterface protocol module to implements inter-OPENSIPS communication )
PROTO_HEP , PROTO_SCTP , PROTO_TCP, PROTO_TLS , PROTO_UDP , PROTO_WS , PROTO_WSS

How to Install and use Opensips on your VoIP platform

Install from git repo

git clone git@github.com:OpenSIPS/opensips.git opensips_head
install gcc
make all

Install from apt

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 049AD65B
echo "deb http://apt.opensips.org trusty 2.4-releases" >/etc/apt/sources.list.d/opensips.list

check if opensips is running

ps -uax|grep opensips

Configuration ( opensips.cfg )

configuring compilation flags for various compile time options use menuconfig.

For this first install the ncurses development library

apt-get install libncurses5-dev
make menuconfig

Running menuconfig post installation from path use osipsconfig

compiling modules

prerequisites

apt-get install build-essential openssl bison flex
make && make install

After succesfull installation check version

opensips -V
version: opensips 2.2.7 (x86_64/linux)
flags: STATS: On, DISABLE_NAGLE, USE_MCAST, SHM_MMAP, PKG_MALLOC, F_MALLOC, FAST_LOCK-ADAPTIVE_WAIT
ADAPTIVE_WAIT_LOOPS=1024, MAX_RECV_BUFFER_SIZE 262144, MAX_LISTEN 16, MAX_URI_SIZE 1024, BUF_SIZE 65535
poll method support: poll, epoll_lt, epoll_et, sigio_rt, select.
main.c compiled on  with gcc 4.8

A config file opensips.config has 3 main logical parts :

1.global parameters – network listeners, available transport protocols, forking (and number of processes), the logging

2.modules section – the modules that are to be loaded  with path to their .so file

3.routing logic – logic for routing sip traffic

Routes

OpenSIPS routing logic uses several types of routes. Each type of route is triggered by a certain event and allows you to process a certain type of message (request or reply).

route
SIP requests routing. The main ‘route’ block identified by ‘route{…}’ or ‘route[0]{…}’ is executed for each SIP request.
To send a reply or forward the request, explicit actions must be called inside the route block. in example below which sends 200 ok reply for each options request.

route {
if(is_method("OPTIONS")) {
sl_send_reply("200", "ok");
exit();
}
route(1);
}
route[1] {
forward();
}

branch_route
Handles different branches of a SIP request. if the branch is not dropped the branch will be automatically sent out. It is executed only by TM module after it was armed via t_on_branch(“branch_route_index”).

if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
}
branch_route[MANAGE_BRANCH] {
xdbg("new branch [$T_branch_idx] to $ru\n");
route(NATMANAGE);
}

or lookup location and discard branches where uri matches ip 1.2.3.4 by using drop()

route {
lookup("location");
t_on_branch("op3");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
branch_route[op3] {
if(uri=~"1\.2\.3\.4") {
drop();
}
}

failure_route
Failed transaction routing block. It contains a set of actions to be taken each transaction that received only negative replies (>=300) for all branches which completes the transaction. The ‘failure_route’ is executed only by TM module after it was armed via t_on_failure(“failure_route_index”).

if (is_method("INVITE")) {
if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
}

failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
}

or on failure relay to voice mail

route {
lookup("location");
t_on_failure("op1");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
failure_route[op1] {
if(is_method("INVITE")) {
t_relay("udp:voicemail.server.com:5060");
}
}

onreply_route
Reply routing block. It can be stateful (if bound to a transaction) or stateless (if global reply route).
If the reply is not dropped (only provisional replies can be), it will be injected and processed by the transaction engine. There are three types of onreply routes:

global – catches all replies and uses simple definition ‘onreply_route {…}’ or ‘onreply_route[0] {…}’.
Exmaple for “global” reply route set the whole transaction

route {
seturi("sip:bob@opensips.org");  first branch
append_branch("sip:alice@opensips.org");  second branch
t_on_reply("global");
t_on_branch("1");
t_relay();
}

onreply_route {
xlog("OpenSIPS received a reply from $si\n");
}

onreply_route[global] {
if (t_check_status("1[0-9][0-9]")) {
setflag(1);
log("provisional reply received\n");
if (t_check_status("183"))
drop;
}
}

per request/transaction – it catches all received replies belonging to a certain transaction and uses “t_on_reply()” at request time, in REQUEST ROUTE – named ‘onreply_route[N] {…}’.

per branch – it catches only the replies that belong to a certain branch from a transaction via “t_on_reply()” ) at request time, but in BRANCH ROUTE, when a certain outgoing branch is processed – named ‘onreply_route[N] {…}’.
Certain ‘onreply_route’ blocks can be executed by TM module for special replies. For this, the ‘onreply_route’ must be armed for the SIP requests whose replies should be processed within it, via t_on_reply(“onreply_route_index”).

Exmaple of reply route set for this branch only


branch_route[1] {
if ($rU=="alice")
t_on_reply("alice");
}

onreply_route[alice] {
xlog("received reply on the branch from alice\n");
}

error_route

executed automatically on meeting and error such as parsing error in SIP request processing, script assert failure. Performs error handling . The Default action is to discard request. In error_route, the following pseudo-variables are available to get access to error details:

$(err.class) - the class of error (now is '1' for parsing errors)
$(err.level) - severity level for the error
$(err.info) - text describing the error
$(err.rcode) - recommended reply code
$(err.rreason) - recommended reply reason phrase
error_route {
xlog("--- error route class=$(err.class) level=$(err.level)
info=$(err.info) rcode=$(err.rcode) rreason=$(err.rreason) ---\n");
xlog("--- error from [$si:$sp]\n+++++\n$mb\n++++\n");
sl_send_reply("$err.rcode", "$err.rreason");
exit;
}

local_route

executed automatically as TM created a new request, internally (no UAC side). This is a route intended to be used for message inspection, accounting and for applying last changes on the message headers. Routing and signaling functions are not allowed.

local_route {
if (is_method("INVITE") && $ru=~"@foreign.com") {
append_hf("P-hint: foreign request\r\n");
exit;
}
if (is_method("BYE") ) {
acc_log_request("internally generated BYE");
}
}

startup_route
Executed only once when OpenSIPS is started and before the processing of SIP messages begins. Used in initilization cases cases such as loading some data in the cache.

startup_route {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
cache_store("local", "rule1", "$avp(i:100)");
}

timer_route
Route executed periodically at a configured interval of time specified next to the name(in seconds).

timer_route[gw_update, 300] {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
$shv(i:100) =$avp(i:100);
}

event_route
execute script code when an event is triggered. If no way to handle the event specified, default will be synchronously.
Triggered by the event_route module when an event is raised by the OpenSIPS Event Interface such as event raised by the pike module when it decides an ip should be blocked called E_PIKE_BLOCKED or E_SCRIPT_EVENT etc ( checke events interface for more events)

event_route[E_PIKE_BLOCKED] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}
event_route[E_PIKE_BLOCKED, async] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}

Scripting Language

Opensips scripting provided more advanced controls

1. Core Keywords

Keywords specific to SIP messages which can be used mainly in ‘if’ expressions.
af – address family of the received SIP message. It is INET if the message was received over IPv4 or INET6 if the message was received over IPv6.

if(af==INET6) {
log("Message received over IPv6 link\n");
};

dst_ip – IP of the local interface where the SIP message was received.

if(dst_ip==127.0.0.1) {
log("message received on loopback interface\n");
};

dst_port – local port where the SIP packet was received

if(dst_port==5061)
{
log("message was received on port 5061\n");
};

from_uri – reference to the URI of ‘From’ header.

if(is_method("INVITE") &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; from_uri=~".*@opensips.org")
{
log("the caller is from opensips.org\n");
};

method – SIP method of the message.

if(method=="REGISTER")
{
log("this SIP request is a REGISTER message\n");
};

msg:len – the size of the message

if(msg:len&amp;amp;amp;amp;amp;gt;2048)
{
sl_send_reply("413", "message too large");
exit;
};

$retcode – value returned by last function executed like $?. If tested after a call of a route, it is the value retuned by that route.

route {
route(1);
if($retcode==1)
{
log("The request is an INVITE\n");
};
}

route[1] {
if(is_method("INVITE"))
return(1);
return(2);
}

proto – transport protocol of the SIP message.

if(proto==UDP)
{
log("SIP message received over UDP\n");
};

status – status code of the reply.

if(status=="200")
{
log("this is a 200 OK reply\n");
};

1.10 src_ip – source IP address

if(src_ip==127.0.0.1)
{
log("the message was sent from localhost!\n");
};

1.11 src_port – source port of the SIP message (from which port the message was sent by previous hop).

if(src_port==5061)
{
log("message sent from port 5061\n");
}

1.12 to_uri – URI from To header.

if(to_uri=~"sip:.+@opensips.org")
{
log("this is a request for opensips.org users\n");
};

1.13 uri – request URI.

if(uri=~"sip:.+@opensips.org")
{
log("this is a request for opensips.org users\n");
};

2. Core Values

Values that can be used in ‘if’ expressions to check against Core Keywords

INET – IPv4 connection. , INET6 – IPv6 connection , TCP , UDP

max_len – test message’s size.

if(msg:len&amp;amp;amp;amp;amp;gt;max_len)
{
sl_send_reply("413", "message too large to be forwarded over UDP without fragmentation");
exit;
}

myself – reference to the list of local IP addresses, hostnames and aliases that has been set in OpenSIPS configuration file. This lists contain the domains served by OpenSIPS.

if(uri==myself) {
log("the request is for local processing\n");
};

null – reset the value of a per-script variable or to delete an avp.

$avp(i:12) = null;
$var(x) = null;

3. Core parameters

abort_on_assert – Set to true in order to make OpenSIPS shut down immediately in case a script assert fails.

abort_on_assert = true // default is false

advertised_address – address advertised in Via header and other destination lumps (e.g RR header).

advertised_port – port advertised in Via header and other destination lumps (e.g. RR).

alias – set alias hostnames for the server

alias=udp:company.tel.com:5060
alias=tcp:company.tel.com:5060

auto_aliases – to control if aliases should be automatically discovered from DNS lookup and added during fixing listening sockets.

auto_aliases=no // default value is no
auto_aliases=0

cfg_file – Returns the name of the corresponding OpenSIPS config file

cfg_line – corresponding line inside the OpenSIPS config file.
check_via – Check if the address in top most via of replies is local.

check_via=1 // Default value is 0 (check disabled)

children – Number of worker processes (children) to be created for each UDP or SCTP interface you have defined. children=16 // Default value is 8

chroot – If set, OpenSIPS will chroot (change root directory) to this valid path in the system value.

debug_mode – This option will automatically force:

  • staying in foreground
  • set logging level to 4 (debug)
  • set logging to standard error
  • enable core dumping
  • set UDP worker processes to 2
  • set TCP worker processes to 2
  • Default value is false/0 (disabled).

db_version_table – name of the table version to be used by the DB API to check the version of the used tables.

db_default_url – default DB URL to be used by modules if no per-module URL is given.

db_default_url=”mysql://opensips:opensipsrw@localhost/opensips”

db_max_async_connections – Maximum number of TCP connections opened from a single OpenSIPS worker to each individual SQL backend. Default value is 10.
Individual backends are determined from DB URLs as follows: [ scheme, user, pass, host, port, database ]

disable_503_translation – If ‘yes’, OpenSIPS will not translate the received 503 replies into 500 replies .
disable_core_dump – By default core dump limits are set to unlimited or a high enough value. Set this config variable to ‘yes’ to disable core dump-ing (will set core limits to 0).

disable_core_dump=yes //Default value is 'no'.

disable_dns_blacklist– DNS resolver, when configured with failover, can automatically store in a temporary blacklist the failed destinations. This will prevent (for a limited period of time) OpenSIPS to send requests to destination known as failed. So, the blacklist can be used as a memory for the DNS resolver.

The temporary blacklist created by DNS resolver is named “dns” and it is by default selected for usage (no need use the use_blacklist()) function. The rules from this list have a life time of 4 minutes – you can change it at compile time, from resolve.c . Can be ‘yes’ or ‘no’. By default the blacklist is disabled (Default value is ‘yes’).

disable_dns_failover – By default DNS-based failover is enabled. Set this config variable to ‘yes’ to disable the DNS-based failover. This is a global option, affecting the core and the modules also.

disable_stateless_fwd – controls the handling of stateless replies:

  • yes – drop stateless replies if stateless fwd functions (like forward) are not used in script
  • no – forward stateless replies

dns – controls if the SIP server should attempt to lookup its own domain name in DNS. Default is no.

dns_retr_time – Time in seconds before retrying a dns request. Default value is system specific, depends also on the ‘/etc/resolv.conf’ content (usually 5s).

dns_retr_no – Number of dns retransmissions before giving up.

dns_servers_no – How many dns servers from the ones defined in ‘/etc/resolv.conf’ will be used. Default value is to use all of them.

dns_try_ipv6 – If it is set to ‘yes’ and a DNS lookup fails, it will retry it for ipv6 (AAAA record). Default value is ‘no’.

dns_try_naptr – Disables the NAPTR lookups when doing DNS based routing for SIP requests – if disabled, the DNS lookup will start with SRV lookups. By default it is enabled, value ‘yes’.

dns_use_search_list

dst_blacklist – static (read-only) IP/destination blacklist. These lists can be selected from script (at runtime) to filter the outgoing requests, based on IP, protocol, port, etc.

filter out requests going to ips of my gws

dst_blacklist = gw:{( tcp , 192.168.2.200 , 5060 , "" ),( any , 192.168.2.201 , 0 , "" )}

block requests going to prohibited networks

dst_blacklist = net_filter:{ ( any , 192.168.1.120/255.255.255.0 , 0 , "" )}

block message requests with nasty words

dst_blacklist = msg_filter:{ ( any , 192.168.20.0/255.255.255.0 , 0 , "MESSAGE*ugly_word" )}

block requests not going to a specific subnet

dst_blacklist = net_filter2:{ !( any , 192.268.30.0/255.255.255.0 , 0 , "" )}

Each rule is defined by:

  • protocol : TCP, UDP, TLS or “any” for anything
  • port : number or 0 for any
  • ip/mask
  • test patter – is a filename like matching (see “man 3 fnmatch”) applied on the outgoing request buffer (first_line+hdrs+body)

enable_asserts – Set to true in order to enable the assert script statement.

event_pkg_threshold – A number representing the percentage threshold above which the E_CORE_PKG_THRESHOLD event is raised, warning about low amount of free private memory. It accepts integer values between 0 and 100. Default value is 0 ( event disabled ).

event_pkg_threshold = 90

event_shm_threshold
A number representing the percentage threshold above which the E_CORE_SHM_THRESHOLD event is raised, warning about low amount of free shared memory. It accepts integer values between 0 and 100.
Default value is 0 ( event disabled ).

event_shm_threshold = 90

exec_dns_threshold – A number representing the maximum number of microseconds a DNS query is expected to last. Anything above the set number will trigger a warning message to the logging facility. Default value is 0 ( logging disabled ).

exec_dns_threshold = 60000

exec_msg_threshold – A number representing the maximum number of microseconds the processing of a SIP msg is expected to last. Anything above the set number will trigger a warning message to the logging facility. Aside from the message and the processing time, the most time consuming function calls from the script will also be logged. Default value is 0 ( logging disabled ).

exec_msg_threshold = 60000

include_file – load additional routes/blocks with file path

include_file "proxy_regs.cfg"

import_file – Same as include_file but will not throw an error if file is not found.

import_file "proxy_regs.cfg"

listen – Set the network addresses the SIP server should listen to. syntax is protocol:address[:port]

The listen definition may accept several optional parameters for:

configuring an advertised IP and port only for an interface. Syntax “AS 11.22.33.44:5060”
setting a different number of children for this interface only (for UDP, SCTP and HEP_UDP interfaces only). This will override the global “children” parameter. Syntax “use_children 5”
Remember that the above parameters only affect the interface they are configured for; if they are not defined for a given interface, the global values will be used instead.

listen = udp:*
listen = udp:eth1
listen = tcp:eth1:5062
listen = tls:localhost:5061
listen = hep_udp:10.10.10.10:5064
listen = ws:127.0.0.1:5060 use_children 5
listen = sctp:127.0.0.1:5060 as 99.88.44.33:5060 use_children 3
On startup, OpenSIPS reports all the interfaces that it is listening on. The TCP engine processes will be created regardless if you specify only UDP interfaces here.
3.41 log_facility – control the facility for logging in syslog. Default value is LOG_DAEMON.

log_facility=LOG_LOCAL0

3.42 log_level – logging level (how verbose OpenSIPS should be). Higher values make OpenSIPS to print more messages.

log_level=1 — print only important messages (like errors or more critical situations) recommended for running proxy as daemon
log_level=4 — print a lot of debug messages use it only when doing debugging sessions

Actual values are:

-3 – Alert level
-2 – Critical level
-1 – Error level
1 – Warning level
2 – Notice level
3 – Info level
4 – Debug level
The ‘log_level’ parameter is usually used in concordance with ‘log_stderror’ parameter.

Value of ‘log_level’ parameter can also be get and set dynamically using log_level Core MI function or $log_level script variable.
3.43 log_name – Set the id to be printed in syslog. The value must be a string and has effect only when OpenSIPS runs in daemon mode (fork=yes), after daemonize. Default value is argv[0].

log_name=”osips-5070″

3.44 log_stderror – write log messages to standard error. Possible values are:
– “yes” – write the messages to standard error
– “no” – write the messages to syslog , also the default

max_while_loops – maximum loops that can be done within a “while”. Comes as a protection to avoid infinite loops in config file execution. Default is 100.

max_while_loops=200

maxbuffer – size in bytes not to be exceeded during the auto-probing procedure of discovering the maximum buffer size for receiving UDP messages. Default value is 262144.

maxbuffer=65536

mem-group – Defines a group of modules (by name) to get separate memory statistics.In order for the feature to work you have to run “make generate-mem-stats” and complile with the variable SHM_EXTRA_STATS defined and complile with the variable SHM_SHOW_DEFAULT_GROUP definedwill generate the statistics for the default group

mem-group = “interest”: “core” “tm”
mem-group = “runtime”: “dialog” “usrloc” “tm”

mem_warming – Only relevant when the HP_MALLOC compile flag is enabled. If set to “on”, on each startup, OpenSIPS will attempt to restore the memory fragmentation pattern it had before the stop/restart.
Memory warming is useful when dealing with high volumes of traffic (thousands of cps on multi-core machines – the more cores, the more useful), because processes must mutually exclude themselves when chopping up the initial big memory chunk. By performing fragmentation on startup, OpenSIPS will also behave optimally in the first minute(s) after a restart. Fragmentation usually lasts a few seconds (e.g. ~5 seconds on an 8GB shm pool and 2.4Ghz CPU) – traffic will not be processed at all during this period.

mem_warming = on

mem_warming_percentage – How much of OpenSIPS’s memory should be fragmented with the pattern of the previous run, upon a restart.

mem_warming_percentage = 50 //Default value: 75

mem_warming_pattern_file – Default value: “CFG_DIR/mem_warming_pattern”.The memory fragmentation pattern of a previous OpenSIPS run. Used at startup, if mem_warming is enabled.

mem_warming_pattern_file = “/var/tmp/my_memory_pattern”

memdump | mem_dump – Log level to print memory status information (runtime and shutdown). Default: memdump=L_DBG (4)

memlog | mem_lo – Log level to print memory debug info. It has to be less than the value of ‘log_level’ parameter if you want memory info to be logged. Default: memlog=L_DBG (4)

mcast_loopback – If set to ‘yes’, multicast datagram are sent over loopback. Default value is ‘no’.

mcast_loopback=yes

mcast_ttl – Set the value for multicast ttl. Default value is OS specific (usually 1).

mhomed – Set the server to try to locate outbound interface on multihomed host. By default is not (0) – it is rather time consuming.

mhomed=1

mpath – Set the module search path. This can be used to simplify the loadmodule parameter

mpath="/usr/local/lib/opensips/modules"<br> loadmodule "mysql.so"<br> loadmodule "uri.so"<br> loadmodule "uri_db.so"<br> loadmodule "sl.so"<br> loadmodule "tm.so"<br> ...

open_files_limit – If set and bigger than the current open file limit, OpenSIPS will try to increase its open file limit to this number. Note: OpenSIPS must be started as root to be able to increase a limit past the hard limit (which, for open files, is 1024 on most systems).

open_files_limit=2048

poll_method – (deprecated post 2.2) poll method to be used by the I/O internal reactor – by default the best one for the current OS is selected. The available types are: poll, epoll_lt, sigio_rt, select, kqueue, /dev/poll.

Starting with version 2.2, epoll_et is deprecated and if it is used in the script, it will be automatically replaced by epoll_lt.

poll_method=select

port – port the SIP server listens to. The default value for it is 5060.

reply_to_via – If it is set to 1, any local reply is sent to the address advertised in top most Via of the request. Default value is 0 (off).

reply_to_via=0

query_buffer_size -If set to a value greater than 1, inserts to DB will not be flushed one by one. Rows to be inserted will be kept in memory until until they gather up to query_buffer_size rows, and only then they will be flushed to the database.

query_buffer_size=5

query_flush_time – If query_buffer_size is set to a value greater than 1, a timer will trigger once every query_flush_time seconds, ensuring that no row will be kept for too long in memory.

query_flush_time=10

rev_dns – should the SIP server attempt to lookup its own IP address in DNS. If this parameter is set to yes and the IP address is not in DNS a warning is printed on syslog and a “received=” field is added to the via header. Default is no.

server_header – The body of Server header field generated by OpenSIPS when it sends a request as UAS. It defaults to “OpenSIPS (<version> (<arch>/<os>))”.

server_header=”Server: My Company SIP Proxy”

server_signature – control “Server” header in any locally generated message. If it is enabled (default=yes) a header is generated as Server: OpenSIPS (0.9.5 (i386/linux))

shm_hash_split_percentage – Only relevant when the HP_MALLOC compile flag is enabled. It controls how many memory buckets will be optimized. (e.g. setting it to 2% will optimize the first 81 most used buckets as frequency). The default value is 1.

shm_secondary_hash_size – Only relevant when the HP_MALLOC compile flag is enabled. It represents the optimization factor of a single bucket (e.g. setting it to 4 will cause the optimized buckets to be further split into 4). The default value is 8.

sip_warning – Can be 0 or 1. If set to 1 (default value is 0) a ‘Warning’ header is added to each reply generated by OpenSIPS. The header contains several details that help troubleshooting using the network traffic dumps.

sip_warning=0

tcp_children – Number of children processes to be created for reading from TCP connections. If no value is explicitly set, the same number of TCP children as UDP children (see “children” parameter) will be used.

tcp_children=4

tcp_accept_aliases – If enabled, OpenSIPS will enforce RFC 5923 behaviour when detecting an “;alias” Via header field parameter and will reuse any TCP (or TLS, WS, WSS) connection opened for such SIP requests (source IP + Via port + proto) when sending other SIP requests backwards, towards the same (source IP + Via port + proto) pair. Default value 0 (disabled).

tcp_listen_backlog – maximum length for the queue of pending connections for the TCP listeners. Default configured value is 10.

tcp_connect_timeout – Time in milliseconds before an ongoing blocking attempt to connect will be aborted. Default value is 100ms.

tcp_connect_timeout = 5

tcp_connection_lifetime – Lifetime in seconds for TCP sessions. Default value is defined in tcp_conn.h: define DEFAULT_TCP_CONNECTION_LIFETIME 120.

tcp_connection_lifetime = 3600

tcp_max_connections – maximum number of tcp connections. Default is defined in tcp_conn.h: define DEFAULT_TCP_MAX_CONNECTIONS 2048

tcp_max_connections = 4096

tcp_max_msg_time – maximum number of seconds that a SIP message is expected to arrive via TCP. Default value is 4

tcp_max_msg_time = 8

tcp_no_new_conn_bflag -A branch flag to be used as marker to instruct OpenSIPS not to attempt to open a new TCP connection when delivering a request, but only to reuse an existing one (if available). If no existing conn, a generic send error will be returned.

This is intended to be used in NAT scenarios, where makes no sense to open a TCP connection towards a destination behind a NAT (like TCP connection created during registration was lost, so there is no way to contact the device until it re-REGISTER). Also this can be used to detect when a NATed registered user lost his TCP connection, so that opensips can disable his registration as useless.

 tcp_no_new_conn_bflag = TCP_NO_CONNECT<br> ...<br> route {<br> ...<br> if (isflagset(DST_NATED) &amp;&amp; $proto == "TCP")<br>     setbflag(TCP_NO_CONNECT);<br>     ...<br>     t_relay("0x02"); // no auto error reply<br>     $var(retcode) = $rc;<br>     if ($var(retcode) == -6) {<br>         xlog("unable to send request to destination");<br>         send_reply("404", "Not Found");<br>         exit;<br>     } else if ($var(retcode) &lt; 0) {<br>         sl_reply_error();<br>         exit;<br>     }<br> } 

3.77 tcp_threshold – A number representing the maximum number of microseconds sending of a TCP request is expected to last. Anything above the set number will trigger a warning message to the logging facility. Default value is 0 ( logging disabled ).

tcp_threshold = 60000

tcp_keepalive – Enable or disable TCP keepalive (OS level). Enabled by default.

tcp_keepalive = 1

tcp_keepcount -Number of keepalives to send before closing the connection (Linux only).

Default value: 0 (not set). Setting tcp_keepcount to any value will enable tcp_keepalive.

tcp_keepcount = 5

tcp_keepidle – Amount of time before OpenSIPS will start to send keepalives if the connection is idle (Linux only).
Default value: 0 (not set)

tcp_keepidle = 30

tcp_keepinterval – Interval between keepalive probes, if the previous one failed (Linux only).Default value: 0 (not set). Setting tcp_keepinterval to any value will enable tcp_keepalive.

tcp_keepinterval = 10

tls_ca_list

tls_certificate

tls_ciphers_list

tls_domain

tls_handshake_timeout

tls_log

tls_method

tls_port_no

tls_private_key

tls_require_certificate

tls_send_timeout

tls_verify

tos – TOS (Type Of Service) to be used for the sent IP packages (both TCP and UDP).

 tos=IPTOS_LOWDELAY<br> tos=0x10<br> tos=IPTOS_RELIABILITY

user_agent_header – The body of User-Agent header field generated by OpenSIPS when it sends a request as UAC. It defaults to “OpenSIPS (<version> (<arch>/<os>))”.

user_agent_header=”User-Agent: My Company SIP Proxy”

wdir – working directory used by OpenSIPS at runtime.

 wdir="/usr/local/opensips" 

xlog_buf_size – Default value: 4096

Size of the buffer used to print a single line on the chosen logging facility of OpenSIPS. If the buffer is too small, an overflow error will be printed, and the concerned line will be skipped.

xlog_buf_size = 8388608 #given in bytes

xlog_force_color

xlog_default_level -Default value for the logging level of the xlog core function, when the log_level parameter is omitted.

xlog_default_level = 2 #L_NOTICE // Default value: -1

Routes

OpenSIPS routing logic uses several types of routes. Each type of route is triggered by a certain event and allows you to process a certain type of message (request or reply).

  • route
    SIP requests routing. The main ‘route’ block identified by ‘route{…}’ or ‘route[0]{…}’ is executed for each SIP request.
    To send a reply or forward the request, explicit actions must be called inside the route block. in example below which sends 200 ok reply for each options request.
route {
if(is_method("OPTIONS")) {
sl_send_reply("200", "ok");
exit();
}
route(1);
}
route[1] {
forward();
}
  • branch_route
    Handles different branches of a SIP request. if the branch is not dropped the branch will be automatically sent out. It is executed only by TM module after it was armed via t_on_branch(“branch_route_index”).
if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
}
branch_route[MANAGE_BRANCH] {
xdbg("new branch [$T_branch_idx] to $ru\n");
route(NATMANAGE);
}

or lookup location and discard branches where uri matches ip 1.2.3.4 by using drop()

route {
lookup("location");
t_on_branch("op3");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
branch_route[op3] {
if(uri=~"1\.2\.3\.4") {
drop();
}
}
  • failure_route
    Failed transaction routing block. It contains a set of actions to be taken each transaction that received only negative replies (>=300) for all branches which completes the transaction. The ‘failure_route’ is executed only by TM module after it was armed via t_on_failure(“failure_route_index”).
if (is_method("INVITE")) {
if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
}

failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
}

or on failure relay to voice mail

route {
lookup("location");
t_on_failure("op1");
if(!t_relay()) {
sl_send_reply("500", "relaying failed");
}
}
failure_route[op1] {
if(is_method("INVITE")) {
t_relay("udp:voicemail.server.com:5060");
}
}
  • onreply_route
    Reply routing block. It can be stateful (if bound to a transaction) or stateless (if global reply route).
    If the reply is not dropped (only provisional replies can be), it will be injected and processed by the transaction engine. There are three types of onreply routes:

global – catches all replies and uses simple definition ‘onreply_route {…}’ or ‘onreply_route[0] {…}’.
Exmaple for “global” reply route set the whole transaction

route {
seturi("sip:bob@opensips.org");  first branch
append_branch("sip:alice@opensips.org");  second branch
t_on_reply("global");
t_on_branch("1");
t_relay();
}

onreply_route {
xlog("OpenSIPS received a reply from $si\n");
}

onreply_route[global] {
if (t_check_status("1[0-9][0-9]")) {
setflag(1);
log("provisional reply received\n");
if (t_check_status("183"))
drop;
}
}

per request/transaction – it catches all received replies belonging to a certain transaction and uses “t_on_reply()” at request time, in REQUEST ROUTE – named ‘onreply_route[N] {…}’.

per branch – it catches only the replies that belong to a certain branch from a transaction via “t_on_reply()” ) at request time, but in BRANCH ROUTE, when a certain outgoing branch is processed – named ‘onreply_route[N] {…}’.
Certain ‘onreply_route’ blocks can be executed by TM module for special replies. For this, the ‘onreply_route’ must be armed for the SIP requests whose replies should be processed within it, via t_on_reply(“onreply_route_index”).

Exmaple of reply route set for this branch only


branch_route[1] {
if ($rU=="alice")
t_on_reply("alice");
}

onreply_route[alice] {
xlog("received reply on the branch from alice\n");
}
  • error_route

executed automatically on meeting and error such as parsing error in SIP request processing, script assert failure. Performs error handling . The Default action is to discard request. In error_route, the following pseudo-variables are available to get access to error details:

$(err.class) - the class of error (now is '1' for parsing errors)
$(err.level) - severity level for the error
$(err.info) - text describing the error
$(err.rcode) - recommended reply code
$(err.rreason) - recommended reply reason phrase
error_route {
xlog("--- error route class=$(err.class) level=$(err.level)
info=$(err.info) rcode=$(err.rcode) rreason=$(err.rreason) ---\n");
xlog("--- error from [$si:$sp]\n+++++\n$mb\n++++\n");
sl_send_reply("$err.rcode", "$err.rreason");
exit;
}
  • local_route

executed automatically as TM created a new request, internally (no UAC side). This is a route intended to be used for message inspection, accounting and for applying last changes on the message headers. Routing and signaling functions are not allowed.

local_route {
if (is_method("INVITE") && $ru=~"@foreign.com") {
append_hf("P-hint: foreign request\r\n");
exit;
}
if (is_method("BYE") ) {
acc_log_request("internally generated BYE");
}
}
  • startup_route
    Executed only once when OpenSIPS is started and before the processing of SIP messages begins. Used in initilization cases cases such as loading some data in the cache.
startup_route {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
cache_store("local", "rule1", "$avp(i:100)");
}
  • timer_route
    Route executed periodically at a configured interval of time specified next to the name(in seconds).
timer_route[gw_update, 300] {
avp_db_query("select gwlist where ruleid==1",$avp(i:100));
$shv(i:100) =$avp(i:100);
}
  • event_route
    execute script code when an event is triggered. If no way to handle the event specified, default will be synchronously.
    Triggered by the event_route module when an event is raised by the OpenSIPS Event Interface such as event raised by the pike module when it decides an ip should be blocked called E_PIKE_BLOCKED or E_SCRIPT_EVENT etc ( checke events interface for more events)
event_route[E_PIKE_BLOCKED] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}
event_route[E_PIKE_BLOCKED, async] {
xlog("The E_PIKE_BLOCKED event was raised\n");
}

opensipsctlrc

opensipsctlrc file controls the opensipsctl and osipsconsole utilities. It is a shell script utility to manage opensips from command line

opensipsctl can manage

  • Start, stop, and restart
  • Show, grant, and revoke ACLs Add, remove, and list aliases
  • Add, remove, and configure an AVP
  • Low Cost Route (LCR)
  • Remote Party Identity (RPID)
  • Add, remove, and list subscribers
  • Add, remove, and show the usrloc table in-Random Access Memory (RAM)
  • Monitor

Ref :

Lua Scripts for kamailio Routing

Kamailio uses a native scripting laguage for its configuration file kamailio.cfg . This components of this file are :

  • global parameters
  • loading modules
  • module parameters
  • routing blocks like request_route {…}, reply_route {…}, branch_route {…} etc

These parameters including initialization event routes , are interpeted and loaded at kamailio startup.

We know that restart of sip server hinder all ongoing traffic and slows development of routing logic.
Due to limitation of customizatiosn with native language and mostly due to the fact that interpreter precompiles kamailio.cfg at startup preventing routing script to reload without restart , other programming languages were used such as Kamailio Embedded Interface (KEMI) framework.

Post v5 of kamailio , the interpreters of these languages were integrated with kamailio and feature rich SIP routing logic could be written with them for runtime execution. The routing blocks are in form of functions written in a KEMI ( Kamaialio EMbedded Interface) supported scripting language such as Lua as discussed in this article. Other components are still initialised by kamailio.cfg at starup. Apart from above mentioned advantages of programming languages , another plus point is that it enables test-cases , debug functionality without having to restart the server for code update.

KEMI supported programming languages:

  • JavaScript (app_jsdt)
  • Lua (app_lua)
  • Python (app_python)
  • Python3 (app_python3)
  • Squirrel (app_sqlang)

Kamailio has other modules that allow inline execution of scripts written in other programming languages, but don’t implement the KEMI yet. Such as
Perl (app_perl)
.Net (C#, etc.)
(app_mono),
Java (app_java)

As Kamailio becomes the interpreter for these languages , it executes logic faster at runtime . KEMI also extends the modules with extension to kamailio c functions

Lua KEMI Interpreter

Lua interpreter is linked from liblua library in app_lua module.

//loading 
loadmodule "app_lua.so"
//script path
modparam("app_lua", "load", "/path/to/script.lua")
//specifying engine
cfgengine "lua"

Predefined functions in app_lua module

ksr_request_route() : executed by Kamailio core every time a SIP request is received, equivalent of request_route {} from kamailio.cfg

ksr_reply_route() : executed by Kamailio core every time a SIP Response (reply) is received, equivalent of reply_route {} from kamailio.cfg

ksr_onsend_route() : executed when a SIP request (and optionally for a response) is sent out, equivalent of onsend_route {}

branch route callback : name of the Lua function to be executed instead of a branch route has to be provided as parameter to KSR.tm.t_on_branch(…)

onreply route callback : name of the Lua function to be executed instead of an onreply route has to be provided as parameter to KSR.tm.t_on_reply(…)

failure route callback : name of the Lua function to be executed instead of a failure route has to be provided as parameter to KSR.tm.t_on_failure(…)

branch failure route callback : name of the Lua function to be executed instead of an event route for branch failure has to be provided as parameter to KSR.tm.t_on_branch_failure(…)

event route callback : name of the Lua function to be exectued instead of module specific event_route blocks is provided via event_callback parameter of that module

KSR is the new dynamic object exporting Kamailio functions. sr is the old static object exporting Kamailio functions

route.lua for routing logic

function ksr_request_route()
    KSR.info("===== request - from kamailio lua script\n");
    if KSR.maxfwd.process_maxfwd(10) < 0 then
        KSR.sl.send_reply(483, "Too Many Hops");
        return;
    end
    //KSR.sl.sreply(200, "OK Lua");
    KSR.pv.sets("$du", "sip:127.0.0.1:5080")
    KSR.tm.t_on_branch("ksr_branch_route_one");
    KSR.tm.t_on_reply("ksr_onreply_route_one");
    KSR.tm.t_on_failure("ksr_failure_route_one");
    if KSR.tm.t_relay() < 0 then
        KSR.sl.send_reply(500, "Server error")
    end
end

function ksr_reply_route()
    KSR.info("===== response - from kamailio lua script\n");
end

function ksr_branch_route_one()
    KSR.info("===== branch route - from kamailio lua script\n");
end

function ksr_onreply_route_one()
    KSR.info("===== onreply route - from kamailio lua script\n");
end

function ksr_failure_route_one()
    KSR.info("===== failure route - from kamailio lua script\n");
end

Core Kemi functions

KSR.add_local_rport() : Set the internal flag to add rport parameter to local generated Via header.

KSR.add_tcp_alias() : Adds a tcp port alias for the current connection (if tcp). Can help in firewall or nat traversal

KSR.add_tcp_alias_via() : Adds the port from the message via as an alias to TCP connection.

void KSR.dbg(…) : debug log

KSR.dbg("debug log message from embedded interpreter\n");

void KSR.err(…) : error logging

KSR.err("error log message from embedded interpreter\n");

void KSR.info(…) : info log

KSR.info("info log message from embedded interpreter\n");

KSR.force_rport() : Add rport parameter to the top Via of the incoming request and sent the SIP response to source port.

KSR.is_method() : Return true if the value of the parameter matches the method type of the SIP message.

if(KSR.is_method("INVITE")) {
  ...
}

KSR.is_method_in() ; Return true if SIP method of the currently processed message is matching one of the corresponding characters given as parameter. Matching the method is done based on corresponding characters:
I – INVITE
A – ACK
B – BYE
C – CANCEL
R – REGISTER
M – MESSAGE
O – OPTIONS
S – SUBSCRIBE
P – PUBLISH
N – NOTIFY
U – UPDATE
K – KDMQ
G – GET
T – POST
V – PUT
D – DELETE

if KSR.is_method_in("IABC") then
  -- the method is INVITE, ACK, BYE or CANCEL
  ...
end

KSR.is_INVITE() : Return true if the method type of the SIP message is INVITE.

KSR.is_ACK() : true if the method type is ACK.

KSR.is_BYE() : true if the method type is BYE.

KSR.is_CANCEL() : true if CANCEL.

KSR.is_REGISTER() : true if REGISTER.

KSR.is_MESSAGE() : true if SIP message is MESSAGE.

KSR.is_SUBSCRIBE() : true if SIP message is SUBSCRIBE.

KSR.is_PUBLISH() : true if PUBLISH.

KSR.is_NOTIFY() : true if NOTIFY.

KSR.is_OPTIONS() : true if OPTIONS.

KSR.is_INFO() : true if INFO.

KSR.is_UPDATE() : true if UPDATE.

KSR.is_PRACK() : true if PRACK.

KSR.is_myself(…) : Return true of the URI address provided as parameter matches a local socket (IP) or local domain.

if KSR.is_myself("sip:127.0.0.1:5060") then
  ...
end

KSR.is_myself_furi() : Return true if the URI in From header matches a local socket (IP) or local domain.

KSR.is_myself_ruri() : Return true if the R-URI matches a local socket (IP) or local domain.

KSR.is_myself_turi() : Return true if the URI in To header matches a local socket (IP) or local domain.

KSR.is_myself_suri() : true if the URI built from source IP, source port and protocol matches a local socket (IP).

KSR.is_myself_suri() : true if the source IP matches a local socket (IP).

void KSR.log(…) : Write a log message specifying the level value. The level parameter can be: “dbg” , “info” , “warn” , “crit” , “err”

KSR.setflag(…) : Set the SIP message/transaction flag ( int from 0 to 31 ) at the index provided by the parameter.

KSR.resetflag(…) : Reset the SIP message/transaction flag ( int from 0 to 31 ) at the index provided by the parameter.

KSR.isflagset(…) :Return true if the message/transaction flag at the index provided by the parameter is set (the bit has value 1).

KSR.setbflag(…) : Set the branch flag(0-31) at the index provided by the parameter.

KSR.resetbflag(…) : Reset the branch flag(0-31) at the index provided by the parameter.

KSR.isbflagset(…) : Return true if the branch flag at the index provided by the parameter is set (the bit has value 1).

KSR.setbiflag(…) : Set the flag at the index provided by the first parameter to the branch number specified by the second parameter. The flag parameter has to be a number from 0 to 31. The branch parameter should be between 0 and 12 (a matter of max_branches global parameter).

KSR.resetbiflag(…) : Reset a branch flag by position and branch index.

KSR.isbiflagset(…) : Test if a branch flag is set by position and branch index.

KSR.setsflag(…) : Set a script flag.

KSR.resetsflag(…) : Reset a script flag.

KSR.issflagset(…) : Test if a script flag is set.

KSR.seturi(…) : Set the request URI (R-URI).

KSR.seturi("sip:alice@voip.com");

KSR.setuser(…)

KSR.setuser("alice");

KSR.sethost(…)

KSR.sethost("voip.com");

KSR.setdsturi(…)

KSR.setdsturi("sip:voip.com:5061;transport=tls");

KSR.resetdsturi(…) : Reset the destination URI (aka: outbound proxy address, dst_uri, $du).

KSR.isdsturiset(…) : Test if destination URI is set.

KSR.force_rport(…) : Set the flag for “rport” handling (send the reply based on source address instead of Via header).

KSR.set_drop(…) : Set the DROP flag, so at the end of KEMI script execution, the SIP request branch or the SIP response is not forwarded.

KSR.set_advertised_address() : Set the address (host or ip) to be advertised in Via header.

KSR.set_advertised_port() : Set the port (in string format) to be advertised in Via header.

KSR.set_forward_close(…) : Set the flag to close the connection after forwarding the message.

KSR.set_forward_no_connect(…) : Set the flag to not open a connection if the connection to the target does not exist when attempting to forward a message.

KSR.set_reply_close(…) : Set the flag to close the connection after sending a response.

KSR.set_reply_no_connect(…) : Set the flag to not open a connection if the connection for sending the response does not exist.

KSR.forward(…) : Forward the SIP request in stateless mode to the address set in destination URI ($du), or, if this is not set, to the address in request URI ($ru).

KSR.forward_uri(…) : Forward the SIP request in stateless mode to the address provided in the SIP URI parameter.

KSR.forward_uri("sip:127.0.0.1:5080;transport=tcp");

KSR.hdr.append(…) : Append header to current SIP message (request or reply).

KSR.hdr.append("X-My-Hdr: " + KSR.pv.getw("$si") + "\r\n");

KSR.hdr.append_after(…) : Append header to current SIP message (request or reply). It will be added after the first header matching the name hdrname.

KSR.hdr.append_after("X-My-Hdr: " + KSR.pv.getw("$si") + "\r\n", "Call-Id");

KSR.hdr.insert(…) : Insert header to current SIP message (request or reply). It will be added before the first header.

KSR.hdr.insert("X-My-Hdr: " + KSR.pv.getw("$si") + "\r\n");

KSR.hdr.insert_before(…) : Insert header to current SIP message (request or reply). It will be added before the header matching the name hdrname.

KSR.hdr.insert_before("X-My-Hdr: " + KSR.pv.getw("$si") + "\r\n", "Call-Id");

KSR.hdr.remove(…) : Remove all the headers with the name hdrval.

KSR.hdr.remove("X-My-Hdr");

KSR.hdr.is_present(…) : Return greater than 0 if a header with the name hdrval exists and less than 0 if there is no such header.

if(KSR.hdr.is_present("X-My-Hdr") > 0) {
  ...
}

KSR.hdr.append_to_reply(…) : Add a header to the SIP response to be generated by Kamailio for the current SIP request.

KSR.hdr.append_to_reply("X-My-Hdr: " + KSR.pv.getw("$si") + "\r\n");

PV And Special KEMI Functions

PV And Special KEMI Functions

KSR.pv submodule provides the functions to get, set and test the values of pseduo-variables.
The pvname that appears in the next sections in the function prototypes has to be a valid pseudo-variable name for Kamailio native configuration file (for example $ru, $var(x), $shv(z), …).

KSR.pv.get(…) : Return the value of pseudo-variable pvname. The returned value can be string or integer.

KSR.dbg("ruri is: " + KSR.pv.get("$ru") + "\n");

KSR.pv.gete(…) : Return the value of pseudo-variable pvname if it is different than $null or the empty string (“”) if the variable is having the $null value.

KSR.dbg("avp is: " + KSR.pv.gete("$avp(x)") + "\n");

KSR.pv.getvn(…) : Return the value of pseudo-variable pvname if it is different than $null or the parameter vn if the variable is having the $null value.

KSR.dbg("avp is: " + KSR.pv.getvn("$avp(x)", 0) + "\n");

KSR.pv.getvs(…) : Return the value of pseudo-variable pvname if it is different than $null or the parameter vs if the variable is having the $null value.

KSR.dbg("avp is: " + KSR.pv.getvs("$avp(x)", "foo") + "\n");

KSR.pv.getw(…) : Return the value of pseudo-variable pvname if it is different than $null or the string <> if the variable is having the $null value. This should be used instead of KSR.pv.get(…) in the scripting languages that throw and error when attempting to print a NULL (or NIL) value.

KSR.dbg("avp is: " + KSR.pv.getw("$avp(x)") + "\n");

KSR.pv.seti(…) : set the value of pseudo-variable pvname to integer value provided by parameter val.

KSR.pv.seti("$var(x)", 10);

KSR.pv.sets(…) : set the value of pseudo-variable pvname to string value provided by parameter val.

KSR.pv.sets("$var(x)", "kamailio");

KSR.pv.unset(…) : Set the value of pseudo-variable pvname to $null.

KSR.pv.unset("$avp(x)");

KSR.pv.is_null(…) : Return true if pseudo-variable pvname is $null.

if(KSR.pv.is_null("$avp(x)")) {
  ...
}

KSR.x.modf(…) : Execute a function (specified by fname) exported by a Kamailio module.

KSR.x.modf("sl_send_reply", "200", "OK");

KSR.x.exit(…) : stop the execution of the SIP routing script.

KSR.x.drop(…) : stop the execution of the SIP routing script and drop routing further the SIP request branch or response.

KEMI Module Functions

Module specific exported KEMI functions.

Acc

KSR.acc.acc_db_request()

KSR.acc.acc_log_request()

KSR.acc.acc_request()

app_lua

executing Lua scripts from config file.

KSR.app_lua.dofile()

KSR.app_lua.dostring()

KSR.app_lua.run()

KSR.app_lua.run_p1()

KSR.app_lua.run_p2()

KSR.app_lua.run_p3()

KSR.app_lua.runstring()

Async

asynchronous operations for handling SIP requests

KSR.async.route()

KSR.async.task_route()

auth

KSR.auth.auth_challenge()

KSR.auth.consume_credentials()

KSR.auth.has_credentials()

KSR.auth.pv_auth_check()

auth_db

KSR.auth_db.auth_check()

KSR.auth_db.is_subscriber()

-tbd –

Ref :

Secure Communication with RTP, SRTP , ZRTP and DTLS

With advent of Voice over IP , the real time streaming of data/audio/video also became critically important to be protected from eavesdropping or modification over the open internet.

While Secure Real-time Transport Protocol (SRTP) is a profile of the Real-time Transport Protocol (RTP), which can provide confidentiality, message authentication, and replay protection to the RTP traffic and to the control traffic for RTP, the Real-time Transport Control Protocol (RTCP).

ZRTP is a protocol that negotiates the keys and other information required to setup a SRTP audio and video session

DTLS keying happens on the media path, independent of any out-of-band signalling channel present.

SRTP provides a framework for encryption and message authentication of RTP and RTCP streams by negotiating keys. It defines a set of default cryptographic transforms and it allows new transforms to be introduced in the future. SRTCP securely provides the same features to RTCP, as the ones provided by SRTP to RTP.

Jitsi Client SRTP configuration

An offer can include any of –

  • plain RTP (RTP/AVP),
  • RTP with RTCP-based feedback (RTP/AVPF),
  • Secure RTP (RTP/SAVP), or
  • Secure RTP with RTCP-based feedback (RTP/SAVPF)

SDP for RTP/AVP

v=0
o=987654321-jitsi.org 0 0 IN IP4 x.x.x.x.
s=-
c=IN IP4 x.x.x.x
t=0 0
m=audio 24380 RTP/AVP 9
a=rtcp-xr:voip-metrics
a=rtpmap:9 G722/8000
a=sendrecv
m=audio 24400 RTP/AVP 9
a=rtcp-xr:voip-metrics
a=rtpmap:9 G722/8000
a=sendrecv

or

v=0.
o=987654321-jitsi.org 0 0 IN IP4 x.x.x.x.
s=-.
c=IN IP4 x.x.x.x.
t=0 0.
m=audio 5018 UDP/TLS/RTP/SAVP 9.
a=rtpmap:9 G722/8000.
a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level.
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level.
a=rtcp-xr:voip-metrics.
a=setup:actpass.
a=fingerprint:sha-1 B9:0F:89:EE:BD:1F:B1:C4:86:B6:D7:5C:25:88:53:F4:02:F4:F5:91.
m=audio 5018 RTP/SAVPF 9.
a=rtpmap:9 G722/8000.
a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level.
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level.
a=rtcp-xr:voip-metrics.
a=setup:actpass.
a=fingerprint:sha-1 B9:0F:89:EE:BD:1F:B1:C4:86:B6:D7:5C:25:88:53:F4:02:F4:F5:91.

The m line indicates which mode of RTP and RTCP is it offering .

Case where offerer/calleer wants to establish a Secure RTP audio stream on plain RTP with DTLS-SRTP as the key management protocol.

type: offer, sdp: 
v=0
o=- 2977074634695769063 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1 2
a=msid-semantic: WMS i2CKXQdort5QF76tyO5SUKyyyyPfMYR4kjZO
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:w5/T
a=ice-pwd:zuPM49QcEX3cKRQiKylJU4Y6
a=ice-options:trickle
a=fingerprint:sha-256 5A:70:05:55:C1:5A:82:51:02:D3:00:A3:BF:E7:EF:62:DF:29:EB:F2:9F:5F:51:58:12:D9:4C:AA:41:36:86:13
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:9 urn:ietf:params:rtp-hdrext:sdes:mid
a=sendrecv
a=msid:i2CKXQdort5QF76tyO5SUKyyyyPfMYR4kjZO 5ffdb0f9-48b1-43bc-9f63-ea032643aeba
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:2215726670 cname:e6egqLfRbLu6vH45
a=ssrc:2215726670 msid:i2CKXQdort5QF76tyO5SUKyyyyPfMYR4kjZO 5ffdb0f9-48b1-43bc-9f63-ea032643aeba
a=ssrc:2215726670 mslabel:i2CKXQdort5QF76tyO5SUKyyyyPfMYR4kjZO
a=ssrc:2215726670 label:5ffdb0f9-48b1-43bc-9f63-ea032643aeba
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=ice-ufrag:w5/T
a=ice-pwd:zuPM49QcEX3cKRQiKylJU4Y6
a=ice-options:trickle
a=fingerprint:sha-256 5A:70:05:55:C1:5A:82:51:02:D3:00:A3:BF:E7:EF:62:DF:29:EB:F2:9F:5F:51:58:12:D9:4C:AA:41:36:86:13
a=setup:actpass
a=mid:2
a=sctpmap:5000 webrtc-datachannel 1024

SRTP on kamailio

For Secure Communication kamailio supports – Digest SIP User authentication , Authorization via ACL or group membership , IP and Network authentication , TLS support for SIP signaling , transparent handling of SRTP for secure audio , TLS domain name extension support ,authentication and authorization against database (MySQL, PostgreSQL, UnixODBC, BerkeleyDB, Oracle, text files), RADIUS and DIAMETER.

Code to set flag rtp_secure_media to true if both TLS and SRTP are active

<condition field="${rtp_has_crypto}" expression="^(AES_CM_128_HMAC_SHA1_32|AES_CM_128_HMAC_SHA1_80)$" break="never">	<action application="set" data="rtp_secure_media=true"/></condition>

Invite from Jitsi client alternatively offering 3 different types of audio SDP’s – RTP/SAVPF , RTP/SAVP and RTP/AVP. Which ever will be accepted by the other endpoint will be communicated back using SDP in 200 OK.

INVITE sip:99999999999@x.x.x.x:5080 SIP/2.0
   Call-ID: 2a34d1e981602c82c345513f3f2f89ed@0:0:0:0:0:0:0:0
   CSeq: 1 INVITE
   From: "altanai" ;tag=bed49270
   To: 
   Via: SIP/2.0/UDP y.y.y.y:5060;branch=z9hG4bK-3130-9657d2ae9b662779bc08cdd32881828f
   Max-Forwards: 70
   Contact: "altanai" 
   User-Agent: Jitsi2.10.5550Mac OS X
   Content-Type: application/sdp
   Content-Length: 2336
   v=0
   o=7777777777-jitsi.org 0 0 IN IP4 y.y.y.y
   s=-
   c=IN IP4 y.y.y.y
   t=0 0
   m=audio 5016 UDP/TLS/RTP/SAVP 9
   a=rtpmap:9 G722/8000
   a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level
   a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
   a=rtcp-xr:voip-metrics
   a=setup:actpass
   a=fingerprint:sha-1 55:CF:25:5D:D5:65:71:C8:D9:FF:97:AD:CC:F2:08:DB:38:DD:81:38
m=audio 5016 RTP/SAVPF 9
   a=rtpmap:9 G722/8000
   a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level
   a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
   a=rtcp-xr:voip-metrics
   a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:Ekb2qAA8F7VCmz0FMSrad0rIt8duHQFedu/KxMbD
   a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:rEeGiaLCUbFw0sS0FxARgX9i5pwEj/frxxbgGkch
   a=crypto:3 AES_192_CM_HMAC_SHA1_80 inline:up9VO2T/rfu8V0cecA4RuG0aWgSaCC5gD/p/RdY1odg1p/0Pto0=
   a=crypto:4 AES_192_CM_HMAC_SHA1_32 inline:6yLDM31gAuwrlL0qkH72QYJLwtzX1IX+Z+7UML3VA5CpIbUWeAw=
   a=crypto:5 AES_256_CM_HMAC_SHA1_80 inline:2Q3b3UpPJMosXTrm/0Ui5q3Mw8tQ6ig5Xq0jt4Ibj0t5hVQx5KBRbC+8sMJDMg==
   a=crypto:6 AES_256_CM_HMAC_SHA1_32 inline:yVs8C3xPFY2LAUXIH+dlgBBNSz+jm1cbAQlAgv8hPKGe1zfu2wzx1d465UfFzQ==
   a=crypto:7 F8_128_HMAC_SHA1_80 inline:bhIPhj1TryAB63p/g8B3gL5NXJJ7V4kbjXqYaU54
   a=setup:actpass
   a=fingerprint:sha-1 55:CF:25:5D:D5:65:71:C8:D9:FF:97:AD:CC:F2:08:DB:38:DD:81:38
m=audio 5016 RTP/SAVP 9
   a=rtpmap:9 G722/8000
   a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level
   a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
   a=rtcp-xr:voip-metrics
   a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:Ekb2qAA8F7VCmz0FMSrad0rIt8duHQFedu/KxMbD
   a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:rEeGiaLCUbFw0sS0FxARgX9i5pwEj/frxxbgGkch
   a=crypto:3 AES_192_CM_HMAC_SHA1_80 inline:up9VO2T/rfu8V0cecA4RuG0aWgSaCC5gD/p/RdY1odg1p/0Pto0=
   a=crypto:4 AES_192_CM_HMAC_SHA1_32 inline:6yLDM31gAuwrlL0qkH72QYJLwtzX1IX+Z+7UML3VA5CpIbUWeAw=
   a=crypto:5 AES_256_CM_HMAC_SHA1_80 inline:2Q3b3UpPJMosXTrm/0Ui5q3Mw8tQ6ig5Xq0jt4Ibj0t5hVQx5KBRbC+8sMJDMg==
   a=crypto:6 AES_256_CM_HMAC_SHA1_32 inline:yVs8C3xPFY2LAUXIH+dlgBBNSz+jm1cbAQlAgv8hPKGe1zfu2wzx1d465UfFzQ==
   a=crypto:7 F8_128_HMAC_SHA1_80 inline:bhIPhj1TryAB63p/g8B3gL5NXJJ7V4kbjXqYaU54
m=audio 5016 RTP/AVP 9
a=rtpmap:9 G722/8000
a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level
a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=rtcp-xr:voip-metrics

Kamailio in secure mode selects the SRTP block of Audio SDP and responds in 200 OK

RTP to SRTP Bridging in Freeswitch

RTP to SRTP in Freeswitch

Enable ZRTP globally. Can override this on a per channel basis http://wiki.freeswitch.org/wiki/ZRTP (on how to enable zrtp)

When SRTP it’s critical to not offer or accept variable bit rate codecs, doing so would leak information and possibly compromising SRTP stream. (FS-6404)

Supported SRTP Crypto Suites:

AEAD_AES_256_GCM_8

This algorithm is identical to AEAD_AES_256_GCM (see Section 5.2 of [RFC5116]), except that the tag length, t, is 8, and an
authentication tag with a length of 8 octets (64 bits) is used. An AEAD_AES_256_GCM_8 ciphertext is exactly 8 octets longer than its
corresponding plaintext.

AEAD_AES_128_GCM_8

This algorithm is identical to AEAD_AES_128_GCM (see Section 5.1 of [RFC5116]), except that the tag length, t, is 8, and an
authentication tag with a length of 8 octets (64 bits) is used. An AEAD_AES_128_GCM_8 ciphertext is exactly 8 octets longer than its
corresponding plaintext.

AES_CM_256_HMAC_SHA1_80 | AES_CM_192_HMAC_SHA1_80 | AES_CM_128_HMAC_SHA1_80

AES_CM_128_HMAC_SHA1_80 is the SRTP default AES Counter Mode cipher and HMAC-SHA1 message authentication with an 80-bit authentication
tag. The master-key length is 128 bits and has a default lifetime of a maximum of 2^48 SRTP packets or 2^31 SRTCP packets, whichever comes
first.

AES_CM_256_HMAC_SHA1_32 | AES_CM_192_HMAC_SHA1_32 | AES_CM_128_HMAC_SHA1_32

This crypto-suite is identical to AES_CM_128_HMAC_SHA1_80 except that the authentication tag is 32 bits. The length of the base64-decoded key and salt value for this crypto-suite MUST be 30 octets i.e., 240 bits; otherwise, the crypto attribute is considered invalid.

AES_CM_128_NULL_AUTH

The SRTP default cipher (AES-128 Counter Mode), but to use no authentication method. This policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 of [RFC3711].

SRTP variables that modify behaviors based on direction/leg:

rtp_secure_media

possible values:
mandatory – Accept/Offer SAVP negotiation ONLY
optional – Accept/Offer SAVP/AVP with SAVP preferred
forbidden – More useful for inbound to deny SAVP negotiation
false – implies forbidden
true – implies mandatory

default if not set is accept SAVP inbound if offered.

rtp_secure_media_inbound | rtp_secure_media_outbound

This is the same as rtp_secure_media, but would apply to either inbound
or outbound offers specifically.

How to specify crypto suites:

By default without specifying any crypto suites FreeSWITCH will offer crypto suites from strongest to weakest accepting the strongest each
endpoint has in common. If you wish to force specific crypto suites you can do so by appending the suites in a comma separated list in the order that you wish to offer them in.

Examples:
rtp_secure_media=mandatory:AES_CM_256_HMAC_SHA1_80,AES_CM_256_HMAC_SHA1_32
rtp_secure_media=true:AES_CM_256_HMAC_SHA1_80,AES_CM_256_HMAC_SHA1_32
rtp_secure_media=optional:AES_CM_256_HMAC_SHA1_80
rtp_secure_media=true:AES_CM_256_HMAC_SHA1_80

Additionally you can narrow this down on either inbound or outbound by specifying as so:

rtp_secure_media_inbound=true:AEAD_AES_256_GCM_8
rtp_secure_media_inbound=mandatory:AEAD_AES_256_GCM_8
rtp_secure_media_outbound=true:AEAD_AES_128_GCM_8
rtp_secure_media_outbound=optional:AEAD_AES_128_GCM_8

rtp_secure_media_suites

Optionaly you can use rtp_secure_media_suites to dictate the suite list and only use rtp_secure_media=[optional|mandatory|false|true] without having to dictate the suite list with the rtp_secure_media* variables.

In vars.xml

SIP and TLS settings. http://wiki.freeswitch.org/wiki/Tls valid options: sslv2,sslv3,sslv23,tlsv1,tlsv1.1,tlsv1.2 default: tlsv1,tlsv1.1,tlsv1.2

TLS cipher suite: default ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH The actual ciphers supported will change per platform. openssl ciphers -v ‘ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH’ Will show you what is available in your verion of openssl.

Logs :

A client at 7777777777@ is trying to call 9999999999@ , which freeswtch has to proxy and convert from RTP to SRTP.
The following debug logs form sofia external show this process.

recv 1215 bytes from udp/[]:4642 at 07:08:27.374857:


INVITE sip:9999999999@:5080;transport=UDP SIP/2.0
   Via: SIP/2.0/UDP :47851;branch=z9hG4bK-524287-1---7cc8ad9383e9787d;rport
   Max-Forwards: 70
   Contact: :47851;transport=UDP>
   To: :5080;transport=UDP>
   From: :5080;transport=UDP>;tag=5df9f82c
   Call-ID: lFNvnuABQfOpROxfFp-MZQ..
   CSeq: 1 INVITE
   Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE
   Content-Type: application/sdp
   User-Agent: Z 5.2.28 rv2.8.115
   Allow-Events: presence, kpml, talk
   Content-Length: 607
v=0
   o=Z 20472192 0 IN IP4 
   s=Z
   c=IN IP4 
   t=0 0
   m=audio 8000 RTP/AVP 106 9 3 111 0 8 97 110 112 98 101 100 99 102
   a=rtpmap:106 opus/48000/2
   a=fmtp:106 minptime=20; cbr=1; maxaveragebitrate=40000; useinbandfec=1
   a=rtpmap:111 speex/16000
   a=rtpmap:97 iLBC/8000
   a=fmtp:97 mode=20
   a=rtpmap:110 speex/8000
   a=rtpmap:112 speex/32000
   a=rtpmap:98 telephone-event/48000
   a=fmtp:98 0-16
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=rtpmap:100 telephone-event/16000
   a=fmtp:100 0-16
   a=rtpmap:99 telephone-event/32000
   a=fmtp:99 0-16
   a=rtpmap:102 G726-32/8000
   a=sendrecv

[NOTICE] switch_channel.c:1104 New Channel sofia/external/7777777777@:5080 [ed5e07ee-bd00-4a47-b4e1-6abc9dd23ed6]

[DEBUG] switch_core_state_machine.c:584 (sofia/external/7777777777@:5080) Running State Change CS_NEW (Cur 1 Tot 33)

[DEBUG] sofia.c:10078 sofia/external/7777777777@:5080 receiving invite from :4642 version: 1.9.0 -742-8f1be0 64bit

[DEBUG] sofia.c:7291 Channel sofia/external/7777777777@:5080 entering state [received][100]

[DEBUG] sofia.c:7301 Remote SDP:
v=0
o=Z 20472192 0 IN IP4 
s=Z
c=IN IP4 
t=0 0
m=audio 8000 RTP/AVP 106 9 3 111 0 8 97 110 112 98 101 100 99 102
a=rtpmap:106 opus/48000/2
a=fmtp:106 minptime=20; cbr=1; maxaveragebitrate=40000; useinbandfec=1
a=rtpmap:111 speex/16000
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=20
a=rtpmap:110 speex/8000
a=rtpmap:112 speex/32000
a=rtpmap:98 telephone-event/48000
a=fmtp:98 0-16
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=rtpmap:100 telephone-event/16000
a=fmtp:100 0-16
a=rtpmap:99 telephone-event/32000
a=fmtp:99 0-16
a=rtpmap:102 G726-32/8000
[DEBUG] sofia.c:7693 (sofia/external/7777777777@:5080) State Change CS_NEW -> CS_INIT
[DEBUG] switch_core_state_machine.c:603 (sofia/external/7777777777@:5080) State NEW
[DEBUG] switch_core_state_machine.c:584 (sofia/external/7777777777@:5080) Running State Change CS_INIT (Cur 1 Tot 33)
[DEBUG] switch_core_state_machine.c:627 (sofia/external/7777777777@:5080) State INIT
[DEBUG] mod_sofia.c:93 sofia/external/7777777777@:5080 SOFIA INIT
[DEBUG] switch_core_state_machine.c:40 sofia/external/7777777777@:5080 Standard INIT
[DEBUG] switch_core_state_machine.c:48 (sofia/external/7777777777@:5080) State Change CS_INIT -> CS_ROUTING
[DEBUG] switch_core_state_machine.c:627 (sofia/external/7777777777@:5080) State INIT going to sleep
[DEBUG] switch_core_state_machine.c:584 (sofia/external/7777777777@:5080) Running State Change CS_ROUTING (Cur 1 Tot 33)
[DEBUG] switch_channel.c:2249 (sofia/external/7777777777@:5080) Callstate Change DOWN -> RINGING
[DEBUG] switch_core_state_machine.c:643 (sofia/external/7777777777@:5080) State ROUTING
send 389 bytes to udp/[]:4642 at 07:08:27.376085:

SIP/2.0 100 Trying

   Via: SIP/2.0/UDP :47851;branch=z9hG4bK-524287-1---7cc8ad9383e9787d;rport=4642;received=
   From: :5080;transport=UDP>;tag=5df9f82c
   To: :5080;transport=UDP>
   Call-ID: lFNvnuABQfOpROxfFp-MZQ..
   CSeq: 1 INVITE
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Content-Length: 0

After the invote is recived and processed with 100 trying reply , the routing and rtp secure trabformation begins by adding crypto keys and forarding to

[DEBUG] mod_sofia.c:154 sofia/external/7777777777@:5080 SOFIA ROUTING
[DEBUG] switch_core_state_machine.c:236 sofia/external/7777777777@:5080 Standard ROUTING
[INFO] mod_dialplan_xml.c:637 Processing 7777777777 <7777777777>->9999999999 in context public
Dialplan: sofia/external/7777777777@:5080 Action set(rtp_secure_media=optional) 
Dialplan: sofia/external/7777777777@:5080 Action log(INFO Forwarding calls 9999999999@ )
Dialplan: sofia/external/7777777777@:5080 Action bridge(sofia/external/9999999999@)
[DEBUG] switch_core_state_machine.c:286 (sofia/external/7777777777@:5080) State Change CS_ROUTING -> CS_EXECUTE

[DEBUG] switch_core_state_machine.c:643 (sofia/external/7777777777@:5080) State ROUTING going to sleep

[DEBUG] switch_core_state_machine.c:584 (sofia/external/7777777777@:5080) Running State Change CS_EXECUTE (Cur 1 Tot 33)

[DEBUG] switch_core_state_machine.c:650 (sofia/external/7777777777@:5080) State EXECUTE

[DEBUG] mod_sofia.c:209 sofia/external/7777777777@:5080 SOFIA EXECUTE

[DEBUG] switch_core_state_machine.c:328 sofia/external/7777777777@:5080 Standard EXECUTE

ed5e07ee EXECUTE sofia/external/7777777777@:5080 set(rtp_secure_media=optional)

[DEBUG] mod_dptools.c:1593 SET sofia/external/7777777777@:5080 [rtp_secure_media]=[optional]

ed5e07ee EXECUTE sofia/external/7777777777@:5080 log(INFO  Forwarding calls   9999999999@ )

[INFO] mod_dptools.c:1787  Forwarding calls   9999999999@ 

…

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [1 AEAD_AES_256_GCM_8 inline:aHJ1yquBtm4Lzfi2oMpe6cV7IBEy3YgKxrJ3qjvLuRXSuZfHcV4VtVNwHDw]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [1 AEAD_AES_256_GCM_8 inline:qeJbqlSbnKBNew575hSZ3LX78o6GBsjgOrSMxzGH/zb1E7mkls1Mda93U9w]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [1 AEAD_AES_256_GCM_8 inline:VghMVsjWQwnOAAjBJ1NTB3jZgfpNV/Yu4poxkAPMqkC7C+fhPKApCJrWg3U]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [2 AEAD_AES_128_GCM_8 inline:7XNrjjwC/eOVnWlBSp74DfiIGAEYn/BN+latfA]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [2 AEAD_AES_128_GCM_8 inline:UQrFpy9Q7L5DI/ww4e5IAmwy7BxSw5yd/T0v0Q]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [2 AEAD_AES_128_GCM_8 inline:ZqkEPrUFHkaQ+7CROp52H/JO0MbrYWk/Eyl9lQ]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:PTGAm2KlbfuKtIUVGtXknKKzALAzfILZJuPOjfO9S07eWRE6FR0aMUvjuehJgw]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:ahHIB0o/dp3SliYWK9BkxM7TfzILwG0bjDn7JuvYi+puRkTM4mYvvsSmywLaYA]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:crAs8dPcWJkEEGj5nqTvFGl/TWpxxb86k+dX5gBXhh+q6DO2pEqWNkQmm55aLA]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:SLBJWjgMdfiYX7TUwWQ9CmqUsILLJrpBIVjbfuQmpBIFLvvA/XU]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [4 AES_CM_192_HMAC_SHA1_80 fNazWgWwNRPjUKNHVqkz44]

2819d6c2 2019-03-19 07:08:27.375398 [DEBUG] switch_core_media.c:1204 Set Local text crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:hbe9qqETBSK5hRQ8DI9mXL4QAjjGSR8tGDiTHCJF3yxCrRk1ajk]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:8q8mer9N2V4qVxnaazuJeT0KXgW2scONy36J3KaS]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:TP5NQ1yB8ZSCCwZMgXur9VHZ5SlpNfnXePj7eZrk]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:HT3F3iYG8H/majhBZbOs2Z8ye/WEVGT5Oytx2oQS]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:fEohh92lX2xLmeFYlt8YouM2jN4z5pU05d90BYfoAKU6m4CWv8g8AnifDUKk9A]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:+uBNmLcvj41hXoMxNlMNBpq68gU4PmLwYcdopEB/X/jfPElkUgHfguPIgIFJUg]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:cqk7D3+KMQ+31R4FFDRRzn/aluyIgjxBL59vfxcsdf5OW9izEJtU+06GewJyIA]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:Tv25TfP9fQZ+ljs/tFlHohkckiK4F6cemzEjHSvo2+q6No4ai+o]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:CY/Dizd1QrlobZtgnigr0hWE+oDSx4S1F51Zpo4aZamN+8ZMdp8]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:aEox/7IMps5c+uOWbosZ618+opkJV/GnrKc2EnAhVnDNeo91+No]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:0LwKGyljIed0zhukiMMyD5ive0ZsyybwBrnevcAv]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:eZN8rAG8UPPntdYxsg1kkWL4qMsVgTiGGiS4UeUM]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:bAYzbfr+El8usaTkPBR6iFuTda4uLNGjyx9lQWkX]

[DEBUG] switch_core_media.c:1204 Set Local audio crypto Key [9 AES_CM_128_NULL_AUTH inline:5m3142gGG1HZ5VnoXsAOyopSwDCYbrIsGpdbEO3D]

[DEBUG] switch_core_media.c:1204 Set Local video crypto Key [9 AES_CM_128_NULL_AUTH inline:zXk67wjwRhSilq0kiz5TWxXqrxuTaWTA3qqbVo/G]

[DEBUG] switch_core_media.c:1204 Set Local text crypto Key [9 AES_CM_128_NULL_AUTH inline:FRP9CJbBO+PRj6I9RSBAiMxRZ/qFtyrEXPfxocG0]

[DEBUG] sofia_glue.c:1299 sofia/external/9999999999@ sending invite version: 1.9.0 -742-8f1b7e0 64bit

Local SDP:

v=0
o=FreeSWITCH 1552960557 1552960558 IN IP4 
s=FreeSWITCH
c=IN IP4 
t=0 0
m=audio 18750 RTP/SAVP 102 9 0 8 103 101
a=rtpmap:102 opus/48000/2
a=fmtp:102 useinbandfec=1; maxaveragebitrate=30000; maxplaybackrate=48000; ptime=20; minptime=10; maxptime=40; stereo=1
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:103 telephone-event/48000
a=fmtp:103 0-16
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=crypto:1 AEAD_AES_256_GCM_8 inline:aHJ1yquBtm4Lzfi2oMpe6cV7IBEy3YgKxrJ3qjvLuRXSuZfHcV4VtVNwHDw
a=crypto:2 AEAD_AES_128_GCM_8 inline:7XNrjjwC/eOVnWlBSp74DfiIGAEYn/BN+latfA
a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:PTGAm2KlbfuKtIUVGtXknKKzALAzfILZJuPOjfO9S07eWRE6FR0aMUvjuehJgw
a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:SLBJWjgMdfiYX7TUwWQ9CmqUsILLJrpBIVjbfuQmpBIFLvvA/XU
a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:8q8mer9N2V4qVxnaazuJeT0KXgW2scONy36J3KaS
a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:fEohh92lX2xLmeFYlt8YouM2jN4z5pU05d90BYfoAKU6m4CWv8g8AnifDUKk9A
a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:Tv25TfP9fQZ+ljs/tFlHohkckiK4F6cemzEjHSvo2+q6No4ai+o
a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:0LwKGyljIed0zhukiMMyD5ive0ZsyybwBrnevcAv
a=crypto:9 AES_CM_128_NULL_AUTH inline:5m3142gGG1HZ5VnoXsAOyopSwDCYbrIsGpdbEO3D
a=ptime:20
a=sendrecv

Once the SDP is ready with crypto keys it is the forwarded to the next_up

send 2104 bytes to udp/[]:5060 at 07:08:27.378167:


INVITE sip:9999999999@ SIP/2.0
   Via: SIP/2.0/UDP :5080;rport;branch=z9hG4bKmF251mK2pN35B
   Max-Forwards: 69
   From: "7777777777" >;tag=vcKeKD6SN02cB
   To: >
   Call-ID: a27898fd-c4b8-1237-ddaa-02a933b32da0
   CSeq: 1935861 INVITE
   Contact: :5080>
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 1304
   X-FS-Support: update_display,send_info
   Remote-Party-ID: "7777777777" >;party=calling;screen=yes;privacy=off
v=0
   o=FreeSWITCH 1552960557 1552960558 IN IP4 
   s=FreeSWITCH
   c=IN IP4 
   t=0 0
   m=audio 18750 RTP/SAVP 102 9 0 8 103 101
   a=rtpmap:102 opus/48000/2
   a=fmtp:102 useinbandfec=1; maxaveragebitrate=30000; maxplaybackrate=48000; ptime=20; minptime=10; maxptime=40; stereo=1
   a=rtpmap:9 G722/8000
   a=rtpmap:0 PCMU/8000
   a=rtpmap:8 PCMA/8000
   a=rtpmap:103 telephone-event/48000
   a=fmtp:103 0-16
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=crypto:1 AEAD_AES_256_GCM_8 inline:aHJ1yquBtm4Lzfi2oMpe6cV7IBEy3YgKxrJ3qjvLuRXSuZfHcV4VtVNwHDw
   a=crypto:2 AEAD_AES_128_GCM_8 inline:7XNrjjwC/eOVnWlBSp74DfiIGAEYn/BN+latfA
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:PTGAm2KlbfuKtIUVGtXknKKzALAzfILZJuPOjfO9S07eWRE6FR0aMUvjuehJgw
   a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:SLBJWjgMdfiYX7TUwWQ9CmqUsILLJrpBIVjbfuQmpBIFLvvA/XU
   a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:8q8mer9N2V4qVxnaazuJeT0KXgW2scONy36J3KaS
   a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:fEohh92lX2xLmeFYlt8YouM2jN4z5pU05d90BYfoAKU6m4CWv8g8AnifDUKk9A
   a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:Tv25TfP9fQZ+ljs/tFlHohkckiK4F6cemzEjHSvo2+q6No4ai+o
   a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:0LwKGyljIed0zhukiMMyD5ive0ZsyybwBrnevcAv
   a=crypto:9 AES_CM_128_NULL_AUTH inline:5m3142gGG1HZ5VnoXsAOyopSwDCYbrIsGpdbEO3D
   a=ptime:20

Kamailio Security

Security is Critical for a VoIP platform as it is susceptible to hacks , misuse , eavesdropping or just sheer misuse of the system by making robotic flood calls . Kamailio SIP Server provides some key features to meet these challenges which will be discussed in this blog .

Sanity checks for incoming SIP requests

Being a gateway on the VOIP system permiter is a challenging task due to the security threast it posses. It is must to configure per request initial checks for all incoming SIP request. This ideally should be the first step in routing clock before any other processing.

request_route {
    route(REQINIT);
    ... 
    // proceed with routing 
}

Pointers for functionality

For replies coming from local users , usually behind NAT , do not open a new TCP connection on each reply

set_reply_no_connect();

For indialog requests also close connection after forwarding the request.

if(has_totag()) {
    set_forward_no_connect();
}

Check if any IP is flooding the server with messages and block for some time ( ANTI-FLOOD and pike decsribed later in the article ).
Ofcourse exclude self IP . sample to do blocking using hastable’s psedi variable ipban

if(src_ip!=myself) {
    if (!pike_check_req()) {
        $sht(ipban=>$si) = 1;
        exit;
    }
}

Friendly-scanners are type of botnets probing and scanning known IP ranges(5060,5061..) for SIP server, softswitches, cloud PBX. Once they detect a suitably open server they use brute force tactic to send all commonly/default username/passwords accounts. The prime purpose is to extract all vulenrable accounts for creating fradulent calls such as crating DOS attacks using high tarffic and consuming all bandwidth from good calls, free internation calls or imposter/scam calls.

Among some obvious ways to block the flood of packets by these scanner are

  • imply strict firewalls rules for allowing only known client IP’s
  • changing default SIP port from 5060 to some other non standard port in network
  • checking User agent for known attackes such as (sipcli , sipvicious , sip-scan , sipsak , sundayddr , friendly-scanner , iWar , CSipSimple , SIVuS , Gulp , sipv , smap , friendly-request , VaxIPUserAgent , VaxSIPUserAgent , siparmyknife , Test Agent)
if($ua =~ "friendly-scanner|sipcli|sipvicious|VaxSIPUserAgent") {
    exit;
}
  • track unsuccesfull quick/consecutive attempts from an IP and block its access temporatliy or permamntly. Such as failing to REGISTER / autehticate for 3 consecutive time should block it .

Track if the message is hopping too many times within the server server , intra or inter networks not reaching the destination . mf_process_maxfwd_header(maxvalue). Note maxvalue is added is no Max-Forward header is found in the message.

mf_process_maxfwd_header(10)

Sanity is a complete module by itself to perform various checks and validation such as

  • ruri sip version – (1) – checks if the SIP version in the request URI is supported, currently only 2.0
  • ruri scheme – (2) – checks if the URI scheme of the request URI is supported (sip[s]|tel[s])
  • required headers – (4) -checks if the minimum set of required headers to, from, cseq, callid and via is present in the request
  • via sip version – (8) – disabled
  • via protocol – (16) – disabled
  • Cseq method – (32) – checks if the method from the Cseq header is equal to the request method
  • Cseq value – (64) – checks if the number in the Cseq header is a valid unsigned integer
  • content length – (128) – checks if the size of the body matches with the value from the content length header
  • expires value – (256) – checks if the value of the expires header is a valid unsigned integer
  • proxy require – (512) – checks if all items of the proxy require header are present in the list of the extensions from the module parameter proxy_require.
  • parse uri’s – (1024) – checks if the specified URIs are present and parseable by the Kamailio parsers
  • digest credentials (2048) – Check all instances of digest credentials in a message
  • duplicated To/From tags (4096) – checks for the presence of duplicated tags in To/From headers.
  • authorization header (8192) – checks if the Authorization is valid if the scheme in “digest” always returns success for other schemes.
    sample for URI checks for list of parsed URIs: Request URI (1), From URI (2) and To URI (4).

Full route[REQINIT] block

route[REQINIT] {

set_reply_no_connect();
if(has_totag()) {
    set_forward_no_connect();
}

if(src_ip!=myself) {
    if (!pike_check_req()) {
        $sht(ipban=>$si) = 1;
        exit;
    }
}

if($ua =~ "friendly-scanner|sipcli|sipvicious|VaxSIPUserAgent") {
    exit;
}

if (!mf_process_maxfwd_header("10")) {
    sl_send_reply("483","Too Many Hops");
    exit;
}

if(is_method("OPTIONS") && uri==myself && $rU==$null) {
    sl_send_reply("200","Keepalive");
    exit;
}

if(!sanity_check("17895", "7")) {
    xlog("Malformed SIP request from $si:$sp\n");
    exit;
}
}

Access Control Lists and Permissions

permission module handles ACL by storing permission rules in plaintext configuration files , hosts.allow and hosts.deby by tcpd.

#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
...
# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif
..
#!ifdef WITH_IPAUTH
    if((!is_method("REGISTER")) && allow_source_address()) {
        # source IP allowed
        return;
    }
#!endif

Functions

Call Routing

if (allow_routing("rules.allow", "rules.deny")) {
    t_relay();
};

Registration permissions

if (method=="REGISTER") {
    if (allow_register("register")) {
        save("location");
        exit;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};

URI permissions

if (allow_uri("basename", "$rt")) {  // Check Refer-To URI
    t_relay();
};

Address permissions

// check if sourec ip/port is in group 1
if (!allow_address("1", "$si", "$sp")) {
    sl_send_reply("403", "Forbidden");
};

Trusted Requests

if (allow_trusted("$si", "$proto")) {
    t_relay();
};

checks protocols which could be one of the “any”, “udp, “tcp”, “tls”, “ws”, “wss” and “sctp”.

Hiding Topology Details

Stripping the SIP routing headers that show topology details involves steps such as hiding the local IP address of user agent , hiding path taken to reach the server , obscuring the core SIP server’s ip and details etc . Some headers which giave away information are

  • top most Via header
  • contact address
  • Record-Route headers
  • sometimes the Call-ID header

This goes a long way in helping to keep the inner network topology secure from malacious exploiters, expecially to protect IP of the PSTN gateways which could let to an costly mess or gensrally from attackers and reverse engineering.

Topoh module hides the network topology by removing the internal IP addresa and instead add ing them in encrypted form the same sip packet. Diff server using the same shared secret key can encode decode the encrypted addresses.

This way it doesnt not even have to store the state of the call and is transpoarent to all call routing logic

loadmodule topoh.so

modparam("topoh", "mask_key", "somekey")
modparam("topoh", "mask_ip", "1.1.1.1")
modparam("topoh", "mask_callid", 1)

topoh module

Primarily it does these things
hide the addresses of PSTN gateways
protect your internal network topology
interconnection provider – to keep the details of connected parties secret to the other, to prevent a bypass of its service in the future

loadmodule topoh.so
modparam("topoh", "mask_key", "YouDoHaveToChangeThisKey")
modparam("topoh", "mask_ip", "10.0.0.1")
modparam("topoh", "mask_callid", 1)

Params

mask_key (str)
mask_ip (str)
mask_callid (integer)
uparam_name (str)
uparam_prefix (str)
vparam_name (str)
vparam_prefix (str)
callid_prefix (str)
sanity_checks (integer)
uri_prefix_checks (integer)
event_callback (str)

Primarily tis module uses mask key to code the trimmed via header information and insert them into pre specified param names with prefixes. Hence it can work with stageful or stateless proxy and can also work if server is restarted in between

topos module

Offers topology hiding by stripping the SIP routing headers that show topology details.

It requires 2 modules rr module since server must perform record routing to ensure in-dialog requests are encoded/decoded and database module to store the data for topology stripping and restoring.

Params :
storage (str) – could be redis or database backend

modparam("topos", "storage", "redis")

db_url (str)

modparam("topos", "db_url", "dbdriver://username:password@dbhost/dbname") 
modparam("topos", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio”

mask_callid (int) – Whether to replace or not the Call-ID with another unique id generated by Kamailio. ( present with topoh)
sanity_checks (int) – with sanity module to perform checks before encoding /decoding
branch_expire (int)
dialog_expire (int)
clean_interval (int)
event_callback (str) – callback event

modparam("topos", "event_callback", "ksr_topos_event")
..
function ksr_topos_event(evname)
 KSR.info("===== topos module triggered event: " .. evname .. "\n");
 return 1;
end

event route :
event_route[topos:msg-outgoing]

loadmodule "topos.so"
loadmodule "topos_redis.so"

//topos params 
modparam("topos", "storage", "redis")
//branch_expire is 10 min
modparam("topos", "branch_expire", 10800)
// dialog_expire is 1 day
modparam("topos", "dialog_expire", 10800)
modparam("topos", "sanity_checks", 1)

FireWall

To save from the automatic port scans that attackers carry out to hack into the system use the script below

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:CHECK_TCP - [0:0]
:ICMP - [0:0]
:PRIVATE - [0:0]
:PSD - [0:0]
:SERVICES - [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -i eth0 -p ipv6 -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -j SERVICES 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
-A CHECK_TCP -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,ACK FIN -m state --state INVALID,NEW,RELATED -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags PSH,ACK PSH -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-option 64 -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-option 128 -j DROP 
-A ICMP -p icmp -m icmp --icmp-type 11/1 -m limit --limit 5/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 11/0 -m limit --limit 5/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 3 -m limit --limit 10/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 8 -m limit --limit 10/sec --limit-burst 10 -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -j DROP 
-A PRIVATE -d 192.168.0.0/16 -j DROP 
-A PRIVATE -d 172.16.0.0/12 -j DROP 
-A PRIVATE -d 10.0.0.0/8 -j DROP 
-A PRIVATE -j RETURN 
-A PSD -p tcp -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-port-unreachable 
-A PSD -p tcp -m statistic --mode random --probability 0.050000 -j TARPIT  --reset 
-A PSD -p tcp -m statistic --mode random --probability 0.500000 -j TARPIT  --tarpit 
-A PSD -p udp -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-port-unreachable 
-A PSD -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-host-unreachable  
-A SERVICES -p icmp -m state --state INVALID -j DROP 
-A SERVICES -p icmp -j ICMP 
-A SERVICES -p tcp -j CHECK_TCP 
-A SERVICES -p udp -m udp --dport 123 -m state --state NEW -j ACCEPT 
-A SERVICES -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m tcp --dport 53 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m udp -m multiport --dports 5060 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m udp -m multiport --dports 5061 -m state --state NEW -j ACCEPT 
-A SERVICES -i eth0 -j PSD 
COMMIT

Update/Remove Server and User Agent Headers

Rewrite server header to save the exact version of server from hackers

server_header="Server: Simple Server"

or completely rmemove it from traces

server_signature=no

and

user_agent_header="User-Agent: My SIP Server"

Remove Server warnings from traces and log file

Warnings expose the vulnerabilities of system and it is best to remove them in production enviornment

user_agent_header="User-Agent: My SIP Server"

Anti Flood

During Auth or logging there is a fair chance of leaking credentials or the fact that users opt for weak password themselves compromising the system via bruteforcing username/password . Or attacker may be bruteforcing prefixes to understand config and routing logic
Random unnecessary flood of SIP requests can consume CPU and make it slow or unavailable for others as Denial of Service . These situations can be made less daunting via pike module

pike modules

tracks the number of SIP messages per source IP address, per period.

loadmodule "pike.so"

// pike params 
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 20)
modparam("pike", "remove_latency", 4)

//routing logic inclusion
route {
  if (!pike_check_req()) {
    xlog("L_ALERT","ALERT: pike block $rm from $fu (IP:$si:$sp)\n");
    exit;
  }
  ...
}

Fail2Ban

can syslog files for specific messages based on regular expressions and act upon matching by banning IP addresses.

Traffic Monitoring and Detection

Secfilter module

offer an additional layer of security over our communications. It can perform

  • Blacklisting user agents, IP addresses, countries, domains and users.
  • Whitelisting user agents, IP addresses, countries, domains and users.
  • Blacklist of destinations where the called number is not allowed.
  • SQL injection attacks prevention.

Digest Authetication

Digest is a cryptographic function based on symmetrical encryption.
Read more

tbd

Ref :

Opensips as SIP gateway

OpenSIP provided dispatcher modules which computes hashes over parts of the request and selects an address from a destination set which is then as outbound proxy.

Combination of opensips working scenarios scripts with code is at https://github.com/altanai/opensipsexamples.

In the config of opensips load the file dispatcher.list with destination sets

modparam("dispatcher", "list_file", "/var/run/opensips/dispatcher.list")
 proxies
 2 sip:127.0.0.1:5080
 2 sip:127.0.0.1:5082
 gateways
 1 sip:127.0.0.1:7070
 1 sip:127.0.0.1:7072
 1 sip:127.0.0.1:7074

or one can also load the sets from the database

modparam("dispatcher", "db_url", "mysql://user:passwb@localhost/database")

Tthe algorithm used to select the destination address.
“0” – hash over callid
“1” – hash over from uri.
“2” – hash over to uri.
“3” – hash over request-uri.
“4” – round-robin (next destination).
“5” – hash over authorization-username (Proxy-Authorization or “normal” authorization). If no username is found, round robin is used.
“6” – random (using rand()).
“7” – hash over the content of PVs string. Note: This works only when the parameter hash_pvar is set.
“X” – if the algorithm is not implemented, the first entry in set is chosen.

and the state of the destination address can be

“a”: active
“i”: inactive
“p”: probing

Load Balancer

Opensip can function as load balancer , distributing the load between different SIP Application servers .

example of gateway sets file in dbtext/diapatcher.list

id(int,auto) setid(int) destination(string) socket(string,null) state(int) weight(int) priority(int) attrs(string) description(string)
1:1:sip\:10.20.30.40\:5060:null:0:1:1:'carrier':'load balancer for OB'
2:2:sip\:10.50.60.70\:5060:null:0:1:1:'carrier':'Load balancer for IB'

Health Monitoring

Probing and pinging features in Opensips can detect whether gateways are responding or not . Threshold and probing mode can fine tune the behaviour.

OpenSIPS config file

sample config file for dispatcher module

 debug=9            debug level (cmd line: -dddddddddd)
 fork=no
 log_stderror=yes  (cmd line: -E)
 children=2
 check_via=no      (cmd. line: -v)
 dns=off           (cmd. line: -r)
 rev_dns=off       (cmd. line: -R)
 port=5060
 
mpath="/usr/local/lib/opensips/modules/"
loadmodule "maxfwd.so"
loadmodule "sl.so"
loadmodule "dispatcher.so"

—————– setting module-specific parameters —————

dispatcher params

 modparam("dispatcher", "list_file", "../etc/dispatcher.list")
 // modparam("dispatcher", "force_dst", 1)
 route{
 if ( !mf_process_maxfwd_header("10") )
 {
 sl_send_reply("483","To Many Hops");
 drop();
 };
 ds_select_dst("2", "0");
 forward();
 // t_relay();
 }
 

dbtext is an implementation for a simplified database engine based on text files. It can be used by OpenSIPS DB interface instead of other database module (like MySQL). It keeps everything in memory.

The db_text database system architecture contains

  • a database is represented by a directory in the local file system. NOTE: when you use db_text in OpenSIPS, the database URL for modules must be the path to the directory where the table-files are located, prefixed by “text://”,
    e.g., “text:///var/dbtext/opensips”.
  • a table is represented by a text file inside database directory.

Minimal OpenSIPS location db_text table definition

username(str) contact(str) expires(int) q(double) callid(str) cseq(int)

Minimal OpenSIPS subscriber db_text table example

username(str) password(str) ha1(str) domain(str) ha1b(str)
suser:supasswd:xxx:alpha.org:xxx

This database interface don’t support the data insertion with default values. All such values specified in the database
template are ignored.

db_mode (integer)

Set caching mode (0 – default) or non-caching mode (1). In caching mode, data is loaded at startup. In non-caching mode, the module check every time a table is requested whether the correspondingfile on disk has changed, and if yes, will re-load table from file.

Set db_mode parameter

modparam(“db_text”, “db_mode”, 1)

loadmodule "/path/to/opensips/modules/db_text.so"
modparam("module_name", "database_URL", "text:///path/to/dbtext/database
")

Subscriber and Location

Definition of ‘subscriber’ table (one line)

username(str) domain(str) password(str) first_name(str) last_name(str) phone(str) email_address(str) datetime_created(int) datetime_modified(int) confirmation(str) flag(str) sendnotification(str) greeting(str) ha1(str) ha1b(str) perms(str) allow_find(str) timezone(str,null) rpid(str,null)

Definition of ‘location’ and ‘aliases’ tables (one line)

username(str) domain(str,null) contact(str,null) received(str) expires(i
nt,null) q(double,null) callid(str,null) cseq(int,null) last_modified(st
r) flags(int) user_agent(str) socket(str)

Definition of ‘version’ table and sample records

table_name(str) table_version(int)
subscriber:3
location:6
aliases:6

Configuration file using dbtext databse for oersistant storage . Also using auth

debug_mode=yes
children=4

check_via=no    # (cmd. line: -v)
dns=no          # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)

listen=udp:10.100.100.1:5060

loadmodule "modules/dbtext/dbtext.so"

loadmodule "modules/sl/sl.so"
loadmodule "modules/tm/tm.so"
loadmodule "modules/rr/rr.so"
loadmodule "modules/maxfwd/maxfwd.so"
loadmodule "modules/usrloc/usrloc.so"
loadmodule "modules/registrar/registrar.so"
loadmodule "modules/textops/textops.so"
loadmodule "modules/textops/mi_fifo.so"

loadmodule "modules/auth/auth.so"
loadmodule "modules/auth_db/auth_db.so"

----------------- setting module-specific parameters ---------------

-- mi_fifo params --

modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")

-- usrloc params --

modparam("usrloc", "db_mode", 2)
modparam("usrloc|auth_db", "db_url", "text:///tmp/opensipsdb")

modparam("auth_db", "calculate_ha1", 1)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "user_column", "username")
modparam("auth_db", "domain_column", "domain")

route{
// initial sanity checks -- messages with max_forwards==0, or excessively long requests
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
};
if ($ml &amp;gt;=  65535 ) {
sl_send_reply("513", "Message too big");
exit;
};

// we record-route all messages -- to make sure that subsequent messages will go through this proxy;
if (!$rm=="REGISTER") record_route();
&lt;pre&gt;&lt;code&gt;// subsequent messages withing a dialog should take the path determined by record-routing
if (loose_route()) {
    // mark routing logic in request
    append_hf("P-hint: rr-enforced\r\n");
    route(1);
    exit;
};

if (!is_myself("$rd")) {
    // mark routing logic in request
    append_hf("P-hint: outbound\r\n");
    route(1);
    exit;
};

//if the request is for other domain use UsrLoc 
if (is_myself("$rd")) {
    if ($rm=="REGISTER") {
        # digest authentication
        if (!www_authorize("", "subscriber")) {
            www_challenge("", "0");
            exit;
        };

        save("location");
        exit;
    };

    lookup("aliases");
    if (!is_myself("$rd")) {
        append_hf("P-hint: outbound alias\r\n");
        route(1);
        exit;
    };

    # native SIP destinations are handled using our USRLOC DB
    if (!lookup("location")) {
        sl_send_reply("404", "Not Found");
        exit;
    };
};
append_hf("P-hint: usrloc applied\r\n");
route(1);&lt;/code&gt;&lt;/pre&gt;
}

route[1]
{
if (!t_relay()) {
sl_reply_error();
};
}

Kamailio as Inbound/Outbound proxy or Session Border Controller

A typical voice core network consists of B2BUA SIP server with media proxy and media processing units / servers along with components for billing , user profile management , shared memory/ cache , transcoders , call routing logic etc . However a VOIP provider would not want to interface these critical servers to outside world directly , there for a SBC ( Session Border Controller ) comes into picture .

The role of an SBC is to shield the core network from external entities such as user agent’s , carrier network while also providing security , auth and accounting services . In many cases SBC also provides NAT traversal and policy control features ( such as rate limiting , ACL etc ) . In advanced cases transcoding, topology concealment and load balancing is also achievable via a SBC such as Kamailio .

Following sections are usecases / features kamailio can extend to. Routing scripts at https://github.com/altanai/kamailioexamples

Block user based on excessive REGISTER request  till an expiry time

For instance to block DDOS attacks , kamailio can check for the number of register requests a user sends and block above a threshold number subsequently .

if($sht(auth_block_list=>$au::auth_count)==30){
    $var(block) = $Ts - 900;
    $var(expire) = $Ts - 300;

    if($sht(auth_block_list=>$au::last_block) > $var(block)){
        xlog("L_INFO", "$fU@$fd - REGISTER - $au User Already Blocked for Exceeded Register Requests.\n");
        sl_send_reply("403", "Already Blocked Forbidden");
        exit;
    } else if($sht(auth_block_list=>$au::last_auth) > $var(expire)) {
        $sht(auth_block_list=>$au::last_block) = $Ts;
        xlog("L_INFO", "$fU@$fd - REGISTER - $au User Blocked for Exceeded Register Requests.\n");
        sl_send_reply("403", "Blocked Forbidden");
        exit;
    } else {
        $sht(auth_block_list=>$au::auth_count) = 0;
    } 
}

Anti Flood with Pike Module

To be on edge of a voip pltform , a SIP server must keep trac of all incoming request and their sources. Blocking the ones which exceed the limit or appear like a dos attack. Pike module reports high traffic from an IP if detected.

A sample script to detect high traffic from an IP and add it to ban list for a while . But exclude the known ip sources such as PSTN gateways etc

#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif
...
# ----- pike params -----
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)
...
route[REQINIT] {
...
if(src_ip!=myself) {
	if($sht(ipban=>$si)!=$null) {
		# ip is already blocked
		xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
		exit;
	}
	if (!pike_check_req()) {
		xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
		$sht(ipban=>$si) = 1;
		exit;
	}
}

Access Control List with Permission Module

permission module handles ACL by storing permission rules in plaintext configuration files , hosts.allow and hosts.deby by tcpd.

#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
...
# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif
..
#!ifdef WITH_IPAUTH
    if((!is_method("REGISTER")) && allow_source_address()) {
        # source IP allowed
        return;
    }
#!endif

Functions

Call Routing

if (allow_routing("rules.allow", "rules.deny")) {
    t_relay();
};

Registration permissions

if (method=="REGISTER") {
    if (allow_register("register")) {
        save("location");
        exit;
    } else {
        sl_send_reply("403", "Forbidden");
    };
};

URI permissions

if (allow_uri("basename", "$rt")) {  // Check Refer-To URI
    t_relay();
};

Address permissions

// check if sourec ip/port is in group 1
if (!allow_address("1", "$si", "$sp")) {
    sl_send_reply("403", "Forbidden");
};

Trusted Requests

if (allow_trusted("$si", "$proto")) {
    t_relay();
};

checks protocols which could be one of the “any”, “udp, “tcp”, “tls”, “ws”, “wss” and “sctp”.

Perform Load Balancing with Dispatcher Module

Load balancing is critical to a production ready system to provide High availability and load sharing among available servers. This could be either stateless or stateful where they use call state tracking

Dispatcher module in Kamailio lends capabilities of SIP traffic dispatcher to it. It can load routes to gateways or destination sets from any storage source such as mysql , psql database or even plain text file (modparam("dispatcher", "db_url", <datasource_name>).

It can also assign priority for routing sip traffic to it ( modparam("dispatcher", "priority_col", "dstpriority"))

To discover active of inactive gateways it uses TM module. One can choose one among many algorithms to share the load , like

  • 0 – hash over callid
  • 1 – hash over from URI
  • 2 – hash over to URI
  • 3 – hash over request-URI
  • 4 – round-robin (next destination)
  • 5 – hash over authorization-username
  • 6 – random destination (using rand())
  • 7 – hash over the content of PVs string
  • 8 – select destination sorted by priority attribute value (serial forking ordered by priority).
  • 9 – use weight based load distribution . Needs attribute ‘weight’ per each address
  • 10 – call load distribution ie route to one that has the least number of calls associated
  • 11 – relative weight based load distribution(rweight)
  • 12 – dispatch to all destination in setid at once (parallel forking).
  • x – if the algorithm is not implemented, the first entry in set is chosen.

some attributes passed with each destination set

  • duid – identify a destination (gateway address). Practically the load within the group is associated with this value.
  • maxload – upper limit of active calls per destination
  • weight – percent of calls to be sent to that gateways
  • rweight – relative weight based load distribution.
  • socket – sending socket for the gateway including keepalives
  • ping_from – from URI in OPTIONS keepalives

Active host usage probability is, rweight/(SUM of all active host rweights in destination group). recalculation is fired as host enables or disables.

Every destination has congestion threshold(weight) and after enabling c (congestion control), rweight is also used to control congestion tolerance lowering the weight by 1 as congestion is detected.

EWMA ( exponential weighted moving average ) is speed at which the older samples are dampened.

nametypesizedefaultnullkeyextra
idunsigned int10noprimaryauto
increment
setidintnot specified0no
destinationstring192“”no
flagintnot specified“”no
priorityintnot specified0no
attrsstring1980no
descriptionstring64“”no

To insert into dispatcher

INSERT INTO "dispatcher" VALUES(1,1,'sip:192.168.0.1:5060',0,12,'rweight=50;weight=50;cc=1;','');

set ping gateway once per second

modparam("dispatcher", "ds_ping_interval", 1)

enabling congestion metrics

modparam("dispatcher", "ds_ping_latency_stats", 1)

latency estimator

modparam("dispatcher", "ds_latency_estimator_alpha", 900)
loadmodule "dispatcher.so"
...
# ----- dispatcher params ----- 
modparam("dispatcher", "db_url", DBURL) 
modparam("dispatcher", "table_name", "dispatcher") modparam("dispatcher", "flags", 2) 
modparam("dispatcher", "dst_avp", "$avp(AVP_DST)") modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)") modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)") modparam("dispatcher", "sock_avp", "$avp(AVP_SOCK)")
...

request_route {
# do checks , indialog etc ...
# dispatch destinations 
route(DISPATCH); 
}

# Dispatch requests
route[DISPATCH] {
     # round robin dispatching on gateways group '1'
     if(!ds_select_dst("1", "4")) {
         send_reply("404", "No destination");
         exit;
     }
     xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
     t_on_failure("RTF_DISPATCH");
     route(RELAY);
     exit;
 }


# Try next destinations in failure route, except if session gets cancelled 
failure_route[RTF_DISPATCH] {
     if (t_is_canceled()) {
         exit;
     }
     # next DST - only for 500 or local timeout
     if (t_check_status("500") or (t_branch_timeout() and !t_branch_replied())) {
         if(ds_next_dst()) {
             t_on_failure("RTF_DISPATCH");
             route(RELAY);
             exit;
         }
     }
 }

Mask inner IPS with topology hiding

-tbd

PSTN gateway routing

-tbd

Kamailio basic setup as proxy for FreeSWITCH

Freeswitch PBX system

Setting up a in house hosted Enterprise PBX system for within enterprise communication .

Installation of Freeswitch on hosted server

source code

apt-get install git
git clone https://stash.freeswitch.org/scm/fs/freeswitch.git

verify installation by checking version

freeswitch -version
FreeSWITCH version: 1.9.0-742-8f1b7e0~64bit (-742-8f1b7e0 64bit)

post installation

optional arguments you can pass to freeswitch:
-nf — no forking
-reincarnate — restart the switch on an uncontrolled exit
-reincarnate-reexec — run execv on a restart (helpful for upgrades)
-u [user] — specify user to switch to
-g [group] — specify group to switch to
-core — dump cores
-help — this message
-version — print the version and exit
-rp — enable high(realtime) priority settings
-lp — enable low priority settings
-np — enable normal priority settings
-vg — run under valgrind
-nosql — disable internal sql scoreboard
-heavy-timer — Heavy Timer, possibly more accurate but at a cost
-nonat — disable auto nat detection
-nonatmap — disable auto nat port mapping
-nocal — disable clock calibration
-nort — disable clock clock_realtime
-stop — stop freeswitch
-nc — do not output to a console and background
-ncwait — do not output to a console and background but wait until the system is ready before exiting (implies -nc)
-c — output to a console and stay in the foreground

Options to control locations of files:
-base [basedir] — alternate prefix directory
-cfgname [filename] — alternate filename for FreeSWITCH main configuration file
-conf [confdir] — alternate directory for FreeSWITCH configuration files
-log [logdir] — alternate directory for logfiles
-run [rundir] — alternate directory for runtime files
-db [dbdir] — alternate directory for the internal database
-mod [moddir] — alternate directory for modules
-htdocs [htdocsdir] — alternate directory for htdocs
-scripts [scriptsdir] — alternate directory for scripts
-temp [directory] — alternate directory for temporary files
-grammar [directory] — alternate directory for grammar files
-certs [directory] — alternate directory for certificates
-recordings [directory] — alternate directory for recordings
-storage [directory] — alternate directory for voicemail storage
-cache [directory] — alternate directory for cache files
-sounds [directory] — alternate directory for sound files

Tracing SIP messages and Freeswitch processing for call from external user to internal user .Freeswitch acts as B2BUA

Receives incoming Call INVITE

recv 823 bytes from tcp/[caller_ip]:35365 at 09:55:07.936234:
   ------------------------------------------------------------------------
   INVITE sip:to_number@sometelco.com:5060 SIP/2.0
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport
   Max-Forwards: 70
   Contact: <sip:from_number@192.168.1.23:55934;transport=tcp&gt;
   To: <sip:to_number@sometelco.com:5060&gt;
   From: "from_number"<sip:from_number@sometelco.com:5060&gt;;tag=47a61272
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 INVITE
   Allow: OPTIONS, SUBSCRIBE, NOTIFY, INVITE, ACK, CANCEL, BYE, REFER, INFO
   Content-Type: application/sdp
   Supported: replaces
   User-Agent: X-Lite release 5.4.0 stamp 94385
   Content-Length: 208

   v=0
   o=- 1553248503383592 1 IN IP4 192.168.1.23
   s=X-Lite release 5.4.0 stamp 94385
   c=IN IP4 192.168.1.23
   t=0 0
   m=audio 49874 RTP/AVP 8 101
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-15
   a=sendrecv
   ------------------------------------------------------------------------

checks with ACL for permission and set NAT. Isolate SDP for processing.

New Channel sofia/internal/from_number@sometelco.com:5060 [a8a2003f-5755-40fe-ab63-aab2f5264886]

Running State Change CS_NEW (Cur 1 Tot 274)
receiving invite from caller_ip:35365 version: 1.9.0 -742-8f1b7e0 64bit
IP caller_ip Approved by acl "domains[]". Access Granted.
Setting NAT mode based on nat.auto
Channel sofia/internal/from_number@sometelco.com:5060 entering state [received][100]
Remote SDP:
v=0
o=- 1553248503383592 1 IN IP4 192.168.1.23
s=X-Lite release 5.4.0 stamp 94385
c=IN IP4 192.168.1.23
t=0 0
m=audio 49874 RTP/AVP 8 101
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

mainatin and Updates call-state (switch_core_state_machine ) CS_NEW -> CS_INIT -> CS_ROUTING -> RINGING and send 100 trying to caller

State Change CS_NEW -&gt; CS_INIT
State NEW
Running State Change CS_INIT (Cur 1 Tot 274)
State INIT
SOFIA INIT
Standard INIT
State Change CS_INIT -&gt; CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 1 Tot 274)
Change DOWN -&gt; RINGING
State ROUTING
send 413 bytes to tcp/[caller_ip]:35365 at 09:55:07.937474:
   ------------------------------------------------------------------------
   SIP/2.0 100 Trying
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport=35365;received=caller_ip
   From: "from_number"<sip:from_number@sometelco.com:5060&gt;;tag=47a61272
   To: <sip:to_number@sometelco.com:5060&gt;
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 INVITE
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Content-Length: 0

   ------------------------------------------------------------------------

checks dialplan to route incoming call. In this case action is to bridge the incoming call to internal user

mod_sofia.c:154 sofia/internal/from_number@sometelco.com:5060 SOFIA ROUTING
switch_core_state_machine.c:236 sofia/internal/from_number@sometelco.com:5060 Standard ROUTING

mod_dialplan_xml.c:637 Processing from_number <from_number&gt;-&gt;to_number in context public
Dialplan: sofia/internal/from_number@sometelco.com:5060 parsing [public-&gt;dialplan_cutsom] continue=false
Dialplan: sofia/internal/from_number@sometelco.com:5060 Regex (PASS) [dialplan_cutsom] destination_number(to_number) =~ /^(\d+)$/ break=on-false
Dialplan: sofia/internal/from_number@sometelco.com:5060 Action log(INFO ***** Forwarding calls to gateway ****** ) 
Dialplan: sofia/internal/from_number@sometelco.com:5060 Action bridge({sip_auth_username=user,sip_auth_password=pass,sip_route_uri=sip:to_number@ip_addr;transport=tls,sip_invite_req_uri=sip:to_number@sometelco.com;transport=tls}sofia/external/to_number@ip_addr) 

update call state CS_ROUTING -> CS_EXECUTE

State Change CS_ROUTING -> CS_EXECUTE
State ROUTING going to sleep
Running State Change CS_EXECUTE (Cur 1 Tot 274)
State EXECUTE
SOFIA EXECUTE

set the crypto and codecs for the new call

switch_ivr_originate.c:2159 Parsing global variables
switch_channel.c:1104 New Channel sofia/external/to_number@ip_addr [cc1ae238-9efd-4f51-93e9-05abd48bea4d]
mod_sofia.c:5026 (sofia/external/to_number@ip_addr) State Change CS_NEW -> CS_INIT
switch_core_state_machine.c:584 (sofia/external/to_number@ip_addr) Running State Change CS_INIT (Cur 2 Tot 275)
switch_core_state_machine.c:627 (sofia/external/to_number@ip_addr) State INIT
mod_sofia.c:93 sofia/external/to_number@ip_addr SOFIA INIT
Set Local audio crypto Key [1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU]
Set Local video crypto Key [1 AEAD_AES_256_GCM_8 inline:Ehr3LoDR8Ur+wtNAMqoqIDn3S7V2inE2/n++awxS6/1P2ijcqfk12+LM/Pc]
Set Local text crypto Key [1 AEAD_AES_256_GCM_8 inline:NVSfjOmSS5BaP/5yqg+SOXcqvEFTHHrC8R5AYkkClXLuNOXYoaUYlrIWeW0]
Set Local audio crypto Key [2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ]
Set Local video crypto Key [2 AEAD_AES_128_GCM_8 inline:YWdfNLSx6MqG9WQ3TmsV/cSBDqjRUAbHE0rRCg]
Set Local text crypto Key [2 AEAD_AES_128_GCM_8 inline:DFXOP2V2Ep6FoHNz5HIMrm0cu6Za8I5wOI/hUw]
Set Local audio crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw]
Set Local video crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:LkU3i9MD25k2wtTfSXUvhlxo66GtMWnXkKoxSdgRZyANoeOhufYnXzbXDo+7+w]
Set Local text crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:AUgUOVmFunzotvwZ6KuMDnBRR2XKk1DsX2qg465MsT6OAxHc2qKBFpeQEpxrqA]
Set Local audio crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc]
Set Local video crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:OiFbZQ6mWuf5sHJT1pFPU6EWxEvQAO/0rcp8uGMf79k7RSR3IQA]
Set Local text crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:XyednWJmzRfsWQOgdhKaMeOeE/OLmnwo6hVEZWl4OJdKdgK6TVc]
Set Local audio crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2]
Set Local video crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:ImgbbD6cnhnH19O1knP5SSIUULsZTaNJJIUepxt0]
Set Local text crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:V7+IbSZmTdQNjh/upUZ5TFDSlgarhDTVfV+AcUA+]
Set Local audio crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ]
Set Local video crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:MX6CGCrMEioUCJsIOCxRqlHOx4mUYRw4DslpY25njZQAkH6MgG/9hp7G8xr44A]
Set Local text crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:ikCz2sYLGoMO+dlrZj+znlQ3djAkGSYzSLLu6Az8u2THWPgnkFJXVgXSxHOaHw]
Set Local audio crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ]
Set Local video crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:K0dZtwH1Q7AuSMBPPUesy047c4nAF+QuFsVvGdf3fYJDOD0Uwxo]
Set Local text crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:96SwyWAdV1a+BU3UbiX1PHdkRlSS4RtmwPWNPbCR3NDm1MyBh58]
Set Local audio crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG]
Set Local video crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:mQlgScFq1iMKEW8vobzwhmN9TWSmVblAv9u7c1/c]
Set Local text crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:WAQveMfrQkPBcfqH2qLmuzY63VLfT+N30/YLyuqE]
Set Local audio crypto Key [9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K]
Set Local video crypto Key [9 AES_CM_128_NULL_AUTH inline:qpAkfc1bWnZ0Y/1ql+dNvhIGgxxWZoVltnRD5kqn]
Set Local text crypto Key [9 AES_CM_128_NULL_AUTH inline:LyhSlzI3X38WKPwZ83035Ddvse4J/2KnKoydo2FD]

set proxy route and create SDP for sending invite to bridged client

sofia_glue.c:1268 sip:to_number@ip_addr;transport=tls Setting proxy route to sofia/external/to_number@ip_addr
sofia_glue.c:1299 sofia/external/to_number@ip_addr sending invite version: 1.9.0 -742-8f1b7e0 64bit
Local SDP:
v=0
o=FreeSWITCH 1553228435 1553228436 IN IP4 via_addr
s=FreeSWITCH
c=IN IP4 via_addr
t=0 0
m=audio 20072 RTP/SAVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=crypto:1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU
a=crypto:2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ
a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw
a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc
a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2
a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ
a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ
a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG
a=crypto:9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K
a=ptime:20
a=sendrecv
m=audio 20072 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv

attach the SDP to INVITE and proceed forwarding INVITE to callee

send 1988 bytes to tls/[ip_addr]:5061 at 09:55:07.939831:
   ------------------------------------------------------------------------
   INVITE sip:to_number@sometelco.com;transport=tls SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK21Qm9U3eHX0Nc
   Max-Forwards: 69
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 INVITE
   Contact: <sip:mod_sofia@via_addr:5080&gt;
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 1162
   X-FS-Support: update_display,send_info
   Remote-Party-ID: "from_number" <sip:from_number@via_addr&gt;;party=calling;screen=yes;privacy=off

   v=0
   o=FreeSWITCH 1553228435 1553228436 IN IP4 via_addr
   s=FreeSWITCH
   c=IN IP4 via_addr
   t=0 0
   m=audio 20072 RTP/SAVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=crypto:1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU
   a=crypto:2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw
   a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc
   a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2
   a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ
   a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ
   a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG
   a=crypto:9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K
   a=ptime:20
   m=audio 20072 RTP/AVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=ptime:20
   ------------------------------------------------------------------------

manage and update call state for this call leg too CS_INIT -> CS_ROUTING -> CS_CONSUME_MEDIA

Standard INIT
State Change CS_INIT -&gt; CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 2 Tot 275)
Channel sofia/external/to_number@ip_addr entering state [calling][0]
State ROUTING
SOFIA ROUTING
State Change CS_ROUTING -&gt; CS_CONSUME_MEDIA
State ROUTING going to sleep
Running State Change CS_CONSUME_MEDIA (Cur 2 Tot 275)
State CONSUME_MEDIA
State CONSUME_MEDIA going to sleep
recv 365 bytes from tls/[ip_addr]:5061 at 09:55:07.940977:
   ------------------------------------------------------------------------
   SIP/2.0 100 trying -- your call is important to us
   Via: SIP/2.0/TLS via_addr:5080;rport=59774;branch=z9hG4bK21Qm9U3eHX0Nc;received=via_addr
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 INVITE
   Server: ZenTrunk
   Content-Length: 0

   ------------------------------------------------------------------------

Callee from PBX throws auth challenge

recv 483 bytes from tls/[ip_addr]:5061 at 09:55:08.046934:
   ------------------------------------------------------------------------
   SIP/2.0 407 Proxy Authentication Required
   Via: SIP/2.0/TLS via_addr:5080;received=via_addr;rport=59774;branch=z9hG4bK21Qm9U3eHX0Nc
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;;tag=f1cff938000510c1d9006e5a2a4e240b-5736
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 INVITE
   Proxy-Authenticate: Digest realm="domain.com", nonce="XJSyI1yUsPf0w1bAocvH4IOCayfWt3bX", qop="auth"
   Content-Length: 0

   ------------------------------------------------------------------------
send 387 bytes to tls/[ip_addr]:5061 at 09:55:08.047056:
   ------------------------------------------------------------------------
   ACK sip:to_number@sometelco.com;transport=tls SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK21Qm9U3eHX0Nc
   Max-Forwards: 69
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;;tag=f1cff938000510c1d9006e5a2a4e240b-5736
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070461 ACK
   Content-Length: 0

   ------------------------------------------------------------------------

calleer sends re-invit with auth details

Authenticating 'altanai' with 'Digest:"doamin.com":altanai:pass'.
send 2273 bytes to tls/[ip_addr]:5061 at 09:55:08.047387:
   ------------------------------------------------------------------------
   INVITE sip:to_number@sometelco.com;transport=tls SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK3aHDBQmje6p8Q
   Max-Forwards: 69
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 INVITE
   Contact: <sip:mod_sofia@via_addr:5080&gt;
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Proxy-Authorization: Digest username="altanai", realm="domain.com", nonce="XJSyI1yUsPf0w1bAocvH4IOCayfWt3bX", cnonce="apLWcMcrEjerigKpM7MtoA", algorithm=MD5, uri="sip:to_number@sometelco.com;transport=tls", response="0044b00a4d5026252b32eed619d70f9d", qop=auth, nc=00000001
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 1162
   X-FS-Support: update_display,send_info
   Remote-Party-ID: "from_number" <sip:from_number@via_addr&gt;;party=calling;screen=yes;privacy=off

   v=0
   o=FreeSWITCH 1553228435 1553228436 IN IP4 via_addr
   s=FreeSWITCH
   c=IN IP4 via_addr
   t=0 0
   m=audio 20072 RTP/SAVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=crypto:1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU
   a=crypto:2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw
   a=crypto:4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc
   a=crypto:5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2
   a=crypto:6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ
   a=crypto:7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ
   a=crypto:8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG
   a=crypto:9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K
   a=ptime:20
   m=audio 20072 RTP/AVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=ptime:20
   ------------------------------------------------------------------------
2019-03-22 09:55:08.041945 [DEBUG] sofia.c:7291 Channel sofia/external/to_number@ip_addr entering state [calling][0]
recv 365 bytes from tls/[ip_addr]:5061 at 09:55:08.048255:
   ------------------------------------------------------------------------
   SIP/2.0 100 trying -- your call is important to us
   Via: SIP/2.0/TLS via_addr:5080;rport=59774;branch=z9hG4bK3aHDBQmje6p8Q;received=via_addr
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 INVITE
   Server: ZenTrunk
   Content-Length: 0

   ------------------------------------------------------------------------

Call is accepted by callee , 200 OK is received by Freeswitch PBX

recv 1451 bytes from tls/[ip_addr]:5061 at 09:55:14.223460:
   ------------------------------------------------------------------------
   SIP/2.0 200 OK
   Via: SIP/2.0/TLS via_addr:5080;received=via_addr;rport=59774;branch=z9hG4bK3aHDBQmje6p8Q
   Record-Route: <sip:3.92.18.95:5060;lr;ftag=8jByBXa2pF1Fj&gt;
   Record-Route: <sip:18.205.1.67;lr;ftag=8jByBXa2pF1Fj;did=fd.0971&gt;
   Record-Route: <sip:ip_addr:5060;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes&gt;
   Record-Route: <sip:ip_addr:5061;transport=tls;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes&gt;
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;;tag=D0r5K6pp80Ujm
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 INVITE
   Contact: <sip:to_number@34.201.27.78:5080;transport=udp&gt;
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, refer
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 380
   Remote-Party-ID: "to_number" <sip:to_number@34.201.27.78&gt;;party=calling;privacy=off;screen=no

   v=0
   o=FreeSWITCH 1553215954 1553215955 IN IP4 18.212.123.47
   s=FreeSWITCH
   c=IN IP4 18.212.123.47
   t=0 0
   m=audio 33516 RTP/SAVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=sendrecv
   a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==
   a=ptime:20
   m=audio 0 RTP/SAVP 19
   a=rtpmap:19 
   ------------------------------------------------------------------------

send ACK to callee

Update Callee ID to "to_number" <to_number&gt;
Channel sofia/external/to_number@ip_addr entering state [completing][200]
sofia.c:7301 Remote SDP:
v=0
o=FreeSWITCH 1553215954 1553215955 IN IP4 18.212.123.47
s=FreeSWITCH
c=IN IP4 18.212.123.47
t=0 0
m=audio 33516 RTP/SAVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=crypto:3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==
a=ptime:20
m=audio 0 RTP/SAVP 19

send 953 bytes to tls/[ip_addr]:5061 at 09:55:14.224320:
   ------------------------------------------------------------------------
   ACK sip:to_number@34.201.27.78:5080;transport=udp SIP/2.0
   Via: SIP/2.0/TLS via_addr:5080;rport;branch=z9hG4bK4Ka6cj5NBFDUK
   Route: <sip:ip_addr:5061;transport=tls;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes&gt;
   Route: <sip:ip_addr:5060;r2=on;lr;ftag=8jByBXa2pF1Fj;nat=yes&gt;
   Route: <sip:18.205.1.67;lr;ftag=8jByBXa2pF1Fj;did=fd.0971&gt;
   Route: <sip:3.92.18.95:5060;lr;ftag=8jByBXa2pF1Fj&gt;
   Max-Forwards: 70
   From: "from_number" <sip:from_number@via_addr&gt;;tag=8jByBXa2pF1Fj
   To: <sip:to_number@ip_addr&gt;;tag=D0r5K6pp80Ujm
   Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
   CSeq: 2070462 ACK
   Contact: <sip:mod_sofia@via_addr:5080&gt;
   Proxy-Authorization: Digest username="altanai", realm="domain.com", nonce="XJSyI1yUsPf0w1bAocvH4IOCayfWt3bX", cnonce="apLWcMcrEjerigKpM7MtoA", algorithm=MD5, uri="sip:to_number@sometelco.com;transport=tls", response="0044b00a4d5026252b32eed619d70f9d", qop=auth, nc=00000001
   Content-Length: 0

   ------------------------------------------------------------------------

set audio codecs, update call state CS_CONSUME_MEDIA -> CS_EXCHANGE_MEDIA

entering state [ready][200]
looking for crypto suite [AEAD_AES_256_GCM_8] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
looking for crypto suite [AEAD_AES_128_GCM_8] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
looking for crypto suite [AES_CM_256_HMAC_SHA1_80] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
Found suite AES_CM_256_HMAC_SHA1_80
Set Remote Key [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
Set telephone-event payload to 101@8000
Set Codec sofia/external/to_number@ip_addr PCMA/8000 20 ms 160 samples 64000 bits 1 channels
sofia/external/to_number@ip_addr Original read codec set to PCMA:8
Set telephone-event payload to 101@8000
sofia/external/to_number@ip_addr Set 2833 dtmf send payload to 101 recv payload to 101
AUDIO RTP [sofia/external/to_number@ip_addr] 10.130.74.15 port 20072 -> 18.212.123.47 port 33516 codec: 8 ms: 20
Starting timer [soft] 160 bytes per 20ms
Set 2833 dtmf send payload to 101
Set 2833 dtmf receive payload to 101
Set rtp dtmf delay to 40
Activating audio Secure RTP SEND
srtp:sdes:AES_CM_256_HMAC_SHA1_80
Activating audio Secure RTP RECV
srtp:sdes:AES_CM_256_HMAC_SHA1_80
has been answered
Callstate Change DOWN -> ACTIVE
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMU:0:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
Set telephone-event payload to 101@8000
Set Codec sofia/internal/from_number@sometelco.com:5060 PCMA/8000 20 ms 160 samples 64000 bits 1 channels
sofia/internal/from_number@sometelco.com:5060 Original read codec set to PCMA:8
Set telephone-event payload to 101@8000
sofia/internal/from_number@sometelco.com:5060 Set 2833 dtmf send payload to 101 recv payload to 101
AUDIO RTP [sofia/internal/from_number@sometelco.com:5060] 10.130.74.15 port 29426 -> 192.168.1.23 port 49874 codec: 8 ms: 20
Starting timer [soft] 160 bytes per 20ms
Set 2833 dtmf send payload to 101
Set 2833 dtmf receive payload to 101
Set rtp dtmf delay to 40

send early media/ RTP to Callee

 Pre-Answer sofia/internal/from_number@sometelco.com:5060!
 Callstate Change RINGING -> EARLY
 2019-03-22 09:55:14.221933 [DEBUG] switch_core_media.c:8147 Audio params are unchanged for sofia/internal/from_number@sometelco.com:5060.
 2019-03-22 09:55:14.221933 [DEBUG] mod_sofia.c:881 Local SDP sofia/internal/from_number@sometelco.com:5060:
 v=0
 o=FreeSWITCH 1553219088 1553219089 IN IP4 via_addr
 s=FreeSWITCH
 c=IN IP4 via_addr
 t=0 0
 m=audio 29426 RTP/AVP 8 101
 a=rtpmap:8 PCMA/8000
 a=rtpmap:101 telephone-event/8000
 a=fmtp:101 0-16
 a=ptime:20
 a=sendrecv
Pre-Answer sofia/internal/from_number@sometelco.com:5060!
Callstate Change RINGING -&gt; EARLY
2019-03-22 09:55:14.221933 [DEBUG] switch_core_media.c:8147 Audio params are unchanged for sofia/internal/from_number@sometelco.com:5060.
2019-03-22 09:55:14.221933 [DEBUG] mod_sofia.c:881 Local SDP sofia/internal/from_number@sometelco.com:5060:
v=0
o=FreeSWITCH 1553219088 1553219089 IN IP4 via_addr
s=FreeSWITCH
c=IN IP4 via_addr
t=0 0
m=audio 29426 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv

send 1254 bytes to tcp/[caller_ip]:35365 at 09:55:14.232934:
   ------------------------------------------------------------------------
   SIP/2.0 200 OK
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport=35365;received=caller_ip
   From: "from_number"<sip:from_number@sometelco.com:5060&gt;;tag=47a61272
   To: <sip:to_number@sometelco.com:5060&gt;;tag=NjvKFKQaHp52e
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 INVITE
   Contact: <sip:to_number@via_addr:5060;transport=tcp&gt;
   User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
   Accept: application/sdp
   Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, PUBLISH, SUBSCRIBE
   Supported: timer, path, replaces
   Allow-Events: talk, hold, conference, presence, as-feature-event, dialog, line-seize, call-info, sla, include-session-description, presence.winfo, message-summary, refer
   Session-Expires: 120;refresher=uas
   Content-Type: application/sdp
   Content-Disposition: session
   Content-Length: 220
   Remote-Party-ID: "to_number" <sip:to_number@sometelco.com&gt;;party=calling;privacy=off;screen=no

   v=0
   o=FreeSWITCH 1553219088 1553219089 IN IP4 via_addr
   s=FreeSWITCH
   c=IN IP4 via_addr
   t=0 0
   m=audio 29426 RTP/AVP 8 101
   a=rtpmap:8 PCMA/8000
   a=rtpmap:101 telephone-event/8000
   a=fmtp:101 0-16
   a=ptime:20
   ------------------------------------------------------------------------
entering state [completed][200]
Channel [sofia/internal/from_number@sometelco.com:5060] has been answered
Callstate Change EARLY -&gt; ACTIVE
Originate Resulted in Success: [sofia/external/to_number@ip_addr]
State Change CS_CONSUME_MEDIA -&gt; CS_EXCHANGE_MEDIA
Running State Change CS_EXCHANGE_MEDIA (Cur 2 Tot 275)
State EXCHANGE_MEDIA
SOFIA EXCHANGE_MEDIA
recv 507 bytes from tcp/[caller_ip]:35365 at 09:55:14.459247:
   ------------------------------------------------------------------------
   ACK sip:to_number@via_addr:5060;transport=tcp SIP/2.0
   Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---104aee5ed0b7ca66;rport
   Max-Forwards: 70
   Contact: <sip:from_number@192.168.1.23:55934;transport=tcp&gt;
   To: <sip:to_number@sometelco.com:5060&gt;;tag=NjvKFKQaHp52e
   From: "from_number"<sip:from_number@sometelco.com:5060&gt;;tag=47a61272
   Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
   CSeq: 1 ACK
   User-Agent: X-Lite release 5.4.0 stamp 94385
   Content-Length: 0

   ------------------------------------------------------------------------

Sip server Brekeke

We used Brekeke SIP server to run our SIP applications . Although there are newer versions of Brekeke SIP server out now . More awesome than before , we prefer using the old one for the sake of not messing with legacy SIP applications . The official site for brekeke is – http://www.brekeke.com/sip/ .

A general architecture of Brekeke SIP server is . brekeke

Here are the steps of installing and configuring a Brekeke SIP server .

Step 1: Download the Server form http://www.brekeke.com/sip/ and run the setup file .

brekeke0

brekeke01

brekeke1

brekeke8

brekek2 brekek3 brekek6

brekeke4 brekeke5 brekeke7  brekeke9

Step 2: It is always good to give a look to README file . brekeke11

Step 3: Run the local implementation of SIP server at localhost or 127.0.0.1 at port 8080brekeke12

Step 4: Important is to get the license which will help us activate the SIP server . One can obtain a free license from http://www.brekeke.com/downloads/sip-server-trial-license.phpbrekeke12_001

Step 5 : Once the license is activates , we can goto the console screen after loggin with default username and password sa . brekeke13

Step 6 : Once we are at console , we could add/ delete / modify parameters like port , start/shutdown status etc . brekeke14 brekeke14_001Step 7 : Once the server is all setup , just add the IP and port of SIP server to SIP clients server filed . Now all the SIP request and response will be catered by this SIP Server

Kamailio Architecture , Core and Modules

Post has been edited after publishing with updated content and Kamailio modules .

Introduction to Kamailio and its role in telephony is covered here . This article just describes the structure of kamailio source code , core and its associated modules which define the behaviour of machine.

kamailio architecture

Core

The core includes:

memory manager
SIP message parser
locking system
DNS and transport layer management (UDP, TCP, TLS, SCTP)
configuration file parser and interpreter
stateless forwarding
pseudo-variables and transformations engines
RPC control interface API
timer API

The internal libraries include:

components from old Kamailio cores
database abstraction layers (DB API v1 and v2)
management interface (MI) API
statistics engine

Modules

there over 150 modules in kamailio delaing with various feature areas that can be catagorised as below

  • registrar and user location management
  • accounting, authorization and authentication
  • text and regular expression operations
  • stateless replying
  • stateful processing – SIP transaction management
  • SIP dialogs tracking – active calls management
  • instant messaging and presence extensions
  • RADIUS and LDAP support
  • SQL and no-SQL database connectors
  • MI and RPC transports
  • Enum, GeoIP API and CPL interpreter
  • topology hiding and NAT traversal
  • load balancing and least cost routing
  • asynchronous SIP request processing
  • interactive configuration file debugger
  • Lua, Perl, Python and Java SIP Servlet extensions

Locking Management

Kamailio provides a custom locking system its root element is a mutex semaphore, that can be set (locked) or unset (unlocked).
locking.h lib provides the functionality in C code.

Simple Locks API

gen_lock_t
lock_alloc(…)
lock_dealloc(…)
lock_init(…)
lock_destroy(…)
lock_get(…)
lock_try(…)
lock_release(…)

Lock Set API

gen_lock_set_t
lock_set_alloc(…)
lock_set_dealloc(…)
lock_set_init(…)
lock_set_destroy(…)
lock_set_get(…)
lock_set_release(…)

A problem however with locks is that processes can eat a lot of CPU. Locking issues also occur when locks are set but not unset resulting in no more SIP messages being processed. Hence Kamailio uses gdb with PID and get backtraces to the lock that wasnt released .

gdb /path/to/kamailio PID
gdb> bt

Memory Manager

Multliple processes run simultenously within kamailio server, hence it bears private and shared memeories to facailitate their working.
One can increase shared memory using -m and private memory using -M command line option.

Private Memory

Since this is specific per process, no synchronization is needed to access structures allocated in it, such as varaible not needed by pther process or ones for temporary operations. provate memory manager is accessed via mem/mem.h.

pkg_malloc(…)
pkg_free(…)
pkg_realloc(…)

Shared Memory

the data stored in shared memeory is visible in all Kamailio modules such as user location , TM structures for stateful processing, routing rules for the dispatcher etc. shared memeory can be acceses via mem/shm_mem.h. Here locks are used to prvent race conditions.

shm_malloc(…)
shm_free(…)
shm_realloc(…)

Problems in memory management can occur due to :
Out of memory by allocating memory at runtime and not freeing it afterwards , called memory leaks
writing more than allocated for that structure, called segmentation fault.

Data Structures

str
struct sip_uri
struct sip_msg
struct msg_start
struct hdr_field
struct to_body
struct via_body

SIP Parser

kamailio has an incremental parser. Lib file for SIP message parsing is parser/msg_parser.c with the corresponding header file parser/msg_parser.h.

parse_uri(…)
parse_msg(…)
parse_headers(…)
parse_to(…)


Since kamailio has a modular architecture with core components and modules to extend the functionality, this article will be discussing few of the essential modules in Kamailio. Specific modules Discussed in this Article :

  • UserLoc
  • Registrar
  • Dialog
  • UAC
  • XHTTP
  • Websocket

Few categories of modules discoverable via apt-cache search kamailio

  • kamailio – very fast and configurable SIP proxy
  • kamailio-autheph-modules – authentication using ephemeral credentials module for Kamailio
  • kamailio-berkeley-bin – Berkeley database module for Kamailio – helper program
  • kamailio-berkeley-modules – Berkeley database module for Kamailio
  • kamailio-carrierroute-modules – carrierroute module for Kamailio
  • kamailio-cnxcc-modules – cnxcc modules for Kamailio
  • kamailio-cpl-modules – CPL module (CPL interpreter engine) for Kamailio
  • kamailio-dbg – very fast and configurable SIP proxy [debug symbols]
  • kamailio-dnssec-modules – contains the dnssec module
  • kamailio-erlang-modules – earlang modules for Kamailio
  • kamailio-extra-modules – extra modules for Kamailio
  • kamailio-geoip-modules – contains the geoip module
  • kamailio-ims-modules – IMS module for Kamailio
  • kamailio-java-modules – contains the app_java module
  • kamailio-json-modules – Json parser and jsonrpc modules for Kamailio
  • kamailio-kazoo-modules – kazoo modules for Kamailio
  • kamailio-ldap-modules – LDAP modules for Kamailio
  • kamailio-lua-modules – contains the app_lua module
  • kamailio-memcached-modules – interface to memcached server
  • kamailio-mono-modules – contains the app_mono module
  • kamailio-mysql-modules – MySQL database connectivity module for Kamailio
  • kamailio-outbound-modules – Outbound module for Kamailio
  • kamailio-perl-modules – Perl extensions and database driver for Kamailio
  • kamailio-postgres-modules – PostgreSQL database connectivity module for Kamailio
  • kamailio-presence-modules – SIMPLE presence modules for Kamailio
  • kamailio-purple-modules – Provides the purple module, a multi-protocol IM gateway
  • kamailio-python-modules – contains the app_python module
  • kamailio-radius-modules – RADIUS modules for Kamailio
  • kamailio-redis-modules – Redis database connectivity module for Kamailio
  • kamailio-sctp-modules – sctp module for Kamailio
  • kamailio-snmpstats-modules – SNMP AgentX subagent module for Kamailio
  • kamailio-sqlite-modules – SQLite database connectivity module for Kamailio
  • kamailio-tls-modules – contains the TLS kamailio transport module
  • kamailio-unixodbc-modules – unixODBC database connectivity module for Kamailio
  • kamailio-utils-modules – Provides a set utility functions for Kamailio
  • kamailio-websocket-modules – Websocket module for kamailio
  • kamailio-xml-modules – XML based extensions for Kamailio’s Management Interface
  • kamailio-xmpp-modules – XMPP gateway module for Kamailio

The first set under explanation is Usrloc and Register module which take care of user persistance in Database and handling an incoming register request with authentication and validation.

The first set under explanation is Usrloc and Register module which take care of user persistance in Database and handling an incoming register request with authentication and validation.

Usrloc Module

keeps a user location table and provides access to the table for other modules

Parameters:

  • nat_bflag
  • user_column
  • domain_column
  • contact_column
  • expires_column
  • q_column
  • callid_column
  • cseq_column
  • methods_column
  • flags_column
  • cflags_column
  • user_agent_column
  • received_column
  • socket_column
  • path_column
  • ruid_column
  • instance_column
  • server_id_column
  • connection_id_column
  • keepalive_column
  • partition_column
  • use_domain
  • desc_time_order
  • timer_interval
  • db_url
  • db_mode
  • db_load
  • db_insert_update
  • matching_mode
  • cseq_delay
  • fetch_rows
  • hash_size
  • preload
  • db_update_as_insert
  • db_check_update
  • timer_procs
  • xavp_contact
  • db_ops_ruid (int)
  • handle_lost_tcp (int)
  • close_expired_tcp (int)
  • expires_type (int)
  • db_raw_fetch_type (int)
  • db_insert_null (int)
  • skip_remote_socket (int)
  • db_timer_clean (int)
  • server_id_filter (int)

RPC Commands

ul.dump
ul.lookup table AOR
ul.rm table AOR
ul.rm_contact table AOR contact
ul.flush
ul.add
ul.db_users
ul.db_contacts
ul.db_expired_contacts

Statistics

users
contacts
expires
registered_users

Functions

ul_register_domain(name)
ul_insert_urecord(domain, aor, rec)
ul_delete_urecord(domain, aor)
ul_delete_urecord_by_ruid(domain, ruid)
ul_get_urecord(domain, aor)
ul_lock_udomain(domain)
ul_unlock_udomain(domain)
ul_release_urecord(record)
ul_insert_ucontact(record, contact, expires, q, callid, cseq, flags, cont, ua, sock)
ul_delete_ucontact (record, contact)
ul_get_ucontact(record, contact)
ul_get_all_ucontacts (buf, len, flags)
ul_update_ucontact(contact, expires, q, callid, cseq, set, res, ua, sock)
ul_bind_ursloc( api )
ul_register_ulcb(type ,callback, param)
ul_get_num_users()

Registrar Module

SIP registration processing logic can be defined here .

Path support – off , lazy , strict ( RFC 3327)

GRU ( Globally Routbale User agent URIs)  support –  public , temporary ( RFC 5627)

Dependencies :

  • usrloc – User Location Module.
  • sl – Stateless Replies.

Parameters :

  • default_expires
  • default_expires_range
  • expires_range
  • min_expires
  • max_expires
  • default_q
  • realm_prefix
  • append_branches
  • aor_avp (str)
  • case_sensitive
  • received_avp (str)
  • received_param
  • max_contacts
  • retry_after
  • sock_flag
  • sock_hdr_name
  • method_filtering
  • use_path
  • path_mode
  • path_use_received
  • path_check_local
  • reg_callid_avp
  • xavp_cfg
  • xavp_rcd
  • gruu_enabled
  • outbound_mode
  • regid_mode
  • flow_timer
  • contact_max_size

Functions :

save(domain, [, flags [, uri]])
lookup(domain [, uri])
lookup_branches(domain)
registered(domain [, uri [, match_option [, match_action]]])
add_sock_hdr(hdr_name)
unregister(domain, uri[, ruid])
reg_fetch_contacts(domain, uri, profile)
reg_free_contacts(profile)

Event Routes :

event_route[usrloc:contact-expired]

Statistics :

max_expires
max_contacts
default_expires
accepted_regs
rejected_regs

Ref : http://kamailio.org/docs/modules/stable/modules/registrar.html

Dialog Module

We know that dialog represent the p2p relationship between 2 sip clients and contains sequence of transactions along with routing information and facilitate sequencing of more messages

Keep track of current dialogs also provides API support . It can be loaded and used like given below .

loadmodule "dialog.so"
..

# ---- dialog params ----
modparam("dialog", "enable_stats", 1)
modparam("dialog", "dlg_flag", 4)
modparam("dialog", "event_callback", "ksr_dialog_event")

Parameters :

  • enable_stats (integer)
  • hash_size (integer)
  • rr_param (string)
  • dlg_flag (integer)
  • timeout_avp (string)
  • default_timeout (integer)
  • early_timeout (integer)
  • noack_timeout (integer)
  • end_timeout (integer)
  • dlg_extra_hdrs (string)
  • dlg_match_mode (integer)
  • detect_spirals (integer)
  • db_url (string)
  • db_mode (integer)
  • db_update_period (integer)
  • db_fetch_rows (integer)
  • db_skip_load (integer)
  • table_name (string)
  • call_id_column (string)
  • from_uri_column (string)
  • from_tag_column (string)
  • to_uri_column (string)
  • to_tag_column (string)
  • from_cseq_column (string)
  • to_cseq_column (string)
  • from_route_column (string)
  • to_route_column (string)
  • from_contact_column (string)
  • to_contact_column (string)
  • from_sock_column (string)
  • to_sock_column (string)
  • h_id_column (string)
  • h_entry_column (string)
  • state_column (string)
  • start_time_column (string)
  • timeout_column (string)
  • sflags_column (string)
  • toroute_name_column (string)
  • vars_table_name (string)
  • vars_h_id_column (string)
  • vars_h_entry_column (string)
  • vars_key_column (string)
  • vars_value_column (string)
  • profiles_with_value (string)
  • profiles_no_value (string)
  • bridge_controller (string)
  • bridge_contact (string)
  • initial_cbs_inscript (int)
  • send_bye (int)
  • wait_ack (int)
  • ka_timer (int)
  • ka_interval (int)
  • ka_failed_limit (int)
  • timeout_noreset (int)
  • timer_procs (int)
  • enable_dmq (int)
  • track_cseq_updates (int)
  • lreq_callee_headers (string)
  • event_callback (str) –
  • name of the function in the kemi configuration file (embedded scripting language such as Lua, Python, …) to be executed instead of event_route[…] blocks. The function receives a string parameter with the name of the event, the values are: ‘dialog:start’, ‘dialog:end’, ‘dialog:failed’. It is also executed if ‘$dlg_ctx(timeout_route)’ is set
function ksr_dialog_event(evname)
KSR.info("===== dialog module triggered event: " .. evname .. "\n");
if (evname == "dialog:end") or (evname == "dialog:failed") then
logger.log("info", "in dialog event callback with event-name - " .. evname .. " start CDR process ")
if not cdrProcess.post() then
logger.log("err", "Failed")
else
logger.log("info", "successfully posted")
core.exit()
end
end
end
  • h_id_start (int)
  • h_id_step (int)

Functions :

set_dlg_profile(profile,[value])
unset_dlg_profile(profile,[value])
is_in_profile(profile,[value])
get_profile_size(profile,[value],size)
dlg_isflagset(flag)
dlg_setflag(flag)
dlg_resetflag(flag)
dlg_bye(side)
dlg_refer(side, address)
dlg_manage()
dlg_bridge(from, to, op)
dlg_get(callid, ftag, ttag)
is_known_dlg()
dlg_set_timeout(timeout [, h_entry, h_id])
dlg_set_timeout_by_profile(profile, [value], timeout)
dlg_set_property(attr)
dlg_remote_profile(cmd, profile, value, uid, expires)
dlg_set_ruri()

Statistics :

active_dialogs
early_dialogs
processed_dialogs
expired_dialogs
failed_dialogs

RPC Commands :

dlg.list
dlg.list_ctx
dlg.dlg_list
dlg.dlg_list_ctx
dlg.terminate_dlg
dlg.end_dlg
dlg.profile_get_size
dlg.profile_list
dlg.bridge_dlg

Exported Variables :

$DLG_count
$DLG_status
$DLG_lifetime
$dlg(…)
$dlg_ctx(…)
$dlg_var(key)

Event Routes :

event_route[dialog:start] , event_route[dialog:end] , event_route[dialog:failed]

UAC module

This set deals with RTP proxy and RTP engine which are used for proxing media streams via kamailio server .


This set deals with HTTP and Websocket adapters to handle web pone based ( such as webRTC) calls on kamailio

XHTTP

Provides basic HTTP/1.0 server functionality .

SIP requires a Content-Length header for TCP transport. But most HTTP clients do not set the content length for normal GET requests. Therefore, the core must be configured to allow incoming requests without content length header:

tcp_accept_no_cl=yes

Parameters :

url_skip : if there is a match , event route is not executed
modparam(“xhttp”, “url_skip”, “^/RPC2”)

url_match : if there is no match , event route is not executed
modparam(“xhttp”, “url_match”, “^/sip/”)

event_Callback : function in the kemi configuration file (embedded scripting language such as Lua, Python) to be executed instead of event_route[xhttp:request] block
Example :
modparam(“xhttp”, “event_callback”, “ksr_xhttp_event”)
and the event callback function implemented in Lua
function ksr_xhttp_event(evname)
KSR.info(“===== xhttp module triggered event: ” .. evname .. “\n”);
return 1;
end

Function

xhttp_reply(code, reason, ctype, body) – Send back a reply with content-type and body.

event_route[xhttp:request] {
xhttp_reply("200", "OK", "" , "");
or 
xhttp_reply("403", "Forbidden", "", "");
}

Event Routes

xhttp:request
The event route is executed when a new HTTP request is received.

event_route[xhttp:request] {
xhttp_reply(“200”, “OK”, “text/html”, “<html><body>OK – [$si:$sp]</body></html>”);
}

Websocket Module

provide websocket ( ws and wss) support to kamailio ( RFC 6455). Handles handshaking, management (including connection keep-alive), and framing for the SIP and MSRP WebSocket sub-protocols (RFC 7118 and RFC 7977).

-tbd

IPTV ( Internet Based Television )

We know the power of Internet protocol suit as it takes on the world of telecom . Alreday half of Communication has been transferred from legacy telecom signalling protocols like SS7 to IP based communication ( Skype , Hangouts , whatsapp , facebook call ) . The TV service providers too are largely investing in IP based systems like SIP and IMS to deliver their content over Telecom’s IP based network ( Packet switched ).

A consumer today wants HD media content anytime anywhere . The traditional TV solutions just dont match upto the expectations anymore . The IPTV provider in todays time must make investments to deliver content that is media-aware, and device-aware. Not only this it should be  personal, social, and interactive . after all its all about user  experience.

Few popular applications for IPTV solutions developers are

  • Menu overlay with detailed description of channels , categories , programs , movies
  • Replay option also referred to as timeshift . It allows a user to pause , resume and  record the show in his absence and view it later
  • Video on demand which concerns paying and viewing music albums , movies etc on demand
  • Live streaming of events such as president speech , tennis match etc .

Application that can be build around the IPTV context

  • Record and Playback content
  • Information overlay on streaming content
  • Social networking services integrated with IPTV content
  • Parental Control to realtime view , monitor and control what your child is watching on the IPTV
  • Watch the surveillance  footage from IP cameras anywhere
  • Real time communication on IPTV  with advanced features like call continuity , content sync .

Telephony Solutions with Kamailio

Kamailio™ (former OpenSER) is an Open Source SIP Server released under GPL.

Kamailio primarily acts as a SIP server for VOIP and telecommunications platforms under various roles and can handle load of hight CPS ( Calls per second ) with custom call routing logic with the help of scripts .

Rich features set suiting to telephony domain that includes IMS extensions for VoLTE; ENUM; DID and least cost routing; load balancing; routing fail-over; Json and XMLRPC control interface, SNMP monitoring.

To integrate with a carrier grade telecom network as SBC / gateway / inbound/outbound proxy , it can act as IPv4-IPv6 gateway , UDP/TCP/SCTP/WS translator and even had NAT and anti DOS attack support .

If Kamailio is the central to the VoIP system it can also perform accounting with rich database extensions Mysql PostgreSQL UnixODBC Berkeley DB Oracle Redis, MongoDB Cassandra etc

  • Kamailio is SIP (RFC3261) compliant

It can work as Registrar or Location server. For SIP call logic it can become a Proxy or SIP Application server. Can also act like a Redirect , Dispatcher or simply a SIP over websocket server.

  • Kamailio is Customisable to suit business requirement and scale .

It can be embedded to devices as the binary file is small size. Additional modules can be appended for more functions with the same core.

Due to its modular architecture – core, internal libraries , module interface and ability to extend functionality with scripts such as LUA , Kamailio can be readily integrated to a VOIP ecosystem.

  • Call routing and control with Scripting and programming

Offers stateless and transactional stateful SIP Proxy processing ( suited for inbound gateways ) and serial and parallel forking.

Also NAT traversal support for SIP and RTP traffic ( suited to be WebRTC server )

Among other features it offers load balancing with many distribution algorithms and failover support , flexible least cost routing , routing failover and replication for High Availability (HA).

Can be readily integrated with external databases , caches, notification system ( SNS , APNS , GCM ), voip monitors , CDR processors, API systems etc for  efficient call processing.

  • Transport Layers supported 

    • UDP, TCP, TLS and SCTP
    • IPv4 and IPv6
    • gateways via (IPv4 to IPv6, UDP to TLS, a.s.o.)
    • SCTP multi-homing and multi-streaming
    • WebSocket for WebRTC 
  • Asynchronous TCP, UDP and SCTP,

asynchronous SIP message processing and  inter-process message queues communication system

  • Secure Communication ( TLS  + AAA)

    • Digest SIP User authentication
    • Authorization via ACL or group membership
    • IP and Network authentication
    • TLS support for SIP signaling
    • transparent handling of SRTP for secure audio
    • TLS domain name extension support
    • authentication and authorization against database (MySQL, PostgreSQL, UnixODBC, BerkeleyDB, Oracle, text files), RADIUS and DIAMETER
  • IP and DNS

    • support for SRV and NAPTR DNS lookups
    • SRV DNS failover
    • DNSsec support
    • ENUM support
    • internal DNS caching system – avoid DNS blocking
    • IP level Blacklists
    • multi-homed and multi-domain support
    • topology hiding – hide IP addresses in SIP headers to protect your network architecture
  • Accounting

Kamailio gives event based and configurable accounting data details. Can show multi-leg call accounting ( A leg to B leg ). It can store to database, Radius or Diameter based on module used . Has a prepaid engine.

  • External Interaction

text-based management interface via FIFO file, udp, xmlrpc and unix sockets.

RPC control interface – via XMLRPC, UDP or TCP

  • Rich Communication Services (RCS)

    • SIP SIMPLE Presence Server (rich presence)
    • Presence User Agent ( SUBSCRIBE , NOTIFY and PUBLSH)
    • XCAP client capabilities and Embedded XCAP Server
    • Presence DialogInfo support – SLA/BLA
    • Instant Messaging ( IM) 
    • Embedded MSRP relay
  • Monitoring and Troubleshooting

Support for SNMP – interface to Simple Network Management Protocol.  For Debugging it has config debugger , remote control via XMLRPC and error message logging system .Provides internal statistics exported via RPC and SNMP.

  • Extensibility APIs

The supported  one are Perl  , Java SIP Servlet Application Interface  , Lua  , Managed Code (C#) , Python

  • Multiple Database Backends

(MySQL, PostgreSQL, SQLite, UnixODBC, BerkeleyDB, Oracle, text files) and other database types which have unixodbc drivers. ‘

It can have connections pool and different backends  be used at same time (e.g., accounting to Oracle and authorization against MySQL).

Has connectors for Memcached, Redis , MongoDB and Cassandra no-SQL backends

  • Interconnectivity

Acts as SIP to PSTN gateway and gateway to sms or xmpp and other IM services. Has Interoperability with SIP enabled devices and applications such as SIP phones (Snom, Cisco, etc.), Media Servers (Asterisk, FreeSwitch, etc.)

  • IMS

    • diameter support and authentication
    • I-CSCF, P-CSCF, S-CSCF
    • charging, QOS, ISC
  • Miscellaneous

    • CPL – Call Processing Language (RFC3880)
    • Internal generic caching system
    • Memcached connector
    • Redis NoSQL database connector
    • CLI – kamctl and sercmd
    • Web Management Interface: Siremis
    • SIP-T and SIP-I
    • music on hold queue
    • message body compression/decompression (gzip-deflate)
  • Extensive documentation for both administrators and developers

Scalability:

  • Kamailio can run on embedded systems, with limited resources – the performances can be up to hundreds of call setups per second
  • used as load balancer in stateless mode, Kamailio can handle over 5000 call setups per second
  • on systems with 4GB memory, Kamailio can serve a population over 300 000 online subscribers
  • system can easily scale by adding more Kamailio servers
  • Kamailio can be used in geographic distributed VoIP platforms
  • Kamailio least-cost-routing scales up to millions of routing rules
  • straightforward failover and redundancy

Start Kamalio

service kamailo start

Logs

tail -f /var/log/kamailio

To Check if Kamailio instance is running

>ps -ax | grep “kamailio”

57411 ?        S      0:01 /usr/sbin/kamailio -f /etc/kamailio/kamailio.cfg -P /var/run/kamailio/kamailio.pid -m 4096 -M 128 -u root -g root

Installation and Configuration

Installing kamailio from git repo

clone kamailio from their github https://github.com/kamailio/kamailio

goto desired branch

The contents of clonned folder are

COPYING ChangeLog INSTALL ISSUES Makefile README README.md doc etc misc pkg test utils

run ‘make cfg’ which compiles using gcc abd created ‘src’ folder with contents

make cfg

Makefile Makefile.defs Makefile.groups Makefile.modules Makefile.rules Makefile.sources Makefile.utils core main.c modules.lst Makefile.cfg Makefile.dirs Makefile.libs Makefile.radius Makefile.shared Makefile.targets config.mak lib modules

Edit modules.lst to enable db_mysql and dialplan module

vim src/modules.lst

//the list of extra modules to compile
include_modules= db_mysql

Use ‘make’ command followed by make all . Make sure to have gcc bison and flex installed

make cfg
make all

Alternativey on debian system , use readymade measures like

apt install mysql-server
apt install kamailio kamailio-mysql-modules

To validate and verify the location of kamillio use ‘which kamailio’ which returns /usr/sbin/kamailio

For Modules installation , check all avaible modules with command ‘apt search kamailio’and to install a new module such as websockt module use ‘apt install kamailio-websocket-modules’

Database access
After installaing kamailio , edit the kamailio.cfg file in /etc/kamailio to set the reachabe SIP domain, database engine, username/password etc to connect to databaseand enable the kamdbctl script to run and create users and tables, etc.

SIP_DOMAIN=kamailio.org

SIP_DOMAIN=17.3.4.5

chrooted directory

$CHROOT_DIR=”/path/to/chrooted/directory”

database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE by default none is loaded

DBENGINE=MYSQL

Run kamdbctl to create users and database now

kamdbctl create

the database created is name kamailio and its tables are

+---------------------+
 | Tables_in_kamailio  |
 +---------------------+
 | acc                 |
 | acc_cdrs            |
 | active_watchers     |
 | address             |
 | aliases             |
 | carrier_name        |
 | carrierfailureroute |
 | carrierroute        |
 | cpl                 |
 | dbaliases           |
 | dialog              |
 | dialog_vars         |
 | dialplan            |
 | dispatcher          |
 | domain              |
 | domain_attrs        |
 | domain_name         |
 | domainpolicy        |
 | globalblacklist     |
 | grp                 |
 | htable              |
 | imc_members         |
 | imc_rooms           |
 | lcr_gw              |
 | lcr_rule            |
 | lcr_rule_target     |
 | location            |
 | location_attrs      |
 | missed_calls        |
 | mohqcalls           |
 | mohqueues           |
 | mtree               |
 | mtrees              |
 | pdt                 |
 | pl_pipes            |
 | presentity          |
 | pua                 |
 | purplemap           |
 | re_grp              |
 | rls_presentity      |
 | rls_watchers        |
 | rtpproxy            |
 | sca_subscriptions   |
 | silo                |
 | sip_trace           |
 | speed_dial          |
 | subscriber          |
 | trusted             |
 | uacreg              |
 | uid_credentials     |
 | uid_domain          |
 | uid_domain_attrs    |
 | uid_global_attrs    |
 | uid_uri             |
 | uid_uri_attrs       |
 | uid_user_attrs      |
 | uri                 |
 | userblacklist       |
 | usr_preferences     |
 | version             |
 | watchers            |
 | xcap                |
 +---------------------+

Kamctlrc

The Kamailio configuration file for the control tools. Can set variables used in the kamctl and kamdbctl setup scripts. Per default all variables here are commented out, the control tools will use their internal default values. This file lets to edit  SIP domain, the database engine, username/password/ to connect to database, etc.

## your SIP domain
 SIP_DOMAIN=13.126.169.58
## chrooted directory
# $CHROOT_DIR="/path/to/chrooted/directory"
## database type: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT, or SQLITE
# by default none is loaded

# If you want to setup a database with kamdbctl, you must at least specify this parameter.

 DBENGINE=MYSQL
## database host
# DBHOST=localhost
## database host
# DBPORT=3306
## database name (for ORACLE this is TNS name)
# DBNAME=kamailio
# database path used by dbtext, db_berkeley or sqlite
# DB_PATH="/usr/local/etc/kamailio/dbtext"
database read/write user
# DBRWUSER="kamailio"
## password for database read/write user
# DBRWPW="kamailiorw"

database read only user

# DBROUSER="kamailioro"
## password for database read only user
# DBROPW="kamailioro"
## database access host (from where is kamctl used)
# DBACCESSHOST=192.168.0.1

database super user (for ORACLE this is ‘scheme-creator’ user)

# DBROOTUSER="root"
## password for database super user
## - important: this is insecure, targeting the use only for automatic testing
## - known to work for: mysql
# DBROOTPW="dbrootpw"
## database character set (used by MySQL when creating database)
#CHARSET="latin1"
## user name column
# USERCOL="username"
# SQL definitions

# If you change this definitions here, then you must change them
# in db/schema/entities.xml too.
# FIXME
# FOREVER="2030-05-28 21:32:15"
# DEFAULT_Q="1.0"
# Program to calculate a message-digest fingerprint
# MD5="md5sum"
# awk tool
# AWK="awk"
# gdb tool
# GDB="gdb"

# If you use a system with a grep and egrep that is not 100% gnu grep compatible,
# e.g. solaris, install the gnu grep (ggrep) and specify this below.

grep tool
# GREP="grep"
# egrep tool
# EGREP="egrep"
# sed tool
# SED="sed"
# tail tool
# LAST_LINE="tail -n 1"
# expr tool
# EXPR="expr"

Describe what additional tables to install. Valid values for the variables below are yes/no/ask. With ask (default) it will interactively ask the user for an answer, while yes/no allow for automated, unassisted installs.

#If to install tables for the modules in the EXTRA_MODULES variable.

# INSTALL_EXTRA_TABLES=ask
# If to install presence related tables.
# INSTALL_PRESENCE_TABLES=ask
# If to install uid modules related tables.
# INSTALL_DBUID_TABLES=ask

 Define what module tables should be installed.

If you use the postgres database and want to change the installed tables, then you must also adjust the STANDARD_TABLES or EXTRA_TABLES variable accordingly in the kamdbctl.base script.

standard modules

# STANDARD_MODULES="
standard acc lcr domain group permissions registrar usrloc msilo
alias_db uri_db speeddial avpops auth_db pdt dialog dispatcher
dialplan"

extra modules

# EXTRA_MODULES="
imc cpl siptrace domainpolicy carrierroute userblacklist htable purple sca"
 type of aliases used: DB - database aliases; UL - usrloc aliases
- default: none , ALIASES_TYPE="DB"
control engine: RPCFIFO
 - default RPCFIFO
 CTLENGINE="RPCFIFO"

## path to FIFO file for engine RPCFIFO
# RPCFIFOPATH="/var/run/kamailio/kamailio_rpc_fifo"

## check ACL names; default on (1); off (0)
# VERIFY_ACL=1

## ACL names - if VERIFY_ACL is set, only the ACL names from below list are accepted
# ACL_GROUPS="local ld int voicemail free-pstn"

## check if user exists (used by some commands such as acl);
## - default on (1); off (0)

# VERIFY_USER=1

## verbose - debug purposes - default '0'
# VERBOSE=1

## do (1) or don't (0) store plaintext passwords
## in the subscriber table - default '1'

# STORE_PLAINTEXT_PW=0

Kamailio START Options

PID file path – default is: /var/run/kamailio/kamailio.pid

# PID_FILE=/var/run/kamailio/kamailio.pid

Extra start options – default is: not set

# example: start Kamailio with 64MB share memory: STARTOPTIONS="-m 64"
# STARTOPTIONS=

Kamailio.cfg

config files are used to customize and deploy SIP services since each and every SIP packet is route based on policies specified in conf file ( routing blocks ). Location when installed from source – /usr/local/etc/kamailio/kamailio.cfg , when installed from package – /etc/kamailio/kamailio.cfg

The features in config file :-

  • User authentication

Kamailio doesn’t have user authentication by default , so to enable it one must

#!define WITH_MYSQL
#!define WITH_AUTH

kamdbctl tool is to be used for creating and managing the database.

kamdbctl create

Kamctl is used for adding subscriber information and password.

kamctl add altanai1 123
mysql: [Warning] Using a password on the command line interface can be insecure.
MySQL password for user 'kamailio@localhost': 
mysql: [Warning] Using a password on the command line interface can be insecure.
new user 'altanai1' added

More details in Tools section below .

  • IP authorization
  • accounting
  • registrar and location servicesTo have persisant location enabled so that records are not lost once kamailio are restarted , we need to save it to database and reload when restarting
#!define WITH_USRLOCDB
  • attacks detection and blocking (anti-flood protection)
  • NAT traversal

requires RTP proxy for RTP relay . NAT traversal support can be set by

#!define WITH_NAT
  • short dialing on server
  • multiple identities (aliases) for subscribers
  • multi-domain support
  • routing to a PSTN gateway
  • routing to a voicemail server
  • TLS encryption
  • instant messaging (pager mode with MESSAGE requests)
  • presence services

Kamailio (OpenSER) SIP Server v4.3- default configuration script

Several features can be enabled using ‘#!define WITH_FEATURE’ directives:

To run in debug mode: define WITH_DEBUG

To enable mysql: define WITH_MYSQL

To enable authentication execute: enable mysql and  define WITH_AUTH

To enable IP authentication execute: enable mysql ,  enable authentication ,  define WITH_IPAUTH and  add IP addresses with group id ‘1’ to ‘address’ table

To enable persistent user location execute:


enable mysql

define WITH_USRLOCDB

To enable presence server execute:


enable mysql

define WITH_PRESENCE

To enable nat traversal execute:

define WITH_NAT

Install RTPProxy: http://www.rtpproxy.org

start RTPProxy:

rtpproxy -l your_public_ip -s udp:localhost:7722

option for NAT SIP OPTIONS keepalives: WITH_NATSIPPING

To enable PSTN gateway routing execute:

define WITH_PSTN

set the value of pstn.gw_ip

check route[PSTN] for regexp routing condition

To enable database aliases lookup execute:


enable mysql

define WITH_ALIASDB

To enable speed dial lookup execute:


enable mysql

define WITH_SPEEDDIAL

To enable multi-domain support execute:


enable mysql

define WITH_MULTIDOMAIN

To enable TLS support execute:


adjust CFGDIR/tls.cfg as needed

define WITH_TLS

To enable XMLRPC support execute:


define WITH_XMLRPC

adjust route[XMLRPC] for access policy

To enable anti-flood detection execute:

adjust pike and htable=>ipban settings as needed (default is block if more than 16 requests in 2 seconds and ban for 300 seconds)

define WITH_ANTIFLOOD

To block 3XX redirect replies execute:

define WITH_BLOCK3XX

To enable VoiceMail routing execute:

define WITH_VOICEMAIL

set the value of voicemail.srv_ip

adjust the value of voicemail.srv_port

To enhance accounting execute:


enable mysql

define WITH_ACCDB

add following columns to database


define WITH_MYSQL

define WITH_AUTH

define WITH_USRLOCDB

#!ifdef ACCDB_COMMENT

ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';

ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';

ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';

#!endif

Include Local Config If Exists

import_file “kamailio-local.cfg”

Value defines – IDs used later in config #!ifdef WITH_MYSQL # – database URL – used to connect to database server by modules such # as: auth_db, acc, usrloc, a.s.o.

  
 #!ifndef DBURL 
 #!define DBURL "mysql://kamailio:kamailiorw@localhost/kamailio" 
  #!define DBURL "mysql://kamailio:kamailiorw@localhost/kamailio" 
# !endif

 #!ifdef WITH_MULTIDOMAIN# - the value for 'use_domain' paramete
 #!define MULTIDOMAIN 1
 #!else
 #!define MULTIDOMAIN 0
 #!endif

 # FLT_ - per transaction (message) flags 
 # FLB_ - per branch flags
 #!define FLT_ACC 1
 #!define FLT_ACCMISSED 2
 #!define FLT_ACCFAILED 3
 #!define FLT_NATS 5
 #!define FLB_NATB 6
 #!define FLB_NATSIPPING 

 !substdef "!MY_IP_ADDR!!g"
 #!substdef "!MY_DOMAIN!!g" 
 #!substdef "!MY_WS_PORT!8080!g"
 #!substdef "!MY_WSS_PORT!4443!g"
 #!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
 #!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"&lt;/pre&gt;
 
 #!define WITH_WEBSOCKETS
 #!ifdef WITH_DEBUG
 debug=4
 log_stderror=yes
 #!else
 debug=2
 log_stderror=no
 #!endif

 memdbg=5
 memlog=5
 log_facility=LOG_LOCAL0
 fork=yes
 children=4
 
disable TCP (default on)
 #disable_tcp=yes
 enable_sctp = 0

disable the auto discovery of local aliases based on reverse DNS on IPs (default on)
 #auto_aliases=no

add local domain aliases
#alias=”sip.mydomain.com”

// port to listen to can be specified more than once if needed to listen on many ports
port=5060
#!ifdef WITH_TLS
enable_tls=yes
#!endif

life time of TCP connection when there is no traffic – a bit higher than registration expires to cope with UA behind NAT

#!ifdef WITH_PSTN
# PSTN GW Routing
# - pstn.gw_ip: valid IP or hostname as string value, example:
# pstn.gw_ip = "10.0.0.101" desc "My PSTN GW Address"
# - by default is empty to avoid misrouting
pstn.gw_ip = "" desc "PSTN GW Address"
pstn.gw_port = "" desc "PSTN GW Port"
#!endif

ifdef WITH_VOICEMAIL
# VoiceMail Routing on offline, busy or no answer
# - by default Voicemail server IP is empty to avoid misrouting
voicemail.srv_ip = "" desc "VoiceMail IP Address"
voicemail.srv_port = "5060" desc "VoiceMail Port"
#!endif

Modules Section

set paths to location of modules (to sources or installation folders)

#!ifdef WITH_SRCPATH
mpath="modules/"
#!else
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules/"
#!endif

#!ifdef WITH_MYSQL
loadmodule "db_mysql.so"
#!endif

loadmodule "mi_fifo.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "mi_rpc.so"
loadmodule "acc.so"

#!ifdef WITH_AUTH
loadmodule "auth.so"
loadmodule "auth_db.so"
#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
#!endif

#!ifdef WITH_ALIASDB
loadmodule "alias_db.so"
#!endif

#!ifdef WITH_SPEEDDIAL
loadmodule "speeddial.so"
#!endif

#!ifdef WITH_MULTIDOMAIN
loadmodule "domain.so"
#!endif

#!ifdef WITH_PRESENCE
loadmodule "presence.so"
loadmodule "presence_xml.so"
#!endif

#!ifdef WITH_NAT
loadmodule "nathelper.so"
loadmodule "rtpproxy.so"
#!endif

#!ifdef WITH_TLS
loadmodule "tls.so"
#!endif

#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif

#!ifdef WITH_XMLRPC
loadmodule "xmlrpc.so"
#!endif

#!ifdef WITH_DEBUG
loadmodule "debugger.so"
#!endif

#!ifdef WITH_WEBSOCKETS
loadmodule "xhttp.so"
#loadmodule "websocket.so"
loadmodule "nathelper.so"
#!endif

----- mi_fifo params -----
#modparam("mi_fifo", "fifo_name", "/var/run/kamailio/kamailio_fifo")</pre>

----- ctl params -----
#modparam("ctl", "binrpc", "unix:/var/run/kamailio/kamailio_ctl")</pre>

----- tm params -----
# auto-discard branches from previous serial forking leg
modparam("tm", "failure_reply_mode", 3)
# default retransmission timeout: 30sec
modparam("tm", "fr_timer", 30000)
# default invite retransmission timeout after 1xx: 120sec
modparam("tm", "fr_inv_timer", 120000)</pre>

----- rr params -----
# set next param to 1 to add value to ;lr param (helps with some UAs)
modparam("rr", "enable_full_lr", 0)
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 0)

registrar params


modparam("registrar", "method_filtering", 1)
/* uncomment the next line to disable parallel forking via location */
# modparam("registrar", "append_branches", 0)
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
# max value for expires of registrations
modparam("registrar", "max_expires", 3600)
# set it to 1 to enable GRUU
modparam("registrar", "gruu_enabled", 0)</pre>

enhanced DB accounting


#!ifdef WITH_ACCDB

modparam("acc", "db_flag", FLT_ACC)

modparam("acc", "db_missed_flag", FLT_ACCMISSED)

modparam("acc", "db_url", DBURL)

modparam("acc", "db_extra",

"src_user=$fU;src_domain=$fd;src_ip=$si;"

"dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")

#!endif

usrloc params – enable DB persistency for location entries


#!ifdef WITH_USRLOCDB

modparam("usrloc", "db_url", DBURL)

modparam("usrloc", "db_mode", 2)

modparam("usrloc", "use_domain", MULTIDOMAIN)

#!endif

auth_db params


#!ifdef WITH_AUTH

modparam("auth_db", "db_url", DBURL)

modparam("auth_db", "calculate_ha1", yes)

modparam("auth_db", "password_column", "password")

modparam("auth_db", "load_credentials", "")

modparam("auth_db", "use_domain", MULTIDOMAIN)

permissions params


#!ifdef WITH_IPAUTH

modparam("permissions", "db_url", DBURL)

modparam("permissions", "db_mode", 1)

#!endif

#!endif

alias_db params


#!ifdef WITH_ALIASDB

modparam("alias_db", "db_url", DBURL)

modparam("alias_db", "use_domain", MULTIDOMAIN)

#!endif

speeddial params


#!ifdef WITH_SPEEDDIAL

modparam("speeddial", "db_url", DBURL)

modparam("speeddial", "use_domain", MULTIDOMAIN)

#!endif

domain params

#!ifdef WITH_MULTIDOMAIN
modparam("domain", "db_url", DBURL)
modparam("domain", "register_myself", 1)
#!endif
#!ifdef WITH_PRESENCE

presence params

modparam("presence", "db_url", DBURL)

presence_xml params

modparam("presence_xml", "db_url", DBURL)
modparam("presence_xml", "force_active", 1)

WITH_NAT

rtpproxy params
modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")

nathelper params

 modparam("nathelper", "natping_interval", 30)
 modparam("nathelper", "ping_nated_only", 1)
 modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
 modparam("nathelper", "sipping_from", "sip:pinger@kamailio.org") 

params needed for NAT traversal in other modules

modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
modparam("usrloc", "nat_bflag", FLB_NATB)

tls params

#!ifdef WITH_TLS

modparam("tls", "config", "/etc/kamailio/tls.cfg")

#!endif

pike params

#!ifdef WITH_ANTIFLOOD

modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)

htable params

ip ban htable with autoexpire after 5 minutes

modparam("htable", "htable", "ipban=&gt;size=8;autoexpire=300;")

#!endif

xmlrpc params

modparam("xmlrpc", "route", "XMLRPC");
modparam("xmlrpc", "url_match", "^/RPC")

debugger params

#!ifdef WITH_DEBUGs
modparam("debugger", "cfgtrace", 1)
#!endif

nathelper params

#!ifdef WITH_WEBSOCKETS
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
#!endif

Note: leaving NAT pings turned off here as nathelper is <em>only</em> being used for&nbsp;WebSocket connections. NAT pings are not needed as WebSockets have&nbsp;their own keep-alives.

Routing Logic

Main SIP request routing logic processing of any incoming SIP request starts with this route

request_route { 
# per request initial checks 
route(REQINIT);
 #!ifdef WITH_WEBSOCKETS 
    if (nat_uac_test(64)) {     
        force_rport();     
        if (is_method("REGISTER")) {          
            fix_nated_register();     
        } else {         
            fix_nated_contact();         
            if (!add_contact_alias()) {  
                   xlog("L_ERR", "Error aliasing contact \n");             
                   sl_send_reply("400", "Bad Request");                    exit;         }     } } 
#!endif 
# NAT detection 
route(NATDETECT); 
# CANCEL processing 
if (is_method("CANCEL")) {     
    if (t_check_trans()) {         
        route(RELAY);     
    }     
exit; 
} 

# handle requests within SIP dialogs 
route(WITHINDLG); 
### only initial requests (no To tag) 
# handle retransmissions 
if(t_precheck_trans()) { 
    t_check_trans(); 
    exit; 
} 
t_check_trans(); 

# authentication 
route(AUTH); 

# record routing for dialog forming requests (in case they are routed) - remove preloaded route headers 
remove_hf("Route"); 

if (is_method("INVITE|SUBSCRIBE")) 
record_route(); 

# account only INVITEs 
if (is_method("INVITE")) {     
    setflag(FLT_ACC); # do accounting 
}
# dispatch requests to foreign domains 
route(SIPOUT); 

### requests for my local domains 
# handle presence related requests 
route(PRESENCE); 

# handle registrations 
route(REGISTRAR); 
if ($rU==$null) {     
# request with no Username in RURI     sl_send_reply("484","Address Incomplete");     
exit; 
} 
# dispatch destinations to PSTN route(PSTN); 

# user location service 
route(LOCATION); }

Wrapper for relaying requests

enable additional event routes for forwarded requests – serial forking, RTP relaying handling, a.s.o.

route[RELAY] {
if (is_method(“INVITE|BYE|SUBSCRIBE|UPDATE”)) {
if(!t_is_set(“branch_route”))
t_on_branch(“MANAGE_BRANCH”);
}
if (is_method(“INVITE|SUBSCRIBE|UPDATE”)) {
if(!t_is_set(“onreply_route”))
t_on_reply(“MANAGE_REPLY”);
}
if (is_method(“INVITE”)) {
if(!t_is_set(“failure_route”))
t_on_failure(“MANAGE_FAILURE”);
}
if (!t_relay()) {
sl_reply_error();
}
exit;
}

Per SIP request initial checks

route[REQINIT] { #!ifdef WITH_ANTIFLOOD # flood detection from same IP and traffic ban for a while # be sure you exclude checking trusted peers, such as pstn gateways – local host excluded (e.g., loop to self) if(src_ip!=myself) { if($sht(ipban=>$si)!=$null) { # ip is already blocked xdbg(“request from blocked IP – $rm from $fu (IP:$si:$sp)\n”); exit; } if (!pike_check_req()) { xlog(“L_ALERT”,”ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n”); $sht(ipban=>$si) = 1; exit; } } if($ua =~ “friendly-scanner”) { sl_send_reply(“200”, “OK”); exit; } #!endif if (!mf_process_maxfwd_header(“10”)) { sl_send_reply(“483″,”Too Many Hops”); exit; } if(is_method(“OPTIONS”) && uri==myself && $rU==$null) { sl_send_reply(“200″,”Keepalive”); exit; } if(!sanity_check(“1511”, “7”)) { xlog(“Malformed SIP message from $si:$sp\n”); exit; } }

Handle requests within SIP dialogs

route[WITHINDLG] {
    if (!has_totag()) return;

    if (has_totag()) {

#sequential request withing a dialog should take the path determined by record-routing

        if (loose_route()) {
            #!ifdef WITH_WEBSOCKETS
            if ($du == "") {
                if (!handle_ruri_alias()) {
                    xlog("L_ERR", "Bad alias <$ru>\n");
                    sl_send_reply("400", "Bad Request");
                    exit;
                }
            }
            #!endif
         }
     exit;
     }

#sequential request within a dialog should  take the path determined by record-routing
    if (loose_route()) {
        route(DLGURI);
        if (is_method("BYE")) {
            setflag(FLT_ACC); # do accounting ...
            setflag(FLT_ACCFAILED); # ... even if the transaction fails
        }
        else if ( is_method("ACK") ) {
            # ACK is forwarded statelessy
            route(NATMANAGE);
        }
        else if ( is_method("NOTIFY") ) {
            # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
            record_route();
        }
        route(RELAY);
        exit;
    }

    if (is_method("SUBSCRIBE") && uri == myself) {
    # in-dialog subscribe requests
        route(PRESENCE);
        exit;
    }

if ( is_method("ACK") ) {
    if ( t_check_trans() ) {
        # no loose-route, but stateful ACK;
        # must be an ACK after a 487
        # or e.g. 404 from upstream server
        route(RELAY);
        exit;
    } else {
        # ACK without matching transaction ... ignore and discard
        exit;
    }
}

sl_send_reply("404","Not here");
exit;
}


Handle SIP registrations





User location service

route[LOCATION] {

#!ifdef WITH_SPEEDDIAL
# search for short dialing - 2-digit extension
if($rU=~"^[0-9][0-9]$")
    if(sd_lookup("speed_dial"))
    route(SIPOUT);
#!endif

#!ifdef WITH_ALIASDB
# search in DB-based aliases
    if(alias_db_lookup("dbaliases"))
    route(SIPOUT);
#!endif

$avp(oexten) = $rU;
if (!lookup("location")) {
    $var(rc) = $rc;
    route(TOVOICEMAIL);
    t_newtran();
    switch ($var(rc)) {
        case -1:
        case -3:
           send_reply("404", "Not Found");
        exit;
        case -2:
           send_reply("405", "Method Not Allowed");
        exit;
    }
}

# when routing via usrloc, log the missed calls also
if (is_method("INVITE")) {
    setflag(FLT_ACCMISSED);
}

route(RELAY);
exit;
}

Presence server processing

route[PRESENCE] {

if(!is_method("PUBLISH|SUBSCRIBE"))
return;

if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") {
    route(TOVOICEMAIL);
    # returns here if no voicemail server is configured
    sl_send_reply("404", "No voicemail service");
    exit;
}

#!ifdef WITH_PRESENCE
if (!t_newtran()) {
    sl_reply_error();
    exit;
}

if(is_method("PUBLISH")) {
    handle_publish();
    t_release();
} else if(is_method("SUBSCRIBE")) {
    handle_subscribe();
    t_release();
}
exit;
#!endif

# if presence enabled, this part will not be executed
if (is_method("PUBLISH") || $rU==$null) {
    sl_send_reply("404", "Not here");
    exit;
}
return;
}

IP authorization and user authentication

route[AUTH] {
#!ifdef WITH_AUTH

#!ifdef WITH_IPAUTH
if((!is_method("REGISTER")) && allow_source_address()) {
    # source IP allowed
    return;
}
#!endif

if (is_method("REGISTER") || from_uri==myself)
{
    # authenticate requests
    if (!auth_check("$fd", "subscriber", "1")) {
        auth_challenge("$fd", "0");
        exit;
    }

    # user authenticated - remove auth header
    if(!is_method("REGISTER|PUBLISH"))
        consume_credentials();
    }

# if caller is not local subscriber, then check if it calls
# a local destination, otherwise deny, not an open relay here
    if (from_uri!=myself && uri!=myself) {
        sl_send_reply("403","Not relaying");
        exit;
    }

#!endif
return;
}

Caller NAT detection

route[NATDETECT] {
#!ifdef WITH_NAT
force_rport();

if (nat_uac_test("19")) {
    if (is_method("REGISTER")) {
        fix_nated_register();
    } else {
        if(is_first_hop())
            set_contact_alias();
    }
    setflag(FLT_NATS);
}
#!endif
return;
}

RTPProxy control and signaling updates for NAT traversal

route[NATMANAGE] {

#!ifdef WITH_NAT
if (is_request()) {
    if(has_totag()) {
        if(check_route_param("nat=yes")) {
            setbflag(FLB_NATB);
        }
     }
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
return;

rtpproxy_manage("co");

if (is_request()) {
    if (!has_totag()) {
        if(t_is_branch_route()) {
            add_rr_param(";nat=yes");
        } 
    }
}

if (is_reply()) {
    if(isbflagset(FLB_NATB)) {
        if(is_first_hop())
        set_contact_alias();
    }
}

#!endif
return;
}

URI update for dialog requests

route[DLGURI] {
#!ifdef WITH_NAT
if(!isdsturiset()) {
    handle_ruri_alias();
}
#!endif
return;
}

Routing to foreign domains

route[SIPOUT] {
if (uri==myself) return;

append_hf("P-hint: outbound\r\n");
route(RELAY);
exit;
}

PSTN GW routing

route[PSTN] {
#!ifdef WITH_PSTN
# check if PSTN GW IP is defined
if (strempty($sel(cfg_get.pstn.gw_ip))) {
xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n");
return;
}

# route to PSTN dialed numbers starting with '+' or '00'
# (international format)
# - update the condition to match your dialing rules for PSTN routing
if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$"))
return;

# only local users allowed to call
if(from_uri!=myself) {
sl_send_reply("403", "Not Allowed");
exit;
}

if (strempty($sel(cfg_get.pstn.gw_port))) {
$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);
} else {
$ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":"
+ $sel(cfg_get.pstn.gw_port);
}

route(RELAY);
exit;
#!endif

return;
}

XMLRPC routing

#!ifdef WITH_XMLRPC
route[XMLRPC] {
# allow XMLRPC from localhost
if ((method=="POST" || method=="GET") && (src_ip==127.0.0.1)) {
# close connection only for xmlrpclib user agents
    if ($hdr(User-Agent) =~ "xmlrpclib")
        set_reply_close();
        set_reply_no_connect();
        dispatch_rpc();
    exit;
}
send_reply("403", "Forbidden");
exit;
}
#!endif

Routing to voicemail server

route[TOVOICEMAIL] {
#!ifdef WITH_VOICEMAIL
if(!is_method("INVITE|SUBSCRIBE"))
return;

# check if VoiceMail server IP is defined
if (strempty($sel(cfg_get.voicemail.srv_ip))) {
    xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n");
    return;
}
if(is_method("INVITE")) {
    if($avp(oexten)==$null)
        return;
    $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)+ ":" + $sel(cfg_get.voicemail.srv_port);
} else {
    if($rU==$null)
        return;
    $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip)
+ ":" + $sel(cfg_get.voicemail.srv_port);
}
route(RELAY);
exit;
#!endif

return;
}

Manage outgoing branches

branch_route[MANAGE_BRANCH] {
    xdbg("new branch [$T_branch_idx] to $ru\n");
    route(NATMANAGE);
}

Manage incoming replies

onreply_route[MANAGE_REPLY] {
    xdbg("incoming reply\n");
    if(status=~"[12][0-9][0-9]")
        route(NATMANAGE);
}

Manage failure routing cases

failure_route[MANAGE_FAILURE] {
route(NATMANAGE);

if (t_is_canceled()) {
    exit;
}

#!ifdef WITH_BLOCK3XX
# block call redirect based on 3xx replies.
if (t_check_status("3[0-9][0-9]")) {
    t_reply("404","Not found");
    exit;
}
#!endif

#!ifdef WITH_VOICEMAIL
# serial forking
# - route to voicemail on busy or no answer (timeout)
if (t_check_status("486|408")) {
    $du = $null;
    route(TOVOICEMAIL);
    exit;
}
#!endif
}

Supports pseudo-variables to access and manage parts of the SIP messages and attributes specific to users and server.  Transformations to modify existing pseudo-variables, accessing only the wanted parts of the information. 

Already has over 1000 parameters, variables and functions exported to config file. Supports runtime update framework – to avoid restarting the SIP server when needing to change the config parameters

Tools

kamctl

Manage kamailio from command line, providing lots of operations, such as adding/removing/updating SIP users, controlling the ACL for users, managing the records for LCR or load balancing, viewing registered users and internal statistics, etc. When needed to interact with Kamailio, it does it via FIFO file created by mi_fifo module.

kamdbctl

Helps to configure and database needed by kamailio . First we need to select a database engine in the kamctlrc file by DBENGINE parameter .

Valid values are: MYSQL, PGSQL, ORACLE, DB_BERKELEY, DBTEXT.

The tool can be used to create and manage the database structure needed by Kamailio, therefore it should be immediately after Kamailio installation, in case you plan to run Kamailio with a database backend.

kamcmd

send RPC commands to Kamailio from command line , requires  ctl module

siremis

web management interface for Kamailio, written in PHP , AJAX , web 2.0 using MVC architecture

  • system and database administration tools for Kamailio SIP Server
  • subscriber, database aliases and speed dial management
  • location table view
  • dispatcher (load balancer), prefix-domain translation and least cost routing (lcr) management
  • access control lists (user groups) and permissions management
  • accounting records and missed calls vies
  • manage call data records (generated from acc records)
  • hash table, dial plan table and user preferences table management
  • offline message storage, presence service and sip trace views
  • communication with Kamailio SIP Server via XMLRPC ,  JSONRPC
  • communication with FreeSWITCH via event socket
  • create and display charts from statistic data stored by Kamailio
  • user location statistics charts
  • SIP traffic load charts
  • memory usage charts
  • accounting records charts and summary table
  • SQL-based CDR generation and rating billing engine

———————————–

Things covered in this article

  • Internal architecture
  • Configuration language
  • least cost routing
  • load balancing
  • traffic dispatching
  • DID routing
  • prefix based routing
  • SIP trunks and peering
  • traffic shaping
  • topology hiding
  • flood detection
  • scanning attacks prevention
  • anti-fraud policies

SQL and noSQL connectors

enum and DNS based routing

authentication and authorization

secure communication (TLS)

registration and location services

accounting and call data records

call control – redirect, forward, baring

redundancy and scalability

high availability and failover

websockets and webrtc

References :

Henning Westerholt – Kamailio project-1&1 Internet AG ( 2009 )

Proxying Media Streams via Kamailio’s RTP Proxy

Kamailio is a SIP server which does not play any role by itself in media transmission path. this behaviour leads to media packets having to attempt to stream peer to peer between caller and callee which in turn many a times causes them to get dropped in absence of NAT management

To ensure that media stream is proxied via an RTP proxy kamailio can use RTP proxy module combined with a RTP proxy.

This setup also provides other benefits such as controlling media media , security , Load balancing between many rtp proxies ,bridge signalling between multiple network interfaces etc.

RTP Proxy module

Used to proxy the media stream .

RTP proxies that can be used along with this module are:

RTP proxies can be used for bridging network interfaces , load distribution and balancing etc.It does not support transcoding.

Parameters :

rtpproxy_sock – binds a ip and port for rtp proxy

 modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:12221")

rtpproxy_disable_tout – when rtp proxy is disabled then timeout till when it doesnt connect

rtpproxy_tout – timeout to wait for reply

rtpproxy_retr – num of retries after timeout

nortpproxy_str – sets the SDP attribute used by rtpproxy to mark the message’s SDP attachment with information that it have already been changed. Default value is

“a=nortpproxy:yes\r\n”

and others like

“a=sdpmangled:yes\r\n”

timeout_socket (string)

ice_candidate_priority_avp (string)

extra_id_pv (string)

db_url (string)

table_name (string)

rtp_inst_pvar (string)

Functions

set_rtp_proxy_set(setid) – Sets the Id of the rtpproxy set to be used for the next unforce_rtp_proxy(), rtpproxy_offer(), rtpproxy_answer() or rtpproxy_manage() command

rtpproxy_offer([flags [, ip_address]]) – to make the media pass through RTP the SDP is altered. Value of flag can be
1 – append first Via branch to Call-ID when sending command to rtpproxy.
2 – append second Via branch to Call-ID when sending command to rtpproxy. See flag ‘1’ for its meaning.
3 – behave like flag 1 is set for a request and like flag 2 is set for a reply
a – flags that UA from which message is received doesn’t support symmetric RTP. (automatically sets the ‘r’ flag)
b – append branch specific variable to Call-ID when sending command to rtpproxy
l – force “lookup”, that is, only rewrite SDP when corresponding session already exists in the RTP proxy
i, e – direction of the SIP message when rtpproxy is running in bridge mode. ‘i’ is internal network (LAN), ‘e’ is external network (WAN). Values ie , ei , ee and ii
x – shortcut for using the “ie” or “ei”-flags, to do automatic bridging between IPv4 on the “internal network” and IPv6 on the “external network”. Differentiated by IP type in the SDP, e.g. a IPv4 Address will always call “ie” to the RTPProxy (IPv4(i) to IPv6(e)) and an IPv6Address will always call “ei” to the RTPProxy (IPv6(e) to IPv4(i))
f – instructs rtpproxy to ignore marks inserted by another rtpproxy in transit to indicate that the session is already gone through another proxy. Allows creating a chain of proxies
r – IP address in SDP should be trusted. Without this flag, rtpproxy ignores address in the SDP and uses source address of the SIP message as media address which is passed to the RTP proxy
o – flags that IP from the origin description (o=) should be also changed.
c – flags to change the session-level SDP connection (c=) IP if media-description also includes connection information.
w – flags that for the UA from which message is received, support symmetric RTP must be forced.
zNN – perform re-packetization of RTP traffic coming from the UA which has sent the current message to increase or decrease payload size per each RTP packet forwarded if possible. The NN is the target payload size in ms, for the most codecs its value should be in 10ms increments, however for some codecs the increment could differ (e.g. 30ms for GSM or 20ms for G.723).
ip_address denotes the address of new SDP

such as : rtpproxy_offer(“FRWOC+PS”) is
rtpengine_offer(“force trust-address symmetric replace-origin replace-session-connection ICE=force RTP/SAVPF”);

route { 
... 
if (is_method("INVITE")) 
{ 
    if (has_body("application/sdp")) 
    { 
        if (rtpproxy_offer()) t_on_reply("1"); 
    } else { 
        t_on_reply("2"); 
    } 
} 

if (is_method("ACK") && has_body("application/sdp")) rtpproxy_answer(); 
... 
} 
onreply_route[1] { 
   if (has_body("application/sdp")) rtpproxy_answer(); 
} 
onreply_route[2] { 
   if (has_body("application/sdp")) rtpproxy_offer(); 
} 

rtpproxy_answer([flags [, ip_address]])- rewrite SDP to proxy media , it can be used from REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.

rtpproxy_destroy([flags]) – tears down RTP proxy session for current call. Flags are ,
1 – append first Via branch to Call-ID
2 – append second Via branch to Call-ID
b – append branch specific variable to Call-ID
t – do not include To tag to “delete” command to rtpproxy thus causing full call to be deleted

unforce_rtp_proxy()

rtpproxy_manage([flags [, ip_address]]) – Functionality is to use predfined logic for handling requests
If INVITE with SDP, then do rtpproxy_offer()
If INVITE with SDP, when the tm module is loaded, mark transaction with internal flag FL_SDP_BODY to know that the 1xx and 2xx are for rtpproxy_answer()
If ACK with SDP, then do rtpproxy_answer()
If BYE or CANCEL, or called within a FAILURE_ROUTE[], then call unforce_rtpproxy().
If reply to INVITE with code >= 300 do unforce_rtpproxy()
If reply with SDP to INVITE having code 1xx and 2xx, then do rtpproxy_answer() if the request had SDP or tm is not loaded, otherwise do rtpproxy_offer()
This function can be used from ANY_ROUTE.

rtpproxy_stream2uac(prompt_name, count) – stream prompt/announcement pre-encoded with the makeann command. The uac/uas suffix selects who will hear the announcement relatively to the current transaction – UAC or UAS. Also used for music on hold (MOH).
Params : prompt_name – path name of the prompt to stream
count – number of times the prompt should be repeated. When count is -1, the streaming will be in loop indefinitely until the appropriate rtpproxy_stop_stream2xxx is issued.
Example rtpproxy_stream2xxx usage

if (is_method("INVITE")) { 
rtpproxy_offer();
if (is_audio_on_hold()) {
rtpproxy_stream2uas("/var/rtpproxy/prompts/music_on_hold", "-1");
} else {
rtpproxy_stop_stream2uas();
};
};

rtpproxy_stream2uas(prompt_name, count)

rtpproxy_stop_stream2uac()- Stop streaming of announcement/prompt/MOH

rtpproxy_stop_stream2uas()

start_recording()

Exported Pseudo Variables

$rtpstat

RPC Commands

rtpproxy.enable
rtpproxy.list

Ref : https://kamailio.org/docs/modules/5.3.x/modules/rtpproxy.html