Asterisk 开源 PBX 系统

作者:Brett Schwarz

因此,您需要为小型办公室部署一个专用分组交换机 (PBX) 系统。或者,您可能想要在您家中的 Linux 机器上运行一个语音邮件系统。家庭自动化的交互式语音应答 (IVR) 系统怎么样? 互联网协议语音 (VoIP) 功能也很不错。您如何做到这一切? 一个非常有趣且强大的解决方案是 Asterisk,这是一个基于 Linux 构建的 GPL 许可 PBX 系统,它弥合了传统电话(例如您的电话线)和 VoIP 之间的差距。 Asterisk 还支持许多其他使其成为有吸引力的解决方案的功能。 在本文中,我将介绍其中的一些功能,并为您提供足够的信息来开始使用,而无需购买任何特殊硬件。

背景

Asterisk 是 Digium 赞助的一个开源项目。 主要维护者是 Mark Spencer,但社区贡献了大量的补丁。 截至撰写本文时,它仅在 Intel 的 Linux 上运行,尽管过去在 Linux PPC 上取得了一些成功,并且正在努力将 Asterisk 移植到 *BSD。 Digium 还销售与 Asterisk 配合使用的各种硬件组件(请参阅资源)。 这些组件是 PCI 卡,可将标准模拟电话线连接到您的计算机。 还支持其他硬件,例如 Dialogic 和 Quicknet 的硬件。 Asterisk 有自己的 VoIP 协议,称为 IAX,但它也支持 SIP 和 H.323。 这使我们了解了 Asterisk 最强大的功能之一:它能够在同一个功能丰富的环境中连接不同的技术。 例如,您可以通过 Asterisk 连接 IAX、SIP、H.323 和普通电话线(参见图 1,由 Digium 提供)。

Asterisk Open-Source PBX System

图 1. Asterisk 可以连接普通电话线和多种 VoIP 标准。

开发人员可以通过使用 C API 或使用 AGI(类似于 CGI 脚本)来扩展 Asterisk。 AGI 可以用任何语言编写,并作为外部进程执行。 它们是扩展 Asterisk 功能的最简单和最灵活的方式(参见列表 1)。

列表 1. 示例来电显示 AGI 脚本

#!/bin/sh
# \
exec tclsh "$0" ${1+"$@"}

set port 10000
set hosts [list 192.168.123.166 192.168.123.168]

##
##  Sends the info to the hosts
##
proc sendInfo {ip_ port_ callerid_} {

  if {[catch {socket $ip_ $port_} sock]} {
    return
  }

  fconfigure $sock -buffering line
  puts $sock $callerid_
  close $sock

  return
}

##
##  We get all of the variables from stdin;
##  they start with "agi_"; and populate
##  an array with the values.
##
while {[gets stdin l] > 0} {
  if {[regexp {^agi_([\w]+):[\s]+(.*)} $l -> k v]} {
    set AGI($k) $v
  }
}

##
##      Send the callerid info to each host
##      that we have listed
##
foreach H $hosts {
  sendInfo $H $port $AGI(callerid)
}

入门

官方版本已经很久没有发布了,但有传言说即将发布一个版本。 目前,获取 Asterisk 的最佳方式是通过 CVS

export CVSROOT=\
:pserver:anoncvs@cvs.digium.com:/usr/cvsroot
cvs login (password is "anoncvs")
cvs co asterisk

如果您计划使用 Digium 的 PCI 卡,您也应该看看 zaptel。 如果您计划进行连接,则需要查看 libpri。

没有 configure 脚本,因此您只需使用 make。 您还需要 readline、OpenSSL 和 Linux 2.4.x 以及已安装的内核源代码才能正确编译 Asterisk

cd asterisk
make clean install samples

