SignalWire Trunking with Incredible PBX 2020/2021

SignalWire was developed by the same fine folks that created FreeSWITCH. It is a powerful and inexpensive, but complex, trunking platform. DIDs typically cost 20¢ a month. Outbound voice calls (terminations) are $.0075 per minute while incoming calls are $.0036 per minute. Unlike most VoIP providers, SignalWire bills per leg of a call so there is an additional $.0007 per minute cost for the leg to and from your PBX to SignalWire. SignalWire also rounds all calls up to a full minute for billing purposes. Also be aware that SignalWire termination pricing has more than tripled in less than two years. Because SignalWire calls are processed as anonymous SIP calls, special configuration is required for incoming calls depending upon whether you’ve deployed Incredible PBX 2020/2021 or Incredible PBX 2020/2021 PUBLIC.

Configuring DIDs and SIP Trunking at SignalWire

After signing up for a SignalWire account, a Project ID will be created on your Dashboard.

Click on the Phone Numbers tab and sign up for one or more DIDs after you have funded your account.

Click on the SIP tab and create a new SIP Endpoint. Create a secure USERNAME and PASSWORD. Accept the Default Codecs, and change to Custom Ciphers by disabling AEAD_AES_256_GCM_8.

In the SIP -> SIP Settings tab, make note of your SIP URI. Change the ENCRYPTION SETTING to Required. Disable the AEAD_AES_256_GCM_8 DEFAULT CIPHER. Save your settings.

Return to the Phone Numbers tab and edit each of your Phone Numbers. Set ACCEPT INCOMING CALLS to Voice Calls. Set HANDLE CALLS using SIP Endpoint. Set WHEN A CALL COMES IN to your USERNAME @ Your SIP URI. Save your changes.

Configuring DIDs and SIP Trunking on Incredible PBX 2020/2021

SignalWire requires that all incoming calls arrive on UDP 5060 which rules out using PJsip for your SignalWire Trunk in the default Incredible PBX configuration. Here’s how a SignalWire chan_sip Trunk in FreePBX should be set up assuming signalwire was your assigned USERNAME from above:


Registration String: signalwire:your-password@acctname-12digitcode.sip.signalwire.com

The Outbound Route to process SignalWire calls must include a CallerID Number that is either a DID purchased from SignalWire or a Phone Number that you have Verified in their Phone Number -> Verified procedure. For U.S./Canada 10-digit calling, the Prepend, Prefix, Dial Patterns should be as follows: +1,leave-blank,NXXNXXXXXX.

The Inbound Route to process incoming calls from your SignalWire DIDs should specify your 10-digit DID and assign the incoming call destination desired.

Finally, on Incredible PBX 2020/2021 PUBLIC implementations, edit /etc/asterisk/extensions_override_freepbx.conf. Scroll down to the exten => s,1 line and replace the lines beginning there down to the Zapateller line with this code. Save the file and reload your dialplan: asterisk -rx "dialplan reload"

exten => s,1,NoOp(Beginning s anonymous options)
exten => s,n,GotoIf($["${CHANNEL:0:22}"="SIP/sip.signalwire.com"]?signalwire)
exten => s,n,Goto(realanon)
exten => s,n(signalwire),Set(DID=${CUT(CUT(SIP_HEADER(To),@,1),+,2)})
exten => s,n,Set(DID=${DID:1})
exten => s,n,Goto(from-pstn-e164-us,${DID},1)
exten => s,n(realanon),GotoIf($["${SIPLANG}"!=""]?setlanguage:checkanon)
exten => s,n(setlanguage),Set(CHANNEL(language)=${SIPLANG})
exten => s,n(checkanon),GotoIf($["${ALLOW_SIP_ANON}"!="yes"]?noanonymous)
exten => s,n,Goto(from-trunk,${DID},1)
exten => s,n(noanonymous),Set(TIMEOUT(absolute)=15)
exten => s,n,Log(WARNING,"Rejecting unknown SIP connection from ${CHANNEL(recvip)}")
exten => s,n,Answer
exten => s,n,Wait(2)
exten => s,n,Zapateller()

On traditional Incredible PBX 2020/2021 platforms, you’ll need to edit /etc/asterisk/extensions_custom.conf. Scroll down to the end of the file and add the following code. Save the file and reload your dialplan: asterisk -rx "dialplan reload"

exten => s,7,GotoIf($["${CHANNEL:0:22}"="SIP/sip.signalwire.com"]?signalwire,s,1)

exten => s,1,Set(CALLERID(number)=${CALLERID(number):-10})
exten => s,2,Set(DID=${CUT(CUT(SIP_HEADER(To),@,1),+,2)})
exten => s,3,Set(DID=${DID:1})
exten => s,4,Goto(from-trunk,${DID},1)

Porting Out a SignalWire DID

The procedure to port out a SignalWire DID is documented here.