NAT traversal: STUN, TURN, ICE, what do they actually do?

When searching for nat traversal I found all these protocols but no one can tell me what do they essentially do to traverse nat, surely not by magic? Turns out it’s conceptually very simple.

What nat traversal does is not really “punching holes” on the nat, or delivering message through some tunnel, or some demotic portals, but to simply find the public address:port that can can reach me.

If I’m behind a nat or even multiple nat’s, my packets are relayed by these nat’s and they appear on the public Internet at the out-most nat’s address and port. And reply packets going to that address:port are relayed back to me. So, in some sense, I still got a public address:port that can reach me on the public Internet. The purpose of nat traversal is to find that public address:port.

That’s basically what the initial/classic stun (rfc 3489) does. You send a stun server a message, the stun server looks at the source ip address and port of the ip packet, and reply that back to you. Voilà, you know you public address:port!

Sometimes having that address:port isn’t enough, because many nat poses extra restrictions1. Then we have to resort to having a public-visible relay server in the middle, which is what turn (rfc 5766) does.

Some nat wouldn’t let a packet from an external host through if the host inside never sent a packet to that external host before. There are many ways a nat could make your life difficult, check out “full cone”, “restricted cone”, “symmetric nat”, etc.

As time goes by, stun and turn turns out to be still not enough. For one, one can usually find multiple address that could possibly work, but then which one to use? Eg, maybe a host has an ip assigned by a vpn, if the other host is also in the vpn, we should use this ip over the others; similarly, if the other host is in the same lan, we should use the local ip; even over nat, there could be multiple ip’s that can reach us.

ice fills that gap. It gathers a bunch of address:port’s that possibly works (through stun messages with stun servers), sorts them by preference, and tries them one-by-one according to some algorithm2, and reports to you the best one. If none works, it tries to establish a relay through turn.

Or even gather candidates and try them out in the same time, instead of waiting for full candidates list before trying each out. This speeds up establishing connections and is called trickle ice.

And here is where the new stun comes in. People threw away the algorithm for finding address:port in classic stun, and kept and extended the stun message format. Now ice runs a more thorough algorithm that uses stun messages to communicate with stun servers. And the new stun (rfc 5389) just defines the stun message format. There is a even newer version (rfc 8489) that updated rfc 5389 slightly, but with no fundamental changes.

Similarly, turn is updated in rfc 8656 and now is a message protocol used by ice rather than a standalone solution.