知行合一
全部博文(31)
分类: 系统运维
2009-08-10 23:19:25
在前两章中,我们已经使用认证(authentication)和数据库为OpenSER处理通话做好了准备。SerMyAdmin用来处理数据记录。然而,你仍然不能打给普通电话,因为你没有连上PSTN。现在的挑战是如何将通话由PSTN路由进来和如何将通话路由到PSTN(Public
Switched Telephone Network)
为了能将通话路由到PSTN,你需要一个叫做SIP
PSTN网关(SIP PSTN Gateway)的设备。在市面上,有很多生产这种设备的厂家,诸如Cisco,AudioCodes,Nortel,Quintum等等。你也可以使用Asterisk
PBX完成这个工作。Asterisk是一个你绝对能够承担的起的网关,而且与上面提到的各个厂商的设备兼容。它完全是开源的,也是按照GPL许可的。
这一章的结束,你将能够:
l
将OpenSER与SIP网关连上
l
将认证应用到带内通话
l
使ACLs防止PSTN网关不被没有经过认证的用户使用
l
使用LCR(Least
Cost Route)模块路由你的通话
l
使用SerMyAdmin来管理授信主机(Trusted
Hosts),网关(Gateways)和路由器(Routes)
在这一章中,你将学会如何将通话打到PSTN。我们将介绍三个新的模块(LCR,PERMISSIONS,还有GROUP),他们将帮助你路由这些通话并保证他们的安全。你可以在互联网上轻易的找到关于regexps的指南。如果你对regular
expressions或regexps不熟悉,这条廉洁可以作为参考。
VoIP服务提供商的方案中有很多的部件。为了避免迷失,我们将在每一章中展示下面的这张图片。在这一章中,我们将利用SIP代理部件和PSTN网关一起工作。
本章之后,我们的VoIP提供者将能够使用SIP网关将通话打给PSTN。
在标明给网关的请求中,我们必须验证该用户属于哪一组(group),以查看其是否被允许使用PSTN。
要达到这个目的,我们要使用到‘group’模块。这个暴露了函数is_user_in(“credentials”,
“group”)用来检查用户是否属于指定组。在上面的例子中,我们已经创建了3个组:local代表本地通话,ld代表长途,int代表国际长途。脚本中,我们使用正则表达式(regular
expressions)来检查通话是属于上面介绍的三种中的哪一种。
你必须将这些组插进叫做group的MySQL表中才能使用它。你可以很容易的插入,删除,显示组成员(group
membership):
使用SerMyAdmin来管理你的表也是可能的。要添加和删除组,你可以浏览“User
Groups”部分,在那里,你可以添加,删除组(groups)。
要改变用户的组成员,你可以在下面显示的用户菜单菜单中进行编辑:
使用检查栏选择用户属于的这儿显示的指点的组。
现在,我们要使用PERMISSIONS模块来对来自没有摘要认证过程的PSTN网关的通话进行授权。
我们将使用的allow_trusted()函数有PERMISSIONS模块曝露出来。许可模块可以被用来授权(authorize)REGISTER,REFER,和INVITE请求。我们可以用permissions.allow,permissions.deny,register.allow,和register.deny文件来对其进行管理和调节。然而这个模块中使用的allow_trusted()函数要将请求的源IP地址同我们数据库中的授信表中的数据进行比较检查。
当通话到来时,函数allow_trusted要试着去找到一条符合该请求的规则。该规则包含下面的域
如果下面的规则存在一条,则接受该请求:
l
Ip地址和请求的源IP地址相同
l
传输层协议是“any”或是同请求的传输层协议相符
l
正则表达式为空或符合请求
对于网关来说,不注册到SIP代理上是很正常的事。因此,来自网关的请求不应该接收“407
Proxy Authentication Required”响应。在我们目前的脚本中,所有来自我们域的INVITE请求都要求他们带有凭据。然而,如果像从网关发出的请求,没有凭据发出,从而通话将会失败。所有,为了修正这一点,我们使用allow_trusted()函数检查源IP地址的方式,而不是去检查凭据。
| 不要忘了将授信的IP地址插入我们MySQL数据库的授信表中, |
| 这样我们的脚本才能工作。 |
你可以使用SerMyAdmin来查看,更新授信主机列表(trusted
hosts list)。使用如下显示的授信主机菜单:
要添加新的主机,只需简单的点击“New Trusted Host”菜单选项。
使用函数rewritehostport()前转通话到PSTN网关。
这个脚本的名字为openser.pstn。可以在找到。一份拷贝展示如下。之前的脚本修改处使用高亮显示。
# ------------------ module loading
----------------------------------
route[3] {
route[12] {
PERMISSIONS模块曝露了一些重要的函数以对到我们SIP代理的访问进行控制。其中之一是allow_trusted(),这个函数允许我们控制网关使用IP地址访问代理,而不是使用认证凭据。授信表(trusted
table)是授信地址的存储库。你应该将每个网关的IP地址和传输层协议插入这个数据库。这就使得来自网关的请求避免了标准摘要认证的进行。
PERMISSIONS模块还有些标准的许可和拒绝文件。我们这次不使用这些特性。为了不要日志中的这些信息,请将PERMISSIONS模块的config文件夹下的文件拷贝到/etc/openser文件夹下。
cp /usr/src/openser-
在许可文件中,基于正则表达式来过滤请求是可能的,这可以改进环境的安全性。检查用例文件是不是符合正确的句法。
group.so模块用来检查用户的组成员资格。这个叫做ACL(Access
Control List)。你可以使用openserctl工具(如下)来添加,删除或是显示用户ACLs。
loadmodule “permissions.so”
loadmodule “group.so”
下面的第一行告诉模块到哪去寻找传递需要凭据的数据库。第二行提示模块使用数据库上的缓存(cache)访问以增加性能。
modparam("auth_db|permissions|uri_db|usrloc","db_url",
当的代理服务器收到INVITE请求后,通常的行为是向UAC请求凭据。然而,PSTN网关通常并不对认证进行响应。因此,你需要采取特殊的处理过程。函数allow_trusted()将INVITE请求的源IP地址同数据库中授信表进行对比检查。如果符合,则接受之。如果不符合,则再请求凭据。
if(!allow_trusted()){
| 网关的IP地址插入数据库是很重要的 |
你可以使用诸如SerMyAdmin或是phpMyAdmin的工具来维护数据库。这样可比手动在MySQL的CLI(Command
line interface)操作容易的多。
在授信表中,插入的是网关的IP地址,传输层协议(udp,tcp,tls,any)和正则表达式。
下面是我们按照正则表达式进行通话的路由:
if (uri=~"^sip:[2-9][0-9]{6}@") {
if (uri=~"^sip:1[2-9][0-9]{9}@") {
if (uri=~"^sip:011[0-9]*@") {
本地通话(local call)使用数字7分辨并且以2到9之间的数开头(“^sip:[2-9][0-9]{6}@”)。长途号码符合这条正则
“^sip:1[2-9][0-9]{9}@”,号码以1开头,后面紧接这2-9之间的数,加起来一共9个数字,这样的号码被认为是长途号码。最后,国际长途号码以011+国家编码+地区编码+电话号码作为前缀。所有的情况下,脚本都会被抛到路由4(route
4)
| 将ACL数据插入数据库,对于脚本的正常工作很重要 |
你可以使用openserctl工具,SerMyAdmin或是phpMyAdmin来完成。
最后,我们让路由块4(routing
block 4)来处理PSTN的目的地。函数rewritehostport()用来改变URI的主机部分,也就是说当你使用t_relay()中继请求时,此请求将被发往网关。
route[4] {