这将编译 Asterisk,安装它,并安装示例配置文件。 最后一个目标会覆盖任何现有的配置文件,因此要么跳过此目标,要么备份任何现有的配置文件(如果您想保留它们)。 如果您正在使用 zaptel 或 ISDN,请在编译 Asterisk 之前编译它们。 Asterisk 默认安装在 /usr/sbin/ 中,配置文件位于 /etc/asterisk/ 中。 语音邮件消息存储在 /var/spool/asterisk/voicemail/ 中。 用于计费的 CDR 和日志文件位于 /var/log/asterisk/ 下。

您可以通过键入以下命令启动 Asteriskasterisk在命令行中。 但是,在测试阶段使用 Asterisk 的最佳方法是使用 -vvvc 选项运行它。 -vvv 选项是超详细输出,-c 选项为您提供控制台提示符,允许您与 Asterisk 进程交互。 例如,您可以向 Asterisk 提交命令,例如管理和状态命令。

Asterisk 的操作和功能依赖于几个配置文件。 我们将在本文中讨论其中的三个,但还存在其他几个。 在这里,我们设置 Asterisk,以便用户可以通过 IAX 相互呼叫。 我们还设置了语音邮件,并为用户提供了一种管理其语音邮件消息的方法。

拨号方案

在深入了解 Asterisk 的设置之前,我们应该对拨号方案有一个大致的了解。 它既灵活又强大,但也可能令人困惑。 拨号方案用于定义号码转换和路由,因此是 Asterisk 的核心。 拨号方案定义了上下文,上下文是扩展(数字模式)的容器,用于提供特定功能。 例如,您可能希望为在您的办公室或 дома 中的人员提供一个上下文,以便他们拥有某些拨号权限。 您还可以设置一个外部或访客上下文,该上下文仅允许有限的拨号功能,例如不允许长途拨号。 上下文名称用方括号 ([]) 括起来。 与上下文关联的扩展名在名称之后。

每个扩展名都可以有多个与之关联的步骤(优先级)。 呼叫流程按顺序继续,除非应用程序返回 -1,呼叫终止或应用程序重定向呼叫流程。 扩展条目的语法如下所示

exten => <exten>,<priority>,<application(args)>

以下是一些示例

exten => 9911,1,Wait(1)
exten => 9911,2,Dial(Zap/1/${EXTEN:1})

扩展名用以下方式表示exten =>。 在此示例中,9911 是扩展名; 1 和 2 是优先级或步骤编号(这些需要是连续的); Wait 和 Dial 是应用程序。 Asterisk 使用应用程序来处理扩展名中的每个步骤。 您可以通过在 Asterisk 控制台中键入以下命令来获取有关不同应用程序的帮助show applications列出支持的应用程序,以及show application <application>显示帮助消息。

扩展名匹配可以对拨打的号码以及呼叫号码进行。 这在处理呼叫时提供了更大的灵活性。 也可以使用模式,这些模式以下划线 (_) 开头

  • N—2 到 9 之间的单个数字。

  • X—0 到 9 之间的单个数字。

  • [12-4]—括号内的任何数字。

  • . —通配符。

例如,扩展名 _NXX5551212 将匹配任何信息号码,无论区号如何。

扩展名可以是任何字母数字字符串。 一些特殊字符是内置的

  • s—当未收到拨号数字时,从这里开始,例如来自模拟线路的来电。

  • t—超时发生时使用。

  • i—用于无效拨号数字。

  • o—操作员扩展名。

  • h—挂断扩展名。

创建 IAX 用户

我们创建的第一个文件是 iax.conf 文件(参见列表 2)。 此文件控制 IAX 协议的操作并定义协议的用户。 该协议有两个版本。 旧版本是 IAX,新版本是 IAX2。

列表 2. iax.conf 文件

[general]
port=5036
bindaddr=0.0.0.0
amaflags=default
accountcode=home

[brett]
type=friend
host=dynamic
secret=brettsecret
context=cg1
callerid="brett <111>"

[maria]
type=friend
host=dynamic
secret=mariasecret
context=cg1
callerid="maria <222>"

[niko]
type=friend
host=dynamic
secret=nikosecret
context=cg2
accountcode=external
callerid="Niko <333>"

