ARCAMUSA VOICE ENGINEERING

How to Configure an Asterisk PJSIP Trunk on an Ubuntu VPS

Build a provider-neutral PJSIP trunk model on Ubuntu using documentation addresses, explicit objects, controlled firewall scope and verifiable CLI checks.

Architecture: separate signaling from media

SIP creates, modifies and ends the dialog; RTP or SRTP normally carries audio on different UDP ports. A successful 200 OK and ACK proves signaling reached an accepted dialog, but it does not prove that either media direction is routable. Treat the peer specification, DNS, firewall, PJSIP objects, dialplan and media policy as separate verification domains.

Pre-flight inventory

READ ONLYSENSITIVE OUTPUT
Pre-change inventoryCOMMANDBASH
lsb_release -a
uname -a
timedatectl status
ip -br addr
ip route
ss -lntup
sudo asterisk -V
sudo asterisk -rx "core show uptime"

Record the operating-system release, kernel, UTC synchronization, interface addressing, default route, listeners, Asterisk version and uptime. Healthy output means time is synchronized, the expected interface owns the expected address, the route points to the intended gateway, and Asterisk is running. An unexpected listener is a security finding; a missing Asterisk version or uptime response means configuration work should stop until service state is understood.

Illustrative healthy observationsOUTPUTCONSOLE
System clock synchronized: yes
NTP service: active
Asterisk 22.x (illustrative)
System uptime: 4 days, 03:12:08
WHAT THIS CONFIGURES

Nothing; these are read-only observations.

WHY IT EXISTS

They establish version, time and network facts before change.

EXPECTED STATE

Synchronized UTC, deliberate listeners and known routes.

VERIFY WITH

Compare output to the approved host record.

IF IT FAILS

Resolve time, routing or service health before trunk changes.

ROLLBACK

Not applicable; no state changed.

SECURITY IMPACT

Interface and listener output can expose topology; redact it.

Back up before change

CONFIG CHANGEPRODUCTION CAUTION
Root-only backup commandsCOMMANDBASH
sudo install -d -m 700 /root/asterisk-backup
sudo cp -a /etc/asterisk/pjsip.conf /root/asterisk-backup/pjsip.conf.$(date -u +%Y%m%dT%H%M%SZ)
sudo cp -a /etc/asterisk/extensions.conf /root/asterisk-backup/extensions.conf.$(date -u +%Y%m%dT%H%M%SZ)
sudo cp -a /etc/asterisk/rtp.conf /root/asterisk-backup/rtp.conf.$(date -u +%Y%m%dT%H%M%SZ)

The mode-700 directory limits casual disclosure of dialplan and authentication references. Confirm the files exist and record their exact timestamps. To roll back, copy only the reviewed backup version over the changed file, validate syntax, and use the narrowest supported reload in a controlled window. Never restore an entire directory blindly because unrelated valid changes may be lost.

Firewall planning: signal and media deliberately

CONFIG CHANGEPRODUCTION CAUTION

Permit administration only from an approved documentation range, signaling only from an expected peer when IP authentication applies, and the RTP range actually configured in rtp.conf. The commands below are patterns, not a universal policy. A hostname may resolve to multiple or changing addresses; coordinate that behavior before expressing peer policy as a static firewall rule.

Illustrative UFW policyWARNING / DO NOT COPY BLINDLYBASH
sudo ufw allow from 192.0.2.0/28 to any port 22 proto tcp comment 'approved admin range'
sudo ufw allow from 203.0.113.10 to any port 5060 proto udp comment 'documented SIP peer'
sudo ufw allow from 203.0.113.10 to any port 5061 proto tcp comment 'documented SIP TLS peer'
sudo ufw allow from 203.0.113.10 to any port 10000:20000 proto udp comment 'RTP range; match rtp.conf'
sudo ufw status numbered

Do not open AMI, ARI, a management GUI or SSH to the world because SIP is public. A healthy result lists only intended sources and ports. If audio uses a different negotiated relay, update the approved architecture first rather than broadening UDP indiscriminately.

PJSIP transports

CONFIG CHANGERELOAD REQUIRED

Select the transport required by the peer. Enabling UDP and TLS together does not automatically upgrade calls; the endpoint and URI must select the intended transport. Transport changes can be restart-sensitive in some Asterisk situations, so consult the installed branch and schedule a controlled window.

/etc/asterisk/pjsip.confCONFIGINI
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.0.2.0/24
external_signaling_address=198.51.100.20
external_media_address=198.51.100.20
Optional TLS transport — fake pathsCONFIGINI
[transport-tls]
type=transport
protocol=tls
bind=0.0.0.0:5061
cert_file=/etc/asterisk/keys/example/fullchain.pem
priv_key_file=/etc/asterisk/keys/example/private.key
method=tlsv1_2
verify_server=yes
require_client_cert=no
WHAT THIS CONFIGURES

Separate UDP and TLS listeners with explicit NAT identity.

WHY IT EXISTS

