Kamailio DNS and NAT

  • DNS sub-system in Kamailio
    • DNS failover
    • DNS load balancing
    • NAT ( Network Address Translation)
  • NAT ( Network Address Translation)
  • Why is NAT is important in SIP?
  • Types of NAT solutions
  • NAT behaviours
  • Fixing NAT
  • NAT Traversal Module
    • Why use keepalive when Registrations are already there for NATing ?
    • How keepalives work for NATing ?
    • function nat_keepalive()
    • Params
    • Functions
    • client_nat_test()
      • fix_contact()
      • nat_keepalive()
    • Pseudo Variables
    • Statistics
  • NATHelper Module
    • NAT pinging types
      • UDP packet
      • SIP request
    • params
    • functions
    • Pseudo Variables
    • RPC Commands

In this article, we discuss Nating in a SIP Server like Kamailio. Types of NAT pings, their behaviour and types. Also some implementation of some of the Kamailios modules like

  • NAT Traversal module
  • NAT helper module
  • STUN module

A repository for extensive application of kamailio modules for various usecases is https://github.com/altanai/kamailioexamples

DNS sub-system in Kamailio

To resolve hostname into IPs Kamailio can do either of below

  • use libresolv and a combination of the locally configured DNS server /etc/hosts and the local Network Information Service (NIS/YP a.s.o) or
  • cache the query results and first look into internal cache

DNS failover – if destination resolves to multiple addresses tm can try all of them until it finds one to which it can successfully send the packet or it exhausts all of them, with internal DNS cache. Also used when the destination host doesn’t send any reply to a forwarded invite within the SIP timeout interval (tm fr_timer parameter).

DNS load balancing – SRV based load balancing with weight value in the DNS SRV record.

  • (-) Only the locally configured DNS server (usually in /etc/resolv.conf) is
    used for the requests (/etc/hosts and the local Network Information Service are ignored).
    • optional: disable the DNS cache (use_dns_cache=off or compile without -DUSE_DNS_CACHE).
  • (-) DNS cache uses extra memory
    • optional: disable the DNS cache.
  • (-) DNS failover introduces a very small performance penalty
    • optional: disable the DNS failover (use_dns_failover=off).
  • (-) DNS failover increases the memory usage (the internal structures used to represent the transaction are bigger when the DNS failover support is compiled).
    • optional: compile without DNS failover support (DUSE_DNS_FAILOVER).Turning it off from the config file is not enough in this case (the extra memory will still be used).

NAT ( Network Address Translation)

Network address translation replaces the IP address within packets with a different IP address which internet endpoints can relate with. This enables multiple hosts in a private subnet with their pwn private address ( 10.x.x.x or 192.x.x.x etc ) to share single public IP address interface, to access the Internet.

NAT is bidirectional- If the private ip:port got translated to public ip:port on the inside interface while entering outside internet, on arriving from outside interface it will get translated from public ip:port to private ip:port.

For a SBC ( Session border controller ) or where the kamailio server is directly customer facing, where you dont have a private line or VPN to clients, then it is often encountered with NATed endpoints. Read more about NAT traversal using STUN and TURN here

Why is NAT is important in SIP?

These characteristics of SIP design and operation flows demonstrate why NAT solutions are so important

  • RFC 3261 for SIP presumed end-to-end reachability and does not specify much around ANT issues .
  • No NLRI (Network Layer Reachability Information) translation layer exists, such as DNS or ARP
  • SIP is designed to used RTP which uses dynamically allocated ports to stream media.
    It is comparable to FTP which creates ephemeral connections on unpredictable dynamic ports to send multiplexed data and “metadata”, instead of protocol like HTTP where all data is sent on same connection.
  • UDP (default transport for SIP) is connection less and session tracking requires these be mapped onto a statelful flow, rigorous keepalives and other such techniques like using TCP instead have their own tradeoffs
  • since sip packets put network and transport information right on sip header they are limited by the rateability and awareness of their network interface thereby prevent other endpoint from reaching its ip or port

