Build dSIPRouter Using Terraform


The purpose of this article is to show you how to automate the deployment of dSIPRouter using HashiCorp Terraform.  We ship a Terraform script with dSIPRouter because we do all of our development and testing against Digital Ocean.  Also, we wanted to provide you with an example of how you could implement this for other cloud providers since Terraform has providers for all of the major public clouds and on-premise environments as well.


  • You have a Digital Ocean API Key
  • You have a SSH Key Pair uploaded to Digital Ocean and you know it’s name

Download Terraform and Setup Environment

For congruency, we will be doing this from Windows, but doing so from Linux should be similar.  Please download the following packages (uniformity between OS’s):
  • GitBash –
  • Terraform –
You will need to place your terraform.exe or executable in C:\Windows\System32 or /usr/local/bin or /usr/sbin, or adjust your windows host system environment variables to the download location of terraform.exe. To do so do the following: Right click This PC(MyComputer)
—>advanced system settings
—>environment variables
—>system variables

Get Repository and Setup Terraform Variables

Open a terminal window / command prompt and type the following:
export DIGITALOCEAN_TOKEN=<Digital Ocean token key>
git clone
cd dsiprouter/resources/terraform/do
copy terraform.tfvars.sample terraform.tfvars
terraform init
This will install the Digital Ocean provider since our terraform script is configured to work with Digital Ocean. Edit the terraform.tfvars file, which sets the values of variables needed by the terraform script.
pvt_key_path="C:/Users/alems/Working/andrew" (adjust using path format, andrew is actually the pvt key)
Once modified, you should have all you need to deploy an instance via Terraform.

Build dSIPRouter Using Terraform

Execute the following commands to build dSIPRouter from the master branch using terraform:
terraform apply
If you want to build from another branch you would pass in the branch variable with the value of the branch like this
terraform apply -var branch=v0.643
This is what it will look like as it starts to build: This is what it will look like after it’s completed: You will now be able to login to dSIPRouter using the credentials generated.

Login to dSIPRouter

You can login to dSIPRouter using the dSIPRouter WEB GUI URL and the dSIPRouter GUI Username and dSIPRouter GUI Password generated by the installer.  Enjoy!

Load Balancing FusionPBX Outbound Gateways

In certain situations you want to load balance SIP traffic between multiple SIP endpoints. These SIP endpoints are typically a Session Border Controller (SBC) in your organization or an upstream SIP provider. In any case, you need some logic that will distribute the traffic between the SIP endpoints. In the FusionPBX world (which is based on FreeSWITCH) this module is called Distributor (mod_distributor). In this article we will explain how to configure it.


  • You have at least two gateways defined within FusionPBX, which represents the SIP endpoints that you want to distribute traffic between.

Configuration Steps

  1. Login to FusionPBX and make sure the mod_distributor module is enabled. You can do so by going under Advanced -> Modules. Distributor should be an option to choose from, but should be disabled.  It will need to be enabled. “Enabled” should read True on the distributor line once it’s enabled.
  2. Get Gateway ID’s – right click on the Gateway name and click “Copy Address”. Open up a text editor and paste the address. The Gateway ID is the string after “id=” in the URL. Do this for all of the gateways you want to distribute traffic too.
3. Changing the mod_distributor config xml:
  • SSH to your FusionPBX server, make your way into the /etc/freeswitch directory
  • Using your favorite editor, edit autoload_configs/distributor.conf.xml and add the following:
<list name="my_list_001" total-weight="2">
<node name="978fefdd-45cd-4457-8ecd-5d82eaea3b12" weight="1"/> <!-- my_gateway_001 - its just comment with actual GW name -->
<node name="1a8d448d-e06e-2dab-b6f9-4421a98e4d8e" weight="1"/> <!-- my_gateway_002 -->
4. Save and run the following commands from the FreeSWITCH cli
fs_cli > reloadxml
fs_cli > distributor_ctl reload
5. Updated your Outbound Routing setting. You have something like this now: But, you want to change the last line to something like this: The Distributor command above takes a string value that contains a list that was defined in distributor.conf.xml and returns a gateway based on the weight defined in the configuration. In this case, “my_list_001” is the list used. This module can be used for other use cases where you need to generate random/weighted values.

Using SIPp To Load Test With a Kamailio Proxy

