It is the classic VoIP nightmare: You have successfully installed Asterisk, registered your SIP phone, and dialed a number. The call connects, but then silence ensues. You can hear them, but they can’t hear you (or vice versa). Or perhaps the call connects perfectly but mysteriously drops exactly 30 seconds later.
These are the hallmarks of Asterisk PJSIP NAT issues.
Network Address Translation (NAT) is necessary for preserving IPv4 addresses, but it is the arch-nemesis of VoIP. SIP packets carry IP addresses inside their data payload (SDP), and if your Asterisk server advertises its internal LAN IP to a provider on the public internet, the audio stream will never find its way back.
This guide focuses specifically on configuring the PJSIP NAT settings to ensure two-way audio and stable connectivity, moving beyond the legacy chan_sip methods.
Why PJSIP Handles NAT Differently than Legacy SIP?
If you are migrating from the older chan_sip driver, you might be looking for the familiar nat=yes setting. In the modern chan_pjsip architecture, that command no longer exists.
PJSIP is modular. It decouples the network transport layer from the endpoint configuration. This means you don’t just “turn on NAT” for an extension; you must explicitly define your network topology.
The core problem is simple: Your Asterisk server knows its local IP (e.g., 192.168.1.10), but to communicate with the outside world, it must advertise your router’s Public WAN IP (e.g., 203.0.113.5) in the Session Description Protocol (SDP) headers.
If it fails to do this, your carrier sends the audio to 192.168.1.10, which is a private address that doesn’t exist on the public internet—resulting in one-way audio.
Step 1: Configuring the Transport Object (The Core Fix)
The most critical step in solving PJSIP NAT issues happens in the [transport] section of your /etc/asterisk/pjsip.conf file. This is where you tell Asterisk how to rewrite its IP address in the SIP headers.
You need to define two main concepts: what is “Local” (trusted, internal) and what is “External” (public).
Here is the essential configuration block: (code Ini)
; /etc/asterisk/pjsip.conf
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
; 1. Define your internal network
local_net=192.168.1.0/24
local_net=10.0.0.0/8 ; Add VPN subnets if applicable
; 2. Define your Public IP
external_media_address=203.0.113.5
external_signaling_address=203.0.113.5
; 3. NAT traversal helpers
force_rport=yes
allow_reload=yes
Key Parameters Explained
local_net: This tells Asterisk, “If a request comes from this IP range, do NOT replace the IP address.” This is crucial. If you omit this, internal office phones will try to send audio out to the public internet and back, causing latency or failure. You can specify multiple local_net lines for different subnets.
external_media_address: This replaces the private IP in the SDP (audio) packets with your Public IP when communicating with external endpoints.
external_signaling_address: This replaces the private IP in the SIP (call setup) headers with your Public IP when communicating with external endpoints.
force_rport: Forces Asterisk to send responses back to the source IP address and port from which the request originated, regardless of what the Via header claims. This is essential for NAT traversal at the transport level.
allow_reload=yes: Allows you to reload these transport settings without restarting Asterisk entirely. This is particularly useful when your public IP changes or you need to adjust NAT settings.
Handling Dynamic Public IP Addresses
If you have a dynamic Public IP (common in residential or small business connections), you have two options:
Option 1: Use a Dynamic DNS hostname
(code Ini)
external_media_address=myserver.ddns.net
external_signaling_address=myserver.ddns.net
Option 2: Create an update script Create a script that runs periodically (via cron) to detect IP changes and update the configuration:
(code Bash)
#!/bin/bash
NEW_IP=$(curl -s ifconfig.me)
sed -i “s/external_media_address=.*/external_media_address=$NEW_IP/” /etc/asterisk/pjsip.conf
sed -i “s/external_signaling_address=.*/external_signaling_address=$NEW_IP/” /etc/asterisk/pjsip.conf
asterisk -rx “module reload res_pjsip”
Applying Transport Changes
After editing pjsip.conf, reload the PJSIP module: (code Bash)
asterisk -rx “module reload res_pjsip”
Or from the Asterisk CLI:
module reload res_pjsip
Step 2: Endpoint Settings for Remote Extensions
Configuring the server transport solves the issue of the server being behind NAT. However, what if your users are working from home, and their phone is behind a different NAT?
You need to configure the [endpoint] object to handle the client-side firewall behavior. These settings ensure Asterisk ignores the (often incorrect) IP address the phone claims to have and instead talks to the IP address the packet actually came from.
Add these lines to your remote extension endpoints: (code Ini)
[100]
type=endpoint
context=from-internal
aor=100
auth=100
disallow=all
allow=ulaw
allow=alaw
; NAT Traversal Settings
direct_media=no
force_rport=yes
rtp_symmetric=yes
rewrite_contact=yes
[100]
type=aor
max_contacts=1
qualify_frequency=60
[100]
type=auth
auth_type=userpass
username=100
password=SecurePassword123
The “Magic” Trio for Remote Workers
direct_media=no: This forces all audio to pass through the Asterisk server (“anchoring” the media). Peer-to-peer audio almost always fails over NAT because the two endpoints cannot establish a direct connection through their respective firewalls.
rtp_symmetric=yes: This tells Asterisk to send audio back to the exact IP address and port it received audio from, rather than the port the phone advertised in its SDP. This effectively punches a hole through the client-side router by ensuring response traffic follows the same path as the incoming traffic.
rewrite_contact=yes: This updates the SIP contact header to the actual source IP/port of the request, fixing issues where phones register with their internal LAN IP (e.g., 192.168.0.50) but are actually coming from a public IP.
force_rport=yes: At the endpoint level, this ensures responses are sent to the source port of the request, which is critical for phones behind symmetric NAT.
Additional Endpoint Best Practices
qualify_frequency=60: Sends OPTIONS packets every 60 seconds to keep the NAT binding alive and detect if the endpoint goes offline.
max_contacts=1: Prevents issues where a phone registers multiple times with different contact addresses.
Step 3: Configuring RTP Media Ports
Edit your /etc/asterisk/rtp.conf file to define the port range for audio streams: (code Ini)
[general]
rtpstart=10000
rtpend=10200
This example uses a narrower range (200 ports) than the default 10000-20000, which improves security by reducing your attack surface. With 200 ports, you can support approximately 100 simultaneous calls (each call uses 2 ports).
After editing, reload the RTP module: (code Bash)
asterisk -rx “module reload res_rtp_asterisk”
Router and Firewall Configuration (Port Forwarding)
You can have the perfect Asterisk PJSIP NAT configuration, but if your router blocks the traffic, audio will still fail.
Ensure your router is forwarding the following traffic to your Asterisk server’s Local IP (e.g., 192.168.1.10):
- UDP Port 5060 (or your custom Bind Port): For SIP Signaling (call setup).
- UDP Ports 10000-10200 (or your custom range): For RTP Media (audio). Make sure this matches your rtp.conf configuration.
Port Forwarding Example
On most routers, you’ll create rules like:
External Port: 5060 UDP → Internal IP: 192.168.1.10, Port: 5060
External Port: 10000-10200 UDP → Internal IP: 192.168.1.10, Ports: 10000-10200
Critical Warning: Disable SIP ALG
SIP ALG (Application Layer Gateway) is a router feature that attempts to “fix” SIP packets automatically. However, it typically corrupts PJSIP headers, causing dropped calls, registration failures, and one-way audio.
Disable SIP ALG in your router settings. The option may be called:
- SIP ALG
- SIP Transformations
- SIP Helper
- SIP Passthrough (enable this variant if available)
The location varies by router manufacturer, but it’s usually in Advanced Settings, NAT, or Firewall sections.
Troubleshooting One-Way Audio
If you have applied the settings above and still have silence, use the Asterisk CLI to debug.
Enable PJSIP Logging
From the Asterisk CLI, run:
pjsip set logger on
Make a test call and examine the SIP messages scrolling by.
Check the SDP (Session Description Protocol)
Look for lines starting with c=IN IP4 in the INVITE and 200 OK messages. This shows what IP address is being advertised for media.
If you see:
c=IN IP4 192.168.1.10
(your local IP) sent to an external provider, your external_media_address is not working. Double-check your local_net configuration—you may have defined it too broadly, causing Asterisk to treat external connections as local.
If you see:
c=IN IP4 203.0.113.5
(your public IP) correctly, but audio still fails, the issue is likely:
- Router not forwarding the RTP port range (10000-10200)
- SIP ALG interfering with packets
- Firewall on the Asterisk server itself blocking RTP ports
Test RTP Ports
From an external network, use a tool like nmap to verify your RTP ports are open: (code Bash)
nmap -sU -p 10000-10200 203.0.113.5
You should see the ports as “open” or “open|filtered.”
Verify NAT Detection
From the Asterisk CLI, check if endpoints are being detected as behind NAT:
pjsip show endpoint 100
Look for lines indicating the detected IP address and whether NAT is involved.
IPv6 Considerations
The configurations in this guide are focused on IPv4, which is where NAT issues primarily occur. If you’re using IPv6, NAT is typically not necessary since IPv6 provides enough addresses for end-to-end connectivity. However, if you need to support both IPv4 and IPv6: (code Ini)
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
[transport-udp6]
type=transport
protocol=udp
bind=[::]:5060
Note that external_media_address and NAT settings are only relevant for IPv4 connections.
The Ultimate NAT Solution: Eliminate the Router
Managing NAT is the single most frustrating aspect of on-premise VoIP. Even with correct configurations, a change in your ISP’s dynamic IP or a router firmware update can break your phone system instantly.
HAPBX (High Available Private Branch Exchange) offers a structural solution to this problem: Eliminate the server-side NAT entirely.
Unlike a server sitting in your office closet, HAPBX operates on a Dedicated Cloud Instance that possesses a direct Public IP address.
No NAT Configuration: Because the server is directly on the internet (protected by enterprise-grade firewalls), there is no private-to-public translation required on the server side.
No Port Forwarding: You never have to log into a router to open ports for the server.
Reliability: One-way audio issues related to server misconfiguration vanish, as the media path is direct and unencumbered.
Automatic Failover: Cloud-hosted instances can provide high availability that’s impossible with a single on-premise server behind NAT.