配置文件的第一部分是 general 部分,它定义了 IAX 协议的参数。 列出了四个参数,但也可以定义其他参数。 port 参数是 IAX 将通过其通信的端口号。 它默认为 5036,因此严格来说,不需要该条目。 您可以使用 bindaddr 参数告诉 Asterisk 绑定到特定的 IP 地址—对于具有多个以太网卡的机器。 bindaddr 为 0.0.0.0 会尝试绑定到所有 IP 地址。 参数 amaflags 和 accountcode 用于 CDR。 当它们在 general 部分中定义时,它们将用作默认值。 您也可以在每个用户的基础上定义它们。 amaflags 可以接受的值是 billing、documentation、omit 和 default。 accountcode 可以是任意值。 对于此设置,我为 LAN 本地用户使用 home,为 LAN 外部用户使用 external。 其他几个参数已被省略,但它们大多数是性能参数。

其余部分是用户定义。 我有三个用户:brett、maria 和 niko。 type 定义有三个可能的值:peer 可以接收呼叫,user 可以发出呼叫,friend 可以同时执行这两者。 我已将它们全部定义为 type friend。 我已将所有主机定义为 dynamic,但如果任何主机具有静态 IP 地址,您可以改为指定它。 secret 是用户连接到此 Asterisk 服务器时必须提供的密码。 此文件中使用了两个上下文:[cg1] 和 [cg2]。 在讨论 extensions.conf 文件时,我将更详细地解释这些上下文,但实际上,这些上下文启用了用户的拨号权限。

设置语音邮件

下一个文件是 voicemail.conf(列表 3)。 同样,它有一个 general 部分,用于处理语音邮件的常规或全局参数。 第一个参数 format 列出了消息的音频格式。 接下来的两个参数用于电子邮件通知:serveremail 是源电子邮件地址(发件人字段),attach 指示 Asterisk 将消息附加到电子邮件。 在我们的示例中,我们不希望附加消息。 同样,一些参数已被省略。

<mbox> 是用于保存和访问用户消息的号码。 这也用于 extensions.conf 中,用于将呼叫流程定向到正确的语音邮件箱。 <passwd> 参数在检查消息时需要。 <name> 是用户的姓名。 <email> 和 <pager> 是用于发送消息通知的电子邮件地址。 pager 电子邮件的消息较短,因为它需要在较小的设备(寻呼机和手机)上读取。 许多移动和寻呼机提供商都有电子邮件网关,可以将消息传递到设备。

列表 3. Voicemail.conf 文件

[general]
format=gsm|wav49|wav
serveremail=asterisk
attach=no
maxmessage=180
maxgreet=60

;
;  Voicemail box definitions.
;  mbox# => password,name,email,pager/mobile
;
[cg1]
111 => 1111,Brett,brett_schwarz@yahoo.com
222 => 2222,Maria,maria@foo.com,4255551212@mob.net

定义扩展名

我们在此处检查的最后一个文件是 extensions.conf 文件(列表 4)。 这是最复杂的文件之一,因为它包含拨号方案。 与其功能相比,我的示例中的拨号方案相当简单。 此文件具有 general 和 global 部分。 general 部分类似于先前文件中的 general 部分; 它定义了常规参数。 在此示例中,我没有定义任何常规参数。 global 部分用于定义全局变量。 这些变量可以在拨号方案中使用语法访问${VARIABLE}。 我定义了一个变量:TIMEOUT 是应答超时。 内置变量也可以在拨号方案中使用,例如 CONTEXT、EXTEN 和 CALLERID。

列表 4. extensions.conf 文件

[globals]
TIMEOUT=12

[misc]
exten => t,1,PlayBack(timeout)
exten => t,2,Hangup()
exten => i,1,PlayBack(invalid)
exten => i,2,Hangup()

;  voicemail management
[voicemail]
include => misc
exten => 6245,1,VoiceMailMain2()
exten => 6245,2,Hangup