SIPp is a free open source tool for generating SIP traffic usually for the purpose of load testing SIP components such as a PBX.  In this walkthrough we will detail two methods of running tests using built in settings, or alternatively a generated SIPp xml file. It includes basic user agent scenarios (UAC and UAS). Also, you can use these basic agent scenarios to build call flow scenarios that fit your use cases. The scenario files are basic files that allows you to subscribe simple to very complex call flows. We will touch on a couple scenarios with a focus on load testing a SIP element such as a PBX with a Kamailio Proxy in front of it. SIPp generates SIP traffic according to the scenario specified. You can control the number of calls that are started per second. We will focus on the use of the builtin UAC scenario. At starting time, you can control the rate by specifying parameters on the command line:
  • “-sn” to specify the built in call flow scenario
  • “-sf” to specify a custom scenario file
  • “-r” to specify the call rate in number of calls per seconds
  • “-rp” to specify the “rate period” in milliseconds for the call rate (default is 1000ms/1sec). This allows you to have n calls every m milliseconds (by using -r n -rp m).
In our example, we will run SIPp at 7 calls every 2 seconds (3.5 calls per second) to a SIP Server, without a proxy:
sipp -sn uac -r 7 -rp 2000 <ip of server>
In another example, we will run SIPp at 7 calls every 2 seconds using a SIP Proxy such as Kamailio and OpenSIPS friendly scenario file. If you need help building a scenario file please contact us and we can estimate the about of hours needs to build a scenario file to meet your requirements :
sipp -sf sipproxyfriendly.xml -r 7 -rp 2000 <ip of server>
You can pause the traffic by pressing the ‘p’ key. SIPp will stop placing new calls and wait until all current calls end. You can resume the traffic by pressing ‘p’. To quit SIPp, press the ‘q’ key. SIPp will stop placing new calls and wait until all current calls end. SIPp will then exit. You can also force SIPp to quit immediately by pressing the ‘Q’ key. Current calls will be terminated by sending a BYE or CANCEL message (depending if the calls have been established or not). The same behaviour is obtained by pressing ‘q’ twice.

Enabling Secure WebSockets: FreePBX 12 and sipML5


  • Using chan_sip
  • Using Chrome as your WebRTC client
  • Asterisk 11.x
  • Using FreePBX 12.0.x
  • CentOS 6.x

Download sipML 5

sipML is the WebRTC Client that we are going to use. We need to download the repository

yum install git
cd /var/www/html/
git clone
chown -R asterisk:asterisk sipml5/

Enable SSL on Built-in HTTP Server of Asterisk

vim /etc/asterisk/http_custom.conf


We also need to give asterisk permissions to read the tls certs

chown asterisk:asterisk /etc/pki/tls/certs/localhost.crt
chown asterisk:asterisk /etc/pki/tls/private/localhost.key

Enable Extension for Secure Web Sockets (WSS)

In older version of freepbx, they do not support wss transports, so this will need to be manually configured in /etc/asterisk/sip_custom.conf replacing SOME_EXTENSION and SOMESECRET. The important line is the transport=wss,udp,tcp,tls, which will have wss as the first entry. dtlscertfile and dtlsprivatekey will need to be pointed at the same key cert and key setup in http_custom.conf


Configure sipML5 expert mode

Browse to https://<server-name>/sipml5. Make sure you include the https and click on the demo button. You should now be at a registration screen. Enter in the extension you would like to register as in the display name and private identity. The public identity will follow the following format:


The password will be the secret set for your extensions and the realm will be the ip address or domain name of your server.

We also need to configure expert mode to set the wss address and stun settings.

Under expert mode, the WebSocket Server URL follows the following syntax:


Then set the ice server to the following google address:


Finally select Enable RTCWeb Breaker and hit save.

You should now be able to register to your extension. To troubleshoot, you can bring up the console in chrome by right clicking and selecting inspect. Additionally, make sure you have opened the necessary wss and rtp ports in your firewall (8089/tcp, 10000-20000/udp)

Start up two instances of Chrome and test

To make a call between two webrtc phones, you will need to install chromium, an open source version of the Google Chrome browser. You can alternatively use two computers with chrome installed. You can add a second extension in /etc/asterisk/sip_custom.conf following the same syntax as the previous extension. After an asterisk restart, you should be able to register to the new extension using the same methods and place a call between the two browsers.

Site-to-Site VPN Options Using AWS

