最近,在做标准SIP网关的分布式开发,在注册服务器选型上,最初打算使用freeswitch做为注册服务器,在测试的时候通过抓包,然后分析SIP信令,发现freeswitch软件需要理解SIP信令(比如呼叫相关的信令),并会对信令做出一定的修改,可能会出现问题,然而我们的初衷只是想让freeswitch帮助我们透传信令,还有一些其他原因,最终没有选择使用freeswitch,最后选择使用kamailio,这正是本文要想重点介绍的地方。

       一、注册服务器

      由于不想维护数据库,同时又想达到注册鉴权的目的,通过查阅kamailio的官网介绍及kamailio相关模块的介绍,可以通过脚本等方式劫持SIP信令,这里我们采用python脚本劫持的方法,具体做法如下:

      1、首先在kamailio.cfg里加载python模块的动态库和auth模块的动态库,然后在route(REGISTRAR)里执行python脚本,在python脚本里分析注册信令,如果REGISTER信令里没有带Authorization域,则返回-1,然后调用sl_auth函数(具体函数名字忘记了,就是让kamailio生成一个401要求鉴权的响应给注册发送方),如果REGISTER信令里携带的有Authorization域,获取注册用户名,然后在python里通过http请求向我们的web服务获取该用户的密码,然后再结合Authorization里的相关值进行MD5校验,校验成功,则返回1,然后kamailio服务器会自行回复200 OK,表示该用户注册成功,校验失败,则返回-2,这时调用sl_send_reply函数(响应码为403),表示该用户注册失败。

       2、所有的注册信息都是存放在kamailio内存里,可以通过命令获取注册用户的信息。

       二、负载均衡调度

       首先查看了kamailio负载均衡调度模块dispatcher的相关介绍,但是按照该模块的相关配置并不能完全满足我们的方案需求,需要对该方案做一些调整(由于我们是做视频会议的,当标准SIP设备主动入会时,呼叫的是会议号,kamailio服务并不知道被叫在哪里,同时我们会议的负载均衡策略是另外一个组做的,主动入会的SIP设备呼叫的会议,该会议需要分配到那个标准SIP网关上也不知道),具体方案如下:

       1、修改kamailio配置文件

       在配置文件 kamailio.cfg里添加如下内容:

loadmodule("")
       modparam("dispatcher", "list_file", "/usr/local/etc/kamailio/dispatcher.list")
       modparam("dispatcher", "force_dst", 1)

       2、劫持注册REGISTER信令类似,这里劫持呼叫INVITE信令,分析被叫是否是会议号还是SIP用户,如果发现是会议号,则通过http请求,向相关服务获取该会议所在的SIP网关的IP地址及端口,然后通过dispatcher的reload命令将该SIP网关的IP地址和端口等信息写到dispatcher.list文件里,修改后重新载入配置:调用kamctl dispatcher reload命令,python脚本执行完之后,调用ds_select_dst函数将该呼叫重定向到刚才指定的SIP网关去。

       如果有什么不足或疑问,欢迎留言。