Show & Tell: Building a personal VoIP Telephony Network

17 min read Original article ↗

Since I was a teenager, I have been intrigued by telephone systems. I never had the chance to be an old-school phone-phreak, so I jumped at the chance to become a 21st century phone phreak. I have played with different VoIP technologies on-and-off, and have largely declared Digium's Asterisk PBX (https://www.asterisk.org/) to be my favorite solution.

For the past year, I have been using Asterisk and Twilio as a telephone provider. The costs are less than that of a regular landline in my city, but I have more features than any traditional telephone provider would ever provide.

Asterisk lets you do a lot of really cool stuff with no programming required, although it can be integrated and programmed with Python for endless possible uses. Most businesses prefer commercial PBXs from companies like Mitel or Avaya, but I have always preferred the Open-Source solution. And for those who don't like mucking with configuration files, there's always FreePBX, which wraps Asterisk in an intuitive web front-end. For the purposes of this write-up, though, we'll be using vanilla Asterisk, and configuring it via .conf files and the command line.

Twilio has some of the same functionality as Asterisk, but it is entirely a PaaS solution providing access to traditional PSTN numbers.

In the past, most of my projects were disjointed and more proof-of-concepts than actual useful configurations. My first Asterisk server was an old Compaq tower in my parents' house in Memphis getting free inbound SIP trunking from IPKall in Seattle, and free outbound SIP Trunking from FreeWorldDialup and SIPPhone. Sadly, most of the free services I used to love are offline, but fortunately inexpensive new services are now available that bring me even more functionality than I have had previously.

I am currently using two low-end OVH VPSs running Asterisk (one in America, another in Europe), a Cisco SPA112 SIP gateway, Twilio SIP Trunking, and a generic voice+text cell phone with a Twilio Programmable SIM.

This is all the hardware I use (minus three handsets):

In this write-up I will cover the following:

  • Setting up an Asterisk server in the cloud
  • Securing your Asterisk server
  • Connecting a SIP gateway to a cloud-hosted Asterisk server
  • Setting up Twilio virtual phone numbers
  • Connecting an Asterisk server to Twilio’s SIP trunking service
  • Making and receiving calls using a SIP phone, an Asterisk PBX and Twilio SIP Trunking
  • Connecting a non-data cell phone directly to an Asterisk PBX via T-Mobile’s voice network using Twilio Programmable Wireless
  • Reducing lag in International calls by taking advantage of dedicated fiber routes
  • Creative uses of VoIP technology
  • Cost breakdown of services

Setting up an Asterisk server in the cloud

