Completing RTC's NAT story
In my first post, I touched on all the new features of RTC 1.5. Prathap also posted a blog on RTC 1.5 port manager, which shows how RTC's port manager APIs can be used by user app to communicate outside NAT. Here I will try to complete the NAT picture of RTC 1.5
As mentioned in my first blog, RTC supports the following features for NAT traversal:
1. Port manager APIs (covered by Prathap's' blog)
2. Symmetric UDP signaling for SIP & media stack.
Let's concentrate on the 2nd part here as # 1 is covered by Prathap's blog. RTC 1.5 defines 2 new initialization flags to enable symmetric UDP signaling:
RTCIF_ENABLE_SYMMETRIC_UDP_SIGNALING
RTCIF_PREFER_STATIC_PORT_FOR_SYMMETRIC_UDP
code e.g.
hr = piRTC2->InitializeEx(RTCIF_ENABLE_SYMMETRIC_UDP_SIGNALING |
RTCIF_PREFER_STATIC_PORT_FOR_SYMMETRIC_UDP);
RTCIF_ENABLE_SYMMETRIC_UDP_SIGNALING - This enables symmetric UDP signaling. This means that if a profile is used, whose protocol is UDP, then RTC will send & receive SIP packets using a single source port.
RTCIF_PREFER_STATIC_PORT_FOR_SYMMETRIC_UDP - This flag tells RTC to use port 5060 for symmetric UDP signaling. This is not guaranteed as another app may have opened 5060 already, and thus not available for RTC to use it.
Let's see how this tackles the NAT's following 2 major problems:
1. VOIP Devices behind NAT have an internal IP address that is different from outside the NAT and thus outside servers do not know the "real" address of the device.
2. NAT boxes often keep a mapping, of "opened" ports which are time based, and these mappings get closed by the NAT boxes, if there is no live traffic on that port for a particular time.
The above issues are particularly important for UDP protocol as UDP protocol is not connection oriented and hence the 2 devices "may" not use the same ports to send & receive packets.
Let's see how symmetric UDP signaling may solve the above 2 issues.
The most restrictive type of NAT is symmetric NAT, which uses all 4 parts of the tuple <source IP, source port, dest IP, dest port> to restrict traffic follow across them. Using symmetric signaling with Session border controllers (described below), VOIP devices can communicate outside NAT.
These days, most of the VOIP service providers like Vonage, and others are using UDP as their underlying protocol for SIP as well media.
Such service providers often have deployed, what is called the Session Border Controllers. These smart servers often detect clients that are behind the NAT, when the IP addresses in various SIP headers do not match the source IP address of the packets received from such devices behind the NATs. These servers thus ignore the IP address in the SIP headers coming from a device behind the NAT, and reply back on the source IP address/port that is visible on the IP address header. They also reply back using the same IP address/port on which they received the packet. Thus symmetric UDP is achieved. Such a packet from SBC will pass through the NAT and reach the device. If the device behind the NAT is listening on its source IP address/port, that it used to send its outgoing SIP packets to the SBC server, then it can receive packets back from the server.
Thus # 1 problem is solved for SIP for RTC, if symmetric UDP is used with SBC.
In order to keep the mapping alive, the device behind NAT should keep sending packets at regular intervals to keep the port mapping open. These mappings vary across NAT boxes but are in the order of a minute or more. This mapping can be refreshed for SIP, by refreshing REGISTER requests regularly.
RTC now allows a minimum refresh interval of 19 sec. Thus if the SIP server sets its expiry time to less than a minute, RTC will obey that and refresh that frequently.
This solves refreshing port mapping life problem.
The above theory is applicable for media as well. SBC control VOIP media, such that all media for a call goes through them. Consider this:
When a call is made by a device behind the NAT, it inserts the IP address/port of the RTP port in the SDP. When SBC receives this INVITE, it replaces the IP address/port in SDP by its own IP address/port. and then forwards the INVITE to the receiver. When a reply comes back from the receiver, it again replaces the IP address/port in the receiver's SDP, by its own IP address/port. Hence all media now goes through SBC.
The advantage of symmetric UDP now comes in. Now, since all media will go through SBC, and as SBC can communicate with the device using symmetric UDP, the NAT issues for media traffic is also solved.
RTC, by default, supports symmetric UDP for its media traffic. Besides this, it has one more feature called "early UDP" to punch holes early in the call phase, to allow receiving of the traffic from the SBC (for early media scenarios)
SDP are often exchanged in provisional packets like 183 and PRACKs for "early media" scenarios" .Here the device can start getting media from the other side, before the call gets connected (before a final 200 OK response is received for the INVITE). For this scenario, RTC does not start sending any traffic until the 200 is received. But it opens up its receive ports to start receiving the early media.
However, if RTC VOIP device is behind NAT, until a mapping is established on the NAT, NAT won't allow traffic from outside to reach the device inside NAT. Hence RTC's media stack sends "Early UDP" packets to the remote IP address/port, in order to punch holes though the NAT. Once that is done, RTC device can start receiving early media. The early UDP behavior is registry configurable (HKLM\Comm\RTC\NAT, DWORD - EnableEarlyUDPPackets) and is off by default.
[Author: Rajesh Khetan]
Comments
Anonymous
November 19, 2006
Sir, What I want to do is to be able to retrieve the IP address of remote party. For example, upon receiving INVITATION from a remote party, I want to get its IP address. Can you please provide me with a sample code for this purpose? Thank you, best regards, Ali KoyuncuAnonymous
November 30, 2006
I assume you want to retrieve the IP addresses from the SDP.You can use IRTCSessionDescriptionManager interface to get access to incoming SDP, and thus figure out the remote IP address. This will give you access to IP before you accept/reject the call.Or you can use port manager interface. Once you accept the call, RTC calls back into port manager interface APIs to get local address mapping. It also includes the remote address during that time. Check this blog to see how to use port manager:http://blogs.msdn.com/cenet/archive/2006/11/10/real-time-communications-rtc-1-5-port-manager.aspx