Hack 76. Explore NAT Traversal
Network Address Translation (NAT) poses a fundamental problem for VoIP. But like so many problems, the first step toward a solution is realizing you've got a problem.
Have you ever tried a Voice over IP application that purports to let you talk to your buddies over the Net, only to fire it up and not be able to call them or, worse yet, to hear only dead silence on the other end? Chances are, the VoIP application is being broken by your firewall router.
The Internet is designed such that most private networks that have access to the Internet do so using a device called a NAT firewall. By using NAT, computers on the private networks are afforded a certain amount of security when accessing the Internet, because the NAT firewall can block certain network services and log all access attempts. The most common form of NAT is called masquerading, which uses a public IP address on the firewall's external interface to conceal all of the computers connected to the private interface. In this way, those computers "masquerade" as the firewall to the outside world.
The problem with this practice is that it breaks applications that rely on that public IP address. When a private computer makes a request, the server handling the request might attempt to respond to the requester using the firewall's public IP address rather than the requestor's private IP address, which is unknown to the responding server. This wreaks havoc on many protocols, including the file transfer protocol (FTP) and SIP.
Indeed, SIP's poor NAT traversal capabilities are famous. That is, if you have a router that does NAT, as most broadband routers do, it can potentially cause problems with using SIP. This is because the SIP protocol requires SIP hosts to instruct each other on how they can be reached by using the Via header, which looks like this:
Via: SIP/2.0/UDP 127.0.0.1:6655
This can cause issues when your SIP host places its internal IP address in the Via header instead of the external address of the NATing router. There are a plethora of solutions to this problem, including Simple Traversal of UDP NATs (STUN) and RFC 3581. STUN is a client-side technique used to determine the correct external IP address and port, which are then placed in the Contact header. RFC 3581 is a server-side solution where the server responds to the host that sent it the packet instead of the host in the Contact header. You can see this in action by using the sip_ping.pl script from the previous hack:
# ./sip_ping.pl -v proxy01.sipphone.com | grep Via Via: SIP/2.0/UDP 127.0.0.1:6655;branch=z9hG4bK1116737044 Via: SIP/2.0/UDP 127.0.0.1:6655;rport=14328;received=220.127.116.11;branch=z9hG4bK1116737044
Note the addition of the rport and the received parameters in the response of this ping. These show the remote port and IP address, respectively. While our client stated to the server that its Contact is 127.0.0.1 port 6655, the remote host decided to send the packet back the way it came, to 18.104.22.168 on port 14328.
Some router manufacturers have tried to get into the game and transparently rewrite SIP packets that pass through them. Although this was borne out of good intentions, it can cause problems on certain SIP implementations when the returning response does not match what was transmitted. If you're trying to use SIP behind a firewall and you aren't aware that that well-meaning firewall has altered your transmissions, it will be next to impossible to get around the fundamental problem of SIP using other, more generally accepted solutions (like STUN; more on that later). Here is an example of a SIP packet sent through a router with SIP translation enabled:
# ./sip_ping.pl -v proxy01.sipphone.com | grep Via Via: SIP/2.0/UDP 127.0.0.1:6655;branch=z9hG4bK1116737081 Via: SIP/2.0/UDP 10.1.1.5:6655;branch=z9hG4bK1116737081
Note that since the packet was rewritten, the remote host's RFC 3581 implementation did not insert the received and rport fields. However, when the packet returned, a different IP address was inserted in the Via header. This can be especially troublesome on hosts with multiple IP addresses, as the router rewriting the headers might be assuming that all responses should go to one host. This can be a good thing when you have a single SIP device on the private network, but it's a bad thing when you've got a whole building full of SIP phones. If the router is rewriting SIP headers arbitrarily, it won't be possible for all of these phones to receive their SIP responses.
The sip_ping.pl script takes two additional arguments (-s, for source, and -p, for port) that you can use to explore NAT traversal. These are the source IP address and the source port to be placed in the Via and Contact headers. By taking the rport and received addresses of the preceding example, we can rewrite the headers correctly to make it appear as though our packet is coming from the external interface of the NAT firewall:
# ./sip_ping.pl -v s 22.214.171.124 p 14328 proxy01.sipphone.com | grep Via Via: SIP/2.0/UDP 126.96.36.199:14328;branch=z9hG4bK1116737949 Via: SIP/2.0/UDP 188.8.131.52:14328;branch=z9hG4bK1116737949
This now specifies the correct external IP address and port in the Via header. By specifying the public IP and port, we can now traverse NAT, even when contacting remote hosts that do not support RFC 3581. This is a great example of how we can get around the NAT problem with SIP.
Now, if only our SIP clientthe phonewere smart enough to employ this technique itself, our SIP phone would appear as though it were outside the firewall to the remote SIP devices it calls. That's where the STUN protocol comes into play.
6.6.1. Get STUNned
STUN is an IETF recommendation that allows SIP clients to connect to a STUN server on the Internet to determine what address and port the connecting client appears to have from behind a NAT host. This way, the client can send the appropriate SIP Via headers, and, at least in theory, the SIP devices it calls will be able to respond by sending packets to the client's NAT firewall. Once a SIP device sends response packets to the NAT firewall, it's up to the firewall to forward them to the appropriate client on the private network.
So, there are two steps to hacking out a functional STUN server. First, set up and configure the server. Second, configure your NAT firewall so that it forwards inbound VoIP traffic to your SIP phone.
To build a STUN server, you'll need a Unix box (Linux, BSD, Mac OS X, etc.) that has a non-NATted connection to the Interneti.e., it has a public IP address. There is a Win32 version of STUN, too, but compiling on Unix is a lot less trouble. You can obtain the STUN server software from http://sourceforge.net/projects/stun/. Download and unpack it into your Unix machine's /usr/src/ directory; then compile and install it like this:
# wget http://kent.dl.sourceforge.net/sourceforge/stun/stund_0.94_Oct29.tgz # cd /usr/src # tar xvzf stund_0.94_Oct29.tgz # cd stund # make # cp server /usr/sbin/stund # /usr/sbin/stund &
That last command launches the STUN server. Make a note of your STUN server's internal IP address (on a small network, this is probably your default gateway), as you'll need to provide it to your SIP phone as the STUN server address.
6.6.2. But What About RTP?
So, STUN will allow your SIP client to know what to put in the SIP Via header, but remember that the VoIP call also relies upon RTP (an entirely different protocol) for transporting the voice packets. These packets must flow on two separate UDP sockets: one from you to the person you're calling and one from that person back to you. NAT breaks this, too! To make sure your SIP phone can receive voice packets behind the NAT box, you'll need to tell the NAT box to forward incoming RTP traffic to your SIP phone's IP address.
For the sake of this example, I'm going to use the X-Lite softphone, a free STUN-aware SIP softphone for Mac and Windows. Download it from http://www.counterpath.com/ and install it. (Review "Use a Softphone with a VoIP TSP" [Hack #4] for a quick refresher.) If you want to attempt this hack with another softphone, be sure it supports both SIP and STUN, or no cigar.
Get the IP address of the computer where X-Lite is installed. Make a note of it (I'll use 10.1.1.50 for this example). You'll need to tell your NAT firewall to forward all VoIP traffic to this address. If your NAT box runs Linux, you can use the following commands to forward all the inbound VoIP traffic to 10.1.1.50your IP phone. This assumes the Internet-facing interface is eth0 and its address is 184.108.40.206, so replace that address to suit your firewall:
# iptables -t nat -A PREROUTING -p udp -i eth0 -d 220.127.116.11 \ --dport 5060 -j DNAT --to 10.1.1.50:5060 # iptables -A FORWARD -p udp -i eth0 -d 10.1.1.50 --dport 5060 \ -j ACCEPT # iptables -t nat -A PREROUTING -p udp -i eth0 -d 18.104.22.168 \ --dport 5061 -j DNAT --to 10.1.1.50:5061 # iptables -A FORWARD -p udp -i eth0 -d 10.1.1.50 --dport 5061 \ -j ACCEPT # iptables -t nat -A PREROUTING -p tcp -i eth0 -d 22.214.171.124 \ --dport 5000 -j DNAT --to 10.1.1.50:5000 # iptables -A FORWARD -p tcp -i eth0 -d 10.1.1.50 --dport 5000 \ -j ACCEPT # iptables -t nat -A PREROUTING -p tcp -i eth0 -d 126.96.36.199 \ --dport 5001 -j DNAT --to 10.1.1.50:5001 # iptables -A FORWARD -p tcp -i eth0 -d 10.1.1.50 --dport 5001 \ -j ACCEPT
Now, any inbound SIP (ports 5060 and 5061) or RTP (ports 5000 and 5001 in this example) traffic will be forwarded directly to host 10.1.1.50, where your SIP softphone is running. (Ordinarily, you wouldn't need to forward the SIP ports for outbound calls to work; STUN takes care of that as long as the SIP client can use STUN.)
Next up is configuration of the STUN client in the softphone. Launch X-Lite and configure it as you normally would; then add the private address of your NAT machine, which is now running a STUN server as well, to the Primary STUN Server entry of X-Lite's preferences dialog. Now, call somebody outside your private network to see if it works (if that person is also behind a NAT, it might not!).