We recently worked with a customer that had a requirement that their application needed to connect via Site-to-Site VPN to there clients application.  They had a few choices, but they decided to move there application to Amazon Web Services  (AWS) and connect to there clients datacenter from there.  Therefore we setup a Virtual Private Cloud (VPC) within Amazon and started down the path of setting up a Site-to-Site Virtual Private Network (VPN) connection.

There are multiple ways of implementing a VPN within Amazon as discussed here.  In most cases, it’s going to come down to using a AWS Hardware VPN or a Software VPN.  The AWS Hardware VPN can be configured within a couple clicks and it gives you the option to generate the configuration for multiple well known firewalls, which  you can use to configure your firewall or you can provide to your firewall administrator.  The Software VPN consists of running an EC2 instance that has software that implements VPN functionality.

The main factor in deciding AWS Hardware VPN versus Software VPN should be based on who’s initiating the traffic.  In our case, the customers application needed to initiate the request.  This means that we had to leverage the Software VPN approach because the AWS Hardware VPN can not initiate traffic.  It can only accept request.  So, it’s great for a company that wants to migrate systems from there datacenter to Amazon and then have there user access the systems. Hence, their users are the initiators of the traffic.

The installation and setup of a Software VPN isn’t really that difficult, but you have to have some basic understanding of how AWS networking works.  There are a few Software VPN implementations, but we selected OpenSWAN.  There’s a few good articles that we used.

One of the main gotcha’s in setting up OpenSwan are to ensure that the Access Control List (ACL) defined by the far end (the Router that you are establishing the VPN with) matches the Right side configuration parameter within the setup.  Once you read thru the above articles you will know what I mean.

The average time to setup an AWS Hardware VPN is 5 hours.  This includes configuration, testing and turn-up with the far end.

The average time to setup a Software VPN is 10-20 hours.  It really depends on the complexity of the Amazon VPC and how you need traffic to be routed and represented.

About dOpenSource

We provide Amazon Web Services (AWS) consulting with a focus on DevOPs and Infrastructure Migration.
We are proud to be based in Detroit, MI with coverage from 9am-8pm ET.  We have staff on the East and
West Coast.  You can purchase support from us by going to

Configuring FreePBX and Aastra Phones

This quick article explains how to configure Aastra phones to register with FreePBX 13.x as an extension.

In order to manually provision phones you need the following basic information:

  • Server IP
  • Server Port (the default is 5060)
  • Extension
  • Secret (the password for the phone)

In our example, lets assume the following internal network info for the FreePBX server:

  • Server IP: |
  • Server Port: 5060

You now need the Extension and Secret. This can be found by logging into the FreePBX GUI and going to extensions section of the interface. You will see a list of extensions. Below we only show one extension, which is 10000

extension list

You can click on that extension and locate the Secret, which is outlined in red.

extension list

Now that you have this information you can login to the Aastra phone and click on “Global SIP”. You will enter the Extension and Secret into the fields that are outlined at the top and the Server IP and Server Port will replace the data outlined at the bottom.

aastra phone global sip settings

Note – you will need to reboot your phone after configuring the phone.

IP Address of XenServer VM’s Using the Command Line

Issue: Needed to get the IP address of a VM running on my XenServer.

Resolution: Execute this command

xe vm-list params=name-label,networks | grep -v "^$"

The command yielded me a list of the VM’s with the ip address.

name-label ( RW) : DevStackOSDomU
networks (MRO): 2/ip:; 1/ip:; 0/ip:
name-label ( RW) : Control domain on host:
networks (MRO): <not in database>


Note, I only had 1 VM on this Xenserver, but I needed the IP address:


FreeSWITCH 1.6 Quick Install Guide for Debian Jessie

Our Goal

There’s a lot of FreeSWITCH material out on the web.  Our goal is to provide you a concise document that provides the necessary steps or scripts to install the latest stable release of FreeSWITCH.

What is FreeSWITCH

FreeSWITCH is an OpenSource VoIP platform that enables you to build communication platforms that span from a simple PBX to a sophisticated backend communication framework that allows thousands of calls to interconnect per second.


  • Debian Jessie is installed
  • You have root or sudo access via the CLI

