VoIP

In the world of telecom, VoIP is still a relatively new concept. For the century or so prior to VoIP, the only way to connect your site to the PSTN was through the use of circuits provided for that purpose by your local telephone company. VoIP now allows for connections between endpoints without the PSTN having to be involved at all (although in most VoIP scenarios, there will still be a PSTN component at some point, especially if there is a traditional E.164 phone number involved).

PSTN Termination

Until VoIP totally replaces the PSTN, there will be a need to connect calls from VoIP networks to the public telephone network. This process is referred to as termination. What it means is that at some point a gateway connected to the PSTN needs to accept calls from the VoIP network and connect them to the PSTN network. From the perspective of the PSTN, the call will appear to have originated at the termination point.

Asterisk can be used as a PSTN termination point. In fact, given that Asterisk handles protocol conversion with ease, this can be an excellent use for an Asterisk system.

In order to provide termination, an Asterisk box will need to be able to handle all of the protocols you wish to connect to the PSTN. In general, this means that your Asterisk box will need a PRI circuit to handle the PSTN connection, and SIP channels to handle the calls coming from the VoIP network. The underlying principle is the same regardless of whether you’re running a small system providing PSTN trunks to an office full of VoIP telephones, or a complex network of gateway machines deployed in strategic locations, offering termination to thousands of subscribers.

Calls from the VoIP network will arrive in the dialplan in whatever context you assigned to the incoming SIP channels, and the dialplan will relay the calls out through the PSTN interface. At its very simplest, a portion of a dialplan that supports termination could look like this:

[from-voip-network]
exten => _X.,1,Verbose(2, Call from VoIP network to ${EXTEN})
   same => n,Dial(DAHDI/g0/${EXTEN})

In reality, though, you will often have to handle a more complex routing plan that takes into consideration things like geography, corporate policy, cost, available resources, and so forth.

Warning

Given that most PSTN circuits will allow you to dial any number, anywhere in the world, and given that you will be expected to pay for all incurred charges, we cannot stress enough the importance of security on any gateway machine that is providing PSTN termination. Criminals put a lot of effort into cracking phone systems (especially poorly secured Asterisk systems), and if you do not pay careful attention to all aspects of security, you will be the victim of toll fraud. It’s only a matter of time.

Do not allow any unsecured VoIP connections into any context that contains PSTN termination.

PSTN Origination

Obviously, if you want to pass calls from your VoIP network to the PSTN, you might also want to be able to accept calls from the PSTN into your VoIP network. The process of doing this is commonly referred to as origination. This simply means that the call originated in the PSTN.

In order to provide origination, a phone number is required. You will therefore need to obtain a circuit from your local phone company, which you will connect to your Asterisk system. Depending on where you are in the world, there are several different types of circuits that could provide this functionality, from a basic analog POTS line to a carrier-grade SS7 circuit.

Note

Phone numbers as used for the purpose of origination are commonly called direct inward dialing numbers (DIDs). This is not strictly the case in all situations (for example, the phone number on a traditional analog line would not be considered a DID), but the term is useful enough that it has caught on. Historically, a DID referred to a phone number associated with a trunk connected to customer premise equipment (CPE).

Since phone numbers are controlled by the traditional telecom industry, you will need to obtain the number either from a carrier directly, or from one of the many companies that purchase numbers in bulk and resell them in smaller blocks. If you obtain a circuit such as a PRI circuit, you will normally be able to order DID numbers to be delivered with that circuit.

In order to accept a call from a circuit you are using for origination, you will normally need to handle the passing of the phone number that was called. This is because PSTN trunks can typically handle more than one phone number, and thus the carrier needs to identify which number was called so that your Asterisk system will know how to route the call. The number that was dialed is commonly referred to as the Dialed Number Identification Service (DNIS) number. The DNIS number and the DID do not have to match,[78] but typically they will. If you are ordering a circuit from the carrier, you will want to ask that they send the DNIS (if they don’t understand that, you may want to consider another carrier).

