Skip to content

Set up a SIP trunk on Asterisk with PJSIP

This guide walks you through the full setup of a Vohippo trunk on Asterisk with the PJSIP driver (Asterisk 16 and later): every section of pjsip.conf explained, the dialplan for outbound and inbound calls, caller ID, NAT and codecs. At the end you will find the commands to check that everything works and fixes for the most common problems.

13 min readUpdated

What you need before you start

A SIP trunk is the link between your PBX and the carrier: your extensions' calls travel over the Internet to the telephone network, and your numbers ring on the PBX. On Asterisk the trunk is a set of PJSIP objects written in pjsip.conf, plus two contexts in the dialplan. If you first want to see what the service includes, the page on the Vohippo SIP trunk sums up channels, prices and limits.

Get these things ready before you open the editor:

  • A SIP account dedicated to the PBX, created in the portal under SIP accounts. If you do not have access yet, you can sign up to the portal.
  • The account's username and password, copied with no spaces before or after.
  • At least one verified caller ID: a number bought on Vohippo (it is already set up, «Native CLID») or one of your own numbers from another carrier, verified by SMS, WhatsApp or voice call.
  • Asterisk 16 or later with the res_pjsip module loaded and access to the console (asterisk -rvvv).

Picture a small firm with four extensions on an Asterisk box in the office: a single SIP account for the trunk is enough, because channels are set on the account with «Simultaneous outbound calls» (from 1 to 1000; each channel beyond the first costs €0.50 a month). In the portal it is also worth setting the «Daily spending limit» and the enabled destinations straight away: they are your first line of defence if the PBX is ever compromised, as the VoIP security guide explains.

The trunk in pjsip.conf

The configuration is made of four sections plus one: the credentials, where to find us, the registration and the endpoint itself. The last one (identify) is there to recognise calls coming from us. Replace UTENTE_DAL_PORTALE and PASSWORD_DAL_PORTALE with your account's username and password.

; /etc/asterisk/pjsip.conf — trunk verso Vohippo
[vohippo-auth]
type=auth
auth_type=userpass
username=UTENTE_DAL_PORTALE
password=PASSWORD_DAL_PORTALE

[vohippo-aor]
type=aor
contact=sip:sip.vohippo.com:5060
qualify_frequency=60

[vohippo-reg]
type=registration
transport=transport-udp
outbound_auth=vohippo-auth
server_uri=sip:sip.vohippo.com
client_uri=sip:[email protected]
retry_interval=60
expiration=600

[vohippo]
type=endpoint
transport=transport-udp
context=da-vohippo
aors=vohippo-aor
outbound_auth=vohippo-auth
from_user=UTENTE_DAL_PORTALE
from_domain=sip.vohippo.com
disallow=all
allow=alaw,ulaw,g722
dtmf_mode=rfc4733
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes

[vohippo]
type=identify
endpoint=vohippo
match=sip.vohippo.com

The configuration uses a transport called transport-udp. If your pjsip.conf does not have one yet, add it at the top of the file: it is the UDP transport on port 5060, the same one our server uses.

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060

What each section does

auth: the credentials

The vohippo-auth section holds the SIP account's username and password. Asterisk uses it when our server replies with an authentication challenge (the classic 401): it is normal for the first REGISTER to be rejected and the second, with credentials, to be accepted. The same object serves both registration and outbound calls, because both refer to it with outbound_auth.

aor: where to find the server

The AOR (Address of Record) tells Asterisk which address to send the trunk's calls to: sip:sip.vohippo.com:5060. With qualify_frequency=60 Asterisk sends an OPTIONS request every minute and keeps an eye on whether the server is reachable; if it stopped answering, you would see it straight away with pjsip show endpoint vohippo.

registration: being found for inbound calls

Registration is what makes inbound calls work: it tells our server which public address your Asterisk is at, so when someone calls one of your numbers we know where to send it. expiration=600 is the registration lifetime in seconds (ten minutes, the platform default); Asterisk renews it on its own before it expires. With retry_interval=60, if registration fails, Asterisk tries again every minute.

endpoint: the trunk itself

The vohippo endpoint brings everything else together. context=da-vohippo is the dialplan context where inbound calls land. from_user and from_domain put the account username and our domain in the From field. disallow=all followed by allow=alaw,ulaw,g722 limits the codecs to the ones the platform accepts. dtmf_mode=rfc4733 sends keypad tones as events separate from the audio, the method our server uses.

The last four lines are about the network. direct_media=no keeps the audio on Asterisk at all times instead of letting it flow directly between phone and carrier. rtp_symmetric, force_rport and rewrite_contact make Asterisk reply to the address and port the packets actually come from: these are the options that solve most NAT problems.

identify: recognising who is calling

When an INVITE arrives, Asterisk has to work out which endpoint it belongs to. The identify section with match=sip.vohippo.com says that everything coming from our server is the Vohippo trunk, so it goes into the da-vohippo context. Without this section inbound calls would be rejected or end up in the anonymous context.