Let’s Install (with Explanation of each command)

  • Install Public Key: We need to install the FreeSWITCH public key so that we validate the packages that we are going to install came from and was not tampered with.
    wget -O - | apt-key add -
  • Setup Repository: Setup the Debian repository file with the necessary configuration to download the FreeSWITCH packages
    echo "deb jessie main" > /etc/apt/sources.list.d/freeswitch.list 
  • Install the Packages: We will first update our local repository using apt-get update, which will obtain the metadata of the FreeSWITCH packages since we just added the FreeSWITCH repository. It will also update the metadata for other repositories as well. Lastly, we will install FreeSWITCH using the apt-get install -y freeswitch-meta-all command
    apt-get update && apt-get install -y freeswitch-meta-all
  • Secure the Extensions: By default all of the extensions have a password of 1234. FreeSWITCH will warn you that all extensions are using a default password of 1234 and ask that you change it by putting an entry in the /var/log/freeswitch/freeswitch.log file. Also, it will delay any outbound calls for a few seconds. You can change the default password by running these commands.
    sed -i "s/1234/10082013/" /etc/freeswitch/vars.xml
    fs_cli -x reloadxml

    Where the extension passwords will now be 10082013. You can change the default password by just replacing 10082013 with your password.

Register SIP Phones

Now we can validate that the install was successful. We can do this by registering 1 or more SIP phones. The default install of FreeSWITCH comes with a set of users. Let’s register extension 1000 and 1001 with two separate VoIP phones and make calls between the sip phones. Remember that your password for each extension is 10082013 or whatever you manually changed it too.

A2BIlling RESTFUL API: Installing and Configuring

We were recently hired to customize the core A2Billing project to meet some custom business rules and they wanted to use the A2Billing Restful API to integrate A2Billing with other systems in their environment.  There are a lot of blog posts on how to install and configure the core A2Billing project, but very little info on the Restful API.  Therefore, I will explain how to configure it with the assumption that A2Billing is already installed and configured.  I will use CentOS 7 to demonstrate how to set it up.   If you need help you can hire us by purchasing support time.


  • CentOS  6 or 7 is being used
  • A2Billing version 2.2.0 is already installed and working

Architecture and Background

The A2Billing Restful API is developed by Star2Billing, the same company that develops A2Billing.   It’s built using Python and Flask.  Flask has a number of components, but the main components used is the RESTful request dispatching.  The bits are located on GitHub at  The install script is only supported on Debian, but most of our customers use A2Billing with the FreePBX on CentOS.  Therefore, we will focus on installing it on CentOS.

Installation Steps

Download the bits from github

cd /usr/src
git clone
cd a2billing-flask-api

Install the required libraries

There are a number of Python libraries needed.  The included makefile contains the commands to install the libraries.  The list of libraries can be found in a file called “requirements.txt” if are really interested in what libraries are being used. Execute make to install.

If running Python < 2.7.9

pip install -r requirements.txt
pip install virtualenv

Modify the Activation Script

Change path on the activate_this and sys.path lines to reflect the actual location of the a2billing-flask-api

vi a2billing-flash-api/a2billing-flask-app.wsgi
import os
import sys
activate_this = '/usr/src/a2billing-flask-api/a2billing_flask_api_env/bin/'
execfile(activate_this, dict(__file__=activate_this))
apache_configuration= os.path.dirname(__file__)
project = os.path.dirname(apache_configuration)
workspace = os.path.dirname(project)

sys.path.insert(0, '/usr/src/a2billing-flask-api/a2billing_flask_api/lib/python2.6/site-packages')
sys.path.insert(1, '/usr/src/a2billing-flask-api/a2billing_flask_api/lib/python2.7/site-packages')

# os.environ['DJANGO_SETTINGS_MODULE'] = 'newfies_dialer.settings'
# import django.core.handlers.wsgi
# application = django.core.handlers.wsgi.WSGIHandler()

from a2billing_flask_api import app as application

Installed the WSGI Plugin for Apache

The A2Billing Flask API depends on Flask API (surprise).  In order to get Flask to execute within your Apache server you need the WSGI Plugin

yum install mod_wsgi

For Apache 2.2

Listen 9090
WSGISocketPrefix /var/run/wsgi
<VirtualHost *:9090>

WSGIDaemonProcess a2billing_flask_app user=asterisk group=asterisk threads=5
WSGIScriptAlias / /usr/src/a2billing-flask-api/a2billing_flask_api/a2billing_flask_app.wsgi
WSGIPassAuthorization On

<Directory /usr/src/a2billing-flask-api>
WSGIProcessGroup a2billing_flask_app
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
ErrorLog "/var/log/httpd/a2billing-flask.log"

For Apache 2.4

Listen 9090
WSGISocketPrefix /var/run/wsgi
<VirtualHost *:9090>