[iax]
include => misc
exten => 111/222,1,SetCIDName("it's your wife!")
exten => 111/222,2,agi(callerid.agi)
exten => 111/222,3,Dial(IAX/brett/s,${TIMEOUT})
exten => 111/222,4,Voicemail2(111)
exten => 111,1,agi(callerid.agi)
exten => 111,2,Dial(IAX/brett/s,${TIMEOUT})
exten => 111,3,Voicemail2(111)
exten => 222,1,Dial(IAX/maria/s,${TIMEOUT})
exten => 222,2,Voicemail2(222)
exten => maria,1,Goto(iax,222,1)
exten => 333,1,Dial(IAX/niko/s,${TIMEOUT})

[afterhours]
include => misc
exten => _.,1,Wait(1)
exten => _.,2,Answer
exten => _.,3,Background(vm-menu)

exten => 1,1,Voicemail2(111)
exten => 2,1,Voicemail2(222)
exten => 3,1,Voicemail2(333)

[cg1]
include => iax
include => voicemail

[cg2]
include => afterhours|1:00-6:00|*|*|*
include => iax

所有其他部分都是上下文定义。 上下文只是数字模式的分组。 在这里,我定义了几个上下文,这些上下文定义了拨号方案:voicemail、iax 和 afterhours。 将这些视为单独的或微型拨号方案。 然后,我定义了两个上下文,我将它们分配给用户。 这些上下文通过使用 include 关键字继承了我已定义的其他上下文的功能。

第一个上下文 voicemail 列出了允许用户访问其语音邮件消息的数字模式。 用户可以拨打 6245,应用程序 VoicemailMain2 会提示他们输入邮箱号码和密码。 然后,用户可以管理(收听、删除等等)其邮箱中的消息。

iax 上下文用于 IAX 用户之间的 PBX 拨号。 我们为每个用户定义了各种扩展名。 具有用户姓名 (maria) 的条目重定向到扩展号码条目。 对于 111 扩展名,我还匹配了 callerid。 如果 callerid 匹配,我将更改 callerid 名称,使其具有相对意义。 例如,如果拨打的扩展名是 111,并且 callerid 是 222,则 callerid 名称将更改为“it's your wife!”。 每当我的妻子打电话给我时,此消息都会显示在我的客户端上(我不会深入探讨我如何利用此优势)。

最后一个数字模式上下文用于在深夜到达的呼叫。 因为我不想在晚上被外部用户打扰,所以我匹配任何拨打的号码 (_.)。 它等待一秒钟,然后应答呼叫。 应答后,它会播放背景消息,以便呼叫者可以选择要给谁留言(“给 brett 请按 1”)。 因此,如果呼叫者按下 1,则呼叫将转到 1,1,Voicemail2(111) 条目,该条目会将用户发送到 111 邮箱。 这是如何构建 IVR 系统的简单示例。

[cg1] 和 [cg2] 上下文包含我已经定义的其他上下文内的功能。 这使我可以轻松创建不同的用户组。 例如,[cg1] 具有我已定义的所有功能,但 [cg2] 仅具有 iax 功能,并在深夜被定向到语音邮件。 可以通过利用 Asterisk 拨号方案的灵活性来构建强大的拨号功能。 我的示例仅显示了可能性的一瞥。 您还可以通过使用宏来简化拨号方案,但我将其作为读者的练习。

使用 AGI

在 extensions.conf 文件中,一个名为 callerid.agi 的条目调用 AGI 脚本。 这是一个说明 AGI 接口的简单示例。 该脚本放置在 /var/lib/asterisk/agi-bin/ 目录中,并由 Asterisk 作为外部进程调用。 AGI 和 Asterisk 通过 stdin、stdout 和 stderr 进行通信。 变量通过 stdin 传递到 AGI,AGI 可以通过 stdout 将信息传递回 Asterisk。 发往 Asterisk 控制台的消息写入 stderr。 始终将两个参数传递给 AGI:AGI 的完整路径和通过 exten 条目传递给 AGI 的参数。 AGI 收集 callerid 并将其发送到在另一台机器上运行的 GUI 应用程序。 GUI 应用程序可以从我的网站检索(参见图 2)。 AGI 脚本也可用于检索信息。 如果您需要查询数据库以获取有关呼叫或用户的信息,您也可以使用 AGI 接口。