Types of NAT solutions

  • Client-side NAT traversal – clients are responsible for identifying their WAN NLRI and adding ip and port to navigate them in outside world
  • Server-side NAT traversal – SIP server should discover the client’s WAN addressing while clients continue to work transparently behind NAT. Requires that DIP server look at the source and destination ip and port of actual packets instead of relying on the encapsulated sip headers and SDP body.
  • ALG (Application Layer Gateways) – mostly applied at router itself. wodk by susbtitung public IP/port information inplace of provate and vice versa for return packets. Limitataions – they dont provide a fullproof fix example they may fix Via but not the Contact address or SDP body or RTP ports
WebRTC signalling and media flow on Open public network
Open network leading to smooth p2p media stream

Far-end NAT traversal solution ( TURN server)

WebRTC media flow when peers are behind NAT . Uses TURN relay mechanism
public private ip mapping , firewalls and private network obstruct p2p media flow. TURN is useful to relay media pckets

NAT behaviours

Cone NATSymmetric NAT
Local client performs an outbound connection to a remote UA and a dynamic rule is created for the destination IP tuple, allowing the remote machine to connect back.Local client allows inbound connections from a specific source IP address and port, also NAT assigns a new random source port for each destination IP tuple
Further subdivied into:
1. Full Cone NAT
2. Restricted Cone NAT – all requests from the same internal IP address and port are mapped to the same external IP address and port.
-3. Port-Restricted Cone NAT


NAT not only applies to sip signalling packets but also to RTP. Even RTP packets are not able to transverse accross private -public network interfaces to the right place across a NAT’d connection.

To solve two-way media RTP performs RTP latching, where client listens for at least one RTP frame arriving at the destination port it advertised, and harvests the source IP and port from that packet and uses that for the return RTP path. RTP latching works out of the box for public RTP endpoints but not for ones behind NAT.

It is thus recommended to use an intermediate RTP relay such as RTPengine on kamailio. It is controlled via a UDP control socket by kamailio as an external process. More on installation and descrition of RTP engine on kamailio is covered here. When RTPengine control module receives RTP offer /answer from Kamailio, it opens a pair of RTP/RTCP ports to receive traffic and substitues in SDP. Doing so for both ends makes RTP engine come in the path of media stream packets for both directions.

A first INVITE has no no corresponding on NAT ( as no port has been allocated yet ) so the c= contact and m = media lines would look like

c=IN IP4
m=audio 23767 RTP/AVP 0 101.

We can force RTP to go through a proxy by changing c line and m line to

c=IN IP4 address-of-proxy  
m=audio port-on-proxy RTP/AVP 0 101

A separate daemon called an RTP proxy (with a public IP address) that both user agents can send their audio to, can be setup by calling force_rtp_proxy().

Fixing NAT

When the client is behind NAT, following needs to be taken careof to provide smooth operation

  1. Ensuring Tranactional replies are sent to correct source address ( maybe using ;rport param and forcerport() method ) instead of just relying on via header transport protocol and port.