Transport controls signaling protocol and advertised reachable address.

EXPECTED STATE

Only the peer-required transport is selected for the trunk.

VERIFY WITH

`pjsip show transports` and a narrow listener check.

IF IT FAILS

Inspect certificate, bind conflict, DNS and transport selection.

ROLLBACK

Restore the prior transport block and apply the branch-appropriate controlled reload or restart.

SECURITY IMPACT

Private keys require strict ownership; UDP provides no signaling encryption.

AOR and contact location

CONFIG CHANGERELOAD REQUIRED
/etc/asterisk/pjsip.confCONFIGINI
[carrier-aor]
type=aor
contact=sip:sip.example.net:5060
qualify_frequency=60
qualify_timeout=3.0

A static contact tells Asterisk where to send requests. max_contacts applies when contacts are created by inbound registration and is not a substitute for a static trunk contact. Qualification can show whether OPTIONS receives a response, but “Available” does not prove call admission, destination authorization or RTP.

Outbound authentication

CONFIG CHANGESENSITIVE OUTPUT
Private configuration fragmentWARNING / DO NOT COPY BLINDLYINI
[carrier-auth]
type=auth
auth_type=userpass
username=EXAMPLE_USERNAME
password=LOAD_FROM_PRIVATE_DEPLOYMENT_PROCESS

The public example intentionally contains no working credential. Keep the actual file readable only by the service account and authorized administrators, and do not place it in source control or tickets. Digest challenges may expose usernames and derived responses in traces, so redact those fields even though the plaintext password is not present.

Endpoint policy

CONFIG CHANGERELOAD REQUIRED
/etc/asterisk/pjsip.confCONFIGINI
[carrier-endpoint]
type=endpoint
transport=transport-udp
context=from-carrier-restricted
disallow=all
allow=ulaw,alaw
aors=carrier-aor
outbound_auth=carrier-auth
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
from_user=+12025550123

The endpoint combines channel policy. Context isolation prevents an inbound peer from reaching unrestricted dialplan destinations. Codec order must reflect both licensed capability and the peer agreement. NAT options should address observed packet behavior, not be enabled reflexively; direct_media=no keeps Asterisk in the media path, which simplifies control but consumes relay resources.

Outbound registration when required

CONFIG CHANGERELOAD REQUIRED
/etc/asterisk/pjsip.confCONFIGINI
[carrier-registration]
type=registration
transport=transport-udp
outbound_auth=carrier-auth
server_uri=sip:sip.example.net
client_uri=sip:EXAMPLE_USERNAME@sip.example.net
contact_user=carrier-inbound
retry_interval=60
forbidden_retry_interval=600
expiration=300

Registration-auth trunks use REGISTER to establish a binding. An IP-authenticated trunk may not register at all, so “No registrations found” can be correct. A registered state proves only the REGISTER transaction; it does not prove INVITE authorization, route capacity, called-number policy or media.

Illustrative registration outputOUTPUTCONSOLE
$ sudo asterisk -rx "pjsip show registrations"

 <Registration/ServerURI................>  <Auth.........>  <Status.....>
==========================================================================
 carrier-registration/sip:sip.example.net  carrier-auth    Registered

Inbound identify mapping

CONFIG CHANGERELOAD REQUIRED
/etc/asterisk/pjsip.confCONFIGINI
[carrier-identify]
type=identify
endpoint=carrier-endpoint
match=203.0.113.10

The identify object maps packets from the documentation address to the endpoint. Confirm the packet source at Asterisk, including any authorized proxy or SBC; do not add broad networks simply to make matching succeed. If the source is not stable, use the peer’s supported identification model and document its trust boundary.

Restricted outbound test dialplan

CONFIG CHANGEPRODUCTION CAUTION
/etc/asterisk/extensions.confWARNING / DO NOT COPY BLINDLYASTERISK
[from-internal-test]
exten => _+120255501XX,1,NoOp(Controlled documentation-range test)
 same => n,Set(CALLERID(num)=+12025550123)
 same => n,Dial(PJSIP/${EXTEN}@carrier-endpoint,30)
 same => n,Hangup()

The narrow example pattern avoids creating an unrestricted international route. Replace it only through an approved dialplan design with authentication, authorization, fraud limits and emergency-service handling. Validate the selected context and a single authorized test destination before expanding scope.

RTP range and firewall alignment

CONFIG CHANGERELOAD REQUIRED
/etc/asterisk/rtp.confCONFIGINI
[general]
rtpstart=10000
rtpend=20000
strictrtp=yes

The firewall and NAT policy must match the locally configured range, but the peer’s media addresses may differ from its SIP address. Do not assume 10000–20000 is universal. After changing the range, validate that active calls are not disrupted and that sufficient ports remain for expected concurrency.

Validate objects before a call