WSGIDaemonProcess a2billing_flask_app user=asterisk group=asterisk threads=5
WSGIScriptAlias / /usr/src/a2billing-flask-api/a2billing_flask_api/a2billing_flask_app.wsgi
WSGIPassAuthorization On

<Directory /usr/src/a2billing-flask-api>
WSGIProcessGroup a2billing_flask_app
WSGIApplicationGroup %{GLOBAL}
# Order deny,allow
# Allow from all
<strong>Require all granted</strong>
ErrorLog "/var/log/httpd/a2billing-flask.log"

Setup the database configuration parameters.

The database configuration information is located in a file called

vi a2billing_flask_api/

change the name (database name), user and passwd parameters based on your A2Billing Installation

'name': 'mya2billing',
'engine': 'peewee.MySQLDatabase',
'user': 'a2billinguser',
'passwd': 'a2billing',

Start Web Server and Test

service httpd restart

Test it locally:

curl -u admin:admin http://localhost:9090/api/callerid/

Test it from a Remote System:

curl -u admin:admin http://<external ip>:9090/api/callerid/

You should get a list of calling card id’s

If you have any problems look in /var/log/httpd/a2billing-flask.log

Let me know if you have issues with these instructions and I will fix them.


Autoscaling an Asterisk Cluster Using Docker Images – Part 1: Setting Up the Plumbing

Series Intro

This series of articles will give you the information you need to standup a cluster of Asterisk servers using Docker containers, which we categorize as media servers where traffic will be load balanced by Kamailio.

Part I Intro

In this article we will configure the plumbing of the cluster and deploy a couple of Asterisk containers (media servers). At the end of this article you will understand how to setup a basic Docker cluster that can automatically discover and auto register Asterisk servers to the cluster.

Bootstrapping the Cluster

Let’s start by setting up the main components of the cluster. We will use Consul, which was developed by HashiCorp to provide the plumping for our cluster. This plumbing includes Service Discovery, DNS, Event notification and other services that we may discuss later on in this series. The documentation for Consul can be found at <>

The prerequisite is to have docker installed

We can start the cluster by running:

docker run -d -p -p -p --volume=/var/run/docker.sock:/tmp/docker.sock --name consul -h voiphost1 agent -ui -server -bootstrap-expect 1 -client

The above command will start the cluster and make the Consul web interface available on the host machine via port 8500 and make a DNS interface available to us on port 8600. Below is a screenshot of the Consul web interface after running the above command.

picture of the consul UI when it first starts

Now we need to have a mechanism to automatically register Asterisk servers with the cluster and specify the SIP ports that the server is listening on. For example, we might want to spin up 3 Asterisk servers to handle the load. We need to have a way to tell the cluster the IP address and the Asterisk SIP port number of these servers without having to manually configure the cluster. This is done using Registrator, which was developed by GliderLabs.

You can start Registrator by by running:

docker run -d -v /var/run/docker.sock:/tmp/docker.sock --privileged gliderlabs/registrator:latest consul://

The above command will start the Registrator container and listen for Docker events using the Unix socket (/var/run/docker.sock). This port acts as a control port for Docker. We will dig deeper into this socket in upcoming articles. All we need to understand right now is that start/stop events is sent via this socket each time a Docker container is started or stopped. We use the volume option (-v) to make the socket available to the Registrator container on /tmp/docker.sock. The last parameter specifies the registry that events should be sent to. In our case, we are using consul as the registry, but Registrator is designed to use other registries. The ip of our registry is the exposed ip address of the Consul server that we started earlier in the article. Here a picture of what Consul looks like after starting the Registrator container

picture of the consul URI after starting the Registrator

Now we need to registrator a coupe of media server, which can be done using:

docker run -d -p 35061:5060 -e "SERVICE_NAME=mediaserver"

docker run -d -p 35062:5060 -e "SERVICE_NAME=mediaserver"

The above commands will start two (2) Asterisk servers with a service name of “mediaserver”. In this example we had to specify the exposed port numbers, but this will typically be done randomly and automatically so that we don’t have to keep track of which port numbers are already in use versus what’s available. We will release our own asterisk server containers for these articles that will handle this for us – we will update the article once that is complete.

Here’s a picture of what Consul looks like now:

picture of the consul after starting media server

In Part II we will discuss how to deploy a SIP Proxy service ran by Kamailio that will automatically know how to route SIP traffic to Asterisk containers that are available on the cluster.