Eliminate NAT Issues with HAPBX Cloud Architecture
Complete Configuration Example
Here’s a complete working configuration for a server behind NAT with remote workers: (code Ini)
; /etc/asterisk/pjsip.conf
; ===== TRANSPORT =====
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.168.1.0/24
local_net=10.0.0.0/8
external_media_address=203.0.113.5
external_signaling_address=203.0.113.5
force_rport=yes
allow_reload=yes
; ===== REMOTE EXTENSION 100 =====
[100]
type=endpoint
context=from-internal
aor=100
auth=100
disallow=all
allow=ulaw
allow=alaw
direct_media=no
force_rport=yes
rtp_symmetric=yes
rewrite_contact=yes
[100]
type=aor
max_contacts=1
qualify_frequency=60
[100]
type=auth
auth_type=userpass
username=100
password=SecurePassword123
; ===== LOCAL EXTENSION 101 (OFFICE PHONE) =====
[101]
type=endpoint
context=from-internal
aor=101
auth=101
disallow=all
allow=ulaw
allow=alaw
direct_media=yes
[101]
type=aor
max_contacts=1
[101]
type=auth
auth_type=userpass
username=101
password=AnotherSecurePass456
Notice that extension 101 (a local office phone) has direct_media=yes because it doesn’t need the NAT traversal settings—it’s on the same local network as the Asterisk server.
Conclusion
Resolving Asterisk PJSIP NAT issues requires a shift in thinking from “turning on NAT” to “defining network topology.” By correctly setting local_net and external_media_address in the Transport layer, and utilizing rtp_symmetric, rewrite_contact, and force_rport in the Endpoint layer, you can achieve crystal-clear, two-way audio.
The key steps are:
- Configure your transport with proper local_net and external_*_address settings
- Set up endpoints with the NAT traversal trio for remote users
- Forward the correct UDP ports on your router (5060 and RTP range)
- Disable SIP ALG on your router
- Test and troubleshoot using pjsip set logger on
However, if you are tired of debugging RTP ports and fighting with router configurations, consider moving your communications to HAPBX. Experience the stability of a Dedicated Instance where NAT issues simply do not exist, allowing you to focus on your business rather than network topology. Check HAPBX pricing or start a free trial now!