Server

SIP Trunk Basics for Sysadmins

By Prabath Thalangama· October 24, 2026· 3 min read
#sip#voip#telecom#troubleshooting

Introduction

If you run a PBX (Asterisk, FreeSWITCH, 3CX) you'll eventually connect it to the outside world with a SIP trunk from an ITSP (internet telephony service provider). Most trunk problems are network problems, and they're very diagnosable once you know which part of SIP does what.

Concepts

SIP is two channels:

  • Signalling (SIP) — the call-control messages: REGISTER, INVITE, 100 Trying, 180 Ringing, 200 OK, ACK, BYE. Text, HTTP-like. Usually UDP or TCP port 5060, or TLS on 5061 (SIPS).
  • Media (RTP) — the actual audio, negotiated inside the SIP messages via SDP. A separate UDP stream, typically in a range like 10000–20000, on whatever IP/port each side advertised in its SDP.

A trunk is either registration-based (your PBX sends REGISTER and keeps the binding alive with periodic re-registers) or IP-authenticated (the provider accepts calls from your fixed public IP with no registration).

A call, simplified

PBX                         ITSP
 |  INVITE (SDP: my media = 203.0.113.5:10004)
 | ------------------------------------------->
 |                 100 Trying
 | <-------------------------------------------
 |                 180 Ringing
 | <-------------------------------------------
 |                 200 OK (SDP: their media = 198.51.100.7:24010)
 | <-------------------------------------------
 |  ACK
 | ------------------------------------------->
 |  <====== RTP audio both directions ======>
 |  BYE
 | ------------------------------------------->
 |                 200 OK

Hands-on

Firewall / NAT rules

On the PBX host or the edge firewall, for a PBX behind NAT:

# SIP signalling
-A INPUT -p udp --dport 5060 -s <ITSP_SIP_IP>/32 -j ACCEPT
# RTP media (match your PBX's configured range)
-A INPUT -p udp --dport 10000:20000 -j ACCEPT

In Asterisk pjsip.conf, tell it its public address so the SDP it sends contains the public IP, not 192.168.x.x:

[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0:5060
external_media_address = 203.0.113.5
external_signaling_address = 203.0.113.5
local_net = 192.168.1.0/24

Forward 5060/udp and the RTP range on the router to the PBX.

Watch the signalling

# Asterisk
asterisk -rx "pjsip set logger on"
asterisk -rx "pjsip show registrations"
asterisk -rx "pjsip show endpoints"

# Or capture it
sudo tcpdump -ni any -s0 -A 'udp port 5060'

# Full-featured: sngrep gives a ladder diagram of each call
sudo sngrep

Verification and troubleshooting

  • Registration fails (401/403, or nothing) — wrong credentials or realm; the provider's IP isn't in your allow rule; or a 5060 conflict with another SIP process. pjsip show registrations shows the last status.
  • Calls ring but drop at answer (200 OK then BYE) — the ACK isn't reaching the far end, usually a NAT/Contact-header issue. Check external_signaling_address.
  • One-way audio — the classic NAT symptom. One side is sending RTP to a private IP it saw in the other side's SDP, or the return RTP is blocked because the firewall didn't see the outbound packet first. Fix external_media_address, open the RTP range, and consider enabling a SIP ALG off (SIP ALGs on consumer routers usually make this worse) or a media relay / rtpengine.
  • No audio at all — SDP negotiated a codec neither side actually supports, or RTP is fully blocked. sngrep shows the negotiated codec; tcpdump 'udp portrange 10000-20000' shows whether RTP is flowing.
  • Calls fail after ~30 minutes — session timers (RFC 4028) expiring because re-INVITEs aren't getting through, or a stateful firewall's UDP timeout is shorter than your re-register/OPTIONS interval. Send keepalive OPTIONS every 30 s.
  • Inbound calls don't arrive — the provider routes DIDs to your registration's Contact or to a configured IP; if you're registration-based behind NAT, the binding must be kept fresh (short expires, plus qualify).
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.