In the dialplan, you associate the incoming circuit with a context that will know how to handle the incoming digits. As an example, it could look something like this:

[from-pstn] 
; This is the context that would be listed in the config file
; for the circuit (i.e. chan_dahdi.conf)

exten => _X.,1,Verbose(2,Incoming call to ${EXTEN})
    same => n,Goto(number-mapping,${EXTEN},1)

[number-mapping] 
; This context is not strictly required, but will make it easier
; to keep track of your DIDs in a single location in your dialplan. 
; From here you can pass the call to another part of the dialplan
; where the actual dialplan work will take place.

exten => 4165551234,1,Dial(SIP/0000FFFF0001)
exten => 4165554321,1,Goto(autoattendant-context,start,1)
exten => 4165559876,1,VoiceMailMain() ; a handy back door for listening
                                      ; to voice messages

exten => i,1,Verbose(2,Incoming call to invalid number)

In the number-mapping context you explicitly list all of the DIDs that you expect to handle, plus an invalid handler for any DIDs that are not listed (you could send invalid numbers to reception, or to an automated attendant, or to some context that plays an invalid prompt).

VoIP to VoIP

Eventually, the need for the PSTN will likely vanish, and most voice communications will take place over network connections.

The original thinking behind the SIP protocol was that it was to be a peer-to-peer protocol. Technically, this is still the case. What has happened, however, is that things have gotten a bit more complicated. Issues such as security, privacy, corporate policies, integration, centralization, and so forth have made things a bit more involved than simply putting a URI into a SIP phone and having a SIP phone somewhere else ring in response.

The SIP protocol has become bloated and complex. Implementing SIP-based systems and networks has arguably become even more complicated than implementing traditional phone PBXs and networks.[79]

We are not going to get into the complexities of designing and implementing VoIP networks in this book, but we will discuss some of the ways you can configure Asterisk to support VoIP connectivity to other VoIP systems.

Configuring VoIP Trunks

In Asterisk, there is no need to explicitly install your VoIP modules (unless for some reason you did not compile Asterisk with the required modules). There are several VoIP protocols that you can choose to use with Asterisk, but we will focus on the two most popular: SIP and IAX.

Configuring SIP trunks between Asterisk systems

SIP is far and away the most popular of the VoIP protocols—so much so that many people would consider other VoIP protocols to be obsolete (they are not, but it cannot be denied that SIP has dominated VoIP for several years now).

The SIP protocol is peer-to-peer and does not really have a formal trunk specification. This means that whether you are connecting a single phone to your server or connecting two servers together, the SIP connections will be similar.

Connecting two Asterisk systems together with SIP

The need to be able to connect two Asterisk systems together to allow calls to be sent between them is a fairly common requirement. Perhaps you have a company with two physical locations and want to have a PBX at each location, or maybe you’re the administrator of the company PBX and you like Asterisk so much that you would also like to install it at home. This section provides a quick guide on configuring two Asterisk servers to be able to pass calls to each other over SIP. In our example, we will creatively refer to the two servers as serverA and serverB.

The first file that must be modified is /etc/asterisk/sip.conf. This is the main configuration file for setting up SIP accounts. First, this entry must be added to sip.conf on serverA. It defines a SIP peer for the other server:

[serverB]

;
; Specify the SIP account type as 'peer'.  This means that incoming
; calls will be matched on IP address and port number.  So, when Asterisk
; receives a call from 192.168.1.102 and the standard SIP port of 5060,
; it will match this entry in sip.conf.  It will then request authentication
; and expect the password to match the 'secret' specified here.
;
type = peer
;
; This is the IP address for the remote box (serverB). This option can also
; be provided a hostname.
;
host = 192.168.1.102
;
; When we send calls to this SIP peer and must provide authentication,
; we use 'serverA' as our username.
;
username = serverA
;
; This is the shared secret with serverB.  It will be used as the password
; when either receiving a call from serverB, or sending a call to serverB.
;
secret = apples
;
; When receiving a call from serverB, match it against extensions
; in the 'incoming' context of extensions.conf.
;
context = incoming
;
; Start by clearing out the list of allowed codecs.
;
disallow = all
;
; Only allow the ulaw codec.
;
allow = ulaw

