One of the things causing the most problems is one-way audio or no audio when dealing with user agents behind NAT devices that attempt to communicate with user agents on the public internet or behind a different NAT device. These NAT devices can be ADSL routers, firewalls, wireless LAN routers, etc. In order to understand NAT and RTP proxying, you must understand what happens when a user agent registers with a SIP Registrar and when a call is made.
In the following sections, functions from the nathelper module will be used as examples. Mediaproxy will be covered later in this document.
NOTE: SER has two different offerings for dealing with NAT and RTP proxying, namely rtpproxy and mediaproxy. These two solutions work independently of each other and are covered else where in this document. Much confusion has been caused by these two NAT solutions. Also, the nathelper module noted above is generally considered part of the rtpproxy solution, although you can use its exposed functions with mediaproxy.
When a user agent contacts SER with a REGISTER message, the user agent will only see its private IP address behind the NAT (ex. 192.0.2.13). Thus, it will believe that the correct contact information is myself@192.0.2.13:5060 and will include that in the REGISTER message (port 5060 is assumed to be the port the user agent is listening on). Of course, nobody can reach myself@192.0.2.13:5060 on the Internet as this address is valid only behind the users NAT device.
SER will receive a REGISTER message from a.b.c.d:f where a.b.c.d is the public IP address of the NAT and f is the to port allocated by the NAT to this communication just initiated. SER will be able to respond to a.b.c.d:f and reach the user agent and must therefore register this address instead of the one presented by the user agent. Nathelpers function for testing if the user agent is behind NAT is called nat_uac_test(). A parameter can be specified to indicate which tests should be done. We recommend using 19 (all tests). A description of the various tests is beyond the scope of this document.
Also, SER must record whether the user agent is behind NAT in order to properly process later messages. This is done by setting a flag for the UA using the setflag() function. This flag will be available for testing for both caller and callee.
Nathelper provides the fix_nated_contact() function for re-writing the Contact header. This action is not strictly according to the RFC, so nathelper (>0.9.0) has another function fix_nated_register() that will only register the correct address and port without rewriting the Contact header.
NOTE: Section 10.3 of RFC3261 says you must not alter the contact header while processing REGISTER messages, therefore, you should never use fix_nated_contact() while processing REGISTER requests. Instead, always use fix_nated_register() and use fix_nated_contact() for all other message types.
Also, the core function force_rport() is often used for all NATed messages to ensure that the Via headers (used for matching transactions etc) include the remote port number. This way the response in the transaction is sent back to the correct port. This only works for clients that support symmetric signalling (listen on the same port as they send). However, most clients are now symmetric.
An extra problem is that the NAT device will only reserve port f for a certain time, so if nothing more happens, the NAT will close the port and ser will not be able to contact the user agent. This is solved by either the user agent sending regular messages to SER or SER must send regular messages to a.b.c.d:f (keep-alive).
When an INVITE message is sent from a user agent, it will contain an SDP (Session Description Protocol) payload (read attachment or content). This payload describes various things about the user agent, ex. what type of sessions it supports, and where the party being called can reach the caller. As above, this information will for example be 192.0.2.13:23767. 23767 is the port the user agent has allocated and where it will listen for the actual sound (Real Time Protocol/RTP) for the session. At the time of the INVITE, there is no corresponding port on the NAT (as no RTP has yet been sent). The related SDP lines in the INVITE would look like this (c=contact, m=media):
c=IN IP4 192.0.2.13.
m=audio 23767 RTP/AVP 0 101.
In addition, the contact information will, as for the REGISTER message, be wrong. SER must change the contact information to the public address a.b.c.d:f as for the REGISTER message. With nathelper, this is done by calling fix_nated_contact(). Other transaction-starting messages like ACK, CANCEL, and BYE should also have the contact header fixed.
For the audio, SER can only do three things with the INVITE before forwarding to the user agent being called:
Add an SDP command direction:active to the SDP content
Change the c= line to a.b.c.d
Force RTP to go through a proxy by changing the c-line to c=IN IP4 address-of-proxy and the m-line to m=audio port-on-proxy RTP/AVP 0 101.
#1 is a way to tell the called user agent that it should wait until it receives audio and then just assume that it should send its own audio back to the same address (this is called symmetric RTP). This only works for user agents with a public IP or with a known RTP port on the NAT (for example by using STUN). If both are behind NAT, both will wait for the other to start and nothing will happen. However, this can be a good method for PSTN gateways with public addresses. You do this with nathelper by calling fix_nated_sdp("1").
#2 is basically the same as #1, but the called user agent gets some more information. You can do this with nathelper by calling fix_nated_sdp("2"). You can do both #1 and #2 at the same time by specifying 3.
#3 means that you need to set up a separate daemon called an RTP proxy (with a public IP address) that both user agents can send their audio to. You thus add an extra step (which can add latency in the audio) and for each call you need to handle 2 x required bandwidth for the codec the user agents are using (ex. 88 Kbps for G.711). With nathelper, you call force_rtp_proxy().
Please note that the calling user agent can have a public IP address, while the called user agent is behind a NAT. The OK returned by the called user agent will have to be manipulated as above and thus NAT handling code must also be included in the onreply_route[x] part of ser.cfg. The called user agent also has the flag set as described in the REGISTER section above (setflag). So, in the onreply route one can check whether the called user agent is behind NAT. If so, the contact header should be changed and (if desired) RTP proxying enforced.
Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs) also known as STUN…
STUN is a protocol for the user agent to discover its own public IP address. You will need to install a STUN server (not part of SER). The user agent will then try to change the contact and SDP information itself. When STUN is used by a user agent, SER does not have to do any rewriting as described in previous section. The exception is when a user agent is behind a symmetric NAT (the different types of NAT is beyond the scope of this document). In this situation the user agent should NOT try to rewrite as the STUN protocol will provide the wrong port. SER can then be used to rewrite contact and SDP information for these situations. For outgoing calls from a symmetric NAT, the direction:active rewrite can be used, but calls between user agents behind symmetric NATs must always be handled with an RTP Proxy server.
WARNING: Some user agents have faulty implementations of STUN. If STUN then has a wrong conclusion, you may end up with one-way audio (or no audio) or calls that are disconnected. Some situations can actually be detected by SERs NAT detection tests (by comparing the senders source address/port with the contact header in the INVITE, nathelper test flag 16), but it is recommended to test new user agents in different NAT scenarios to make sure that a combined.
Some NATs and firewalls have a built-in SIP Traversal mechanism, such as Cisco 3600 routers with IOS version 12.3(9). Such a capability is often referred to as an Application Level Gateway (ALG). A SIP ALG will rewrite all SIP messages transparently (both ways). If this is done correctly, both the user agent and SER will be happy. If not, nobody is happy and you either have to turn off the ALG in the router or you have to use SER on another SIP port (like 5065). However, you will then get other NAT-related problems. The fix-faulty-ALG-problem is not really possible to do in SER 0.9.0, but the next version will introduce new features designed to address this issue.
A second variant is Session Border Controllers (SBC). These are difficult to define as a group as they can do many things, but most often they will act as a full B2BUA (terminate the SIP and RTP sessions for both user agents so that both only see the SBC). SBCs are most often used by service providers to control the edge of their networks.