Kamailio Behind NAT

Kamailio
Kamailio 4

After returning home from AstriCon 10, I decided to start-up a new server and see how long it would take me to run a working Kamailio server behind NAT (on a private IP). Bottom line? About 30 minutes.

I was lucky to help staff the Kamailio booth this year and was honored to help so many other VoIP professionals (and enthusiasts) with their questions about Kamailio, so without further ado…

What is Kamailio?

Kamailio (OpenSER) is an open source SIP server capable of handling thousands of call set-ups per second. Some amazing features include: 

  • Secure communication via TLS
  • Load Balancing
  • WebSocket support for WebRTC
  • failover
  • Security
  • and mucho mas

 Who should use Kamailio?

If you’re running fewer than 100 phones, you  most likely won’t have a need for Kamailio — unless you want failover, enhanced security, WebRTC, or one of the other Kamailio features.

I use Kamailio to help protect my systems from scanners, brute force SIP attacks, and other fun aspects of running business on the Interwebs.

… but … I digress …

Running Kamailio behind NAT

Many of us don’t have access to large numbers of public IP addresses. Some of us also like running systems on private IP addresses for personal reasons.

In the past (and still today), it was recommended that you run Kamailio on a public IP address. Regardless of the reason, with a patched rtpproxy and an advertised public IP address, you can have Kamailio running on a private IP address very quickly.

(NOTE: This tutorial was written for Kamailio 4.0 and an old version of RTPProxy. I recommend running the current version of both.)

Step 1: Install Kamailio

I chose to install Kamailio on CentOS. I’m not going to get into a religious war here on what OS you should use. Most of the development team of Kamailio use debian… I like CentOS, and that’s what I choose to deploy.

There’s an excellent tutorial for installing Kamailio posted on the main wiki: Install And Maintain Kamailio v4.0.x Version From GIT.

For CentOS, I first disable selinux, and then install some pre-reqs:

yum -y install gcc gcc-c++ bison openssl-devel libtermcap-devel ncurses-devel doxygen curl-devel newt-devel mlocate lynx tar wget nmap bzip2 unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel mysql-connector-odbc mysql mysql-devel mysql-server flex libxml2 libxml2-devel pcre pcre-devel git

Some of these aren’t fully necessary for the deployment, but are good tools to have. I also generally install the development tools group as well.

yum groupinstall "Development Tools"

Once everything is ready (a reboot doesn’t hurt), it’s time to download and install Kamailio.

mkdir -p /usr/local/src/kamailio-4.0
cd /usr/local/src/kamailio-4.0
git clone --depth 1 git://git.sip-router.org/sip-router kamailio
cd kamailio
git checkout -b 4.0 origin/4.0
make cfg

Next, open modules.1st. I use vi. You can use whatever you’d like.

vi modules.1st

Find the section that says include_modules and add db_mysql. It will look like:

include_modules= db_mysql

Save the file… and let’s continue.

make all
make install

Step 2: Create the Database

Open the kamctlrc file, uncomment the mysql database reference, and change the default passwords:

vi /usr/local/etc/kamailio/kamctlrc
DBENGINE=MYSQL

Save the file and run the following command:

/usr/local/sbin/kamdbctl create

This creates the kamailio database for you.

Step 3: Modify the Kamailio config file

Kamailio builds a default file for you. We’re going to quickly modify it to get this demo working.

vi /usr/local/etc/kamailio/kamailio.cfg

Insert the following after the #!Kamailio line:

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB
#!define WITH_ANTIFLOOD
#!define WITH_NAT

This adds a minimal amount of protection to your system (with ANTIFLOOD) and allows you to authenticate users to your system. It will also start the ball rolling for NATted communication.

Next, find the line that says: #!define DBURL “mysql://kamailio:kamailiorw@localhost/kamailio” and replace with:

#!define DBURL "mysql://USERNAME:PASSWORD@localhost/kamailio"

Next, find the line that says: #listen=udp:10.0.0.10:5060 and underneath it, add:

listen=udp:PRIVATEIP:5060 advertise PUBLICIP:5060

Save the file. Smile.

The advertise function here is key for running behind NAT along with…

Step the Fourth: Install the Patched rtpproxy

(NOTE: If you use the current version of rtpproxy, you won’t need to install the patch– it includes the advertise option)

rtpproxy is an open source program written by Sippy Software and available from their website, rtpproxy.org. The current stable version of rtpproxy is 1.2.1 and is missing one awesome feature — the ability to use an advertised address.

Luckily there are programmers who have resolved this issue for us.

Back in 2009, Daniel Goepp posted a patch to RTPproxy to support putting rtpproxy behind NAT.

Another Daniel, Daniel-Constantin Mierla, posted a patched version of rtpproxy on github.

We’ll choose the github for this example. I downloaded as a zip file and installed.