Note

Be sure to change the host option to match the appropriate IP address for your own setup.

Now put the following entry in /etc/asterisk/sip.conf on serverB. It is nearly identical to the contents of the entry we put on serverA, but the name of the peer and the IP address were changed:

[serverA]

type = peer
host = 192.168.1.101
username = serverB
secret = apples
context = incoming
disallow = all
allow = ulaw

At this point you should be able to verify that the configuration has been successfully loaded into Asterisk using some CLI commands. The first command to try is sip show peers. As the name implies, it will show all SIP peers that have been configured:

*CLI> sip show peers
Name/username       Host             Dyn Forcerport ACL Port     Status     
serverB/serverA     192.168.1.101                       5060     Unmonitored 
1 sip peers [Monitored: 0 online, 0 offline Unmonitored: 1 online, 0 offline]

Note

You can also try sip show peer serverB. That command will show much more detail.

The last step in setting up SIP calls between two Asterisk servers is to modify the dialplan in /etc/asterisk/extensions.conf. For example, if you wanted any calls made on serverA to extensions 6000 through 6999 to be sent over to serverB, you would use this line in the dialplan:

exten => _6XXX,1,Dial(SIP/${EXTEN}@serverB)
Connecting an Asterisk system to a SIP provider

When you sign up for a SIP provider, you may have service for sending and/or receiving phone calls. The configuration will differ slightly depending on your usage of the SIP provider. Further, the configuration will differ between each provider. Ideally, the SIP provider that you sign up with will provide Asterisk configuration examples to help get you connected as quickly as possible. In case they do not, though, we will attempt to give you a common setup that will help you get started.

If you will be receiving calls from your service provider, the service provider will most likely require your server to register with one of its servers. To do so, you must add a registration line to the [general] section of /etc/asterisk/sip.conf:

[general]
...
register => username:password@your.provider.tld
...

Next, you will need to create a peer entry in sip.conf for your service provider. Here is a sample peer entry:

[myprovider]

type = peer
host = your.provider.tld
username = username
secret = password
; Most providers won't authenticate when they send calls to you,
; so you need this line to just accept their calls.
insecure = invite
dtmfmode = rfc2833
disallow = all
allow = ulaw

Now that the account has been defined, you must add some extensions in the dialplan to allow you to send calls to your service provider:

exten => _1NXXNXXXXXX,1,Dial(SIP/${EXTEN}@myprovider)
Encrypting SIP calls

Asterisk supports TLS for encryption of the SIP signaling and SRTP for encryption of the media streams of a phone call. In this section we will set up calls using SIP TLS and SRTP between two Asterisk severs. The first step is to ensure the proper dependencies have been installed. Ensure that you have both OpenSSL and LibSRTP installed. If either one of these was not installed, reinstall Asterisk after installing these dependencies to ensure that support for TLS and SRTP are included. Once complete, make sure that the res_srtp module was compiled and installed. To install OpenSSL, the package is openssl-devel on CentOS and libssl-dev on Ubuntu. To install LibSRTP, the package is libsrtp-devel on CentOS and libsrtp0-dev on Ubuntu.

Next we will configure SIP TLS. You must enable TLS using the global tlsenable option in the [general] section of /etc/asterisk/sip.conf on both servers. You can optionally specify an address to bind to if you would like to limit listening for TLS connections to a single IP address on the system. In this example, we have the IPv6 wildcard address specified to allow TLS connections on all IPv4 and IPv6 addresses on the system:

[general]

tlsenable = yes
tlsbindaddr = ::

