Switching to a software PBX, Part 2
January 1, 2009
InPart 1 we talked about the connection of the handset to the Asterisk server, going over OpenVPN. That task did involve quite a bit of configuration work: installing and configuring OpenVPN, making the IP connection and configuring the handset to link to Asterisk. Now we complete the other half of the problem: connecting Asterisk to Broadvoice (our current SIP trunk provider) and making all of it provide useful extensions and voicemail. Later articles may cover more advanced features, such as linking Asterisk to our CRM system. Wouldn't it be cool if your customer's profile comes up on your web browser when the phone rings, based on the customer's caller ID? Asterisk can be linked to your CRM system to make that happen. But the first step is to get the basic PBX working.
We'll show these steps starting with connecting to our SIP provider (Broadvoice, in this example), then going on to adding extensions and services. In reality, you would do it in the reverse order: get all the services working on the handset, test everything, and then configure the dial-in to work. We're using Asterisk 1.4 in this article. The configuration will be similar for other versions.
Objectives
We want to provide a typical PBX system that small businesses expect today:
- Upon calling in, the user is prompted, press one for sales, two for support ... if you know the extension of the party you are calling please dial it at any time
- The numbers for sales, support, etc, are mapped to a specific SIP phone extension
- Individual users have extensions that callers can dial
- Most callers expect dial-by-name today, in addition to numeric extensions
- Callers can leave voicemail for system users
- Users can press 9 to dial out of the system
- Users can call each other through the system
All of this is "standard stuff" for a small business PBX. Asterisk and SIP phones can do all of it.
Before you begin, you'll need to:
- Make a list of the extensions and phones you will use, so you know who to configure
- Get a professionally-recorded PBX voice menu
- Select music for the music-on-hold feature. This is the music that plays when the caller is transfering. Note that if you purchase music retail, such as on a CD or from an on-line store, that purchase probably does not give a license to use the music in a PBX system; find some public domain music by searching for creative commons licensed content.
Connecting to the SIP trunk
The trunk is what gets us to the PSTN. Here's the diagram from Part 1:
In this case, we're using Broadvoice as our SIP trunk. Any others would also work in a similar way, and when we're done, it will be clear that it's easy to switch the trunk provider with minimal configuration changes.
Before starting, it is necessary to get Broadvoice to enable Asterisk on the account. Call their customer service number and ask for Asterisk setup and a SIP password. Other SIP trunks may have different procedures.
The trunk is defined in /etc/asterisk/sip.conf.
In the general section,
add this line:
register => 3103567869@sip.broadvoice.com:password:3103567869@sip.broadvoice.com/incoming
Of course our number is 310 356 7869. Use your number.
password is the secret password you got from Broadvoice.
Then add a context in sip.conf:
[sip.broadvoice.com] type=peer user=phone host=sip.broadvoice.com fromdomain=sip.broadvoice.com fromuser=3103567869 secret=password username=3103567869 insecure=very context=from-broadvoice authname=3103567869 dtmfmode=inband dtmf=inband
Again, use your password and your phone number.
One more change is necessary. Add an entry into /etc/hosts
to define sip.broadvoice.com. See their website; you'll
need to pick the best of their proxies for your location.
Turn off any other devices you have that connect to Broadvoice. If they sent you a Sipura or something like that, turn it off. They do not allow more than one device to be active on a line at the same time.
Now there should be a SIP connection to Broadvoice. We need to do something with it.
A "hello world" dialplan
Note the line context=from-broadvoice.
This means that any incoming call on that SIP connection
will go to the from-broadvoice context
within /etc/asterisk/extensions.conf.
extensions.conf is where we will be doing
95% of our configuration. Let's add a from-broadvoice
context. Edit extensions.conf and add:
[from-broadvoice] exten => 3103567869,1,Answer() exten => 3103567869,n,Playback(hello-world) exten => 3103567869,n,Hangup()
In all these examples, substitute your phone number where we have
3103567869. When the Broadvoice SIP line calls in,
it goes to the Broadvoice phone number as its extension. We've
created a simple dial plan which answers, plays "hello world", and hangs up.
Test it by dialing in from a regular phone. You'll hear Allison saying "hello world".
Where is the file? It's /usr/share/asterisk/sounds/hello-world.gsm.
Asterisk looks in the /usr/share/asterisk/sounds directory
if the full path is not specified, and it looks for files with extensions
it knows. These include GSM and WAV and perhaps others, depending
on configuration.
Now we have incoming calls reaching Asterisk, and in Part 1, we had SIP phones reaching Asterisk, so we're ready to start the fun part: making the dialplan do useful things.
Presenting the voice menu
I won't re-cover everything in the Asterisk manual. I will only go over the configuration briefly. Read the manual to understand in detail what is going on.
We're editing extensions.conf, which is the file
that defines the dial plan. First, add global
variables for SIP references. These are a more convenient way
to refer to them later in the dial plan:
[globals] ; skipped JOE=SIP/joe
joe refers to the SIP context in sip.conf.
Here is our complete from-broadvoice context,
which presents the voice menu:
[from-broadvoice]
; you can put more extensions into a separate context
; called staff-incoming, and include it here, to make
; this file easier to edit
; include => staff-incoming
exten => 3103567869,1,Answer()
exten => 3103567869,n,Background(custom/regular-hours-message)
exten => 3103567869,n,WaitExten(15)
exten => 3103567869,n,Hangup()
; Define ext. 101 with music-on-hold
exten => 101,1,Dial(${JOE},22,m)
exten => 102,n,VoiceMail(101@default,u)
exten => 103,n,Hangup()
You'll also need to edit voicemail.conf to define
mailbox 101. I also added a definition for Pacific timezone and changed
some other voicemail settings in that file. I configured
it to email out the voicemails, making it even more convenient
to listen to them and forward them.
Internal calls
Now we need to set up a context to allow
our staff to make internal calls. We call it
staff and it has extensions just
like the incoming plan. In fact, both the incoming
and staff extensions could be put into one context,
and then shared using include.
Note that staff is the context specified
for the SIP phone in the sip.conf file.
That's how SIP extensions come into the dial plan.
We add one more thing in the staff
context:
exten => 800,1,VoiceMailMain()
This lets staff, who have come in over the VPN,
access the voicemail system. Note that by placing
that in the staff context, we are not letting
the voicemail system be accessed by anyone calling in
from an external line. For some, that might be too
restrictive. For us, we treat our voicemail with the same
security we treat email, namely, all access must be
encrypted and secure. The PSTN is neither so it is not
acceptable (to us) for voicemail.
Outbound calling
Add two includes to the staff context:
include => fraud include => outbound
We'll get to the fraud context later. outbound
is simple:
exten => _9NXXXXXXXXX,1,Dial(${OUTBOUNDTRUNK}/${EXTEN:1})
exten => _9NXXXXXXXXX,n,Hangup()
This uses pattern matching to let internal users dial 9 to
pass calls through to the outbound trunk. This is what
the outbound trunk variable looks like in the globals
section of extensions.conf:
OUTBOUNDTRUNK=SIP/sip.broadvoice.com
The sip.broadvoice.com string
does not refer to a DNS name. Rather, it refers
to the context block in sip.conf.
What is the fraud context we have included?
Preventing outgoing call fraud
The North American Numbering Plan is our familiar 3+7 dial plan: 310-356-7869. 310 is the area code. Note that the US is not the only country in the NANP. All of Canada can be reached with the same 3+7 dial format, without dialing any international calling prefix. Calling Canada is fine because their telco regulations provide good consumer protection, and rates to call Canada are similar to long-distance rates in the US (our calls to Canada from Broadvoice are free).
The NANP also covers a dozen or so countries in the Caribbean. These calls don't require any international dialing code like 011+country code. They look just like ordinary 3+7 phone numbers, and with all the new extensions in the US, you could easily be dialing an area code without knowing where it is.
This is a problem because these countries do have expensive international calling rates. Worse, their telco regulations allow "premium" numbers to be created without any distinguishing prefix, such as the US' 900 numbers. It's possible to call a Caribbean number and be billed $25 / minute. Many scams try to induce people to dial these numbers for various reasons. There is no way to fight the charges when this happens, because they were billed under the laws of a foreign country.
Unfortunately, the consequence of this is that, unless your business makes regular calls to the Caribbean, it's better to block all outgoing calls to all the Caribbean countries that are within the NANP. Exceptions can be added as needed. How often do your employees have a business need to call up the Turks and Caicos? Not often enough to not block it at the PBX level. Further, many of these countries offer off-shore casinos and bookies. It's unacceptable for employees to call such numbers. Therefore, we block.
This is our fraud context, which, when included
as we showed above, blocks calls to 900 numbers (premium numbers)
and all the NANP countries in the Caribbean:
[fraud] ; START OF FRAUD BLOCKS ; Old Caribbean code for all countries - 809 exten => _9809XXXXXXX,1,Playback(not-auth-pstn); exten => _9809XXXXXXX,n,Hangup() ; Anguilla exten => _9264XXXXXXX,1,Playback(not-auth-pstn); exten => _9264XXXXXXX,n,Hangup() ; Antigua and Barbuda exten => _9268XXXXXXX,1,Playback(not-auth-pstn); exten => _9268XXXXXXX,n,Hangup() ; Bahamas exten => _9242XXXXXXX,1,Playback(not-auth-pstn); exten => _9242XXXXXXX,n,Hangup() ; Barbados exten => _9246XXXXXXX,1,Playback(not-auth-pstn); exten => _9246XXXXXXX,n,Hangup() ; Bermuda exten => _9441XXXXXXX,1,Playback(not-auth-pstn); exten => _9441XXXXXXX,n,Hangup() ; British Virgin Islands exten => _9284XXXXXXX,1,Playback(not-auth-pstn); exten => _9284XXXXXXX,n,Hangup() ; Cayman Islands exten => _9345XXXXXXX,1,Playback(not-auth-pstn); exten => _9345XXXXXXX,n,Hangup() ; Dominica exten => _9767XXXXXXX,1,Playback(not-auth-pstn); exten => _9767XXXXXXX,n,Hangup() ; Dominican Republic exten => _9829XXXXXXX,1,Playback(not-auth-pstn); exten => _9829XXXXXXX,n,Hangup() ; Grenada exten => _9473XXXXXXX,1,Playback(not-auth-pstn); exten => _9473XXXXXXX,n,Hangup() ; Montserrat exten => _9664XXXXXXX,1,Playback(not-auth-pstn); exten => _9664XXXXXXX,n,Hangup() ; Saint Lucia exten => _9758XXXXXXX,1,Playback(not-auth-pstn); exten => _9758XXXXXXX,n,Hangup() ; St. Vincent and the Grenadines exten => _9784XXXXXXX,1,Playback(not-auth-pstn); exten => _9784XXXXXXX,n,Hangup() ; Trinidad and Tobago exten => _9868XXXXXXX,1,Playback(not-auth-pstn); exten => _9868XXXXXXX,n,Hangup() ; Turks and Caicos exten => _9649XXXXXXX,1,Playback(not-auth-pstn); exten => _9649XXXXXXX,n,Hangup() ; US Virgin Islands exten => _9340XXXXXXX,1,Playback(not-auth-pstn); exten => _9340XXXXXXX,n,Hangup() ; Jamaica exten => _9876XXXXXXX,1,Playback(not-auth-pstn); exten => _9876XXXXXXX,n,Hangup() ; St. Kitts and Nevis exten => _9869XXXXXXX,1,Playback(not-auth-pstn); exten => _9869XXXXXXX,n,Hangup() ; premium numbers exten => _9900XXXXXXX,1,Playback(not-auth-pstn); exten => _9900XXXXXXX,n,Hangup()
That blocks all the NANP countries in the Caribbean, and
it blocks 900 numbers. Test to make sure; dial a number
in 809 (like 809 333 4444) from an internal line, and you should
get the not-auth-pstn sound file.
Note that we have not configured any other international
dialing. We can add countries as needed. Further,
we could create an international-outgoing
context if we wanted to, to give different staff
different levels of calling access. We can define countries
individually, or individual area codes or specific
numbers that are reachable or unreachable. We can
use Asterisk this way to create a "telecom firewall".
I apologize to the citizens of the Caribbean, who have been summarily blocked by our firewall rules. If the Caribbean countries want to be taken off the list, they should:
- Abolish premium numbers entirely within their area codes
- Adopt international calling rates comparable to rates to Western Europe
- Put off-shore casinos within clearly designated exchange codes, so they can be blocked without blocking everyone else in the country
Securing internal context access
We should configure Asterisk to not allow connections
in the staff context except from SIP devices
which are bound to the OpenVPN address. That address is
on a non-routing subnet (10.*.*.*), so outside hosts
can never connect to it. OpenVPN uses public-key based
security, and can also work with firewalls for even
more restrictions. Limiting dial-out to only OpenVPN-connected
lines makes a lot of sense. We can do this by
specifying a bind address in the sip.conf
context:
[joe] ; .... other settings bindaddr = 10.8.0.1
Doing this means that connections to that SIP context can only come on the 10.8.0.1 interface, which is the OpenVPN VPN endpoint.
Conclusion
After much configuration, we have a very basic dial plan that provides our PBX, with extensions, voicemail, and the security features we want. It's great.
But it's just the beginning. What else can we do?
- Build voice applications
- Use the
/var/spool/asterisk/outgoingdirectory feature to initiate outgoing calls from other programs - Use AGI to build "Asterisk scripts"
- Video calls; most softphones now support it, and so does Asterisk
- Integrate Asterisk with your CRM. In fact, we will show that in our next article, where we finally link our Asterisk PBX with our JBoss CRM system.
- Many other ideas - it's limited only by your imagination
What else is in the future? Asterisk was the first full-featured open source PBX, but now, there is another: JBoss Mobicents. This is an open-source JSLEE container for building SIP applications. And the company that supports it is now owned by RedHat. We will, in future, explore Mobicents, and perhaps switch to it. The main attraction for us is we are a Java and JBoss shop, and we would like to have our PBX integrated with our other Java servers.