The dialplan

You need two contexts: one for outbound calls from your phones and one for calls arriving from the trunk. The name of the inbound context must match the one written in context= on the endpoint.

; /etc/asterisk/extensions.conf
[da-interni]                       ; contesto dei tuoi telefoni
exten => _X.,1,Set(CALLERID(num)=390212345678)   ; il tuo numero verificato
 same => n,Dial(PJSIP/${EXTEN}@vohippo,60)
 same => n,Hangup()

[da-vohippo]                       ; chiamate in arrivo dal trunk
exten => _.,1,NoOp(Chiamata in entrata da ${CALLERID(num)})
 same => n,Dial(PJSIP/101&PJSIP/102,25)
 same => n,Voicemail(101@default,u)
 same => n,Hangup()

In the example, da-interni is the context of your phones and da-vohippo the one for calls coming in from the trunk; the names are arbitrary, as long as they match.

Outbound calls

In the da-interni context the _X. pattern catches any dialled number and sends it to the trunk with Dial(PJSIP/${EXTEN}@vohippo,60), waiting up to 60 seconds for an answer. Numbers are dialled as on an ordinary phone: for Italy in national format (06 1234 5678, 345 218 0937), and for other countries with the international prefix, preferably with 00 or + (0044…, +33…). A number without a prefix is read as belonging to the country of the mobile number you verified.

If you have local extensions on the same Asterisk (101, 102…), define them first in the context or in an included context, so they do not go out over the trunk. Vohippo short extensions (2 to 6 digits), on the other hand, connect SIP accounts belonging to the same customer and are free: if you send the trunk a short number that matches one of your accounts, that account rings.

Inbound calls

The da-vohippo context uses the _. pattern, which accepts whatever arrives from the trunk: it rings extensions 101 and 102 together for 25 seconds and then hands over to Asterisk's voicemail. It is a cautious choice, because what Asterisk sees as the extension depends on the registration, not on the number dialled. If you want to handle several numbers differently, look at the first call with pjsip set logger on before writing more precise rules.

In the portal, the number needs a routing flow with a «Ring SIP accounts» step pointing to the trunk account: a number without a flow ends up as «Calls rejected». How to build the steps is explained in the guide on how to set up an inbound number.

Caller ID: the real rules

The caller ID is the number the person you call sees. On the platform every outbound call must carry a verified caller ID: without one, the call is rejected and the call report shows «Caller ID not allowed». There is no anonymous outbound calling. The caller ID is decided in one of two ways.

  • Fixed caller ID on the account: you set it in the portal and it always wins, whatever Asterisk sends. It is the simplest option if the whole office calls out with the same number.
  • «Taken from the call (must be one of your caller IDs)»: the platform reads the number from the INVITE, in this order: P-Asserted-Identity, Remote-Party-ID, From. The first one that matches one of your verified caller IDs is used.

Sending the number from Asterisk

With the example endpoint, from_user puts the account username in the From, not the number set with Set(CALLERID(num)=…). If you want to choose the caller ID from the dialplan (for instance a different number per department), carry the number in P-Asserted-Identity, which the platform reads first, by adding this line to the vohippo endpoint:

send_pai=yes

Reload with pjsip reload and check with the logger that the INVITE contains the P-Asserted-Identity header with your number. The account is recognised from its credentials anyway, so the number can travel in the From too: if you prefer, you can remove from_user and let Asterisk put the caller ID there.

Numbers bought on Vohippo are already caller IDs. A number from another carrier is verified in the portal (code valid for 10 minutes, 5 attempts) and costs €0.02 per answered call. Every case, WhatsApp numbers included, is covered in the guide on caller ID and how to set it.

NAT and firewall

If Asterisk sits behind a router with NAT (the typical case for an office server), the problem to prevent is one-way audio: Asterisk writes its private address into the SIP messages and the return audio cannot find its way back. Our server already handles NAT on its side and the example endpoint does its part, but on Asterisk it is also worth declaring the public address in the transport.

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

In place of 203.0.113.10 put the office's public address, and your internal network in local_net. Then check three things on the router and firewall:

  1. Turn off SIP ALG on the router: it rewrites SIP packets and often breaks them.
  2. Allow port 5060 UDP to and from sip.vohippo.com.
  3. Allow the RTP ports: ours range from 10000 to 20000 UDP; Asterisk's are in rtp.conf (rtpstart and rtpend).

Remember that changes to transports need an Asterisk restart; pjsip reload is not enough. How NAT works and which ports to open are explained step by step in the guide on NAT, firewalls and ports.

Codecs

The platform accepts only G.711 a-law, G.711 µ-law and G.722: that is why the endpoint has disallow=all followed by allow=alaw,ulaw,g722. Order matters: Asterisk offers codecs in the order you write them. With alaw first you get classic European telephone quality; G.722 gives wideband ("HD") audio when the other side supports it too.