unzip master.zip
cd rtpproxy-master
./configure
make all
make install

You now have a version of rtpproxy that will advertise a public IP from behind NAT.

The Fifth Step: Starting the services

Since you’re behind NAT, you’re most likely going to want to forward UDP port 5060 for SIP and a UDP port range for RTP from your firewall to your Kamailio server’s private IP. For this example, let’s use an RTP port range of 20,000 to 30,000. (you’ll take care of your firewall forwarding however is needed on your particular firewall)

Start rtpproxy with a set rtp port range and an advertised public IP:

rtpproxy -A PUBLICIP -F -l PRIVATEIP -m 20000 -M 30000 -s udp:*:7722 -d INFO

Next, start Kamailio

kamctl start

Step 6: Add some users, and make calls

Adding a user is simple:

kamctl add USERNAME PASSWORD

For example, you could run kamctl add qxork superhotyeni which would add the user qxork with a password of superhotyeni.

In Closing…

Kamailio is incredible software… it’s addictive and you start learning that SIP can become a really incredible tool to work with.

To know Kamailio is to know SIP.

And there’s the problem. To know SIP you must learn SIP and play with SIP.

Since most of us don’t have access to spare servers that we can put on a public IP, we’re stuck learning the system on a local NAT at the office or (more commonly) at the house.

Running Kamailio behind NAT allows you to learn, test, and play with SIP. Now, there’s no excuse… let’s start learning!

Additional Reading:
Need Help?

We’re a friendly community. We also have cookies.

Fred Posner provides VoIP consulting services through The Palner Group and LOD Communications. In 2010, Fred Posner and his wife, Yeni Monroy, opened their bakery, in Gainesville, Florida. Contact Fred at qxork.com. Even better… make Yeni happy and buy a Big Fred Cookie!

34 Comments

Sean Harlow October 13, 2013 Reply

I first disable selinux

Not a great start. I know SELinux can get annoying, but like UAC on Windows it’s better for all to do it right and work with SELinux rather than just telling people to turn off a useful security feature.

Also…

Some of us also like running systems on private IP addresses for personal reasons.

Mind explaining? The problems with NAT and thus private addresses for internet communications are well known, especially to those of us dealing with SIP. What possible reason could you have to want to keep dealing with those headaches?

I personally welcome the exhaustion of IPv4, the faster we get IPv6 everywhere the sooner NAT can be eliminated.

Fred Posner October 13, 2013 Reply

Hi Sean,

There’s an irony in complaining that turning off selinux is not a great start while private ips / NAT be completely eliminated.

Not a great start. I know SELinux can get annoying, but like UAC on Windows it’s better for all to do it right and work with SELinux rather than just telling people to turn off a useful security feature.

I guess this depends on what your definition of useful is. There are other ways to secure your system without adding the overhead of selinux.

Much like choosing an OS, there’s pros and cons. For me, I choose to handle security with firewalls and other methods; avoiding selinux for servers.

The problems with NAT and thus private addresses for internet communications are well known, especially to those of us dealing with SIP. What possible reason could you have to want to keep dealing with those headaches?

There are many ways of dealing with NAT; especially with SIP. Although it’s not fun to deal with NAT and SIP, tools included with Kamailio, FreeSWITCH, and Asterisk really deal with this nicely. Benefits of a private IP include aspects of security; such as obscuration, independent numbering with simplified routing, load balancing, and more.

The thought of changing a provider and renumbering a large network is ridiculous. It’s resolved with NAT and exists with ipv6.

Of course, NAT absolutely does not provide security in of itself. It’s a tool that can help with security… which brings me back to the ironic statement.

Rodolfo Negron M. November 27, 2013 Reply

Hello, congratulations for the tutorial, I have would be great that you can help me with Kamailio:
1: I have a public ip connected to the router and from there I assigned 192.168.1.100 as Kamailio server
2: The router has routed all traffic udp / tcp 5060 to 192.168.1.100 I also configured with NAT-A xxxx rtpproxy-F-l 192.168.1.100-m 20000-M 30000-s udp: *: 7722 INFO-d where xxxx is the router.
Problem => 3: The devices can connect from anywhere but at the time of the voice call is transmitted.
Problem => 4: Jitsi allows me to IM but nothing more

Could you give me some advice I have exhausted all options, thanks.

Fred Posner November 27, 2013 Reply

The first step would be to gather some of the logs and post to the Kamailio maillist. Have you contacted the mail-list?

Mike Picher February 15, 2014 Reply

I’m seeing high CPU use with rtpproxy running this on CentOS 6, 64bit…

Anybody else see this?

I found this patch from miconda: https://github.com/miconda/rtpproxy/issues/1

Going to try to get the patch built and see if that fixes it.

Fred Posner February 15, 2014 Reply

