Howto: Kamailio SIP proxy with hosted NAT traversal on Debian Wheezy

This is a bit of a brain-dump so that I don’t forget what I had to do to get Kamailio working on my Debian VPS. I still haven’t managed to test this with two clients each behind a different NAT but it does work when they’re both behind the same NAT. I’ve now tested this with clients behind different NATs and it works fine for me. Your mileage may vary!

I’m using:

  • Debian 7.1 (Wheezy)
  • Kamailio 4.0.3
  • Bind 9.8.4
  • RTPProxy 1.2.1

I leaned heavily on Daniel-Constantin Mierla’s instructions to get this working.

Configure Firewall

Allow RTP media incoming on UDP ports 35000 – 65535 (note: other documents start this range from port 49152 however if you’re using the RTPProxy to get around NAT, then in Debian, its compiled-in port range starts at 35000.)

Allow SIP signalling incoming on TCP and UDP ports 5060 – 5061

Configure DNS

See http://web.mit.edu/sip/sip.edu/dns.shtml for a detailed explanation.

Exerpt from bind9 zone file for example.com:

; SIP RECORDS
; Allows SIP federation across different domains
_sips._tls.example.com. IN SRV 10 0 5061 host.example.com.
example.com. IN NAPTR 10 0 "s" "SIPS+D2T" ""  _sips._tls.example.com.

; HOST RECORDS
host.example.com. IN A <IP-address>

Install software

Follow these instructions to add the apt repository for the latest stable Kamailio release, then:

sudo apt-get install kamailio kamailio-mysql-modules kamailio-tls-modules
sudo apt-get install rtpproxy

If you don’t already have MySQL installed:

sudo apt-get install mysql-server

It will prompt you for a root password. Write this down – you’ll need it shortly.

Configure Kamailio database

In file /etc/kamailio/kamctlrc, set:

SIP_DOMAIN=example.com
DBENGINE=MYSQL

The next command will build the database and create two MySQL accounts in the process:

  • Read-write: username ‘kamailio’ with password ‘kamailiorw’
  • Read-only: username ‘kamailioro’ with password ‘kamailioro’

These accounts can access the MySQL server from localhost only. You can change their usernames and passwords in /etc/kamailio/kamctlrc if you like. If you’re going to do that, do it before running the next command, then when you’re ready:

sudo kamdbctl create

Enter the password for MySQL user root (which you wrote down earlier if you’ve installed MySQL as part of this process). Create all the suggested tables by answering ‘y’ to each option.

Next add some SIP users:

sudo kamctl add user1 password1
sudo kamctl add user2 password2
etc.

You will need to enter the password of the read-write database user (created by the kamdbctl script) each time.

These users will be added for the domain you set in the kamctlrc file SIP_DOMAIN parameter, for example:

user1@example.com
user2@example.com

Configure Kamailio server

In /etc/default/kamailio, set:

RUN_KAMAILIO=yes

In /etc/kamailio/kamailio-local.cfg, set:

#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB
#!define WITH_NAT
#!define WITH_TLS

/* add local domain aliases */
auto_aliases=no
alias=example.com:5061

If you don’t set the last two lines, Kamailio will do a reverse-DNS look-up on the IP addresses on which it’s listening (all of them by default), and will create aliases for all the hosts and all the FQDNs it finds. This is probably fine on a simple box doing just this job but for anything more complex you probably want to set your aliases explicitly to avoid it listening where it shouldn’t.

Make RTPProxy and Kamailio talk to each other

RTPProxy helps Kamailio work around Network Address Translators (NATs). Trouble is, RTPProxy is configured to listen on a Unix socket by default, whereas Kamailio expects to talk to a UDP port bound to the external IP address of your host. You can change either of these configurations to make the two speak to each other.

Using a Unix socket

In /etc/default/rtpproxy, add:

USER=kamailio
GROUP=kamailio

Running RTPProxy as the Kamailio user lets Kamailio talk to its scoket without permissions problems.

In /etc/kamailio/kamailio.cfg, comment out this line by putting a # as its first character, vis:

#modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")

and set this line just below it instead:

modparam("rtpproxy", "rtpproxy_sock", "unix:/var/run/rtpproxy/rtpproxy.sock")

Using a UDP port

This is what Kamailio expects by default. To make it happen, in /etc/default/rtpproxy, set:

CONTROL_SOCK=udp:127.0.0.1:7722
EXTRA_OPTS="-l <IP-address>"

Where <IP-address> is the external IP address of your host.

Either way should work. Don’t do both, obviously, or you’ll just have the same problem in reverse!

Configure TLS

Ensure the server’s private SSL key and public SSL certificate are both readable by the kamailio user. If you’re using the self-signed key/cert that ships with Kamailio by default this is easy:

sudo chown kamailio:kamailio /etc/kamailio/kamailio-selfsigned*

If you have an existing key/cert pair for the host that you want to use, you want to restrict their visibility as much as possible, but you still need to let kamailio read them.
I did this using the Unix group permissions model. I created a new group called ssl-cert and set this as the group for my host’s key and certificate files. I then made sure both files were group readable and then added the kamailio user to this group:

groupadd ssl-cert
chgrp ssl-cert /path/to/certificates/host_privatekey.pem /path/to/certificates/host_server.pem
chmod 0640 /path/to/certificates/host_privatekey.pem
chmod 0644 /path/to/certificates/host_server.pem
usermod -a -G ssl-cert kamailio

Notice that I restricted the private key’s access permissions so that it can only be read by its owner (root) and members of its group (ssl-cert). The public certificate can be read by any user.

Next we need to tell Kamailio where to find CA certificates against which it can verify certificates presented to it by other SIP servers (and by clients should you choose to use this feature). Unfortunately Kamailio doesn’t understand Debian’s certificate store. Instead it expects to read in all its CA certificates from a single file. You can generate such a file from the contents of the Debian certificate store using this command:

for f in /etc/ssl/certs/*.pem ; do cat "$f" >> ~/ca_list.pem ; done

You should then move it to the kamailio configuration directory and set its ownership and permissions sensibly:

sudo mv ~/ca_list.pem /etc/kamailio/
sudo chown kamailio:kamailio /etc/kamailio/ca_list.pem
sudo chmod 0644 /etc/kamailio/ca_list.pem

You should update ca_list.pem after any future changes to Debian’s certificate store. You could make sure this happens by running the above commands as a cron job (for example.)

Next, in /etc/kamailio/tls.cfg, set:

[server:default]
method = TLSv1
verify_certificate = no
require_certificate = no
private_key = /path/to/certificates/host_privatekey.pem
certificate = /path/to/certificates/host_server.pem
ca_list = /etc/kamailio/ca_list.pem

Start everything

Now we should be good to go, so:

sudo service rtpproxy restart
sudo service kamailio restart

You should see a list of the IP address and port bindings as well as a list of valid aliases for the service.

Client configuration

Here’s the generic information you need for any client:

username: user1@example.com
password: password1
proxy: example.com
proxy port: 5061
Preferred transport: TLS
TLS protocols: TLSv1

There are excellent instructions for Jitsi here.

Note: regardless of the client, be sure to disable the SSLv2 and SSLv3 and leave only the TLSv1 protocol enabled, as otherwise TLS won’t connect properly.