Kevin Bataille

Kamailio: Discovery Tutorial – Part 1

I discovered Kamailio a year ago when I needed to develop an SBC (Session Border Controller) whose primary function was to protect an Asterisk instance. Since then, the initial requirement has evolved, and by definition, the technical solution has as well. I have been able to improve my skills with the software and, in the process, gained flexibility with it within a VoIP technical stack.

Since online resources regarding Kamailio use cases are relatively limited, I will try to explain this software through a series of articles featuring configuration examples.

First and foremost, before diving deeper into this tutorial, it is recommended to have some knowledge of SIP (RFC 3261).

Definitions

To better understand the concepts mentioned in this article and the broader Kamailio ecosystem, here is a list of essential definitions.

Core SIP Roles

Note: Most SIP endpoints (like IP phones or PBXs) act as both a UAC and UAS depending on whether they are making or receiving a call

VoIP Components

Switching Classes

What is Kamailio?

Kamailio (formerly OpenSER) is a free and open-source SIP server. It is written in C with a specific focus on performance. Kamailio is highly configurable and can act as a SIP registrar, proxy, or even a load-balancer, thanks to its modular architecture.

Contrary to what one might think, Kamailio is not a PBX and differs from Asterisk, FreeSwitch, and the like. Kamailio is also not a B2BUA (Back-to-Back User Agent); it only manages signaling (SIP), whereas a PBX will additionally manage media (voice) or include call-center features.

To meet a specific need with Kamailio, you must configure it. The default Kamailio configuration does nothing; however, it provides a glimpse of the software’s possibilities. This is also why SIP knowledge is necessary, as you must have an idea of the requests and responses required for the software to function correctly.

Note : media is not handled by Kamailio. For this, I recommand RTPEngine from SIPWise.

Where to find Kamailio documentation?

On the official Kamailio website, you can find two types of documentation: the official wiki and the modules documentation. The official documentation is very thorough, and both the Wiki and the module pages explain Kamailio’s configuration very well.

On the other hand, when it comes to specific use cases and architectures involving third-party components, it is harder to get a high-level overview. Figures like Fred POSNER often praise Kamailio, and thankfully, the Kamailio World YouTube channel exists. Additionally, it is possible to draw inspiration from OpenSIPS documentation and its tutorials, although differences between the two projects appear very quickly.

Installing Kamailio

Kamailio is available on Linux and BSD. On Ubuntu, install Kamailio from the official repositories: $ sudo apt install kamailio

Edit the configuration: /etc/kamailio.cfg.

It is also possible to use Kamailio with Docker using a configuration like the one below:

networks:
  default:
  # database:
  #   external: true

services:
  # Primary Kamailio instance
  kamailio:
    image: ghcr.io/kamailio/kamailio:6.0.4-bookworm
    restart: unless-stopped
    volumes:
      - ./kamailio:/etc/kamailio
      - ./kamailio/logs/kamailio:/var/log/kamailio
    network_mode: host # Expose 5060 for TCP/UDP and 5061 for TLS

  # RTP Engine service
  rtpengine:
    image: fonoster/rtpengine:latest
    container_name: rtpengine
    restart: unless-stopped
    network_mode: "host" # At the moment this option only works in Linux
    environment:
      # RTPENGINE_PUBLIC_IP: ${DOCKER_HOST_ADDRESS:-192.168.1.210} When commented, use Netdiscover
      RTPENGINE_BIND_NG_IP: ${RTPENGINE_BIND_NG_IP:-127.0.0.1}
      RTPENGINE_BIND_NG_PORT: ${RTPENGINE_BIND_NG_PORT:-2223}
      RTPENGINE_PORT_MIN: 10000
      RTPENGINE_PORT_MAX: 20000
      RTPENGINE_LOG_LEVEL: "6"

Note that network_mode: host is only supported on Linux. Furthermore, SIP and RTP protocols do not handle NAT (Network Address Translation) very well if you decide to expose Kamailio and RTPEngine ports via Docker mapping.

Some SIP Notions

For this first article, I will list some of the SIP requests you should know. They will be useful whether you are working with Kamailio or any other PBX.

SIP RequestDescription
INVITEInitiates a call session.
ACKConfirms the receipt of a final response (e.g., after INVITE).
BYETerminates an existing session.
CANCELCancels a pending INVITE request before it is answered.
REGISTERRegisters a user’s location with a SIP server.
OPTIONSQueries the capabilities of a server or endpoint.
INFOCarries mid-session control information (e.g., DTMF).
PRACKAcknowledges reliable provisional responses.
UPDATEModifies session parameters without re-issuing an INVITE.
REFERRequests the recipient to initiate a new request (often for call transfers).

Discovering Kamailio

Let’s begin this tutorial with Kamailio. Here are a few SIP concepts that will be useful if you are a beginner. At the very least, they will serve as a refresher.

Example of an INVITE request

Take the example of a SIP request used to place a call: INVITE. Imagine two users, 1001 and 1002, where 1001 wants to call 1002.

According to RFC 3261, 1001 must send a SIP request to 1002; however, this implies knowing the IP address and the port where 1002 is available. In practice, it never works this way; 1001 will send this request to a SIP server which will be responsible for relaying it (like a proxy) or issuing a new one (like a PBX/B2BUA).

INVITE sip:1002@voip.operator.re SIP/2.0

In a setup with two phones, this request makes 1002‘s phone “ring.” If we sent this message to a generic PBX, it would have the necessary logic to know it has an extension 1001 and would ring extension 1002.

With a PBX

A generic PBX examines the Request-URI in the received INVITE message and has predefined logic to know that 1002 is a device it has registered and that we want to connect to that device. It then sends the call to the corresponding device (1002). This is the “classic” operation of Asterisk, FreeSwitch, or any PBX. To put it simply, if we send this request to Asterisk, it would verify that it has the users (endpoints in PJSIP) and, if the dialplan allows, redirect the request to the recipient (example dialplan line: Dial(PJSIP/${EXTEN},30,tTr)). Response management is automatic with a PBX, as it focuses on the core logic: establishing calls between users, whether local or remote via a trunk.

With Kamailio

Kamailio works in a completely different way. If you want Kamailio to react to this request, you must write it into its configuration and instruct it—much like a programming language—on what actions to take. Roughly speaking, this would involve programming Kamailio to accept INVITE requests, check if the recipient’s Address of Record (AoR) is in memory, respond with a 100 Trying, forward the INVITE to the destination, and finally return a 200 OK to the caller. This results in the following diagram:

Call flow using Kamailio

Here, I have omitted the fact that we must also handle 4XX responses if the callee is busy or away, manage users, and handle voice media (RTP). While all of this might seem difficult to manage, it is essentially “programming” in the broad sense of the term.

Even if this example seems basic, it helps you understand how the system handles and routes your SIP messages. Ultimately, this opens the door to many features, such as managing prepaid or postpaid call authorizations, saving Call Detail Records (CDRs), implementing firewalling, load-balancing, Least Cost Routing (LCR), and more.

Final Word

Kamailio is a software that is difficult to master. Initial encounters can be daunting, and you may sometimes feel like giving up. With a bit of experience, it is possible to achieve great things with Kamailio, which can be used as a Class 5 softswitch (for profesionnals) or a Class 4 softswitch (for ISP and ITSP).

Exit mobile version