If you’re running this on a VM, then yes… without that patch from @miconda, the cpu stays at 100%. Once patched, all is awesomely normal. I’ve only seen this on virtual machines.

Mike Picher February 15, 2014 Reply

Yea, I am running in a virtual.

I finally got the patch applied and re-compiled.

Seems to work better.

I did notice though if I stop kamailio, then start rtpproxy before kamailio I see high CPU. If I boot the server with kamailio starting at boot and then start rtpproxy after CPU is normal for rtpproxy.

Fred Posner February 15, 2014 Reply

Again, if you’re running on a VM without the patch it’s going to eventually use 100% CPU; if not at start then generally after the first use.

Ozed Oseghale June 20, 2014 Reply

Please, I need help with getting the patch to work.

I get errors when I run the patch. Your help will be most appreciated.

##> patch -p1 < patch-file
patching file main.c
Hunk #3 FAILED at 151.
Hunk #4 FAILED at 177.
2 out of 4 hunks FAILED — saving rejects to file main.c.rej
patching file rtpp_command.c
Hunk #1 FAILED at 201.
1 out of 1 hunk FAILED — saving rejects to file rtpp_command.c.rej
patching file rtpp_defines.h
Hunk #1 FAILED at 103.
1 out of 1 hunk FAILED — saving rejects to file rtpp_defines.h.rej

Fred Posner June 20, 2014 Reply

instead of running the patch you can install the patched version…

Ozed Oseghale June 20, 2014 Reply

I installed the github version rtpproxy-master following your instructions, but it was taking up all the CPU. My setup is on AWS. From your previous comments, I understand that running in a virtualized environment can result in high cpu consumption. Do you know of anyway to avoid this problem?

Thanks.

Alexandr March 19, 2014 Reply

I am installed Kamailio with your tutorial (thanks!), and http://kb.asipto.com/asterisk:realtime:kamailio-4.0.x-asterisk-11.3.0-astdb

I can’t dial form 101 to 102 peers, registered in Asterisk via Kamailio, but can listen VoiceMail greeting from Asterisk when got from kamailio SIP 404 Not found on dialing.

Listening on
udp: 192.168.182.23:5080 advertise PUB.LIC.IP.HERE:5080
Aliases:
udp: kamailio.localdomain:5080
udp: localhost.localdomain:5080
udp: localhost:5080
udp: kamailio:5080
*: PUB.LIC.IP.HERE:*
*: PUB.LIC.HOSTNAME.HERE:*

listen=udp:192.168.182.23:5080 advertise PUB.LIC.IP.HERE:5080

SIP trace:

http://pastebin.com/ZYsV7Rip

Fred Posner March 19, 2014 Reply

It looks like one of those (at least) is behind your firewall, no?

Le Thanh Tung April 15, 2014 Reply

Dear sir,

Thanks for your tutorial. I’ve already completed follow your guide. But i meet a problem when running rtpproxy -A PUBLICIP -F -l PRIVATEIP -m 20000 -M 30000 -s udp:*:7722 -d INFO

Message:
rtpproxy: host2bindaddr: Name or service not known

Could your please help me solve this issue.

Thanks for your support.

Best regards,
Tung.

Fred Posner April 16, 2014 Reply

Did you replace PRIVATEIP with an ip that is on the system?

Le Thanh Tung April 17, 2014 Reply

Hi Fred,

Thanks for your reply,

We tried to do as your guide but it seems that our configuration is not good. We test with 2 phones and here are the result:
1. Two phone can connect to each other.
2. Two phone can only comunicate (speak and hear) to each other if they are in the same network. When we connect 3G – Wifi network, we cannot hear to each other.
(We use linephone for test).

Very please if you can help us setup and config our server sothat phones can contact in both 3G and wifi. Please help us as a freelancer if you have time.
I’ll have some money to your training.

Sorry if my English is not good. Please help us.

I’m looking forwarding your reply.

Thanks.
Tung.

Fred Posner April 17, 2014 Reply

Hi Tung,

Yes. Support is available through The Palner Group and LOD Communications.

Jota April 29, 2014 Reply

Broken link:

http://dl.dropbox.com/u/9300853/yum/kamailio/el/6/i386/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 – “The requested URL re
turned error: 404 NOT FOUND”

Fred Posner April 29, 2014 Reply

I don’t have a link here to dropbox…

RTPProxy behind NAT June 20, 2014 Reply

This version works without CPU problems: https://github.com/luismr/rtpproxy-nat-aws

@Fred: Thanks for your tutorial!

Truong Pham Son June 29, 2014 Reply

How can I connect Jitsi to Kamailio?

– I install Jitsi on my Mac.
– I install CentOS on Parallels Desktop on my Mac.
– I install Kamailio on CentOS follow this tutorial.