This part is arguably the easiest. I get my cloud servers from OVH (https://www.ovh.com/us/vps/). Their cheapest VPS is only $3.49/month, and has more the the necessary resources accomplish everything in this article. I use Debian, but Asterisk should be available in the repositories of whatever Linux distro you prefer.

To get Asterisk up-and-running, just run “sudo apt-get install asterisk" (or equivalent). This will install Asterisk and all core dependencies. There are a number of additional packages that you can install for added functionality, but we won't need any today. After installing, your server will start a ready-to-configure instance of Asterisk on boot.

Your server will have a static WAN IP, but I recommend giving it a DNS name if you own a domain name already.

Securing your Asterisk server

Before we talk about configuring Asterisk, there is one warning that should come with running this kind of system in the cloud. You will get attacked - immediately. These attacks are generally not severe enough to disrupt functionality, and can be mitigated to some extent. You should make sure you are on the latest version of Asterisk 15 to avoid being vulnerable to the RTPbleed eavesdropping vulnerability (Note: Some repos still have versions 13 & 14 as the default installation package).

Fail2Ban can be configured to block suspicious SIP/IAX activity automatically, but you should still never create rules that allow access without credentials, and always use highly-secure credentials when making accounts. Do not ever create a [Public] context in any of the configuration files; such rules should be reserved for Asterisk systems running on a closed network. Do not create numerical user accounts, as they are the most commonly scanned for and brute-forced. Key files and two-factor for SSH is also not a bad move. There are also ways to encrypt voice channels to avoid eavesdropping by state entities or ISPs if you are so inclined.

Connecting a SIP gateway to a cloud-hosted Asterisk server

I use a Cisco SPA112 2-port Phone Adapter (http://a.co/f0d8KYE/) to connect to my Asterisk server. At $28 it's not too bad, and I managed to snag a Panasonic KX-TG6531 4-handset cordless phone system for $10 at a electronics recycling center, and new batteries were only $8. All the hardware cost me ~$50 total.

Configuring the device can get a little bit complicated. First, you'll need to either set a Static IP or DHCP reservation for the device and forward ports 5060-5061 through your router or firewall. Next you'll need to configure both the Asterisk server and the Phone Adapter to properly communicate with each other.

Configuring the Asterisk server:

Starting with a vanilla installation of Asterisk, we only need to modify one configuration file to get this working. You'll want to add a new SIP user to the /etc/asterisk/sip.conf file.

You'll need to add the something like this to the bottom of the file:

[ciscophone](!)
type=friend
context=LocalSet
qualify=yes
nat=no
host=dynamic
caninvite=no
disallow=all
allow=ulaw
externip={SERVER IP}

[spa112a](ciscophone)
callerid="Alex Vranas" <5501>
secret={SECURE PASSWORD}

[spa112b](ciscophone)
callerid="Alex Vranas" <5502>
secret={SECURE PASSWORD}

You'll then want to reload the configuration so that this user can log in. You can do this one of two ways. You could just simply restart the service with "service asterisk restart" or "/etc/init.d/asterisk restart". However, there is also a CLI interface you can access at "asterisk -vvvvvr" (more/less 'v' to adjust verbosity 0-5). From there you can run "core reload" to reload most of the config files, most importantly 'sip.conf' and 'extensions.conf'.

Configuring the Phone Adapter:

Now that the Asterisk server has a compatible SIP user configured, we can configure the Cisco device to log in.

You'll enter your credentials into the Quick Setup page when you log into the Cisco device.

I had some difficulties getting everything working smoothly with default settings, specifically, two-way audio and disconnection problems. I found this to be the ideal configuration for the above Asterisk SIP configuration:

Once the settings are saved, you should see the Registration State go to "Registered" on the Information page:

Testing the connection:

Once you have the SIP gateway registered to the Asterisk server, you'll want to test things out. When we set up the SIP account My favorite way to do this is to play music over the line. You'll need to install mpg123 on the Asterisk server for this to work. Just run "sudo apt-get install mpg123". Now we're going to declare the [LocalSet] context we assigned the SPA112 lines to, and create some extensions. Add something like this to the bottom of your "/etc/asterisk/extensions.conf" file:

[LocalSet]
;Demos
include => demo	;Import Demos

;Phones
exten => 5501,1,Dial(SIP/spa112a)	;Cisco SPA112 Line1
 same => n,Hangup()
exten => 5502,1,Dial(SIP/spa112b)	;Cisco SPA112 Line2
 same => n,Hangup()

;Play Music
exten => 6101,1,Answer()
 same => n,MP3Player(/path/to/mp3/file)
 same => n,Hangup()

Once the file is saved you can run "core reload" in the Asterisk CLI again to bring the extensions into play.

We're loading the [demo] context so that we can run some basic tests. The first thing you're going to want to do is dial 600# on your phone to do a basic echo test. This will let you verify that audio is moving both directions, and you'll get feel for the latency between you and the server.

Next, you can dial 6101# to play an MP3 file. The file can be located on the filesystem, or you can enter a web URL, including to MP3-encoded internet radio stations.

If you have two phones, you can now call from one to the other by dialing 5501# and 5502# for lines 1 and 2 respectively.

Setting up Twilio virtual phone numbers

So now you have two phone lines that can call each other, and a collection of test lines. Now what?

Back in the early 2000's there were a handful of free VoIP services available. Leading the pack were FreeWorldDialup and SIPPhone. You could get a virtual number, register with a softphone or link your Asterisk server, and participate in a proprietary VoIP phone network separate from the actual PSTN network.

Unfortunately, I do not know of any networks like this that exist today, though there are a lot more SIP Trunking services available. Pretty much every city has at least one local SIP trunking provider that can issue you local numbers, and there are plenty of national players too. I, however, prefer to use Twilio (https://www.twilio.com/), as many other Trunking providers have pricing that only makes sense for call centers, while Twilio can have a monthly cost less than a dollar if used sparingly enough. It also has a far more impressive feature set, including international numbers, SMS/MMS, scripting, webhooks and programmable SIM cards.

You'll need to go ahead and get registered at and load some money onto your account. Twilio works by charging microtransactions, many less than a cent, to your account balance, rather than charging flat monthly fees for use. You can configure your account to automatically reload if the balance drops below a threshold, otherwise your account will stop working when you run out of money.

You'll want to purchase a phone number. Most US numbers cost $1/month. Once you have purchased a number you can leave it unconfigured. Before you can use it, you'll need to get Twilio connected to your Asterisk server. Twilio lets you browse and search for patterns in numbers, so you can pick and choose one that you like:

Connecting an Asterisk server to Twilio’s SIP trunking service

Once you have a number, you can create a new SIP user in Asterisk for it. Go ahead and add this to the bottom of your "/etc/asterisk/sip.conf" file:

[twilio-trunk](!)
type=peer
context=LocalSet
dtmfmode=auto
canreinivite=no
insecure=port,invite
disallow=all
allow=ulaw
secret={SECURE PASSWORD}

[twilio0](twilio-trunk)
username=twilio0
host={CUSTOM NAME}.pstn.twilio.com
fromuser=+1{PHONE NUMBER}

[twilio1](twilio-trunk)
host=54.172.60.2

[twilio2](twilio-trunk)
host=54.172.60.0

[twilio3](twilio-trunk)
host=54.172.60.1

[twilio4](twilio-trunk)
host=54.172.60.3

This will create a login for Twilio and Asterisk to authenticate one another. Additionally, Twilio can now call into the Asterisk server from any of it's endpoints. You will need to go back and re-enter the 'host' for user "twilio0" once you set up a SIP trunk in Twilio after completing the Origination options in the next steps.

To continue, we need to set up Trunking, Credentials, and Termination in Twilio to match the credentials we stored in the sip.conf file:

Now you have a pathway for your Twilio number to route calls to your server into the [LocalSet] context and reach the 5501 extension to ring your. Now all you have to do is configure your number:

Making and receiving calls using a SIP phone, an Asterisk PBX and Twilio SIP Trunking

Now that you have SIP trunking configured for Termination and Origination, when a call is placed to the number you purchased on Twilio it is routed to the Asterisk PBX and rings extension 5501, which is assigned to Line 1 on the SPA112. You also now have the ability to make calls over Twilio's network, but you don't yet have the required extensions.

If you want to start making outbound US calls via Twilio, you'll need to add some rules to your dialplan:

[LocalSet]

;Demos
include => demo	;Import Demos

;Twilio
exten => _1NXXNXXXXXX,1,Set(CALLERID(all)="Alex Vranas"<+1{PHONE NUMBER}>)
 same => n,Dial(SIP/twilio0/+${EXTEN})	;Home Phone Out
 same => n,Hangup()


;Phones
exten => 5501,1,Dial(SIP/spa112a)	;Cisco SPA112 Line1
 same => n,Hangup()

exten => 5502,1,Dial(SIP/spa112b)	;Cisco SPA112 Line2
 same => n,Hangup()

;Play Music
exten => 6101,1,Answer()
 same => n,MP3Player(http:
 same => n,Hangup()

This new addition to the dialplan will catch all 11-digit numbers that begin with a '1', which includes all US and Canada phone numbers. It will then pass it though the "twilio0" SIP user, which will pass the call outbound through Twilio.

Connecting a non-data cell phone directly to an Asterisk PBX via T-Mobile’s voice network using Twilio Programmable Wireless

This part has been my favorite recently. If you haven't had a chance to play with Twilio's Programmable Wireless service, I highly advise it. For $10 you'll get a three-SIM starter pack that comes with a fun little photo book.

SIMs cost $2/month to keep online, and you can route voice, SMS, data, and commands through Twilio. The idea is to integrate these into IoT devices for the purpose of customer interaction and/or remote control. They weren't really meant to stick inside a regular phone, but they do work if you do. I only use voice and messaging (no data) in the Rate Plan for the SIM card that I put into the $20 Polaroid candybar phone (http://a.co/h3xVhfH) pictured at the top of this article:

With a phone connected to Twilio with Voice and Data, you can then configure a TwiML Bin:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Dial>
        <Sim>{SIM SID}</Sim>
    </Dial>
</Response>

And a SIP Domain (TwiML Bin URL to into the Request URL field, and a new credential list will be needed, but you can use the same access list for your Asterisk server):

And then you need a new SIP user to "sip.conf":

[SIP2CELL]
username=SIP2CELL
type=peer
context=LocalSet
secret={SECURE PASSWORD}
dtmfmode=auto
canreinivite=no
insecure=port,invite
disallow=all
allow=ulaw
host={SIP DOMAIN}.sip.twilio.com

Then you can add it to your [LocalSet] context in "extensions.conf":

exten => 5503,1,Dial(SIP/SIP2CELL)	;Polaroid Cell Phone
 same => n,Hangup()

After reloading your configuration, if you pick up your home phone, and dial 5503#, the cell phone should ring.

Next, you're going to want to configure outbound calls from the phone. You could just route the calls directly through Twilio, or you could route the calls through Asterisk where you will have more control. Obviously, I route mine through Asterisk:

You'll need this Twilio Bin:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial callerId="+1{PHONE NUMBER}">
    <Sip username="SIP2CELL" password="{SECURE PASSWORD}">sip:{{To}}@{ASTERISK SERVER URL}</Sip>
  </Dial>
</Response>

And you'll need to configure the SIM to dial to that Twilo Bin:

Now, numbers dialed on your cell phone will be placed as a SIP call to your Asterisk server. Unfortunately, it seems that all numbers have an assumed "+1", so with this configuration you must dial '1' before every number. This, unfortunately, mean that you have to dial '1', and then '1' again before dialing a area code to get out.

I am trying to learn more about dialplans, as they are pretty much just regular expressions, but I am not good at those either, so I'm working on making dialing make sense.

Regardless, if you dial 15501, you'll ring Line 1 on the SPA112. If you dial 16101, you'll play an MP3 file. If you dial 1600, you'll get an echo test.

You can also set up SMS messaging, but we'll save that for another write-up.

Reducing lag in International calls by taking advantage of dedicated fiber routes

Remember at the beginning of the article, when I mentioned I had two OVH servers? Well, you've probably noticed that everything I have described so far only requires one. My primary Asterisk server is located in Montreal, but I also have one located in Gravelines, France.

They're both on OVH, and I am in Seattle, so if you look at these two graphics, you can see how my home network can connected directly to the Montreal server, and the Montreal server can connect directly to the Gravelines server via leased lines in the Hibernia Transatlantic data cable to London.

I then connect the two together via an Inter-Asterisk eXchange by adding each other to their "/etc/asteris/iax.conf" file.

I add this to the Montreal server:

[Montreal]
type=friend
host=dynamic
secret={SECURE PASSWORD}
context=LocalSet
peercontext=LocalSet
qualify=yes

Then add this to the Gravelines server:

[Gravelines]
type=friend
host=dynamic
secret={SECURE PASSWORD}
context=LocalSet
peercontext=LocalSet
qualify=yes

Your servers can then dial into each other's [LocalSet] contexts with extensions like this:

;Montreal-Gravelines Echo
exten => 6600,1,Answer()
 same => n,Dial(IAX2/Gravelines:{SECURE PASSWORD}@{GRAVELINES ASTERISK SERVER}/600@LocalSet)
 same => n,Hangup()

This will allow you to do an echo test on the Gravelines server through the Montreal server (provided that the Gravelines server has a [LocalSet] context that includes the [demo] context).

The end result is a reduction in latency and an improvement in call quality compared to connecting to the Gravelines server directly. While I could theoretically configure my SPA112 to directly log into the Gravelines Asterisk server, there is no guarantee that it is going to take the best, most reliable path.

My ISP peers with OVH Seattle, so I always have an ultra-low-latency connection to the Montreal server (60ms). My Montreal server always has an ultra-low-latency to the Gravelines server (70ms). So the combined latency is 130ms, while the latency from my home ISP and the Gravelines server is about 180ms. The IAX over the Hibernia cable saves me 50ms for calls to and from Europe. I configured the Gravelines server much like I configured the Montreal server - only I pointed it at the local Twilio endpoints located in London.

I also have the added perk that, provided I had any users in Europe, they would have a reliable, nearby server to connect to rather than connecting across the ocean to the Montreal server.

Creative uses of VoIP technology

So that's pretty much all the tutorial I have, but here's a list of some of the other things I have programmed (or am trying my hardest to program) my system to do:

  • Free outbound to toll-free numbers via Alcazar Networks.
  • Phone extension that allows me to toggle my apartment lights with DTMF tones via IFTTT.
  • Passcode-authenticated toll-free number that lets me use my Twilio account like a phone card from any payphone.
  • Voice-command interface connected to my apartment's front door to let me unlock the door with a secret verbal passphrase after dialing in.
  • Wake-up call that is triggered when my Alexa alarm sounds via IFTTT.
  • Personal instance of "Lenny", a bot that tricks telemarketers into not hanging up. (https://www.reddit.com/r/itslenny/)
  • Bouncing a phone call over the Atlantic ocean as many times as I can (record is 44, before audio started corrupting).

Cost breakdown of services

Hardware:

  • Cisco SPA112: $28
  • Panasonic Cordless phones: $18
  • Polaroid Cell phone: $20
  • Total: $66

Monthly costs:

  • Montreal Server: $3.50
  • Gravelines Server: $3.50
  • 5x Phone Numbers: $5.00
  • 1x SIM card: $2.00
  • Total: $14/month

Usage costs:

Pretty much all voice costs are $0.0045/minute. However, it is important to note that a single phone call can compound these costs. If I make an outbound phone call with the SPA112, I pay by the minute from Asterisk to Twilio, and from Twilio to the PSTN network - so you're actually paying $0.009/minute for outbound and inbound calls.

If you call with the cell phone, you pay for the connection from the Cell to Twilio, from Twilio to Asterisk, from Asterisk back to Twilio, and from Twilio to the PSTN network - costing $0.018/minute (unless it's an internal Asterisk line, in which case you only pay $0.009/minute).

In conclusion:

If you find telephone networks to be intriguing, and you want to learn about bleeding-edge developments in telephony, I highly suggest learning how to use Asterisk and Twilio. Telephones may be nearly 170 years old, but the technology is never going to die - it will only be upgraded.

And thanks to TwilioQuest for teaching me way more about Twilio than what I talked about in this write-up.

Edit (1/10): Fixed some grammar mistakes. Also, thanks for the retweet @Twilio!