草莓加冰 / Freeswitch / Freeswitch与Freeswitch对接

分享

   

Freeswitch与Freeswitch对接

2017-06-06  草莓加冰
1、双机对接
假设你有两台Freeswitch主机,分别为A和B,IP地址分别为192.168.200.A和192.168.200.B。每台机器均使用默认配置,也就是每台机器上100~1019这20个号码之间可以互打电话。位于同一机器上的用户称为本地用户,如果需要与其他机器上的用户通信,则其他机器上的用户就称为外地用户。
如果我们需要两台机器之间的用户可以互拨,最需要解决的问题不是技术上如何配置,而是一个逻辑问题。例如:如果A上的1000想拨打B上的1000,则B上的1000相对于A上的1000来说就是外地用户。
为了完成对接,我们规定:不管是A上的用户还是B上的用户,拨打外网用户均需要在实际的电话号码前加拨0。
在A机上,把以下Dialplan片断加到conf/dialplan/default.xml中(注意在测试时,把配置加得靠前一点,以防与其他现有的配置项相冲突):
<extension name="B"> 
 <condition field="destinantion_number" expression="^0(.*)$"/> 
  <action application="bridge" data="sofia/external/sip:$1@192.168.200.B:5080"/>
  </condition> 
 </extension>
其中,正则表达式^0(.*)$表示匹配所有以0开头的被叫号码,匹配完成后,括号中的匹配结果会被绑定到变量$1中。因此,如果A上的用户呼叫01000,则$1的值就是1000,bridge是一个App,它的参数就变成sofia/external/sip:1000@192.168.200.B:5080,它是一个呼叫字符串。在一个呼叫中,当Freeswitch执行到这里的bridge时,就会从本机的external Profile(本机的5080端口)向B的5080端口发送INVITE呼叫请求。
注意,上述过程中,被叫号码中的第一个0在到达B时丢失了。这是系统对接中常用的一个策略,俗称把“0”吃掉了。
B在5080端口上收到INVITE请求后,由于5080端口默认走public Dialplan,所以查找public.xml,可以找到以下的Dialplan配置项:
<extension name="public_extensions"> 
  <condition field="destination_number" expression="^(10[01][0-9])$">
<action application="transfer" data="$1 XML default"/> 
  </condition> 
  </extension>
上述Dialplan中的正则表达式^(10[01][0-9])$会匹配被叫号码1000,然后执行transfer,并把来话转到default Dialplan。呼叫转到default Dialplan后,路由规则就跟本地用户的来话一样了,因而最终B上的1000就会振铃。如果B接听电话就接通了。
注意,如果你对接不同的服务器,服务器中的用户号码不是默认的1000-1019,那么就在public.xml中的正则表达式^(10[01][0-9])$中添加你的用户号码。如服务器中的用户号码为800-809,则添加^(10[01][0-9]|80[0-9])$。
如果B上的用户要拨打A上的用户,那么只需要在B上做类似A上的配置就可以了。

2、汇接

理论上,所有的对接模式都可以采用上面的双机对接模式,上述的对接模式是一切对接的基础。下面我们考虑更复杂的情况,ABCD开会讨论。D说:“我为你们提供转接服务。”所以D就成了一个汇接局,为ABC之间的通话做转接服务。ABC就称为端局,因为他们只有终端用户。拓扑结构如1-1

 
                                                            1-1 汇接局模式

同时,大家商量新的拨号规则:本地用户之间的通话拨号规则不变,但是如果拨叫其他外地用户的话,则需要拨打相应的局号(如果A上帝额用户呼叫B1000,则拨打B1000),并统一送到D进行汇接。我们以A为例,它上面的Dialplan如下:

<extension name=D>

<condition field=destination_number expression=^([B-Z].*)$>

<action application=bridge data=sofia/external/sip:$1

@192.168.200.D:5080/>

</condition>

</extension>

其中,正则表达式^([B-Z].*)$表示任何以B-Z开头的号码都送到D5080端口上去。注意:这里没有“吃掉”第一位号码,因为如果吃掉的话,D就不知道如何进行下一步路由了。所以,如果A上的用户拨打B1000,在D上将收到B1000

D上,收到5080端口的呼叫请求后,查找public Dialplan对来话进行路由。它的Dialplan设置如下:

<extension name=D>

<condition field=destination_number expression=^D(.*)$>

<action application=transfer data=$1 XML default/>

</condition>

</extension>

上述配置说明,如果被叫号码的首位是D,则说明是一个本地用户,所以“吃掉”首位的D,然后把路由转到default Dialplan进行处理。

对于被叫号码不在本地的用户,使用下面的Dialplan

<extension name=D>

<condition field=destination_number  expression=^([A-CE-Z])(.*)$>

<action application=bridge data=sofia/external/sip:$2

@192.168.200.$1:5080/>

</condition>

</extension>