I have an user : USERNAME – PASSWORD
SIP_DOMAIN=capsule.vn

I tryed many ways. Please teach me how to connect Jitsi to Kamailio.
More detail about my server at: http://stackoverflow.com/questions/24483040/how-to-jitsi-app-connect-my-local-kamailio-server

vineet February 24, 2015 Reply

Hi Frad,
Thanks for Such a Nice Blog ,
I will be thanks full you suggest how do we setup web-socket over SIP on Kamailio

It would really help for me .

Nick October 7, 2015 Reply

FWIW – rtpproxy 2.0 from rtpproxy.org seems to be correctly patched with the -A switch.

Nelson December 21, 2015 Reply

Hello,

Thank you for the post.

I would like to ask you something.
My scenario is an Asterisk and them a Kamailio

I applied the path and it works fine, sdp info is rewrite with the public IP address.

My INVITE: from kamailio to sip vendor
——————————————————

v=0
o=root 1857800054 1857800054 IN IP4 10.18.35.45
s=Asterisk PBX 1.8.32.3
c=IN IP4 10.18.35.45
t=0 0
m=audio 30036 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv
a=nortpproxy:yes

—————————————————————————————-
So far works fine, the problem I see when the OK with SDP is received, Kamailio rewrites the public IP address from the vendor and inserts the “advertised” IP.

My question is: Should Kamailio insert the advertised IP from Kamailio to Asterisk (or sip extensions registered in Kamailio) or should insert local Kamailio IP.

OK With SDP received

v=0
o=HuaweiSoftX3000 33567120 33567121 IN IP4 10.18.35.45
s=Sip Call
c=IN IP4 10.18.35.45
t=0 0
m=audio 30078 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=ptime:20
a=fmtp:101 0-15
a=nortpproxy:yes

Fred Posner December 21, 2015 Reply

This depends on multiple factors, and also how you’re calling the manage rtpproxy. Generally, if you use an advertised address and want to instead show an internal address, you’ll need to pass it in the manage command.

Nelson December 23, 2015 Reply

Thank you for your previous post.

I think in am on the right direction.

Calls is established and I have two way audio.
The problem starts when the callee (remote party) hangs up the call. The caller (Kamailio does not receive the BYE).

I am inserting a contact alias in order to have public IP (8.8.8.8 as an example) advertised in contact.

The problem is that internet router changes the source port and then vendor sends BYE to original port (5060) that is included in the contact alias and then router blocks the request.

if (!add_contact_alias(“8.8.8.8”, “$Rp”, “udp”)) {
xlog(“L_ERR”, “Error in aliasing contact $ctn”);
send_reply(“400”, “Bad request”);
exit;
}
}

¿How can I include nat´d source port in the contact?

Thank you

Kevin F March 23, 2016 Reply

Hi,

I am attempting a similar setup. I have Kamailio connecting the calls fine, just no audio. When performing an RTP debug on the SIP server, I noticed it is not trying to send the RTP packets to Kamailio, but instead tries to connect RTP directly to user (phone). Do you know how I can explicitly make RTP go through Kamailio?

Fred Posner March 23, 2016 Reply

If both phones are trying to send the media to each other, and you do not want this, then you can force a proxy of the media. Just before t_relay() the signalling to the second leg, use rtpproxy module’s function manage_rtpproxy().

Irontec September 8, 2017 Reply

Hi Fred!

First at alt: Congratulations for your posts and community activity 😉

We have just published an alternative/trickie way to have Kamailio on AWS / NAT Hoster ( Spanish but very easy to understand: https://blog.irontec.com/sip-behind-nat-enganar-al-nat-con-mas-nat/)

Thanks!

Melvin Ryan Fetalvero October 25, 2017 Reply

Hi Fred:

I’ve been following your blog and I always see your name in forums and in the freeswitch and kamailio mailing list.

I have a setup similar to the environment you are describing here. In my setup

Client -> (via Kamailio Public IP) -> Kamailio -> RTPPROXY -> (via Freeswitch Public IP) Freeswitch -> DID Gateway

I got it to work before when I hosted my apps in Digital Ocean. After I moved it to amazon ec2. I started having problems with Elastic IP’s and all. After updating some of the config files. And using the Freeswitch Public IP in my Kamailio config. I can now do calls and have two way radio. My only problem is after approximately 30 seconds the call gets cut.

Can you assist me in troubleshooting this issue? Any help or feedback would be appreciated. Thanks.

Melvin

Rehan January 8, 2018 Reply

Hi Fred,

What if i want to relay rtp through SBC i dont want to travel rtp through my kamailio, do i need to install rtpproxy package ?

scenaior
asterisk——–kamailio running on NAT IP————–service provider

waiting for your expert opinion

regards,
Rehan Khan

Leave a Reply