The next step is to get certificates in place. For the purposes of demonstrating the configuration and functionality, we are going to generate self-signed certificates using a helper script distributed with Asterisk. If you were setting this up in a production environment, you might not want to use self-signed certificates. However, if you do, there are a number of applications out there that help make it easier to manage your own certificate authority (CA), such as TinyCA.

The script that we are going to use is ast_tls_cert, which is in the contrib/scripts/ directory of the Asterisk source tree. We need to generate a CA certificate and two server certificates. The first invocation of ast_tls_cert will generate the CA cert and the server cert for serverA. The second invocation of ast_tls_cert will generate the server cert for serverB:

$ cd contrib/scripts
$ mkdir certs
$ ./ast_tls_cert -d certs -C serverA -o serverA
$ ./ast_tls_cert -d certs -C serverB -o serverB -c certs/ca.crt -k certs/ca.key
$ ls certs
ca.cfg  ca.crt  ca.key  serverA.crt  serverA.csr  serverA.key  serverA.pem
serverB.crt  serverB.csr  serverB.key  serverB.pem  tmp.cfg

Now that the certificates have been created, they need to be moved to the appropriate locations on serverA and serverB. We will use the /var/lib/asterisk/keys/ directory to hold the certificates. Move the following files to serverA:

  • ca.crt

  • serverA.pem

And move these files to serverB:

  • ca.crt

  • serverB.pem

With the certificates in place, we can complete the Asterisk configuration. We need to point Asterisk to the server certificate that we just created. Since we’re using self-signed certificates, we also need to point to the CA certificate. In the [general] section of /etc/asterisk/sip.conf on serverA, add these options:

[general]

tlscertfile = /var/lib/asterisk/keys/serverA.pem
tlscafile = /var/lib/asterisk/keys/ca.crt

Make the same changes to sip.conf on serverB:

[general]

tlscertfile = /var/lib/asterisk/keys/serverB.pem
tlscafile = /var/lib/asterisk/keys/ca.crt

Warning

When you create the server certificates, the Common Name field must match the hostname of the server. If you use the ast_tls_cert script, this is the value given to the -C option. If there is a problem verifying the server certificate when you make a call, you may need to fix the Common Name field. Alternatively, for the sake of testing you can set the tlsdontverifyserver option to yes in the [general] section of /etc/asterisk/sip.conf, and Asterisk will allow the call to proceed even if it fails verification of the server certificate.

In the section called “Connecting two Asterisk systems together with SIP”, we created the configuration necessary to pass calls between serverA and serverB. We are now going to modify that configuration so that Asterisk knows that the calls between the two servers should be encrypted. The only change required is to add the transport = tls option to the peer entry for the other server.

On serverA:

[serverB]

type = peer
host = 192.168.1.102
username = serverA
secret = apples
context = incoming                                                           
disallow = all                    
allow = ulaw
transport = tls                   

On serverB:

[serverA]

type = peer
host = 192.168.1.101
username = serverB
secret = apples
context = incoming                                                           
disallow = all                    
allow = ulaw
transport = tls   

Now when you make a call using Dial(SIP/serverA) or Dial(SIP/serverB), the SIP signaling will be encrypted. You can modify the dialplan to force outgoing calls to have encrypted signaling by setting the CHANNEL(secure_bridge_signaling) function to 1:

[default]

exten => 1234,1,Set(CHANNEL(secure_bridge_signaling)=1)
    same => n,Dial(SIP/1234@serverB)

On the side receiving the call, you can check whether the signaling on an incoming call is encrypted using the CHANNEL(secure_signaling) dialplan function. Consider the following example dialplan:

[incoming]

exten => _X.,1,Answer()
    same => n,GotoIf($["${CHANNEL(secure_signaling)}" = "1"]?secure:insecure)
    same => n(secure),NoOp(Signaling is encrypted.)
    same => n,Hangup()
    same => n(insecure),NoOp(Signaling is not encrypted.)
    same => n,Hangup()

