Asterisk High-Availability Kamailio Load Balancer RTP RTPEngine SIP VoIP

RTPEngine with Kamailio as Load-balancer and IP Gateway

This post explains how to setup Kamailio as an SBC and IP Gateway. We are using Debian 8 in this example. It uses Kamailio’s dispatcher module to distribute calls to Asterisk. It uses RTPEngine to proxy media to & from the public internet across the LAN to Asterisk.
This is a powerful setup as you can easily scale out using a single public IP address.
Here is the IP layout we will be implementing:

Kamailio Public (eth0)
Kamailio Private (eth1)
Asterisk machine 1 -
Asterisk machine 2 -

Setup Debian and iptables to act as IP Gateway:

# edit /etc/sysctl.conf
enabled net.ipv4.ip_forward=1

# add iptables rules
iptables -F
iptables -t nat -F

iptables -P INPUT ACCEPT

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth1 -s -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Install RTPEngine + Kamailio with RTPEngine Module.

Download kamailio.cfg

Download sip.conf

Download /etc/default/ngcp-rtpengine-daemon

30 replies on “RTPEngine with Kamailio as Load-balancer and IP Gateway”

Hello Emmanuel,
Thank for example. This example will work only udp transport. I am trying do same setup only public side of kamailio is TCP or TLS and freeswitch side is UDP.
I have really hard time to implement it . Tried on replace contact on REGISTER then save location, but it not really stable sometimes call failing because user contact in DB not up to date. Also I tried adjust $ru on reply to point back to hardware phone. Also RTPENGINE only work for one leg call like volicemail, between extensions no RTP. Any suggestions on that setup ?

Are you using kamailio as the registrar or forwarding the REGISTER packets to FreeSWITCH?

Make sure you are adding the path header when forwarding to FreeSWITCH. If you want FreeSWITCH to use UDP when sending INVITE to the user, you can add the path with a parameter like so:
add_path("", "transport=udp");
Feel free to email me direct at or chat me on Skype: eschmidbauer

Hello Emmanuel,
I use a similar setup with Kamailio as a sip server and Freeswitch as a media server. RTP server was also used when started working behind the NAT. Behind NAT without RTP server, i was not able to hear the voice and hence i came to conclusion RTP Server does all the magic.
Now I’m working within NAT, with similar set up of 3 separate servers(Kamailio,rtp,freeswitch).
But I can never see the RTP server IP in the wireshark packet flow for flawless working calls. The RTP flow actually passes from one client to another client via Freeswitch alone!! What is actual usage of RTP engine now???? Please help to understand the actual need of RTP!
Note: If I remove the RTP engine there is a delay in RTP packet flow which results in delayed voice.

Thanks in advance,

Typically rtpengine is used as an edge RTP proxy. This has the benefit of exposing RTP on a single public IP address to the world, while at the same time being able to distribute the RTP to your private servers (e.g. multiple freeswitch servers). It can help with scaling out your setup and at the same time allowing for simple and secure front-end. If you are not concerned with exposing a single endpoint for RTP (e.g. putting public IPs on your freeswitch servers), then you don’t need to use rtpengine. FreeSWITCH has many settings which will try to detect and fix NAT automatically. If you are using rtpproxy to send media to FreeSWITCH, you need to make sure NAT settings are correctly configured. I hope this answers your question, thanks.

Awwh that was a faster reply, Thank You 🙂
I can now see some dim picture of RTP engine now (in proxy perspective). Say I’m in internal network with no public IP exposure needed, now do I need RTP engine in between kamailio and freeswitch? I’m working on internal network with which calls first lands in kamailio->Freeswitch->(some-X)gateway->extension, in this flow, RTP engine fits somewhere.

Hello Emmanuel,

I’m searching for solution, that somehow mix my two rtp streams (Audio and Video) in one single rtp stream. My setup is Kamailio and RTPProxy and all is proxied (SIP and RTP are behind proxy IP), but still in two different rtp streams, one for audio and one for video. Do you know can I achieve it with this setup (Kamailio and RTPProxy and …in future Asterisk) or do you know some software that can help? Thanks in advance and sorry for my English.