Do not add G.729 or Opus: they are not negotiated on the Vohippo trunk, and an internal phone that only uses those codecs would force Asterisk to transcode or make the call fail. For bandwidth, allow about 100 kbit/s per direction for each G.711 call: four simultaneous calls need roughly 400 kbit/s of free upload. The VoIP codecs guide explains the differences in detail.

Check that it works

From the Asterisk console (asterisk -rvvv), three commands are enough to see where things stopped.

pjsip show registrations     ; deve dire Registered
pjsip show endpoint vohippo  ; stato e codec negoziati
pjsip set logger on          ; traccia SIP completa, per capire un rifiuto

The first should say Registered, the second shows status and negotiated codecs, and the third prints the full SIP trace, which is what you need to understand a rejection. Then run the tests in this order:

  1. Check that the registration shows Registered and that the account also appears as registered in the portal.
  2. Call a mobile from an extension: you must hear and be heard.
  3. Call your virtual number from a mobile: the expected extension must ring.
  4. During a call, press a few keys on a service with a menu to check the DTMF tones.
  5. Open the call reports in the portal: every test must appear with its outcome.

When something does not add up, the logger shows you the server's exact response. In the portal you also have the account's SIP log for the last 7 days, useful for seeing registrations and rejections on our side.

If something goes wrong

These are the most common problems, with the most likely cause.

SymptomLikely causeWhat to do
Registration RejectedUsername or password with a trailing spaceCopy the credentials again from the portal and reload
Registration stops after many errorsThe platform firewall has blocked the IPFix the password, then unblock the address from «IP address security»
Call rejected immediately (403)Caller ID not verified, destination not enabled or no credit leftCheck the reason in the call reports
Busy (486) on outbound calls«Simultaneous outbound calls» reachedIncrease the channels on the account
One-way audioNAT or SIP ALGPublic address in the transport, SIP ALG off
Inbound calls do not arriveTrunk not registered or number without routingCheck the registration and the «Ring SIP accounts» step
Keys do not work in menusDTMF other than RFC 4733Keep dtmf_mode=rfc4733

The platform firewall blocks an address after 5 authentication errors in 10 minutes, with longer and longer blocks if the errors continue: so if you change the password in the portal, update it on Asterisk straight away. In the call reports the rejection reason is written out in full, for example «Destination not enabled on the account» or «Daily spending limit reached».

Frequently asked questions

Does it also work with chan_sip?

This guide uses PJSIP, Asterisk's current driver; chan_sip has been removed from recent versions. The concepts are the same (server, credentials, registration, codecs, NAT), but the option names change: if you can, move to PJSIP.

Can I use IP address authentication instead of a password?

Yes, if your Asterisk has a fixed public IP address: choose «IP address» on the account in the portal and add the address to the authorised ones. In that case the caller ID must be sent in P-Asserted-Identity (recommended) or in the From.

Why are outbound calls rejected if registration works?

Registration only tells you the credentials are right. A call is rejected if the caller ID is not among your verified ones, if the destination is not enabled, if there is no credit or if the spending limit has been reached: the exact reason is in the call reports.

How many channels does the trunk have?

As many as you set on the account with «Simultaneous outbound calls», from 1 to 1000. The limit only applies to outbound calls: inbound calls do not use it up.

Can I register the same account on two PBXs?

An account accepts up to 5 registered devices, but for a production PBX a dedicated account is better: that way channels, spending limits and reports stay separate.

Can Asterisk do IVR, queues and time conditions with Vohippo?

Yes, but they are Asterisk features: Vohippo provides the lines, the numbers and the caller ID, while your PBX handles menus, queues and opening hours. If you would rather not manage a server, consider a cloud PBX.

More guides

Guide: SIP trunk on FreePBX

On FreePBX you do not write files: you fill in a few screens of the web interface. Here you will find what to put in each field of the PJSIP trunk,…

Guide: SIP trunk on 3CX

How to connect a Vohippo SIP trunk to a 3CX PBX, from creating the account in the portal to the first call. Panel labels change between 3CX versions,…

Caller ID

Caller ID is the number the person you call sees. In this guide you will find how Vohippo decides which number to present, how to set it on a phone…

NAT, firewalls and ports

Almost every problem with a VoIP phone that registers but does not ring, or that lets voice through in one direction only, starts between the router…

VoIP codecs

A codec is the way your voice is turned into data to travel over the internet: it decides how much bandwidth a call uses and how good it sounds. Here…

Guide: VoIP security

Toll fraud is rarely a sophisticated attack: someone finds an account with a weak password, registers a device on it and calls expensive destinations…

Try the AI demo in real time

The AI Secretary you set up in Vohippo answers you exactly as it would for your company: it sends you an exact summary of the conversation and only puts the call through when needed. You set the rules, from the app too.

Speaks 32 languages: hello

Let's talk: the demo is given by a person, not a video

One of our operators walks you through the portal live and answers the questions that matter for your case. If you would rather write, we are on WhatsApp.

Signing up is free and with no commitment: we credit your account with trial credit so you can make your test calls.