When a call is sent from serverA to serverB using this configuration, you can see from the output on the Asterisk console that the dialplan determines that the signaling of the incoming call is encrypted:

    -- Executing [1234@incoming:1] Answer("SIP/serverA-00000000", "") in new stack
    -- Executing [1234@incoming:2] GotoIf("SIP/serverA-00000000", 
       "1?secure:insecure") in new stack
    -- Goto (incoming,1234,3)
    -- Executing [1234@incoming:3] NoOp("SIP/serverA-00000000", 
       "Signaling is encrypted.") in new stack
    -- Executing [1234@incoming:4] Hangup("SIP/serverA-00000000", "") in new stack

Now that SIP TLS has been set up for calls between serverA and serverB, we will set up SRTP so that the media streams associated with the call are encrypted as well. Luckily, it is quite easy to configure, compared to what was required to get SIP TLS working. First, make sure that you have the res_srtp module loaded in Asterisk:

*CLI> module show like res_srtp.so 
Module                         Description                              Use Count 
res_srtp.so                    Secure RTP (SRTP)                        0         
1 modules loaded

To enable SRTP, set the CHANNEL(secure_bridge_media) function to 1:

[default]

exten => 1234,1,Set(CHANNEL(secure_bridge_signaling)=1)
    same => n,Set(CHANNEL(secure_bridge_media)=1)
    same => n,Dial(SIP/1234@serverB)

This indicates that encrypted media is required for an outbound call. When the call is sent out via SIP, Asterisk will require that SRTP be used, or the call will fail.

With all of these tools in place, you can ensure that calls between two Asterisk servers are fully encrypted. The same techniques should be applied for encrypting calls between Asterisk and a SIP phone.

The dialplan functions provide a mechanism for verifying the encryption status of an incoming call and forcing encryption on an outgoing call. However, keep in mind that these tools only provide the means for controlling encryption for one hop of the call path. If the call goes through multiple servers, these tools do not guarantee that the call is encrypted through the entire call path. It is important to carefully consider what your requirements are for secure calls and take all of the necessary steps to ensure that those requirements are respected throughout the entire call path. Security is complicated, hard work.

Configuring IAX trunks between Asterisk systems

The Inter-Asterisk eXchange protocol, version 2 (most commonly known as IAX[80]) is Asterisk’s own VoIP protocol. It is different from SIP in that the signaling and media are carried in the same connection. This difference is one of the advantages of the IAX protocol, as it makes getting IAX to work across NAT connections much simpler.

IAX trunking

One of the more unique features of the IAX protocol is IAX trunking. Trunking an IAX connection could be useful on any network link that will often be carrying multiple simultaneous VoIP calls between two systems. By encapsulating multiple audio streams in one packet, IAX trunking cuts down on the overhead on the data connection, which can save bandwidth on a heavily used network link.

IAX encryption

The principal advantage of IAX encryption is that it requires one simple change to the /etc/asterisk/iax.conf file:

[general]
encryption = yes

For extra protection, you can set the following option to ensure that no IAX connection can happen without encryption:

forceencryption = yes

Both of these options can be specified in the [general] section, as well as in peer/user/friend sections in iax.conf.



[78] In traditional PBXs, the purpose of DIDs was to allow connection directly to an extension in the office. Many PBXs could not support concepts such as number translation or flexible digit lengths, and thus the carrier had to pass the extension number as the DID digits, rather than the number that was dialed (the DNIS number). For example, the phone number 416-555-1234 might have been mapped to extension 100, and thus the carrier would have sent the digits 100 to the PBX instead of the DNIS of 4165551234. If you ever replace an old PBX with an Asterisk system, you may find this translation in place, and you’ll need to obtain a list of mappings between the numbers that the caller dials and the numbers that are sent to the PBX. It is also common to see the carrier only pass the last four digits of the DNIS number, which the PBX then translates into an internal number.

[79] There are many proprietary PBX systems in the market that have a basic configuration that will work right out of the box. Asterisk deployments are far more flexible, but seldom as simple.

[80] Pronounced “eeks.”