Host Your Own Home VOIP System using Asterisk

Background

Some cable ISPs like comcast offer home VOIP systems for a hefty monthly fee. In addition to the extra cost, they often require you to rent a gateway from them. By renting a gateway from them, you not only incur an additional monthly fee for this, but more importantly you are giving them a backdoor into your cable modem and allowing them to use it as a wifi hotspot for strangers, often without your knowledge. To regain full control over your home network and VOIP system, you need to buy your own modem and host the VOIP system yourself using free (as in freedom) software.

A VOIP system could just be used for communicating between rooms in your house much like the phones in hotel rooms can call each other. But most likely you will want to be able to receive calls from outside of your house from the PSTN (Public Switched Telephone Network). To do this you will need to purchase a DID (Direct Inward Dialing) number from a SIP provider, which typically involves a small recurring charge.

Prerequisites

On Debian 9 GNU/Linux, the asterisk package needs to be installed.

$ sudo apt-get install -y asterisk

The following information about your SIP provider must be known:

  • SIP_USER – SIP username
  • SIP_SECRET – SIP password
  • SIP_HOST – SIP server hostname (DID Point of Presence)
  • SIP_IP – SIP server IP
  • SIP_PORT – SIP port
  • DID_PHONE_NUMBER – phone number from VoIP provider (10 digits with no delimiters)

The following information about your IP Phone must be known:

  • EXT_NUMBER – a 4 digit extension number
  • EXT_PASSWORD – the extension password
  • VM_NUMBER – a 4 digit voicemail number

The following information must be known about your network:

  • EXTERNHOST – hostname that resolves to your public WAN IP

Decide on the following information:

  • VOICEMAIL_PIN – numeric password for voicemail
  • EMAIL_ADDRESS – email address of voicemail account
Configure sip.conf

There are a ton of possible settings that can go in this file. The file is divided into several sections whose names are enclosed in square brackets.

  • context specifies the name of the context to which each extension is associated and is defined later in extensions.conf
  • register specifies the SIP registration parameters including the username, secret, host-name, and port
  • allowguest=no disables unauthenticated calls
  • allowoverlap=no disables overlap dialing support
  • srvlookup=no disables looking up SRV DNS records on outbound calls, which is unnecessary because we explicitly specified both the SIP IP address and port number in the register line
  • disallow and allow restricts the audio codecs that a device will accept or offer
  • alwaysauthreject=yes enables a security feature where the reject for a wrong password and wrong username appear the same way, which prevents a cracker from gaining knowledge about the system they are attempting to attack
  • canreinvite=no disables SIP re-invites, forcing asterisk to stay in the middle of the media
  • nat=force_rport,comedia modifies the behavior related to a server behind NAT (Network Address Translation); force_rport disables symmetric RTP support and comedia enables symmetric RTP support if the remote side requests it
  • qualify=yes enables sending a SIP OPTIONS command every 2 seconds to check that the device is still online
  • session-timers=refuse disables session timers
  • externhost=EXTERNHOST  specifies the FQDN to be resolved to acquire the public IP address of the asterisk server
  • externrefresh=15 specifies that externhost should be resolved every 15 seconds
  • localnet=192.168.0.0/255.255.0.0 excludes addresses in the subnet from any NATing efforts by asterisk, allowing the source addresses of SIP requests/response to include the internal address
  • host=HOST specifies the hostname of the sip peer
  • host=dynamic means that the sip peer must register
  • secret=SECRET allows a SIP peer to securely prove its identity
  • type=friend specifies that an entity is both a sip peer (receives calls) and user (places calls)
  • defaultuser=SIP_USER specifies the username for authentication in SIP INVITE requests from remote clients
  • fromuser=SIP_USER overrides the username when calling to this peer from asterisk
  • trustrpid=yes trust Remote-Party-ID SIP header
  • sendrpid=yes send Remote-Party-ID SIP header
  • insecure=invite disables authentication requirement for incoming SIP INVITE requests
  • deny and permit restrict the addresses of hosts that can attempt registration
[general]
context=internal
register => SIP_USER:SIP_SECRET@SIP_HOST:SIP_PORT
allowguest=no
allowoverlap=no
srvlookup=no
disallow=all
allow=ulaw
alwaysauthreject=yes
canreinvite=no
nat=force_rport,comedia
qualify=yes
session-timers=refuse
externhost=EXTERNHOST
externrefresh=15
localnet=192.168.0.0/255.255.0.0

[voipms]
context=internal
host=HOST
secret=SIP_SECRET
type=friend
defaultuser=SIP_USER
fromuser=SIP_USER
trustrpid=yes
sendrpid=yes
insecure=invite
deny=0.0.0.0/0.0.0.0
permit=SIP_IP/255.255.255.255

[EXT_NUMBER]
type=friend
host=dynamic
secret=EXT_PASSWORD
context=internal
deny=0.0.0.0/0.0.0.0
permit=192.168.0.0/255.255.0.0
Create a Dialplan

The dialplan is stored in extensions.conf.

[internal]
exten => s,1,Answer()
exten => s,2,Dial(SIP/EXT_NUMBER,10)
exten => s,3,Playback(vm-nobodyavail)
exten => s,4,VoiceMail(EXT_NUMBER@main)
exten => s,5,Hangup()
exten => EXT_NUMBER,1,Answer()
exten => EXT_NUMBER,2,Dial(SIP/EXT_NUMBER,10)
exten => EXT_NUMBER,3,Playback(vm-nobodyavail)
exten => EXT_NUMBER,4,VoiceMail(EXT_NUMBER@main)
exten => EXT_NUMBER,5,Hangup()

exten => _*97,1,VoiceMailMain(${CALLERID(num)}@main)
exten => _*97,2,Hangup()

include => voipms-inbound
include => voipms-outbound

[voipms-outbound]
exten => _1NXXNXXXXXX,1,Dial(SIP/${EXTEN}@voipms)
exten => _1NXXNXXXXXX,n,Hangup()
exten => _NXXNXXXXXX,1,Dial(SIP/1${EXTEN}@voipms)
exten => _NXXNXXXXXX,n,Hangup()
exten => _011.,1,Dial(SIP/${EXTEN}@voipms)
exten => _011.,n,Hangup()
exten => _00.,1,Dial(SIP/${EXTEN}@voipms)
exten => _00.,n,Hangup()

[voipms-inbound]
exten => DID_PHONE_NUMBER,1,Answer()
Configure voicemail.conf
[main]
EXT_NUMBER => VOICEMAIL_PIN, danny, EMAIL_ADDRESS
Reload Asterisk
$ sudo asterisk -rx reload