Configuring PJSIP to Work Through NAT

Getting Started -- Last reviewed 2026-06-26 pjsip nat sip configuration networking getting-started trunking Found this useful? Upvote it. ×

Configuring PJSIP to Work Through NAT

NAT breaks Asterisk in a predictable way: the private IP addresses in SIP headers and SDP are unreachable from outside your network. Calls connect but nobody hears anything. The remote end sends audio to 192.168.1.x and it goes nowhere.

The fix is a handful of settings. Which ones you need depends on which side of NAT the problem is on. Asterisk behind a router needs different treatment than phones behind NAT, and double-NAT needs both.

On this page

Scenario 1: Asterisk and phones behind a NAT router

Asterisk and all phones share a private network. A router handles the internet boundary and port-forwards inbound SIP (UDP 5060) and RTP (UDP 10000-20000) to Asterisk's private IP.

These examples use RFC 5737 documentation addresses.

Device IP
VoIP phone (6001) 192.0.2.20
Asterisk server 192.0.2.10
Router LAN 192.0.2.1
Router WAN 198.51.100.5
ITSP gateway 1 203.0.113.1 (gw1.example.com)
ITSP gateway 2 203.0.113.2 (gw2.example.com)

For this example the ITSP account number is 1112223333 and the DID is 19998887777. This config was written against SIP.US but works with any provider that registers by username and password.

Transport settings that matter for NAT

When Asterisk itself is behind NAT, three transport options do the work:

local_net is your private network range. Traffic to addresses inside this range gets no NAT rewriting. Everything going elsewhere gets the external addresses substituted in.

external_media_address is the public IP Asterisk puts in SDP offers for RTP audio. When the call destination falls outside local_net, this replaces the private address in the media description.

external_signaling_address is the same thing for SIP signaling. Most setups use the same public IP for both. They would differ only if you split signaling and media across separate interfaces or servers.

On the endpoint, direct_media = no keeps Asterisk in the audio path. Without it, PJSIP tries to connect the phone directly to the ITSP. That fails because the phone's private IP is not reachable from outside your network.

Full pjsip.conf configuration

[transport-udp-nat]
type=transport
protocol=udp
bind=0.0.0.0
local_net=192.0.2.0/24
local_net=127.0.0.1/32
external_media_address=198.51.100.5
external_signaling_address=198.51.100.5

[sipus_reg]
type=registration
transport=transport-udp-nat
outbound_auth=sipus_auth
server_uri=sip:gw1.example.com
client_uri=sip:1112223333@gw1.example.com
contact_user=19998887777
retry_interval=60

[sipus_auth]
type=auth
auth_type=userpass
password=your_password
username=1112223333
realm=gw1.example.com

[sipus_endpoint]
type=endpoint
transport=transport-udp-nat
context=from-external
disallow=all
allow=ulaw
outbound_auth=sipus_auth
aors=sipus_aor
direct_media=no
from_domain=gw1.example.com

[sipus_aor]
type=aor
contact=sip:gw1.example.com
contact=sip:gw2.example.com

[sipus_identify]
type=identify
endpoint=sipus_endpoint
match=203.0.113.1
match=203.0.113.2

[6001]
type=endpoint
context=from-internal
disallow=all
allow=ulaw
transport=transport-udp-nat
auth=6001
aors=6001
direct_media=no

[6001]
type=auth
auth_type=userpass
password=your_password
username=6001

[6001]
type=aor
max_contacts=2

The phone (6001) also gets direct_media=no. Without it, Asterisk tries to bridge audio directly between the phone and the ITSP. Since the phone's IP is private, that bridge goes nowhere.

Transports require a full restart

Transport settings take effect only after core restart now, not pjsip reload. Get these right before you go live.

Scenario 2: Asterisk is public, phones are remote behind NAT

If Asterisk has a public IP but the phones are at home or in a branch office, the transport settings above are not relevant. Asterisk knows its own address. The problem is the phones: they advertise private IPs in registration and SDP that Asterisk cannot route back to.

Four endpoint settings handle this:

Setting What it does
rtp_symmetric Send RTP back to the IP and port the audio arrived from, ignoring the address in the SDP
force_rport Send SIP responses to the port the request came from, ignoring the Via header
rewrite_contact Store the Contact URI from the actual source address of the REGISTER packet, not what the phone reported
direct_media=no Keep Asterisk in the audio path
[6001]
type=endpoint
context=from-internal
disallow=all
allow=ulaw
auth=6001
aors=6001
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no

[6001]
type=auth
auth_type=userpass
password=your_password
username=6001

[6001]
type=aor
max_contacts=2
qualify_frequency=60

qualify_frequency=60 sends a SIP OPTIONS ping every 60 seconds. This keeps the NAT mapping alive in the remote router and lets Asterisk notice when a phone disappears.

Double NAT

If both Asterisk and the phones are behind NAT, use both sets of settings: transport-level external_* options on the transport, plus rtp_symmetric, force_rport, and rewrite_contact on the endpoints.

Troubleshooting

One-way audio. Start with direct_media=no. If that is already set, check that UDP 10000-20000 is open inbound on the firewall. If Asterisk is behind NAT, verify external_media_address is set on the transport.

Phone registers but calls have no audio. The culprit is usually rewrite_contact. When a phone registers through NAT, the Contact header contains a private IP. Without rewrite_contact, Asterisk dials back to that private address and the call never connects.

No audio in either direction. Turn on RTP debugging:

asterisk -rx "rtp set debug on"

If Asterisk is sending audio to a private IP from the remote end, the phone is not providing a usable media address. rtp_symmetric tells Asterisk to ignore the SDP and just reply to wherever the audio came from.

Registration drops intermittently. NAT mappings time out. qualify_frequency on the AOR keeps the connection alive with periodic pings. 60 seconds works for most routers; aggressive ones may need shorter.

A solid choice for hosting Asterisk.

High-performance cloud compute starting at $2.50/mo. Deploy a VPS in seconds.

Get $100 Free Credit

Referral link. Helps support this site.

User Notes

Know a tip or gotcha for this topic? Share it below and help others.

Contribute a note

Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.

Moderated before publishing. Email never shown.
Related Snippets