Firewalls and Network Address Translation (NAT) affect IP telephony signaling protocols, making it impossible to call targets outside the private or protected network. While often firewalls and NATs go hand in hand, they impose two different problems which shall be described here.
Both SIP and H.323 calls use a number of different ports, out of which only the signaling ports are well defined - TCP port 1720 for H.323 and TCP port 5060 (early versions of SIP used 5060 UDP as well). To be able to place and receive calls to/from outside the protected network opening these ports is a minimal requirement.
After signaling has started, further channels are required. H.323 often uses a separate TCP connection for capability exchange (H.245), which uses dynamically assigned port numbers. Likewise the RTP media stream uses dynamically assigned port numbers on each side. The only restriction that applies to these ports is that they are in the port range > 1023.
As a result, a firewall protected IP telephony zone needs either a firewall that does not protect ports > 1023 or a firewall that is IP telephony aware - meaning that it monitors all SIP and H.323 messages in order to open and close the required ports on the fly. A third alternative is to deploy an H.323 or SIP proxy outside the protected zone protected by the firewall, perhaps in a DMZ, and configure the firewall to allow communication of endpoints only with this proxy. This is a mid-level security approach, as it permits the relatively safe communication between protected endpoints and a trusted proxy server outside the firewall. This document does not intend to give an overview of suitable firewall solutions, so when installing IP telephony solutions ensure that your firewall supports it.
Another problem occurs if your IP telephony zone resides in a private network (no public IP addresses). SIP and H.323 use TCP for signaling, but the messages carried in the application layer contain IP addresses that are not recognized by the NAT. In addition, the H.323 RAS channel uses UDP for transport. This combination results in the following problems:
One possible solution is the STUN protocol, defined in RFC 3489. An endpoint implementing this protocol connects to a public STUN server to be informed of his public IP address. The result of this query is used as the IP address to register with at a remote server. While STUN seems to be more popular in the SIP world there is no H.323 endpoint that we are aware of that supports this feature.
Another possibility is to use a router that is aware of IP telephony protocols and rewrites the IP addresses within the application layer messages, as they are routed. But this requires full decoding and encoding support for SIP and/or H.323, which is simple for the text-based SIP protocol but quite complex for the ASN.1-based H.323 protocol. In addition, it is always possible that such a router might remove all message content it does not understand, so that trying to transport new protocol features through such a router may inexplicably fail. Such an IP telephony router may come in the form of an application running on the NAT router itself - like the OpenH323Proxy™ [3].
Since the beginning of deploying of SIP based devices for Internet telephony there have been problems with traversing NAT. There are several reasons why SIP does not work through NAT properly:
Many proposals for NAT traversal have been created recently, but none of them works universally and is applicable to all real world scenarios. The proposals include Connection Oriented Media, STUN, TURN, SIP ALG and so on.
All the proposals have been collected into one single document which is called ICE. ICE stands for Interactive Connectivity Establishment. It is a methodology for traversing NAT, but it is not a new protocol, it is a collection of all previously mentioned attempts to traverse NAT which works universally. The methodology is quite complex and requires mutual cooperation of all endpoints involved in the communication.
Although it works universally, such a solution is hard to implement. In this section we will describe a solution that is based on ICE, but we will make a couple of assumptions and simplifications. That will result in a significantly simpler implementation, which is supported by almost any SIP devices available today and which works in most real-world scenarios.
The price for the simplifications will be using of an RTP relay in cases where it is not absolutely necessary, but such cases seem to be quite rare. Simpler solution will also impose higher requirements on SIP devices, fortunately most manufacturers seem to have implemented all necessary features already.
The scenario as presented in following subsections assumes that the SIP proxy is in the public internet and SIP user agents are behind NAT.
One of requirements laid on SIP devices that should work behind NAT is support for symmetric signaling. Normally each SIP user agent is listening on port 5060 for incoming SIP traffic. This port number is usually advertised in the Via header field so that replies will come back on proper port and not to the port from which request was sent, and the port number will be also registered in registrar so any subsequent messages will be sent to 5060 as well.
When sending SIP messages, the user agent is allowed to use a completely different socket, which means that the source port number of the outgoing SIP messages will be different--it will be not 5060, usually it is some high port number assigned by operating system.
That works well when there is no NAT device along the path, but it will not work when the user agent is behind a NAT The reason is that NATs usually do not allow any traffic to the private network unless there was a packet sent from the same IP and port to the public internet. That means if a host with private IP address 192.168.0.1 wants to receive a packet on port 5060 from a host 1.2.3.4 (which is in the public internet), it has to first send a packet with source port 5060 to host 1.2.3.4. The packet will create a binding in the NAT and the NAT box will forward replies from 1.2.3.4 to 192.168.0.1. The binding will expire if there was no traffic for some interval.
Having said that, it is clear that a SIP user agent behind NAT listening on port 5060 will not be able to receive any traffic to that port unless it sends a packet through the NAT with source port 5060.
That is the principle of symmetric signaling. In other words it means that SIP user agents using symmetric signaling send SIP messages from the same source port on which they receive incoming SIP messages (usually 5060). Only that way they will be able to create a binding in the NAT that will allow incoming SIP traffic through.
Fortunately vast majority of developers of SIP devices seems to get this so almost all SIP devices that are available today do support symmetric signaling. That includes Cisco phones, Windows Messenger, Mitel phones, Grandstream, Snom, X-lite and kphone (from version 3.13).
Support for symmetric signaling is a must, SIP user agents not supporting that will not work behind NATs.
Similar problem is with getting media streams through NATs Here again, the party behind NAT must send the first media packet to create a binding and open a pinhole in the NAT box.
We have the same problem here, user agent behind NAT must send media packet with source port that is same as the port on which the user agents expects media from remote party and which was advertised in SDP. Only that way media will be able to pass the NAT in both directions.
In addition to that, the remote party (which is in the public internet) must ignore contents of SDP and send the media not to the IP and port which it received SDP, but to the IP and port from which are media from the remote party coming. That will be the public IP of the NAT box.
This approach is called Connection Oriented Media. It is also known as Symmetric Media.
It will work when one party is behind a NAT and the other party is in the public internet, in that case the party behind NAT will send the first packet and the party in the public internet will use the first packet to determine IP and port to which it should send.
When both parties are behind two different NATs, then this approach will not work. The reason is very simple, since both SIP user agents are behind NAT, both of them need to send the first media packet to open pinholes in NAT. Both of them will use the data received in SDP, but that will not work because NATs might have changed the port number.
To solve the situation, an intermediary in the public internet will be necessary -- an RTP proxy. The RTP proxy will receive all the media traffic from both parties and send it to the other side. Because it will be located in the public internet it can wait for the first media packet from both sides and send subsequent media packets to IPs and port from which it received the first packets.
In order to work behind NATs SIP user agents must support symmetric signaling and symmetric media. In addition to that they should also be able to use an outbound proxy because all SIP traffic has to go through a SIP proxy in the internet.
Vast majority of SIP user agents available today can work properly behind NATs.
Most of the burden with traversing NATs is on the SIP server in the public internet. The SIP server must do the following:
All the necessary NAT traversal features are implemented in the SIP Express Router available from iptel.org. We will now briefly describe how the NAT traversal support works in the server.
When the server receives a registration, it tries to find out if the sender is behind a NAT. It does so by comparing the IP address from which the request came with IP address in Via of the sender. If they differ then the user is behind NAT and the information is saved into user location database along with his contacts.
If the previous test fails then the proxy checks if Contacts contain private IP addresses. If so then the user agent is also behind NAT and the information is saved into user location database.
For user agents behind NAT registrar rewrites IP addresses and ports in Contact header fields with the IP and port from which the REGISTER came and saves the value into the user location database.
Later, when the proxy retrieves the information from the location database, it will get the rewritten values and it will send requests correctly to the IP of the NAT box which will in turn forward the request to the host in the private network.
Session invitation is a little bit more complicated because we want to minimize using of RTP proxy.
When the server receives an INVITE message, it tries to find out if the caller is behind NAT It, again, checks if the IP from which the request came is different from IP in the topmost Via. If they are same then IP in Contact header field is searched for a private (RFC1918) IP address.
If the caller is behind NAT then the server checks for presence of Record-Route header fields in the message. Presence of the header fields indicates that there is another proxy between us and the caller and we do not have to rewrite the contents of Contact header field because the proxy might be behind the NAT and in that case it can route private IPs properly because it is in the same network.
Otherwise we will mark the transaction the INVITE created as “behind NAT” and rewrite Contact and/or SDP The mark will be used later.
After that the proxy server does all the processing as usual. At some point the server performs user location table lookup to find out the current destination of the callee. You might remember that we saved flags about presence of NAT when processing registration. If the callee is behind NAT (the flag in user location database is set), then we will mark the transaction as “behind NAT” if it is not marked yet. After this step the transaction will be marked as “behind NAT” if either caller or callee or both are behind NAT
When the server is just about to forward the request (i.e. no other changes will be made to the request), the server will check for presence of the “behind NAT” mark in the current transaction. If the mark is set and the callee is not in the public internet or does not support symmetric media, then the proxy will send a command to RTP proxy to create a session and then force using of the RTP proxy by rewriting contents of SDP We will do the same in 200 OK when it comes.
We have mentioned that we do not force using of RTP proxy when the callee is in the public internet and does support symmetric media, but how do we know that ? Indeed, there currently is no way of finding out whether a SIP user agent support symmetric media or not. That means we do not force RTP proxy only for destination for which we know that are symmetric, like voicemail or PSTN gateway.
The RTP proxy is a very simple packet forwarder. The SIP server can talk to the RTP proxy using UNIX sockets. When the SIP proxy receives a session invitation that will require using of the RTP proxy then the SIP proxy will ask the RTP proxy for a port number that will be used to forward the media.
When the RTP proxy receives first media packets from both sides, it records IPs and port from which the packets came and starts relaying the media packets.
Using of RTP proxy has some drawback that are worth mentioning. First of all, it introduces another hop on the path from one user agent to another and that results in increased delay. How much the delay will be increased depends on the underlying network and location of the user agents.
Secondly, using of RTP proxy imposes more burden on the server, because all the media traffic has to go through the server. For example, for G.711 is it 64 kbit/s in each direction per call. Care should be taken when building a server for RTP proxy that will receive a lot of media traffic.
In this section we describe how to set up SIP Express Router and RTP proxy for NAT traversal. Note that both proxies (SIP and RTP) must be in the public Internet to make it work.
This section describe only settings necessary for NAT traversal. For complete configuration guide please refer to Section 4.6.2.
First of all, it is necessary to load the nathelper module and configure its parameters. Put the following into the configuration file to load the module:
loadmodule "/usr/local/lib/ser/modules/nathelper.so"
Then set the following parameters:
# We will you flag 6 to mark NATed contacts
modparam("registrar", "nat_flag", 6)
# Enable NAT pinging
modparam("nathelper", "natping_interval", 60)
# Ping only contacts that are known to be
# behind NAT
modparam("nathelper", "ping_nated_only", 1)
The first parameter tells the registrar module which flag should be used to mark contacts behind NAT. Second parameter is interval (in seconds) for keep alive messages (to keep the NAT bindings open), and the last parameter specifies that only contacts that are behind NAT should be pinged.
To check if the sender of a message is behind NAT, we will put the following test at the beginning of the main routing section of the configuration file (right after the test for too large messages):
# special handling for NATed clients; first, nat test is
# executed: it looks for via!=received and RFC1918 addresses
# in Contact (may fail if line-folding used); also,
# the received test should, if complete, should check all
# vias for presence of received
if (nat_uac_test("3")) {
# allow RR-ed requests, as these may indicate that
# a NAT-enabled proxy takes care of it; unless it is
# a REGISTER
if (method == "REGISTER" || ! search("^Record-Route:")) {
log("LOG: Someone trying to register from private IP, rewriting\n");
# This will work only for user agents that support symmetric
# communication. We tested quite many of them and majority is
# smart smart enough to be symmetric. In some phones, like
# it takes a configuration option. With Cisco 7960, it is
# called NAT_Enable=Yes, with kphone it is called
# "symmetric media" and "symmetric signaling". (The latter
# not part of public released yet.)
fix_nated_contact(); # Rewrite contact with source IP of signalling
if (method == "INVITE") {
fix_nated_sdp("1"); # Add direction=active to SDP
};
force_rport(); # Add rport parameter to topmost Via
setflag(6); # Mark as NATed
};
};
The test does exactly what was described in previous sections.
At the end of the processing we also need to perform similar test for the callee and force using of RTP proxy if necessary. Because there can be potentially many places in an average configuration script from which we send out messages (all occurrences of the t_relay() or forward() actions), we will put the whole test into a separate route section and call the section instead of t_relay():
#
# Forcing media relay if necessary
#
route[1] {
if (uri=~"[@:](192\.168\.|10\.|172\.16)" && !search("^Route:")){
sl_send_reply("479", "We don't forward to private IP addresses");
break;
};
if (isflagset(6)) {
force_rtp_proxy();
t_on_reply("1");
append_hf("P-Behind-NAT: Yes\r\n");
};
if (!t_relay()) {
sl_reply_error();
break;
};
}
onreply_route[1] {
if (status =~ "(183)|2[0-9][0-9]") {
fix_nated_contact();
force_rtp_proxy();
};
}
The route section checks if flag 6 (marks NAT) is set and if it is set then it will force using of the RTP proxy. We will also setup an onreply_route section which will process 200 OK messages (we also need to rewrite the “Contact” header field and SDP body in the reply).
Installation and running of the RTP proxy is very simple and straightforward. First of all download the proxy from PortaOne site.
Untar the archive and compile the proxy using:
make -f Makefile.gnu
That will generate a binary called rtpproxy. Start the proxy using ./rtpproxy and restart SER.
SER and the RTP proxy use socket /var/run/rtpproxy.sock to communicate.