SIP Signaling From the Wire Up: Part 6 of 12
If there's a single topic that causes more real world SIP headaches than any other, it's NAT traversal. NAT, Network Address Translation, is how most networks share a single public IP address among multiple devices. It works transparently for web browsing, email, file downloads, and almost everything else on the internet. It does not work transparently for SIP and RTP, and the reasons why are directly responsible for an enormous percentage of VoIP problems, particularly the dreaded one way audio.
Understanding NAT traversal is arguably the most practically useful thing you can learn from this entire series. If you support VoIP systems in any capacity, you will encounter NAT problems. Knowing why they happen gives you a massive head start on fixing them.
How NAT normally works
NAT sits on your router at the boundary between your private network and the public internet. When a device on your private network (say, 10.0.0.50) sends a packet to a server on the internet, the NAT device rewrites the source IP address in the packet header from 10.0.0.50 to the router's public IP address (say, 203.0.113.1). It also records this mapping in a table so that when the response comes back addressed to 203.0.113.1, the NAT device knows to forward it to 10.0.0.50 internally.
For protocols like HTTP, this is seamless. The web browser sends a request, NAT translates it, the server responds to the public address, NAT translates back, and the browser gets its response. The IP addresses embedded in the actual data payload don't matter because HTTP doesn't put network addresses in the body of its messages.
SIP does.
Why SIP breaks through NAT
SIP embeds IP addresses in multiple places inside the message body and headers. Specifically:
- The Contact header contains the sender's IP address and port where it wants to receive future requests
- The Via header contains the sender's IP address
- The SDP body contains the IP address and port where the sender wants to receive RTP audio (the
c=line and them=line)
When a phone behind NAT sends a SIP INVITE, the NAT device rewrites the source IP in the IP packet header, but it has no idea that there are also IP addresses embedded inside the SIP message body. Those embedded addresses remain unchanged as the phone's private IP.
Here's what that looks like in practice. Alice's phone is at private IP 10.0.0.50, behind a NAT device with public IP 203.0.113.1. She sends an INVITE to Bob's server:
What the IP header says (after NAT):
Source: 203.0.113.1 (the public IP -- NAT rewrote this)
Destination: 198.51.100.10 (Bob's server)
What the SIP headers say (unchanged by NAT):
Contact: <sip:[email protected]:5060>
Via: SIP/2.0/UDP 10.0.0.50:5060;branch=z9hG4bK74bf9
What the SDP body says (unchanged by NAT):
c=IN IP4 10.0.0.50
m=audio 49170 RTP/AVP 0
Bob's server receives this INVITE. The SIP signaling works fine because responses can follow the IP header back to 203.0.113.1 (and the NAT device will forward them to Alice based on its mapping table). But when Bob's phone tries to send RTP audio, it looks at the SDP and sees "send audio to 10.0.0.50 port 49170." That's a private address. Bob's phone has no route to 10.0.0.50 because it's not on Alice's private network.
Result: the call connects successfully at the SIP layer. Bob can hear nothing from Alice because his RTP packets are going to an unreachable address. Meanwhile, Alice might be able to hear Bob because her phone knows Bob's correct address from his SDP. This is classic one-way audio, and it is overwhelmingly a NAT problem.
The solutions
Over the years, the industry has developed several approaches to work around this fundamental incompatibility. None of them are elegant. They range from mostly adequate to actively harmful.
STUN (Session Traversal Utilities for NAT)
STUN is the simplest approach. The phone queries a STUN server on the public internet, which tells the phone what its public IP address and port look like from the outside. The phone then uses that public address in its SIP Contact header and SDP body instead of its private address.
A STUN exchange looks like this: the phone sends a binding request to the STUN server from its private address. The request passes through NAT, which assigns a public IP and port. The STUN server sees the request arriving from the public address and sends that address back to the phone. Now the phone knows its "reflexive" address, the public IP and port that NAT assigned.
Phone (10.0.0.50:5060) -> NAT -> STUN Server
|
"You appear as 203.0.113.1:12345"
|
Phone now uses 203.0.113.1:12345 in SIP/SDP
STUN works well in many common scenarios. It fails with symmetric NAT, where the NAT device assigns a different public port for each different destination. The port discovered via STUN (which was created for traffic to the STUN server) won't be the same port used for traffic to the SIP proxy, so the addresses in SIP/SDP are still wrong.
TURN (Traversal Using Relays around NAT)
TURN is the fallback when STUN doesn't work. A TURN server acts as a relay. Instead of the two endpoints sending media directly to each other, both send their media to the TURN server, which forwards it. Because both endpoints initiate outbound connections to the TURN server (which works fine through NAT), the NAT problem is bypassed entirely.
The downside is that every packet in the conversation goes through the relay, which adds latency, consumes bandwidth on the relay, and creates a single point of failure. TURN is used when there's no better option, not as a first choice.
ICE (Interactive Connectivity Establishment)
ICE is a framework that tries multiple connection methods and picks the one that works. The endpoint gathers a list of "candidates," which are addresses it might be reachable at: its local address, its STUN reflexive address, and a TURN relay address. It includes all of these candidates in the SDP offer. The remote end does the same. Both sides then perform connectivity checks on all candidate pairs and select the best one that actually works.
ICE is the standard approach in WebRTC and is increasingly common in modern SIP deployments. It's more complex to implement than STUN alone, but it's significantly more robust because it tests actual connectivity rather than making assumptions.
SIP ALG (Application Layer Gateway)
SIP ALG is a feature built into many routers that attempts to solve the NAT problem by inspecting SIP messages as they pass through the router and rewriting the embedded IP addresses. The router sees the Contact header with 10.0.0.50, knows that address was NATted to 203.0.113.1, and rewrites the Contact to use the public address. It does the same for the SDP body.
In theory, this is an elegant solution. The phone doesn't need to know or care about NAT. The router handles everything transparently.
In practice, SIP ALG is the source of an enormous number of VoIP problems. The implementations in consumer and small business routers are frequently buggy. Common issues include:
- Rewriting headers that shouldn't be rewritten
- Corrupting SDP bodies by changing IP addresses but not updating the Content-Length header
- Mangling SIP messages that use TLS encryption (the router can't inspect encrypted messages but tries anyway)
- Interfering with phones that are already using STUN to handle NAT correctly, double-rewriting addresses into incorrect values
- Breaking registration by rewriting the Contact in REGISTER messages inconsistently
The almost universal advice from VoIP providers is to disable SIP ALG on your router. This advice is so widespread that it's essentially the first troubleshooting step for any SIP problem. If you're supporting VoIP and you haven't turned off SIP ALG, start there. Many call quality and connectivity problems simply disappear when ALG is disabled.
The difficulty is that different router manufacturers call this feature different things. It might be listed as "SIP ALG," "SIP Helper," "SIP Transformations," or buried in an "Application Layer Gateway" settings page. Some routers don't provide an obvious way to disable it. Some have it enabled by default with no option to turn it off without replacing the router.
Session Border Controllers (SBCs)
SBCs are the professional solution. An SBC sits at the network edge and handles SIP and RTP by terminating the session on one side and re-originating it on the other. From the phone's perspective, it's communicating with the SBC. From the far end's perspective, it's communicating with the SBC. The SBC translates between the two, using its own public address in all the right places.
This completely eliminates the NAT problem because the phone only needs to reach the SBC, and the SBC uses publicly routable addresses when communicating with the outside world. SBCs are standard equipment in enterprise VoIP deployments and at SIP trunk providers. Most hosted PBX services use SBCs at their network edge, which is one of the reasons phones registered to cloud PBX platforms tend to have fewer NAT issues than phones connected to on premises PBX systems.
NAT and registration
NAT affects registration in a subtle but important way. When a phone registers from behind NAT, the registrar records the Contact address from the SIP message, which contains the phone's private IP. When an inbound call arrives for that extension, the registrar directs the INVITE to the private address, which is unreachable from outside.
Smarter registrars handle this by looking at the "received" and "rport" parameters that get added to the Via header. These parameters record the actual source address that the registrar saw the REGISTER arrive from (the public NAT address), and the registrar can use that instead of the Contact address for routing inbound requests. This is sometimes called "NAT fix-up" or "force rport."
The other NAT registration problem is UDP timeout. NAT devices maintain their mapping tables for a limited time. If no traffic flows through a particular NAT mapping for a while (typically 30 to 120 seconds for UDP, though it varies by device), the mapping expires and is removed. If the phone's re-registration interval is longer than the NAT timeout, the mapping will expire between registrations. The phone thinks it's registered, but the NAT mapping is gone, so inbound traffic can't reach it.
The standard workaround is to send periodic keep alive packets, often SIP OPTIONS messages or CRLF keep alives, at intervals shorter than the NAT device's UDP timeout. Most phones and PBX systems have a keep alive setting for exactly this purpose.
Diagnosing NAT problems in a trace
When you're looking at a packet capture and you suspect a NAT issue, here's what to check:
-
Look at the SDP
c=line in the INVITE and the 200 OK. If either one contains a private IP address (10.x.x.x, 172.16 through 172.31.x.x, 192.168.x.x) and the other party is on a different network, that's your problem. -
Compare the source IP in the IP packet header with the Contact header in the SIP message. If they're different, the message passed through NAT and the SIP headers weren't corrected.
-
Check for audio flowing in only one direction by looking at the RTP streams. If you see RTP packets from one side but not the other, the missing side's RTP is likely being sent to an unreachable address.
-
Check whether SIP ALG is interfering by comparing the SDP before and after it passes through the router. If you capture on both sides of the NAT device and the SDP has been modified, ALG is active and may be causing the problem.
NAT traversal is messy, and the fact that it works as well as it does is a testament to the workarounds the industry has built. But when it doesn't work, the symptoms are consistent and identifiable once you know what to look for. A PCAP analyzer can parse the SDP and headers from a capture to highlight exactly where the addressing mismatch is, and SIP call stories can walk you through the flow in plain language.
Next up: SIP Response Codes: A Practical Reference, covering the codes you'll actually encounter in troubleshooting and what they mean in practice.
Frequently Asked Questions
Why does NAT break VoIP calls?+
SIP and RTP embed IP addresses inside the message body (SDP), not just in the packet headers. NAT rewrites packet headers but does not touch the payload, so the receiving side sees a private IP address (like 192.168.1.50) that it cannot route to. This causes one-way audio because one side's RTP stream has nowhere to go.
What is the difference between STUN, TURN, and ICE?+
STUN helps a device discover its public IP address by asking an external server, which works when NAT is simple (cone NAT). TURN relays media traffic through a server when direct connectivity is impossible (symmetric NAT). ICE is a framework that tries STUN first and falls back to TURN if needed, picking the best available path.
Should I enable or disable SIP ALG on my router?+
Disable it. SIP ALG (Application Layer Gateway) attempts to rewrite SIP messages to fix NAT issues, but most implementations are buggy and cause more problems than they solve -- corrupted headers, failed registrations, and one-way audio. Modern SIP endpoints handle NAT traversal themselves using STUN or outbound proxies.
Share
Want to know when we publish new articles? Sign up for updates