READ ONLY
PJSIP validationCOMMANDBASH
sudo asterisk -rx "pjsip show transports"
sudo asterisk -rx "pjsip show endpoints"
sudo asterisk -rx "pjsip show endpoint carrier-endpoint"
sudo asterisk -rx "pjsip show aor carrier-aor"
sudo asterisk -rx "pjsip show registrations"
sudo asterisk -rx "pjsip show contacts"
Object validation interpretation
CommandHealthy evidenceMissing or unhealthy evidence
show transportsRequired listener is bound and available.Transport absent or unavailable; inspect bind/certificate.
show endpointObject resolves with intended AOR, auth, codec and context.Object not found or references differ from approved configuration.
show aorStatic contact or registered contact is associated.No contact means Asterisk has no destination for the AOR.
show registrationsRegistered when REGISTER is required; otherwise not applicable.Rejected/unregistered requires response and auth analysis.
show contactsContact is reachable when qualification is used.Unavailable may reflect network, DNS, OPTIONS policy or peer state.

Controlled SIP debugging

SENSITIVE OUTPUTPRODUCTION CAUTION
Asterisk CLI sessionCOMMANDBASH
asterisk -rvvv
pjsip set logger on
# place one authorized test call and record UTC time
pjsip set logger off

Correlate Call-ID across request and response, CSeq across each method, Via for transaction return paths, From and To for dialog identity, and P-Asserted-Identity only inside an authorized trust domain. Enable logging for the shortest necessary interval; high-volume logging can expose identifiers and consume storage.

Narrow packet capture

PACKET CAPTURESENSITIVE OUTPUT
Narrow live capture examplesCOMMANDBASH
sudo tcpdump -ni any host 203.0.113.10 and port 5060
sudo tcpdump -ni any host 203.0.113.10 and udp portrange 10000-20000

The first filter observes UDP signaling to the documented peer; the second observes only the configured example media range. If the peer uses TLS, tcpdump can confirm TCP/TLS establishment but not decrypted SIP content. Never leave an unbounded production capture running. Protect packet files as sensitive records and delete them under the incident retention policy.

Controlled test matrix

Deployment acceptance matrix
TestExpected
Endpoint object existsPASS
AOR resolves/contact knownPASS
RegistrationRegistered / Not applicable
OPTIONS qualifyReachable if used
Outbound INVITELeaves expected transport
100 TryingTransaction reached next hop
180 / 183Progress from identified hop
200 OKSignaling accepted
ACKDialog established
RTP both directionsMedia PASS

Failure matrix

Evidence-led failure routing
SymptomFirst evidenceDeep resource
401 / 407Challenge realm and next authenticated requestPJSIP object guide
403Responding hop, Reason, identity and account policy403 trace guide
408Request/response visibility and retransmissionsSIP debugging workflow
480 / 486Responding hop and destination stateResponse Code Explorer
488Offer/answer codecs and encryption488 SDP guide
503Source, Retry-After and route/resource state503 evidence guide
One-way/no audioSDP addresses and both RTP directionsNAT/RTP guide
Registration rejectedREGISTER challenge and credentialsPJSIP object guide
Endpoint not foundObject name and loaded configPJSIP object guide
No matching identifyActual source and identify matchPJSIP object guide

Rollback and recovery

PRODUCTION CAUTION

Stop testing, disable verbose logging, preserve the Call-ID and failure evidence, then restore only the changed sections from the timestamped backup. Validate the restored syntax and object state before resuming traffic. If a transport change requires a restart on the installed release, use an approved window and confirm active channel drain. Rollback is complete only when baseline registration, signaling and two-way RTP tests match the pre-change record.

Related engineering resources

Authoritative references

Inputs you need from your peer

Peer input to configuration mapping
Peer-provided valueObject or parameter that consumes it
SIP host, port and transportAOR contact plus transport/endpoint
Authentication username and secretauth plus outbound_auth reference
Expected source networksidentify match
Codec and encryption policyendpoint allow/disallow and media_encryption
RTP rangertp.conf plus host/network firewall
Number formatrestricted test dialplan and normalization

Implementation closure

Inputs required

Peer SIP host → AOR contact; authentication username/secret → auth object; expected source networks → identify match; codecs/encryption → endpoint; RTP range → rtp.conf and firewall; number format → dialplan.

Change surface

Asterisk pjsip.conf or included files, extensions.conf, rtp.conf, host firewall, and any upstream network policy.

Apply and reload semantics

Validate syntax and loaded objects first. Use a scoped PJSIP reload only when supported by the installed version; schedule a service restart only when a documented transport change requires it.

Healthy result

Objects load, the expected contact or registration is available, a controlled call completes, and RTP is bidirectional.

Failure path

Use CLI object state, one Call-ID, SIP ladder, SDP, and packet capture to identify the first failed boundary.

Stop conditions

Stop if the backup is incomplete, the peer inputs conflict, the firewall change would be broad, or a test could affect live emergency or customer traffic.

Definition of done

The intended endpoint is selected inbound and outbound, signaling succeeds, media works both ways, logs contain no new errors, and rollback artifacts are retained.

Last substantively reviewed: 2026-09-13