Best regards,

Not sure which version I used for this post. I usually compile latest code from source.

Hi I’m new to kamailio and a checked this post.

Is it possible to use/change this configuration to receive all on private and send on private to freepbx including registrar


yes, this is possible, although there may be some changes required in FreePBX.

Hi Emmanuel,

My client has this setup in their network and a basic P2P call flows like this –

UA1 – Kamailio [RTPEngine] – Asterisk – Kamailio[RTPEngine] – UA2
Audio media flows from UA1 via RTPEngine to Asterisk to UA2 and vice versa.

Is it possible to configure Kamailio/RTPEngine pair so that for a call which is negotiated with audio and video both, the audio takes the above path. However for video I want to route via RTPEngine to destination UA, bypassing Asterisk.


hi, you pointed all rtpengine and kamailio config settings, but nothing at the asterisk side.. can you point in right direction due if i close all ports and only let kamailioasterisk internal ip comuniaciont audio does not happened…

I have installed latest Kamailio to Debian 10 and i have two instances of Asterisk. I jave followed the guide to setup the systems and evennthebIP scheme isnthe same as the example. I have created some users in Kamailio and they can call each other. I would like to have voicemail services and forward services to Asterisk servers. Could you share an example please?

I did follow the guide and i got Kamailio up and running as 2 instances of Asterisk as well. Users should be created in Asterisk or in Kamailio in your example? i am looking to either create users in asterisk or Kamailio, but all the media to go through Asterisk. is this a correct approach? What does Asterisk servers loadbalance in your example here media services or user accounts?
Could you share an example of extensions.conf and the full kamailio.cfg, to make it work please?

It really depends on the design you have chosen. Personally, I prefer to use kamailio as a registrar but others might prefer asterisk or a “hybrid” type setup (where both kamailio & asterisk have sip user data)


I am using kamailio with websocket and forwarded registration to asterisk. But unable to use rtpengine as media relay for asterisk. How it can be done ?

Could you attach some sip traces and more details about your setup?
I have not used asterisk this way but if you are using WebRTC client, asterisk might need to support ICE unless you have rtpengine removing the ICE candidates before sending to asterisk.

Thanks Emmanuel.

My setup is

WebRTC (Agent1) -> Kamailio -> Asterisk -> Kamailio -> WebRTC (Agent2)

WebRTC calling is working properly on local and public network. But when open server from public network found that RTP is traversing through asterisk server instead of kamailio (where rtpengine installed). If I NAT udp port range with asterisk server webrtc calling works properly, but I want to NAT UDP port range with kamailio itself.

For this setup i have implemented below github code

added below cod for small change to route call to asterisk.

# Test if coming from Asterisk
&& $sp==$sel(cfg_get.asterisk.bindport))
return 1;
return -1;

# Send to Asterisk
/*$du = “sip:” + $sel(cfg_get.asterisk.bindip) + “:”
+ $sel(cfg_get.asterisk.bindport);*/
ds_select_dst(1, 4);

# Forward REGISTER to Asterisk
route[REGFWD] {
$var(rip) = $sel(cfg_get.asterisk.bindip);
xlog(“L_INFO”, “Register on asterisk server”);
$uac_req(ruri)=”sip:” + $var(rip) + “:” + $sel(cfg_get.asterisk.bindport);
$uac_req(furi)=”sip:” + $au + “@” + $var(rip);
$uac_req(turi)=”sip:” + $au + “@” + $var(rip);
$uac_req(hdrs)=”Contact: \r\n”;
if($sel(contact.expires) != $null)
$uac_req(hdrs)= $uac_req(hdrs) + “Expires: ” + $sel(contact.expires) + “\r\n”;
$uac_req(hdrs)= $uac_req(hdrs) + “Expires: ” + $hdr(Expires) + “\r\n”;

Hi Avinash, could you share your complete config? I keep getting errors when dialing from webrtc client to another webrtc client.


Leave a Reply

Your email address will not be published. Required fields are marked *