Asterisk Open-Source PBX System

图 2. GUI 应用程序显示来电的来电显示信息。

拨打电话

那么,我们现在可以做什么? 创建上述配置文件并启动 Asterisk 后(asterisk -vvvc),我们可以尝试一些呼叫。 目前,IAX 软客户端的可用性有限。 SIP 软客户端(包括 kphone 和 xten)以及 Cisco、SNOM 和其他供应商的硬客户端也可用,它们可以与 Asterisk 一起使用,但我在本文中专注于使用 IAX。 Gnophone(图 3)是最老的客户端,由 Digium 开发。 还在开发跨平台客户端以及 Windows 客户端。 另一个客户端是 SourceForge 的 tel 项目的客户端。 我修改了该客户端的用户界面(图 4)。 它仍然是 alpha 软件,但功能齐全。 实际上,我使用此客户端在德国 (Reinhard Max)、澳大利亚 (Steve Landers) 和美国(我)之间建立呼叫。 无论您选择哪个客户端,您都需要为要连接的每个 Asterisk 服务器定义您的用户名、密码和上下文。 然后,您可以呼叫 iax.conf 文件中定义的任何人(如果拨号方案设置正确)。 因此,如果我想给我的妻子打电话,我只需拨打 222,或者我可以输入maria(因为我在拨号方案中定义了它)。 如果我想查看我的语音邮件消息,我可以拨打 6245。

Asterisk Open-Source PBX System

图 3. Digium 的 Gnophone 是一个软件电话客户端,您可以将其与 Asterisk 一起使用。

Asterisk Open-Source PBX System

图 4. Alpha 但可工作的软件:tel 项目的客户端的修改版本。

结论

我仅介绍了 Asterisk 的一些功能,但本文应使读者对 Asterisk 的潜力有所了解。 Asterisk 可以很好地从小型设置扩展到更大和更复杂的配置。 例如,位于不同位置的 Asterisk 服务器可以通过 IAX 协议连接,从而创建一个虚拟 PBX。 由于 Asterisk 在 Linux 上运行,您可以利用现有工具来帮助接口和管理 Asterisk。 例如,您可以 Web 访问 CDR、配置文件和语音邮件。 实际上,Asterisk 附带了一个 CGI 脚本,允许您使用 Web 浏览器访问您的语音邮件消息。 我鼓励读者进一步探索 Asterisk 并利用其强大的功能。

致谢

我要感谢 Digium、Reinhard Max 和 Steve Landers 对本文的帮助。

资源

AGI 信息: home.cogeco.ca/~camstuff/agi.html

“Asterisk:一个简易 VoIP 示例”,作者:John Todd(Asterisk 和 SIP 设置): www.onlamp.com/pub/a/onlamp/2003/07/03/asterisk.html

Asterisk 客户端: tel.sf.net

Asterisk 论坛: www.pbxtech.info/forumdisplay.php?f=113

Asterisk HOWTO (Beta): megaglobal.net/docs/asterisk/html

Asterisk Wiki: www.voip-info.org/wiki-Asterisk

Brett 的网站: www.bschwarz.com

跨平台 IAX 客户端和 IAXPhone: iaxclient.sf.net

Digium(文档和硬件): www.digium.com

Asterisk 入门: www.automated.it/guidetoasterisk.htm

Gnophone: www.gnophone.com

关于 Asterisk 的注释: asterisk.drunkcoder.com

Asterisk 的 Perl 模块和其他信息: asterisk.gnuinter.net

Windows IAX 客户端: laser.com/dante/diax/diax.html

Brett Schwarz 与他的妻子、儿子和狗住在华盛顿州西雅图附近。 尽管他熟悉多个平台,但他首选的平台是 Linux。 他在计算机和电信系统方面拥有多年的工作经验。 您可以通过他的主页 www.bschwarz.com 与他联系。

加载 Disqus 评论