Sunday, February 8, 2009

STUN: NAT Traversal

As a software developer, how do you get around the limitations of NAT? STUN - Session Traversal Utilities for NAT (RFC5389) - provides a simple tool for just this purpose. STUN servers and clients are commonplace today, but how do they work? Why do we use them? And what does the average developer need to know?

Prerequisite: NAT Primer or a basic understanding of NAT

Given a decent understanding of NAT, we know that a client behind a NAT device cannot receive inbound packets unless a binding has been established. In the context of UDP, bindings are created by first sending an outbound UDP packet from client to server. This initial packet sets up some state on the NAT device thus allowing subsequent traffic from server to client to proceed unhindered. STUN Binding requests serve this very purpose and more.

For example, suppose a video player client wishes to receive a stream of video packets. The client has somehow learned the video server's source IP and port number (perhaps via RTSP). Two problems must be resolved before video can flow from server to client:
  1. Open a binding on the NAT device
  2. Inform the server of the client's public IP address
Step one is a piece of cake. The client could simply send an empty UDP packet to the server's address. Unfortunately, this one-way transaction doesn't offer enough information to complete step two.

Step two is a little more difficult. The client needs to learn the dynamic mapping that the NAT device created for the first outgoing UDP packet. For example, the client may have sent an empty packet from its internal IP address (192.168.1.100:12345) to the server's public IP address (64.1.2.3:45678). Now, any incoming packets which reach the NAT on the port mapped for 192.168.1.100:12345 will forwarded accordingly. So what is the mapped port? STUN provides the answer.

Using STUN accomplishes step one and easily facilitates step two. Here's how it works: First the video server listens for STUN packets on the port it will be using for video traffic. The client sends a STUN packet to that port on the video server. For the sake of this explanation, assume the STUN packet is just an empty UDP packet with a few attributes used to distinguish it (explained later). Once the server receives this STUN packet, it generates a response. In the response's body, the server will include the source IP and port of the original incoming packet. This address is actually an external ip:port of the NAT device which was dynamically bound to the client's internal address and port earlier (by the first outgoing STUN packet). Once generated, the response is sent back to the NAT device, the NAT device forwards it to the client, and the client receives it. Finally, the client interprets the response's contents and learns its own external address. The client may use this information to refer services. For example, the video server can be told the address and port that it should use for sending video traffic.

One benefit of STUN, over other NAT traversal utilities, is its ability to cope with a complex hierarchy of NAT devices. Protocols such as UPnP lack this ability.

STUN also offers security. Each STUN packet contains a number of key-value attributes. MESSAGE-INTEGRITY is one such field. It provides an encrypted hash of the packet. The server knows the client's encryption key by some other means and it may use that key to authenticate the inbound STUN packet.

Other attributes include the following (refer to RFC5389 for a complete list):

MAPPED-ADDRESSReturned by the server in its response to convey the observed source IP and port of the client.
MESSAGE-INTEGRITYExplained above, used for authentication.
FINGERPRINTUseful for distinguishing STUN packets from other packet types.
SOFTWARETextual description of the software application being used by the agents.
ALTERNATE-SERVERInstructs client to use a different STUN server.

The STUN RFC (5389) is short and certainly a worthwhile read. Note that STUN is not a complete NAT traversal solution. It is merely a NAT traversal "utility." In a future post, I will discuss ICE, Interactive Connectivity Establishment, which puts STUN to work in a complete NAT traversal solution.

If you're looking to get started with STUN and NAT traversal right away, but don't want to spend time implementing your own stack, check out the following:
  1. STUN Client and Server written in C++
  2. stun4j written in Java
  3. JSTUN written in Java
Note that most existing STUN implementations are RFC3489 compliant (which was replaced by RFC5389). If you know of a good RFC5389 implementation, please leave a link in the comments or send me an email and I will add it to this post.

8 comments:

  1. This post is STUNning, thanks !

    ReplyDelete
  2. Why does the client need to know the NAT device public address?

    ReplyDelete
  3. >> Why does the client need to know the NAT device public address?

    The public device of the NAT is *essentially* also the public address of the client. For example, in a peer-to-peer application, your peer needs to know the public address and port to which packets should be sent. Another example: if you're using a session setup protocol (such as RTSP or SIP), referrals are very common.

    ReplyDelete
  4. Well, this is not a RFC 5389 implementation (yet) but I stumbled over this alternative API for RFC 3489:

    http://jstun.javawi.de/

    RFC 5289 is from October 2008. What do you think, how long it takes, a first implementation comes up? Is there a rule of thumb for that?


    Henning

    ReplyDelete
  5. Henning,

    Thanks for the reference, I've added JSTUN to the list.

    I'm afraid there's no rule of thumb for when implementations start popping up for a new RFC. It depends on the popularity and demand for a given topic. Since the new RFC doesn't add tremendous functionality (in this case) it may be some time before RFC5289 implementations start appearing. Then again, you never know...

    John

    ReplyDelete
  6. Very usefull write-up. Thanks!!

    ReplyDelete
  7. I found:

    http://projectkenai.com/projects/icedjava/pages/Home

    It declares RFC 5389 compliance.

    Bye,
    Guido

    ReplyDelete
  8. I am implementing udp hole punching.here first We need to interact with rendezvous server to know the public ip and port.then we establish connection with other peer.will there be separate session for server connection and separate for peer connection or only one session is required to connect both.

    ReplyDelete