VoIP/AsteriskOnFedora
Open source telephony: a Fedora-based VoIP server with Asterisk
Voice over Internet Protocol (VoIP) has emerged as a popular technology for modern voice communications. Many organizations have replaced their analog or proprietary digital telephone systems with VoIP-based solutions. This allows the consolidation of telephone services into an existing IP infrastructure. In addition, using IP to host voice services lets the organization leverage existing expertise–while retaining all of the network’s management advantages. Though not without its disadvantages, VoIP provides a compelling option to those looking for a telephone solution.
This article will present a simple VoIP solution using Asterisk, an open source private branch exchange (PBX) product. It will show you how to install Asterisk, configure it using its LDAP backend, and connect to it using the Ekiga software VoIP client and a Cisco 7900 Series VoIP telephone to make calls.
Prerequisites
There are a few prerequisites to discuss before covering the configuration of Asterisk. First, my instructions assume that you have already installed Fedora 9. Second, you must have an existing LDAP server. The LDAP schema I use in this article is compatible with Fedora Directory Server. I recommend using the FreeIPA system to manage FDS. Fedora 9 provides packages for both FDS (fedora-ds-base) and FreeIPA (ipa-server). Finally, the machine hosting Asterisk must allow incoming UDP connections to ports 5060 (Session Initiation Protocol) and 69 (TFTP) to pass through its firewall.
Install the Asterisk components by executing the command
yum install asterisk asterisk-ldap asterisk-alsa asterisk-voicemail asterisk-voicemail-plain
In order to configure a Cisco 7900 Series VoIP telephone, you will also need to execute
yum install tftp-server
, have an existing DHCP server (the one on an inexpensive wireless router will work fine) and a copy of Cisco’s Session Initiation Protocol (SIP) software for the phone.
The Fedora project does not yet package Asterisk’s audio files because their copyright holder has not yet assigned a license to them (see Red Hat Bugzilla bug #428832). These audio files are required to implement features like an echo test and voicemail. Fortunately, it is quite simple to install them. Visit the Asterisk website and download the latest Asterisk 1.6 series release. Inside the Asterisk archive is another, sounds/asterisk-core-sounds-en-gsm-1.4.11.tar.gz. Extract this archive file into /usr/share/asterisk/sounds.
Configuring the Asterisk PBX
The Asterisk PBX has many features and is very flexible. In this section, I will focus on configuring four things: the SIP module, the extensions module, the external configuration engine, and the realtime LDAP backend. Once Asterisk is configured, I will demonstrate how to add SIP users and extensions to your LDAP database.
Asterisk provides a module to support the SIP protocol. SIP is used to set up and tear down a VoIP phone call. Though individual SIP users will be stored in an LDAP database, some global parameters will exist in the following configuration file. Save this configuration as <path>/etc/asterisk/sip.conf</path>:
[general]
videosupport=yes
allow=all
bindaddr=0.0.0.0
realm=example.com
- videosupport: Enable support for video streaming.
- allow: List of CODEC’s to allow.
- bindaddr: IP address of the device to bind to. 0.0.0.0 ensures that Asterisk will listen on all available network devices.
- realm: The authentication realm.
We will now move on to define extensions. In many cases, an extension is simply a telephone number that will be associated with a SIP user. Individual extensions, like SIP users, will be stored in an LDAP database. However, as with the SIP configuration, global parameters will be configured in a file, <path>/etc/asterisk/extensions.conf</path>. The following example supports the LDAP entries I will use in this article:
[users]
switch => Realtime/@
[demo]
switch => Realtime/@
[default]
include => users
include => demo
This example defines three contexts: default, users, and demo. The line switch => Realtime/@ states that the extensions in a context will be defined using one of Asterisk’s realtime back-ends (in our case, LDAP). Each individual extension will be assigned to one of these contexts. As a collection of available extensions, contexts determine what happens when a user dials a phone number.
Asterisk’s external configuration engines are activated in <path>/etc/asterisk/extconfig.conf</path>. The following example configures Asterisk to pull SIP and extension information using its real-time LDAP back-end:
[settings]
sipusers => ldap,"dc=example,dc=com",sip
sippeers => ldap,"dc=example,dc=com",sip
extensions => ldap,"dc=example,dc=com",extensions
This example causes Asterisk to activate its real-time LDAP back-end look for SIP users, SIP peers, and extensions in the LDAP database. In addition, the base DN used for queries is specified.
The final configuration file we will write configures Asterisk’s real-time LDAP back-end and should be saved as <path>/etc/asterisk/res_ldap.conf</path>.
[_general]
url=ldaps://ldap.example.com:636
protocol=3
basedn="dc=example,dc=com"
user=cn=Directory Manager
pass=LDAP-PASSWORD
[config]
additionalFilter=(objectClass=AstConfig)
filename = AstConfigFilename
category = AstConfigCategory
variable_name = AstConfigVariableName
variable_value = AstConfigVariableValue
cat_metric = AstConfigCategoryMetric
commented = AstConfigCommented
[extensions]
context = AstContext
exten = AstExtension
priority = AstPriority
app = AstApplication
appdata = AstApplicationData
additionalFilter=(objectClass=AsteriskExtension)
[sip]
name = cn
amaflags = AstAccountAMAFlags
callgroup = AstAccountCallGroup
callerid = AstAccountCallerID
canreinvite = AstAccountCanReinvite
context = AstAccountContext
dtmfmode = AstAccountDTMFMode
fromuser = AstAccountFromUser
fromdomain = AstAccountFromDomain
fullcontact = AstAccountFullContact
host = AstAccountHost
ipaddr = AstAccountIPAddress
insecure = AstAccountInsecure
mailbox = AstAccountMailbox
md5secret = AstAccountRealmedPassword
nat = AstAccountNAT
deny = AstAccountDeny
permit = AstAccountPermit
pickupgroup = AstAccountPickupGroup
port = AstAccountPort
qualify = AstAccountQualify
restrictcid = AstAccountRestrictCID
rtptimeout = AstAccountRTPTimeout
rtpholdtimeout = AstAccountRTPHoldTimeout
type = AstAccountType
disallow = AstAccountDisallowedCodec
allow = AstAccountAllowedCodec
MusicOnHold = AstAccountMusicOnHold
regseconds = AstAccountExpirationTimestamp
regcontext = AstAccountRegistrationContext
regexten = AstAccountRegistrationExten
CanCallForward = AstAccountCanCallForward
defaultuser = AstAccountDefaultUser
regserver = AstAccountRegistrationServer
additionalFilter = (objectClass=AsteriskSIPUser)
The config, extensions, and sip sections of this file map Asterisk configuration options to LDAP attributes and do not need to be customized. The _general section contains the following options:
- url: The URL pointing to the organization’s LDAP server. The example above uses LDAP over SSL on port 636.
- protocol: The LDAP version to use.
- basedn: The base DN used for queries.
- user: The name of the LDAP administrator. Directory Manager is the name used by the Fedora Directory Server.
- pass: The LDAP directory manager’s password.
Configuring LDAP
With the exception of actual users and extensions, our simple Asterisk installation is fully configured. We will now finish our installation by adding users and extensions to our LDAP database. First, we need to install an Asterisk schema for LDAP at <path>/etc/dirsrv/slapd-DOMAIN/schema/99asterisk.ldif</path>. After the schema has been installed, restart FDS using
service dirsrv restart
dn: cn=schema
#
attributeTypes: (
NAME 'AstContext'
DESC 'Asterisk Context'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstExtension'
DESC 'Asterisk Extension'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstPriority'
DESC 'Asterisk Priority'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstApplication'
DESC 'Asterisk Application'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstApplicationData'
DESC 'Asterisk Application Data'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountAMAFlags'
DESC 'Asterisk Account AMA Flags'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountCallerID'
DESC 'Asterisk Account CallerID'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountContext'
DESC 'Asterisk Account Context'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountMailbox'
DESC 'Asterisk Account Mailbox'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstMD5secret'
DESC 'Asterisk Account MD5 Secret'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountDeny'
DESC 'Asterisk Account Deny'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountPermit'
DESC 'Asterisk Account Permit'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountQualify'
DESC 'Asterisk Account Qualify'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountType'
DESC 'Asterisk Account Type'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountDisallowedCodec'
DESC 'Asterisk Account Disallowed Codec'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountExpirationTimestamp'
DESC 'Asterisk Account Allowed Codec'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRegistrationContext'
DESC 'Asterisk Account AMA Flags'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRegistrationExten'
DESC 'Asterisk Account AMA Flags'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountNoTransfer'
DESC 'Asterisk Account AMA Flags'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountCallGroup'
DESC 'Asterisk Account Call Group'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountCanReinvite'
DESC 'Asterisk Account Can Reinvite'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountDTMFMode'
DESC 'Asterisk Account DTMF Flags'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountFromUser'
DESC 'Asterisk Account From User'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountFromDomain'
DESC 'Asterisk Account From Domain'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountFullContact'
DESC 'Asterisk Account Full Contact'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountHost'
DESC 'Asterisk Account Host'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountInsecure'
DESC 'Asterisk Account Insecure'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountNAT'
DESC 'Asterisk Account NAT'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountPickupGroup'
DESC 'Asterisk Account PickupGroup'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountPort'
DESC 'Asterisk Account Port'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRestrictCID'
DESC 'Asterisk Restrict CallerID'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRTPTimeout'
DESC 'Asterisk RTP Timeout'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRTPHoldTimeout'
DESC 'Asterisk RTP Hold Timeout'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRealmedPassword'
DESC 'Asterisk RTP Hold Timeout'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountAllowedCodec'
DESC 'Asterisk Account Allowed Codec'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountMusicOnHold'
DESC 'Asterisk Account Allowed Codec'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountCanCallForward'
DESC 'Asterisk Can CAll Forward'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountSecret'
DESC 'Asterisk Can CAll Forward'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountName'
DESC 'Asterisk Account Username'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstConfigFilename'
DESC 'Asterisk LDAP Configuration Filename'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstConfigCategory'
DESC 'Asterisk LDAP Configuration Category'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstConfigCategoryMetric'
DESC 'Asterisk LDAP Configuration Category Metric'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstConfigVariableName'
DESC 'Asterisk LDAP Configuration Variable Name'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstConfigVariableValue'
DESC 'Asterisk LDAP Configuration Variable Value'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstConfigCommented'
DESC 'Asterisk LDAP Configuration Commented'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountIPAddress'
DESC 'Asterisk Account IP Address'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountDefaultUser'
DESC 'Asterisk Account Default User'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstAccountRegistrationServer'
DESC 'Asterisk Account Registration Server'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
objectClasses: (
NAME 'AsteriskExtension'
DESC 'PBX Extension Information for Asterisk'
SUP top
AUXILIARY
MUST cn
MAY ( AstContext $ AstExtension $ AstPriority $ AstApplication
$ AstApplicationData )
)
#
objectClasses: (
NAME 'AsteriskIAXUser'
DESC 'IAX2 User information for Asterisk'
SUP AsteriskExtension
AUXILIARY
MUST cn
MAY ( AstAccountAMAFlags $ AstAccountCallerID $ AstAccountContext
$ AstAccountFullContact $ AstAccountHost $ AstAccountMailbox $ AstMD5secret
$ AstAccountDeny $ AstAccountPermit $ AstAccountPort $ AstAccountQualify
$ AstAccountType $ AstAccountDisallowedCodec $ AstAccountExpirationTimestamp
$ AstAccountRegistrationContext$ AstAccountRegistrationExten
$ AstAccountNoTransfer $ AstAccountName )
)
#
objectClasses: (
NAME 'AsteriskSIPUser'
DESC 'SIP User information for Asterisk'
SUP AsteriskExtension
AUXILIARY
MUST cn
MAY ( AstAccountAMAFlags $ AstAccountCallGroup $ AstAccountCallerID
$ AstAccountCanReinvite $ AstAccountContext $ AstAccountDefaultUser
$ AstAccountDTMFMode $ AstAccountFromUser $ AstAccountFromDomain
$ AstAccountFullContact $ AstAccountHost $ AstAccountInsecure
$ AstAccountIPAddress $ AstAccountMailbox $ AstAccountRealmedPassword
$ AstAccountNAT $ AstAccountDeny $ AstAccountPermit $ AstAccountPickupGroup
$ AstAccountPort $ AstAccountQualify $ AstAccountRestrictCID
$ AstAccountRTPTimeout $ AstAccountRTPHoldTimeout $ AstAccountType
$ AstAccountDisallowedCodec $ AstAccountAllowedCodec $ AstAccountMusicOnHold
$ AstAccountExpirationTimestamp $ AstAccountRegistrationContext
$ AstAccountRegistrationExten $ AstAccountRegistrationServer
$ AstAccountCanCallForward $ AstAccountSecret $ AstAccountName )
)
#
objectClasses: (
NAME 'AsteriskConfig'
DESC 'Asterisk configuration Information'
SUP top
AUXILIARY
MUST cn
MAY ( AstConfigFilename $ AstConfigCategory $ AstConfigCategoryMetric
$ AstConfigVariableName $ AstConfigVariableValue $ AstConfigCommented )
)
We may now create two SIP users, one for our Ekiga installation and the other for our Cisco telephone. If you write the following LDIF into a file, you may load it into the LDAP database using
ldapadd -x -D "cn=Directory Manager" -W -f PATH-TO-LDIF
.
dn: ou=sippeers,dc=example,dc=com
ou: sippeers
objectClass: top
objectClass: organizationalUnit
dn: cn=user1,ou=sippeers,dc=example,dc=com
objectClass: top
objectClass: AsteriskSIPUser
cn: user1
AstAccountCallerID: 2001
AstAccountHost: dynamic
AstAccountRealmedPassword: {MD5}a94775781e5bb7d3e4ec047c56f0acc5
AstAccountContext: default
AstAccountType: friend
dn: cn=user2,ou=sippeers,dc=example,dc=com
objectClass: top
objectClass: AsteriskSIPUser
cn: user2
AstAccountCallerID: 2002
AstAccountHost: dynamic
AstAccountRealmedPassword: {MD5}3c7806fa6e6c3416d57f2de223cdea5d
AstAccountContext: default
AstAccountType: friend
The example above defines a minimal SIP user. The attributes used are:
- cn: The SIP user’s account name.
- AstAccountCallerID: The user’s caller ID information.
- AstAccountHost: The user’s host. The dynamic keyword allows a user’s telephone to dynamically register its IP address by logging into Asterisk.
- AstAccountRealmedPassword: The account’s password. The hash of a user’s password may be generated by executing echo -n "SIPUSER:example.com:PASSWORD" | md5sum
- AstAccountContext: The context this user will exist in. This determines which extension context applies to this user. Extension contexts were defined in extensions.conf.
- AstAccountType: Defines the type of client. Asterisk sends calls to peers (i.e., a SIP provider). The user type may place calls only. Friends are both peers and users.
Once a user is defined, one may test Asterisk. Start the Asterisk service by executing
service asterisk start
as root. Execute an Asterisk shell using the command
asterisk -rv
. At Asterisk’s prompt, execute
sip show peer user1 load
. Asterisk should print all of the information for user1.
Once you have defined a user, you may start writing your dial plan. First, we will associate a phone number with each user. Use ldapadd to add the following to your LDAP database:
dn: ou=extensions,dc=example,dc=com
ou: extensions
objectClass: top
objectClass: organizationalUnit
dn: cn=2001-1,ou=extensions,dc=example,dc=com
cn: 2001-1
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2001
AstPriority: 1
AstApplication: Dial
AstApplicationData: SIP/user1,20
dn: cn=2002-1,ou=extensions,dc=example,dc=com
cn: 2002-1
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2002
AstPriority: 1
AstApplication: Dial
AstApplicationData: SIP/user2,20
- AstContext: The context in which this extension exists.
- AstExtension: The extension ID (e.g., what you dial to reach this extension).
- AstPriority: Each extension can execute several commands when it receives a call. The priority determines the order in which commands are executed.
- AstApplication: The command to execute when the extension receives a call. The command Dial connects to another Asterisk user.
- AstApplicationData: Arguments, separated with commas (without spaces), and passed to a command. The Dial has two arguments. The first is the user that the call will be connected to. The second is the number of seconds to wait before quitting.
In order to facilitate testing our installation, we will define the following additional extension. This extension executes three commands to implement an echo test that may be reached by dialing 600.
dn: cn=600-1,ou=extensions,dc=example,dc=com
cn: 600-1
objectClass: top
objectClass: AsteriskExtension
AstContext: demo
AstExtension: 600
AstPriority: 1
AstApplication: Playback
AstApplicationData: demo-echotest
dn: cn=600-2,ou=extensions,dc=example,dc=com
cn: 600-2
objectClass: top
objectClass: AsteriskExtension
AstContext: demo
AstExtension: 600
AstPriority: 2
AstApplication: Echo
dn: cn=600-3,ou=extensions,dc=example,dc=com
cn: 600-3
objectClass: top
objectClass: AsteriskExtension
AstContext: demo
AstExtension: 600
AstPriority: 3
AstApplication: Playback
AstApplicationData: demo-echodone
After schema edits, FDS must be restarted using
service dirsrv restart
The basic Asterisk configuration is now complete. Restart the Asterisk service using
service asterisk restart
Configuring the Ekiga VoIP client
Ekiga is a software VoIP application that supports SIP. Its configuration is straightforward. The first time Ekiga is executed by a user, it provides a wizard that allows one to configure the user’s full name, ekiga.net account (this is not required for the purpose of this article), connection type, audio devices, and video devices. Once the software is configured, setup a SIP account by clicking on Edit→Accounts and selecting add. Figure 1 displays an account configured for our SIP user identified as user1.
After an account is set up, it must be activated. Figure 2 shows that the account I just configured is displayed in Ekiga’s list. Click the checkbox to activate the account.
Figure 3 shows Ekiga’s main interface window. Here, you can see how many accounts have been registered. In order to test your configuration, make a SIP connection to extension 600 and perform an echo test.
Configuring a Cisco VoIP telephone
As mentioned before, using a Cisco phone to connect to Asterisk using SIP requires Cisco’s SIP software. When a Cisco 7900 Series telephone boots, it will try to configure itself using TFTP. We will place some firmware and configuration files on our server so that the phone will boot properly for our installation.
In order to enable TFTP on the Asterisk server, edit <path>/etc/xinetd.d/tftp</path> and set disable to no. The TFTP daemon is configured on Fedora to serve files out of <path>/var/lib/tftpboot</path>. After you have modified its configuration, restart xinetd with the command
service xinetd restart
Cisco’s SIP software package provides the files P0S3-08-2-00.sb2, P0S3-08-2-00.sbn and P0S3-08-2-00.loads. Copy these files to <path>/var/lib/tftpboot</path>.
When booting SIP firmware, the telephone will look for three configuration files: OS79XX.TXT, SIPDefault.cnf, and SIPMAC-ADDRESS.cnf. These files should also be placed in <path>/var/lib/tftpboot</path>.
OS79XX.TXT contains one line: the firmware version to load. Mine contains P0S3-08-2-00.
SIPDefault.cnf contains configurations common to all SIP telephones. The following example lists the image version and the address of our Asterisk server, and instructs the telephones to register with Asterisk:
image_version: P0S3-08-2-00 ; proxy1_address: 192.168.0.10 ; proxy_register: "1" ;
Per-telephone configurations are stored in a file named after the telephone’s MAC address. The telephone’s MAC address may be found in its configuration menu. This configuration will correspond with the SIP information found in LDAP and should be saved as SIPMAC-ADDRESS.cnf:
line1_name : user2 line1_authname : user2 line1_password : PLAINTEXT-PASSWORD
The first step in preparing the telephone is to clear any existing configuration. This may be done by pressing **# settings 3 to access an unlocked Network Configuration menu. Here, find the Erase Configuration menu item and select it. Restart the phone and return to the Network Configuration menu. Ensure DHCP Enabled is set. Reboot the phone.
The phone will pull its network configuration from DHCP and should now respond to pings. Return to the Network Configuration menu and deactivate DHCP. Select the TFTP Server 1 option and set it to your Asterisk / TFTP server. Do not disable DHCP or manually set a TFTP server if your DHCP server provides your TFTP server’s IP address. Reboot the telephone and it should load the SIP software and configuration. As the phone boots, you may see it request files using TFTP by watching the Asterisk server’s <path>/var/log/messages log</path>.
Once the telephone boots, test its configuration by dialing 600. This will execute an echo test. After the echo test, you may make a Cisco telephone to Ekiga call by dialing 2001.
Configuring voicemail
In this section, we will cover configuring Asterisk to provide a voicemail system. The configuration process is similar to that of SIP users and extensions, so this should also serve to reinforce the techniques covered in those sections. We will configure the voicemail module, the external configuration engine, and the real-time LDAP back-end. After the configuration files are setup, we will add information to the LDAP database.
<path>/etc/asterisk/voicemail.conf</path> is similar to <path>sip.conf</path> and <path>extensions.conf</path>. This file configures the voicemail module. As with SIP users and extensions, we will configure global parameters in a file, leaving extension-specific parameters to be configured in LDAP:
[general]
searchcontexts=yes
Add the following line to <path>/etc/asterisk/extconfig.conf</path> in order to activate the real-time LDAP back-end for voicemail:
voicemail => ldap,"dc=example,dc=com",voicemail
Map Asterisk voicemail configuration options to LDAP attributes by adding the following to <path>/etc/asterisk/res_ldap.conf</path>:
[voicemail]
context = AstVMContext
mailbox = AstVMMailbox
password = AstVMPassword
fullname = AstVMFullname
email = AstVMEmail
pager = AstVMPager
tz = AstVMTz
attach = AstVMAttach
saycid = AstVMSaycid
dialout = AstVMDialout
callback = AstVMCallback
review = AstVMReview
operator = AstVMOperator
envelope = AstVMEnvelope
sayduration = AstVMSayduration
saydurationm = AstVMSaydurationm
sendvoicemail = AstVMSendvoicemail
delete = AstVMDelete
nextaftercmd = AstVMNextastercmd
forcename = AstVMForcename
forcegreetings = AstVMForcegreetings
hidefromdir = AstVMHidefromdir
stamp = AstVMStamp
additionalFilter = (objectClass=AsteriskVoicemail)
Now we will move to updating our LDAP database. First, we must add to the LDAP schema that we installed earlier. The following will add support for the attributes required to provide basic voicemail:
attributeTypes: (
NAME 'AstVMMailbox'
DESC 'Asterisk Voicemail Mailbox'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstVMPassword'
DESC 'Asterisk Voicemail Password'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstVMFullname'
DESC 'Asterisk Voicemail Fullname'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
attributeTypes: (
NAME 'AstVMEmail'
DESC 'Asterisk Voicemail Email'
EQUALITY caseIgnoreMatch
SUBSTR caseIgnoreSubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
#
objectClasses: (
NAME 'AsteriskVoicemail'
DESC 'Voicemail information for Asterisk'
SUP top
MUST cn
MAY ( AstContext $ AstVMMailbox $ AstVMPassword $ AstVMFullname
$ AstVMEmail )
)
Add the following LDIF to the LDAP database using <app>ldapadd</app> in order to add voicemail support for the extensions 2001 and 2002:
dn: ou=voicemail,dc=example,dc=com
ou: voicemail
objectClass: top
objectClass: organizationalUnit
dn: cn=2001,ou=voicemail,dc=example,dc=com
cn: 2001
objectClass: top
objectClass: AsteriskVoicemail
AstContext: users
AstVMMailbox: 2001
AstVMPassword: 1234
AstVMFullname: User 1
AstVMEmail: user1@example.org
dn: cn=2002,ou=voicemail,dc=example,dc=com
cn: 2002
objectClass: top
objectClass: AsteriskVoicemail
AstContext: users
AstVMMailbox: 2002
AstVMPassword: 1234
AstVMFullname: User 2
AstVMEmail: user2@example.org
dn: cn=2000-1,ou=extensions,dc=example,dc=com
cn: 2000-1
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2000
AstPriority: 1
AstApplication: Voicemailmain
dn: cn=2001-2,ou=extensions,dc=example,dc=com
cn: 2001-2
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2001
AstPriority: 2
AstApplication: Voicemail
AstApplicationData: 2001,u
dn: cn=2002-2,ou=extensions,dc=example,dc=com
cn: 2002-2
objectClass: top
objectClass: AsteriskExtension
AstContext: users
AstExtension: 2002
AstPriority: 2
AstApplication: Voicemail
AstApplicationData: 2002,u
The second entry defines a mailbox for extension 2001. It uses the following options:
- AstContext: The context in which this mailbox exists.
- AstVMMailboxt: The extension that this mailbox corresponds to.
- AstVMPasswordt: The password used to access the mailbox.
- AstVMFullnamet: The full name of the mailbox owner.
- AstVMEmailt: The mailbox owner’s email address.
Entity four defines an extension, 2000, that will provide access to the voicemail system when dialed.
Entity five adds a command to extension 2001 that executes the Voicemail and provides access to the voicemail system. This command will execute if the Dial command defined earlier is not answered within 20 seconds.
To test the voicemail system, use Ekiga to dial 2002. If you don’t answer the call on the other end, then you should be directed to Asterisk’s voicemail system. To listen to new voicemail, dial 2000.
Conclusion
This article demonstrated how to install Asterisk on a Fedora system and configure SIP users, extensions, and voicemail. We installed all user data into an LDAP database in order to keep it consolidated.
Asterisk has far too many features to cover in one article. The VoIP Wiki has a section dedicated to Asterisk and is a great place to learn more. The VoIP Wiki covers topics such as hooking Asterisk up to the standard public-switched telephone network using direct inward dialing and automatically emailing voicemail messages to users. You can even find information on how to route calls to a user based on his Jabber presence. Clearly, Asterisk is capable of a wide range of applications. And, perhaps best of all, it’s entirely open source!
This entry was posted by The editorial team on Thursday, July 24th, 2008 at 5:37 pm and is filed under Fedora technical. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.