其中,^([A-CE-Z])(.*)$表示匹配所有除D以外的被叫号码。我们以有人拨打B1000为例,匹配成功后,$1的值为B$2的值为1000,所以,bridge的参数中呼叫字符就变成sofia/external/sip:1000@192.168.200.B:5080,因而相当于在D上吃掉了被叫号码中最首位的B,并把电话送到B5080端口上。电话到达B后,B上默认的Dialplan就可以将电话路由到本地用户上,电话接通。这种方式就称为汇接模式。

所有局间的通话都是通过D的,因而它的压力比较大。实际上,如果ABC之间的网络直接可达,则可以让D仅转发SIP信令,而让RTP流直接在端局之间传递。在上述配置的bridge Action之前增加如下参数可以让D工作在Bypass Media(媒体绕过)模式,仅转发SIP信令,而让RTP媒体流在端局间传递:

<action application=set data=bypass_media=true/>

上述参数是在Dialplan中设置的,因而仅针对当前通话有效。如果想让D对所有通话都是用Bypass Media,则可以直接在Profileexternal)中,添加如下设置:

<param name=inbound-bypass-media value=true>

3、双归属

即使采用了Bypass MediaD的压力还是很大。一旦D出现了故障,则ABC之间的用户就都打不通电话了。

为了解决这个问题,它们又找来了E,来做一个备份的汇接局。并且把DE的本地用户都分了一下,放到ABC上,让DE专门做汇接。拓扑结构如图2

  

 

                             图2 双汇接局双归属网络拓扑

<extension name=DE>

<condition field=destination_number expression=^([B-Z].*)$>

<action application=bridge data=sofia/external/sip:$1@IP.D:5080

|sofia/external/sip:$1@IP.E:5080/>

</condition>

</extension>

这里我们修改了呼叫字符串,使用了|”连接两个呼叫字符串。它的意思是,如果第一个呼叫不成功,则使用下一个呼叫字符串。这种方式就称主备用模式。

我们以负荷分担的方式处理话务,就是在端局将50%的通话送到D上,50%通话送到E上。这里我们使用如下Dialplan实现(以A上的额出具路由为例):

<extension name=DE>

<condition field=destination_number expression=^([B-Z].*[13579])$>

<action application=bridge data=sofia/external/sip:$1@IP.D:5080

|sofia/external/sip:$1@IP.E:5080/>

</condition>

</extension>

 

<extension name=ED>

<condition field=destination_number expression=^([B-Z].*[24680])$>

<action application=bridge data=sofia/external/sip:$1@IP.E:5080

|sofia/external/sip:$1@IP.D:5080/>

</condition>

</extension>

通过上述配置,根据正则表达式^([B-Z].*[13579])$,所有被叫号码以奇数结尾的都优先送到汇接局D上(如果失败仍会送到E上)。同理,所有号码以奇数结尾的都优先送到汇接局E上(如果失败仍会送到D上)。

4ACL

在实际环境中,只考虑把电话接通是不够的,还要考虑安全性。上面的方法只使用5080端口从public Dialplan做互通,而发送到5080端口的INVITE是不需要鉴权的,这意味着任何人均可以向它发送INVITE从而按你设定的路由规则打电话。

为了防止这个问题,我们在汇接局上关闭5080端口,而让所有来话都送到5060端口上(internal Profile)。5060端口上的来话是需要先鉴权才能路由的。在这种汇接局模式中,一般会使用IP地址鉴权方式。而IP地址鉴权就会用到ACL

ACL(Access Control List)即 访问控制列表,它通过一个列表矩阵来控制哪些用户可以访问哪些资源。在Freeswitch中,实现了基于ACL的鉴权。

其中,internal Profile默认使用“domains”这个ACL进行鉴权。配置如下:

<param name="apply-inbound-acl" value="domains"/>

上述配置说明,当收到呼叫(INVITE)请求时,要查看“domains”这个ACL,看是否允许来源IP地址进行呼叫。

ACL是在conf/autoload_configs/acl.conf.xml中配置的,其中domains的默认配置如下:

<list name="domains" default="deny">

<!--domains是一种特殊情况,它会根据用户目录中的配置生成ACL-->

      <node type="allow" domain="$${domain}"/>

      <!--如果你想允许某些IP段能通过ACL检查的话,使用cidr=的配置方式 -->

      <!-- <node type=allow cidr=192.168.200.158/32>-->

    </list>

如果我们想在D上允许来自ABC的呼叫,就可以把ABC的地址加到上述配置里面,如可以添加以下配置,以允许来自这些IP的呼叫。

<node type=allow cidr=192.168.200.A/32>

<node type=allow cidr=192.168.200.B/32>

<node type=allow cidr=192.168.200.C/32>

通过设置上述ACL,我们就保证了只有授权的用户才能从D上进行路由。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。

    0条评论

    发表

    请遵守用户 评论公约

    类似文章
    喜欢该文的人也喜欢 更多

    ×
    ×

    ¥.00

    微信或支付宝扫码支付:

    开通即同意《个图VIP服务协议》

    全部>>