DEV Community

Cover image for VoIP NAT Traversal – Getting Through the Maze
SIP GAMES
SIP GAMES

Posted on

VoIP NAT Traversal – Getting Through the Maze

If you have ever tried setting up VoIP calls over the internet, you have probably run into the NAT wall.

Packets go out and somehow don’t come back. SIP signaling breaks, RTP streams vanish, and you’re left staring at dead air.

This article explores NAT traversal in SIP and RTP: why NAT complicates things, what types of NAT exist, and how tools like STUN, TURN, and ICE help us get calls working.


🌐 Quick Primer: What is NAT?

NAT (Network Address Translation) allows multiple devices on a private network to share a single public IP.

Problem? SIP and RTP are peer-to-peer by design, and they often embed private IPs inside signaling (SIP/SDP).

The outside world can’t route to 192.168.x.x.


🧩 Types of NAT

Different NAT behaviors affect how easily SIP/RTP can traverse:

Type of NAT Behavior
Full Cone NAT Any external host can send to mapped port
Restricted Cone NAT Only hosts previously contacted can reply
Port Restricted Cone Same as above but also checks source port
Symmetric NAT New mapping for each destination

👉 Symmetric NAT is the hardest for VoIP — it breaks simple hole punching.


☎️ Navigating SIP Through NAT

SIP headers often carry contact addresses that may be private (e.g., Contact: sip:alice@192.168.1.10).

If the proxy or callee tries to respond there — 💥 call fails.

Key SIP Helpers:

  • rport (RFC 3581): Client adds rport to Via → Server responds back to the source port, not the private IP in the header. Example:
Via: SIP/2.0/UDP 192.168.1.10:5060;branch=z9hG4bK123;rport
Enter fullscreen mode Exit fullscreen mode
  • Contact rewriting (NAT-aware SBCs): SIP servers (B2BUA/SBC) may rewrite Contact headers to reflect the public IP/port.

🎶 Navigating RTP Through NAT

RTP streams face the same NAT issues:

  • SDP offers may contain private IP addresses (e.g., c=IN IP4 192.168.1.10).
  • Even if SIP signaling connects, media won’t flow.

Solution → ICE Framework

ICE (Interactive Connectivity Establishment) gathers multiple candidates (possible addresses) and tries them in priority order.

Types of candidates:

  • Host candidates → Direct local IPs
  • Server reflexive → From STUN server (public-facing IP/port)
  • Relay candidates → Allocated via TURN server (media relay)

❄️ STUN: Simple Traversal of UDP

STUN lets a client discover its public IP/port as seen by a server.

It works well with cone NATs.

Example: SDP with STUN candidates

a=candidate:1 1 UDP 2130706431 192.168.1.10 54400 typ host
a=candidate:2 1 UDP 1694498815 203.0.113.45 60000 typ srflx raddr 192.168.1.10 rport 54400
Enter fullscreen mode Exit fullscreen mode
  • Candidate 1: Local private address (host)
  • Candidate 2: Public IP/port discovered via STUN (server reflexive)

Trickle ICE

Instead of sending all candidates upfront, clients can send them as they’re found. Speeds up call setup.


🌀 TURN: Traversal Using Relays

When NAT is symmetric or firewalls block UDP, STUN fails.

That’s where TURN steps in — media is relayed through a public TURN server.

  • Higher latency and resource cost.
  • Guaranteed connectivity fallback.

🔗 STUN Binding in RTP Setup

When RTP starts, peers send STUN Binding Requests over the selected candidate pair.

This validates the path and confirms bidirectional connectivity.

Caller (UA A)                     Callee (UA B)

- Send STUN Binding ------------> Respond Binding OK
<---------------:- STUN Binding - Respond Binding OK
Enter fullscreen mode Exit fullscreen mode

Once validated, RTP media flows over that same path.

📜 Example: SIP INVITE with ICE Candidates

Here’s what a NAT-traversed SIP INVITE might look like when a UA (behind NAT) sends an offer using ICE with STUN:

INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP 192.168.1.10:5060;branch=z9hG4bK1234;rport
Max-Forwards: 70
From: "Alice" sip:alice@example.com;tag=1928301774
To: sip:bob@example.com
Call-ID: a84b4c76e66710@192.168.1.10
CSeq: 314159 INVITE
Contact: sip:alice@203.0.113.45:60000
Content-Type: application/sdp
Content-Length: 420

v=0
o=alice 2890844526 2890844526 IN IP4 192.168.1.10
s=-
c=IN IP4 192.168.1.10
t=0 0
m=audio 54400 RTP/AVP 0 96
a=rtpmap:0 PCMU/8000
a=rtpmap:96 opus/48000/2
a=ice-ufrag:8hhY
a=ice-pwd:asd88fgpdd777uzjYhagZg
a=candidate:1 1 UDP 2130706431 192.168.1.10 54400 typ host
a=candidate:2 1 UDP 1694498815 203.0.113.45 60000 typ srflx raddr 192.168.1.10 rport 54400
a=end-of-candidates


🔎 Breaking it Down

  • SIP Headers

    • Via + rport: Ensures responses come back through the NAT’s mapped port.
    • Contact: Rewritten (or discovered via STUN/SBC) to include the public IP:port.
    • Call-ID, From tag, To tag: Tie requests and responses into the same dialog.
  • SDP Offer

    • m=audio 54400 RTP/AVP 0 96: Proposes an RTP stream at port 54400 with codecs G.711 (0) and Opus (96).
    • a=ice-ufrag + a=ice-pwd: ICE credentials used to authenticate connectivity checks.
    • a=candidate:1 typ host: Local private address (192.168.1.10:54400).
    • a=candidate:2 typ srflx: Public server-reflexive candidate discovered via STUN (203.0.113.45:60000).
    • a=end-of-candidates: Marks candidate gathering complete.
  • How This Works

    1. Alice sends the INVITE with both private and public candidates.
    2. Bob replies with his own candidates in the 200 OK SDP.
    3. Both sides perform STUN Binding requests across candidates.
    4. The best working path (host → srflx → relay) is selected.
    5. RTP flows over the chosen pair.

📌 In practice:

  • If Alice and Bob are both behind cone NAT, the server-reflexive (STUN) candidate usually works.
  • If either side is behind symmetric NAT, ICE will fall back to TURN relay.
  • This all happens automatically once ICE/STUN/TURN are implemented by the SIP stack or media engine.

🏁 Wrap Up

  • SIP needs help (rport, Contact rewriting, SBCs) to work behind NAT.
  • RTP needs ICE → STUN for discovery, TURN for relaying.
  • STUN binding checks ensure the media path is alive.
  • Symmetric NAT remains the final boss, and TURN is the safety net.

👉 Follow @sip_games for the next level.

Top comments (0)