Monthly Archives: November 2014

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

Advertisements

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

RTP Proxy

Used to proxy the media stream . Example : Sippy RTPproxy , ngcp-rtpproxy-ng . Multiple RTP proxies can be used for load distribution and balancing . RTP proxy can also operated in bridging mode to setup bridge signalling between multiple network interfaces. 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 attachemnt 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

RTP Engine

media streams to be proxied via an RTP proxy.

loadmodule "rtpengine.so"
...

# ----- rtpengine params -----
modparam("rtpengine", "db_url", DBURL)
modparam("rtpengine", "table_name" , "rtpengine")
modparam("rtpengine", "rtpengine_allow_op", 1)
modparam("rtpengine", "queried_nodes_limit", 4)
modparam("rtpengine", "rtpengine_retr", 2)
modparam("rtpengine", "rtp_inst_pvar", "$avp(RTP_INSTANCE)")
modparam("rtpengine", "setid_default", 1)
modparam("rtpengine", "mos_min_pv", "$avp(mos_min)")
modparam("rtpengine", "mos_min_at_pv", "$avp(mos_min_at)")
modparam("rtpengine", "mos_min_packetloss_pv", "$avp(mos_min_packetloss)")
modparam("rtpengine", "mos_min_jitter_pv", "$avp(mos_min_jitter)")
modparam("rtpengine", "mos_min_roundtrip_pv", "$avp(mos_min_roundtrip)")
modparam("rtpengine", "rtpengine_tout_ms", 300)

source : https://github.com/sipwise/rtpengine

Parameters

  • rtpengine_sock (string)
  • rtpengine_disable_tout (integer)
  • rtpengine_tout_ms (integer)
  • rtpengine_allow_op (integer)
  • queried_nodes_limit (integer)
  • rtpengine_retr (integer)
  • extra_id_pv (string)
  • setid_avp (string)
  • force_send_interface (string)
  • read_sdp_pv (string)
  • write_sdp_pv (string)
  • rtp_inst_pvar (string)
  • hash_table_size (integer)
  • hash_table_tout (integer)
  • db_url (string)
  • table_name (string)
  • setid_col (string)
  • url_col (string)
  • weight_col (string)
  • disabled_col (string)
  • setid_default (integer)
  • mos_min_pv (string)
  • mos_min_at_pv (string)
  • mos_min_packetloss_pv (string)
  • mos_min_jitter_pv (string)
  • mos_min_roundtrip_pv (string)
  • mos_max_pv (string)
  • mos_max_at_pv (string)
  • mos_max_packetloss_pv (string)
  • mos_max_jitter_pv (string)
  • mos_max_roundtrip_pv (string)
  • mos_average_pv (string)
  • mos_average_packetloss_pv (string)
  • mos_average_jitter_pv (string)
  • mos_average_roundtrip_pv (string)
  • mos_average_samples_pv (string)
  • mos_A_label_pv (string)
  • mos_min_A_pv (string)
  • mos_min_at_A_pv (string)
  • mos_min_packetloss_A_pv (string)
  • mos_min_jitter_A_pv (string)
  • mos_min_roundtrip_A_pv (string)
  • mos_max_A_pv (string)
  • mos_max_at_A_pv (string)
  • mos_max_packetloss_A_pv (string)
  • mos_max_jitter_A_pv (string)
  • mos_max_roundtrip_A_pv (string)
  • mos_average_A_pv (string)
  • mos_average_packetloss_A_pv (string)
  • mos_average_jitter_A_pv (string)
  • mos_average_roundtrip_A_pv (string)
  • mos_average_samples_A_pv (string)
  • mos_B_label_pv (string)
  • mos_min_B_pv (string)
  • mos_min_at_B_pv (string)
  • mos_min_packetloss_B_pv (string)
  • mos_min_jitter_B_pv (string)
  • mos_min_roundtrip_B_pv (string)
  • mos_max_B_pv (string)
  • mos_max_at_B_pv (string)
  • mos_max_packetloss_B_pv (string)
  • mos_max_jitter_B_pv (string)
  • mos_max_roundtrip_B_pv (string)
  • mos_average_B_pv (string)
  • mos_average_packetloss_B_pv (string)
  • mos_average_jitter_B_pv (string)
  • mos_average_roundtrip_B_pv (string)
  • mos_average_samples_B_pv (string)

Functions

set_rtpengine_set(setid[, setid])
rtpengine_offer([flags])
rtpengine_answer([flags])
rtpengine_delete([flags])
rtpengine_query([flags])
rtpengine_manage([flags])
start_recording([flags])
stop_recording([flags])
Exported Pseudo Variables
$rtpstat

RPC Commands

rtpengine.reload
rtpengine.enable proxy_url/all 0/1
rtpengine.show proxy_url/all
rtpengine.ping proxy_url/all
rtpengine.get_hash_total