VoIPowering Your Office: Siproxd Trumps NAT
May 27, 2008
As detailed an explanation of why SIP and NAT don't mix as you'll ever want to readplus a convenient solution.
Getting SIP (session initiation protocol) traffic through NAT (network address translation) firewalls is a beastly problem, and Siproxd is a good, easy-to-use SIP proxy that conquers the beast. There are many SIP proxies, but these tend to be complex and rather beastly to administer. You can use Siproxd in front of VoIP servers, such as Asterisk, and also standalone IP phones that use outside service providers. Currently it runs on Linux, FreeBSD, OpenBSD, SunOS, and Mac OS X.
Let's take a quick tour to learn why SIP and NAT are in a chronic state of conflict.
SIP negotiates a connection between two endpoints. This negotiation determines what codecs and transport are going to be used. The transport for VoIP calls is usually RTP (real-time transport protocol). Once the connection is established, RTP moves the media stream between the two endpoints. SIP then has nothing more to do until it is time to signal disconnection.
SIP and RTP use different ports, and can even follow different routes. This is not an insurmountable problem for NATit requires a bit of connection-tracking, plus configuring a restricted port range so you don't have to shred your firewall just to pass VoIP traffic.
The real showstopper is that RTP embeds the port numbers, IP addresses, and codecs within the message body. Iptables firewalls only read packet headers, and there is a good reason for thisso they can handle encrypted packets. Encrypted packets do not have encrypted headers (obviously, or they would not be routable). An additional problem is that what we call NAT (Network Address Translation) is most often port masquerading, or Port Address Translation (PAT). This diagram shows a LAN of three PCs using private non-routable IP addresses, and a firewall using PAT to share a single public routable IP address:
---------------- | 192.168.1.10 | ---------------- ---------------- -------- ---------------- | 192.168.1.11 |----|switch|---|NAT firewall |---Internet ---------------- /-------- |18.104.22.168| / ---------------- ---------------- / | 192.168.1.12 |/ ----------------Suppose host 192.168.1.11 wants to visit Enterprise VoIP Planet. When source packets from 192.168.1.11 hit the NAT firewall, they are re-written as 22.214.171.124. When Enterprise VoIP Planet responds to the connection request, it speaks to 126.96.36.199. Then NAT rewrites the destination addresses to the original sender, 192.168.1.11.
Just to compound the fun, all connections must be initiated from behind the firewall to build the NAT tables. SIP requires that both endpoints be capable of initiating connections, which is usually not something we allow LAN PCs to do. This is where one-way VoIP calls come fromone endpoint can send and receive, but the other endpoint can only send.
NAT really needs to go away for good, or at least become an option rather than a requirement. It is a useful hack that has extended the lifespan of IPv4, but its many disadvantages outweigh its benefits. It's a chokepoint that forces every packet entering or leaving your network to be altered. It forces all services to become NAT-aware and adopt nasty hacks and kludges. However, as we shall be dealing with it for the foreseeable future, here is how to set up Siproxd.
Configuring SiproxdThe first and most important rule is do not mix Siproxd with any other NAT-traversal tools. Don't use the iptables SIP connection tracker, don't use a STUN server, don't use another local proxy. Keep it simple.
Next, download and install Siproxd on the same box as your NAT firewall. Debian and Ubuntu include it, so a simple aptitude install siproxd takes care of it. For other Linux distributions you'll probably have to build it from source code. Just follow the good instructions, and don't forget to compare the MD5sum, which is in the release notes.
After installation you'll be editing siproxd.conf. First define your LAN and WAN interfaces. if_inbound is the LAN interface, and if_outbound is the WAN interface:
if_inbound = eth0 if_outbound = eth1And that's all you need to change.
If you have a firewall policy that denies incoming connections, you'll need a couple of rules in your iptables script to allow incoming SIP and RTP traffic:
iptables -A INPUT -m udp -p udp -i eth1 --dport 5060 -j ACCEPT iptables -A INPUT -m udp -p udp -i eth1 --dport 7070:7089 -j ACCEPTThe defaults in siproxd.conf limit RTP to the 7070:7089 port range. You can easily adjust this to suit. Now you have a working configuration and can start Siproxd:
$ siproxdFinally, configure your IP phone to use the proxy. If you're not running your own server, but have a Free World Dialup or Sipgate account or something similar, all you do is enter the LAN address of your Siproxd server as your SIP proxy in your phone's configuration. And that's all there is to it.
Siproxd stores all registrations in /tmp/siproxd_registrations. When you want to make changes and start clean, delete this file and then restart Siproxd.
Running an Asterisk server behind Siproxd is a bit more complex. The Siproxd configuration doesn't change, but you do have to make some changes to /etc/asterisk/sip.conf. Siproxd comes with some good example configuration files, including one for Asterisk. Be sure to also consult the FAQ, README, and other good documentation.