if (client_nat_test("3")){

also Change Media ip address to public IP

if(nat_uac_test("8") && search("Content-type: application/sdp")) {

Any far-end NAT traversal solution ( TURN server) if employed should stay in path of entire Dialog not just for initial INVITE transaction which many times results in ACK being dropped. This can be achived by adding Record-Route header of rr module to the initial INVITE request itself

Set the advertised address of the public-facing inetrface to the Public NAT IP using “listen” parameter

Ensure contact URI is NAT processed by using NATHelper modules which rewrites the domain portion of the Contact URI to contain the source IP and port of the request or reply. add_contact_alias([ip_addr, port, proto]) in NAThelper module which adds “;alias=ip~port~transport” parameter to the contact URI containing either received ip, port, and transport protocol or those given as parameters

Implement RTP proxy which performs NAT for streams such as rtpengine module

NAT Traversal Module

Provides far-end NAT traversal to kamailio’s SIP signalling. Its role is

  • detect user agents behind NAT
  • manipulate SIP headers so that user agents can continue working behind NAT transparently
  • keepalives to UA behind NAT to preserve their visibility in network

Some pros and cons of NATTravsersal module

  • (+) detect even UAs behind multiple cascaded NAT boxes, complex distributed env with multiple proxies
  • (+) handle env where incoming and outgoing paths are diff for SIP messages
  • (+) handle cases when routing path may even change between consecutive dialogs
  • (+) can work for other than registered UA’s also
  • (-) built for IPv4 NAT handling not adapted to support IPv6 session keepalives.

Why use keepalive when Registrations are already there for NATing ?

  1. NAT binding works for registered users who want incoming calls. However for cases like outgoing calls or for presence subscription notifications, failings registration implies inability to receive further in-dialog messages after the NAT binding expires. This artificial binding for registrations makes system unreliable and volatile as it doesnot guarantee the delivery of in-dialog messages for outgoing calls without registration renewal. Therefore keepalive are adopted which also works for unregistered users.
  2. Minimizes the traffic as only border proxies send keepalives which send keepalives statelessly, instead of having to relay messages generated by the registrars.
  3. Also for situations when DNS resolves diff proxies for outgoing or incoming path traditional register based keepalives fail to associate or dissociate correct routes.

How keepalives work for NATing ?

This mechanism works by sending a SIP request to a user agent behind NAT to make that user agent send back a reply. The purpose is to have packets sent from inside the NAT to the proxy often enough to prevent the NAT box from timing out the connection.

Module sends Keeplaives to preserve their visibility only in :

  • Registration – for user agent that have registered to for incoming calls, triggering keepalive for a REGISTER request.
  • Subscription – for presence agents that have subscribed to some events for receiving back notifications with SUBSCRIBE request.
  • Dialogs – for user agents that have initiated an outgoing call for receiving further in-dialog messages.
    When all the conditions to keepalive a NAT endpoint will disappear, that endpoint will be removed from the list with the NAT endpoints that need to be kept alive.

function nat_keepalive()

  • the function needs to be called on proxy directly interacting with UA behind NAT.
  • call only once for the requests (REGISTER, SUBSCRIBE or outgoing INVITEs) that triggers the need for network visibility.
  • call before the request gets either a stateless reply or it is relayed with t_relay()
  • for outgoing INVITE , it triggers dialog tracing for that dialog and will use the dialog callbacks to detect changes in the dialog state.

Dependencies – sl , tm and dialog module


  • keepalive_interval – time interval between sending a keepalive message to all the endpoints that need being kept alive. A negative value or zero will disable the keepalive functionality.
modparam("nat_traversal", "keepalive_interval", 30) // 30 seconds keeplaive inetrval
  • keepalive_method – SIP method to use to send keepalive messages.usual ones are NOTIFY and OPTIONS. Default value is “NOTIFY”.
modparam("nat_traversal", "keepalive_method", "OPTIONS")
  • keepalive_from – SIP URI to use in the From header of the keepalive requests. default sip:keepalive@proxy_ip,with IP address of the outgoing interface
modparam("nat_traversal", "keepalive_from", "sip:keepalive@altanai.com")
  • keepalive_extra_headers – extra headers that should be added to the keepalive messages. Header must also include the CRLF (\r\n) line separator. Multiple headers can be specified by concatenating with \r\n separator.
modparam("nat_traversal", "keepalive_extra_headers", "User-Agent: Kamailio\r\nX-MyHeader: some_value\r\n")
  • keepalive_state_file – filename where information about the NAT endpoints and the conditions for which they are being kept alive is saved . It is used when Kamailio starts to restore its internal state and continue to send keepalive messages to the NAT endpoints that have not expired in the meantime. Also used at kamailio restart as it avoids losing keepalive state information about the NAT endpoints.
modparam("nat_traversal", "keepalive_state_file", "/var/run/kamailio/keepalive_state")


  • client_nat_test ()– Check if the client is behind NAT. Tests to be performed gievn by int can be :
    1 – tests if client has a private IP address or one from shared address space in the Contact field of the SIP message.
    2 – tests if client has contacted Kamailio from an address that is different from the one in the Via field.
    4 – tests if client has a private IP address or one from shared address space in the top Via field of the SIP message.

For example calling client_nat_test(“3”) will perform test 1 and test 2 and return true if at least one succeeds, otherwise false.

  • fix_contact() – replace the IP and port in the Contact header with the IP and port the SIP message was received from. Usually called after a succesfull call to client_nat_test(type)
if (client_nat_test("3")) {
  • nat_keepalive() – Triggers keepalive functionality for the source address of the request. When called it only sets some internal flags, which will trigger later the addition of the endpoint to the keepalive list if a positive reply is generated/received (for REGISTER and SUBSCRIBE) or when the dialog is started/replied (for INVITEs). For this reason, it can be called early or late in the script. The only condition is to call it before replying to the request or before sending it to another proxy. If the request needs to be sent to another proxy, t_relay() must be used to be able to intercept replies via TM or dialog callbacks.

If stateless forwarding is used, the keepalive functionality will not work. Also for outgoing INVITEs, record_route() should also be used to make sure the proxy that keeps the caller endpoint alive stays in the path.

if ((method=="REGISTER" || method=="SUBSCRIBE" ||
    (method=="INVITE" && !has_totag())) && client_nat_test("3"))

Pseudo Variables

  • $keepalive.socket(nat_endpoint)
  • $source_uri


  • keepalive_endpoints – total number of NAT endpoints that are being kept alive.
  • registered_endpoints – NAT endpoints kept alive for registrations
  • subscribed_endpoints – NAT endpoints kept alive for subscriptions.
  • dialog_endpoints – Indicates how many of the NAT endpoints are kept alive for taking part in an INVITE dialog.

NATHelper Module

NAT traversal and reuse of TCP connections.
Helps symmetric UAs who are not able to determine their public address.

NAT pinging types

UDP packet
4 bytes (zero filled) UDP packets are sent to the contact address.
SIP request
a stateless SIP request is sent to the UDP contact address.
(+) low bandwitdh traffic,
(+) easy to generate by Kamailio;
(+) bidirectional traffic through NAT
(+) since each PING request from Kamailio (inbound traffic) will force the SIP client to generate a SIP reply (outbound traffic) – the NAT bind will be surely kept open.
(-) unidirectional traffic through NAT (inbound – from outside to inside);
if many NATs do update the bind timeout only on outbound traffic, the bind may expire and closed.
(-) higher bandwitdh traffic
(-) more expensive (as time) to generate by Kamailio;

Dependencies – usrloc


  • force_socket – Socket to be used when sending NAT pings for UDP communication.
modparam("nathelper", "force_socket", "")
  • natping_interval
  • ping_nated_only
  • natping_processes – How many timer processes should be created by the module for the exclusive task of sending the NAT pings.
  • natping_socket
  • received_avp – AVP used to store the URI containing the received IP, port, and protocol by fix_nated_register
  • sipping_bflag
  • sipping_from
  • sipping_method
  • natping_disable_bflag
  • nortpproxy_str
  • keepalive_timeout
  • udpping_from_path
  • append_sdp_oldmediaip
  • filter_server_id


  • fix_nated_contact() – rewrites the “Contact” header field with request’s source address:port pair
  • fix_nated_sdp() – adds the active direction indication to SDP and updates ource ip address information too
  • add_rcv_param() – add a received parameter to the “Contact” header fields or the Contact URI.
  • fix_nated_register() exports the request’s source address:port into an AVP to be used during save()
  • nat_uac_test()- check if client’s request originated behind a nat
  • is_rfc1918()
  • add_contact_alias() – Adds an “;alias=ip~port~transport” parameter to the contact URI
  • handle_ruri_alias() – Checks if the Request URI has an “alias” parameter and if so, removes it and sets the “$du” based on its value.
  • set_contact_alias()

Pseudo Variables

  • $rr_count – Number of Record Routes in received SIP request or reply.
  • $rr_top_count – If topmost Record Route in received SIP request or reply is a double Record Route, value of $rr_top_count is 2.

RPC Commands


References :

Kamailio Architecture, Core and Modules

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

Kamailio® (successor of former OpenSER and SER) is an Open Source SIP Server released under GPLv2+, able to handle thousands of call setups per second. Kamailio can be used to build large platforms for VoIP and realtime communications – presence, WebRTC, Instant messaging and other applications.  Moreover, it can be easily used for scaling up SIP-to-PSTN gateways, PBX systems or media servers like Asterisk™, FreeSWITCH™ or SEMS.


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

Kamailio architecture

Kamailio follows RFC 3261 for SIP and can act as Registrar, Location server, Proxy, Redirect or event Application Server based on its configuration. The modular architecture of Kamailio enables extending the core functionality in various directions using modules.

Kamailio’s modular architecture

Kamailio Core

At the Core, Kamailio is build for SIP meesage handling. The core includes:

  1. memory manager
  2. SIP message parser
  3. locking system
  4. DNS and transport layer management (UDP, TCP, TLS, SCTP)
  5. configuration file parser and interpreter
  6. stateless forwarding
  7. pseudo-variables and transformations engines
  8. RPC control interface API
  9. timer API

The internal libraries include:

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

Kamailio Modules

There are over 150 modules in Kamailio dealing with add-on features that can be categorised into various functional areas such as

  • registrar and user location management
  • accounting, authorization and authentication
  • text and regular expression operations
  • stateless replying
  • stateful processing – SIP transaction management
stateful processing is per SIP transaction

Each SIP transaction will be kept in memory so that any replies, failures, or retransmissions can be recognized
Forwarding each msg in the dialog without any context.
Application understands the transactions , for example
– recognize if a new INVITE message is a resend
– know that 200 OK reponse belongs to the initial INVITE which it will be able to handle in an onreply_route[x] block.
it doesnt
know that the call is on-going.
However it can use callId to match INVITE and BYE.
Uses : manage call state , routing , call control like forward on busy, voicemailUses : Load distribution , proxying
  • 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

Routing a Call

A SIP server can either

  • direct the call and let the UA contact with each other directly or
  • force itself in the path by inserting a Route header in the SIP message (e record_route())

Locking Management

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

Simple Locks APILock Set API

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 MemoryShared Memory
Memeory is specific per process.
No synchronization is needed to access structures allocated in it, such as varaibles not needed by other process or ones for temporary operations.

Private memory manager is accessed via mem/mem.h
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.

Here locks are used to prvent race conditions.

Shared memeory can be acceses via mem/shm_mem.h.

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

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.


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
  • 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.


  • 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.lookup table AOR
ul.rm table AOR
ul.rm_contact table AOR contact




  • 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 :


Statistics :


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. Dialog module keeps track of current dialogs also provides API support. It can be loaded and used as

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
  • hash_size
  • rr_param
  • dlg_flag
  • timeout_avp
  • default_timeout
  • early_timeout
  • noack_timeout
  • end_timeout
  • dlg_extra_hdrs
  • dlg_match_mode
  • detect_spirals
  • db_url
  • db_mode
  • db_update_period
  • db_fetch_rows
  • db_skip_load
  • table_name
  • call_id_column
  • from_uri_column
  • 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
  • vars_h_id_column
  • vars_h_entry_column
  • vars_key_column
  • 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 callback 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")
             logger.log("info", "successfully posted")
  • 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 :


RPC Commands :


Exported Variables :


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 based ( such as webRTC) calls on kamailio.


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:


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
 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;


  • xhttp_reply(code, reason, ctype, body) – Send back a reply with content-type and body.
event_route[xhttp:request] {
    xhttp_reply("200", "OK", "" , "");
    xhttp_reply("403", "Forbidden", "", "");

Event Routes

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</body></html>");

Websocket Module

This module provides 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).

References :

[1] SER Getting started : https://kamailio.org/docs/ser-getting-started/SER-GettingStarted.pdf

[2] Registrar module in kamailio http://kamailio.org/docs/modules/stable/modules/registrar.html

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


and others like


timeout_socket (string)

ice_candidate_priority_avp (string)

extra_id_pv (string)

db_url (string)

table_name (string)

rtp_inst_pvar (string)


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 { 

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


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")) { 
if (is_audio_on_hold()) {
rtpproxy_stream2uas("/var/rtpproxy/prompts/music_on_hold", "-1");
} else {

rtpproxy_stream2uas(prompt_name, count)

rtpproxy_stop_stream2uac()- Stop streaming of announcement/prompt/MOH



Exported Pseudo Variables


RPC Commands


Ref : https://kamailio.org/docs/modules/5.3.x/modules/rtpproxy.html