BCM SIP ALG原理及实现(应用层实现机制)

一、SIP ALG概念及作用

SIP ALG(SIP Application Layer Gateways):SIP应用层网关

其主要作用就是帮助NAT下的私网终端设备,在不做任何改动的情况下能够与公网上的SIP软交换进行正常的数据交互。

由于其仅是简单的消息数据修改,类似于一种透明代理,并没有事务层相关概念,同时在现网使用中兼容性等问题,导致ALG在解决NAT私网穿越方面并没有得到很好的应用。


二、不同类型NAT特性

不同类型NAT处理传入的UDP分组是方式是不同的。四种主要类型中有三种是可以使用的:完全圆锥型NAT、受限圆锥型NAT和端口受限圆锥型NAT,但大型公司网络中经常采用的对称型NAT(又称为双向NAT)则不能使用。
1、完全圆锥型NAT
从私网客户端的源ip1:port1发出数据,在NAT中产生一个私网地址ip1:port1和公网地址ip2:port2的映射,然后将数据报中的源地址修改为ip2:port2,发向公网A服务器地址ip3:port3,当从公网任意服务器X向ip2:port2发送数据时,NAT都能自动将数据转给ip1:port1。
2、受限圆锥型NAT
从私网客户端的源ip1:port1发出数据,在NAT中产生一个私网地址ip1:port1和公网地址Ip2:port2的映射,然后将数据报中的源地址修改为ip2:port2,发向公网A服务器地址ip3:port3,这时侯并不像完全NAT那样,可以接收任意源地址发向目标地址为ip2:port2的数据报,仅能接收源地址为ip3(源端口可以任意)发向目标地址为ip2:port2的数据报,并自动将数据转给
ip1:port1。
3、端口受限圆锥型NAT
类似于受限圆锥型NAT,并同时加上源端口的判断。NAT仅能接受源地址为ip3:port3发向目标地址为ip2:port2的数据报,并自动将数据转给ip1:port1。

4、对称型NAT
从私网客户端的源ip1:port1发出数据,在NAT中产生一个私网地址ip1:port1和公网地址ip2:port2的映射,然后将数据报中的源地址修改为ip2:port2,发向公网A服务器地址ip3:port3,并且同端口受限圆锥型NAT一样,仅能接收源地址为ip3:port3发向目标地址ip2:port2的数据报。但不同于前三种类型的NAT,当从私网客户端的源ip1:port1发出数据,不是发向刚才的公网A服务器,而是发向公网B服务器地址ip4:port4时,在NAT中之前的私网ip1:port1到公网ip2:port2的端口映射将丢失,并且修改为ip1:port1到公网ip21:port21的映射,由于之前暴露在外面的地址Ip2:port2已经消失,导致公网A服务器无法向私网客户端发包。一般情况下,遇到这种类型的NAT设备,基本上想实现NAT私网穿越已经没戏了。


三、一般SIP终端及软交换NAT私网穿越实现

在讲解SIP ALG原理之前,先给大家简单介绍一下一般SIP终端及软交换是如何实现NAT私网穿越,这里并不针对《VOIP如何实现NAT私网穿越》进行介绍,仅介绍一下国内VOIP厂商常用的实现方法,如果大家对这方面感兴趣的话,可以去网上查一下这方面的资料,技术细节还是比较多。

1、SIP终端使用STUN技术实现穿越
在SIP终端含有STUN客户端功能,在准备与SIP服务器通讯之前,先使用STUN客户端与STUN服务器进行STUN协议交互,从而得到前端NAT设备属于哪种NAT类型,有没有防火墙拦截、是否支持发夹转发等,及暴露在外面可用的公网IP和端口,后面在与SIP服务器交互时,信令中的头域字段及媒体地址直接填写已知的公网IP和端口,从而实现穿越。


2、SIP软交换使用代理技术实现穿越(在国内软交换研发厂家较常用的技术)
A、信令穿越
首先通过终端向软交换发送注册信息,而从得到终端的公网IP和端口,后面软交换主动向终端发送报文时,发向记载的公网IP和端口。
B、媒体穿越
软交换内部含有媒体代理模块,将主叫发送invite到软交换时,软交换给主叫在媒体代理上分配一个媒体端口7000,给被叫分配一个媒体端口7002,然后重新构建一个invite,sdp的地址设置为媒体代理IP:7002,发给被叫,在被叫回应200应答后,重新构建200应答,sdp的地址设置为媒体代理IP:7000,将该200应答发给主叫。这时侯主叫及被叫都知道媒体要发向媒体代理服务器,在媒体代理服务器中虽然知道7000和7002端口是一对,当从7000端口收到数据报后发送7002对应的终端设备,但如何知道私网设备的有效地址?这里采用了等待技术,即等待主被叫设备主动发送媒体包,当主叫设备向7000端口发送数据时,记载该数据报的公网地址,当被叫设备向7002端口发送数据时,记载该数据报的公网地址,这时候知道了7000及7002端口对应的地址后,如果后面在从该端口发来数据报就知道怎么转发了。


四、BCM SIP ALG数据流向

这个培训是讲解应用层SIP ALG实现,开发应用层SIP ALG,就需要清楚信令及媒体的数据包走向,SIP ALG使用了netfilter/iptables技术进行数据包的控制,这里对这些细节不进行讲解,如果感觉兴趣的话,可以学习一下iptables命令的使用,及netfilter HOOK开关相关的资料,在上一节讲解的SIP服务器实现私网穿越中,媒体代理就是使用netfilter HOOK开发的。为了方便后面讲解,这里结合图表简单介绍一下netfilter框架中各勾子的作用。
1、绿色部分的链用于NAT转换
2、柿黄色部分的链用于数据过滤
3、土黄色部分的链可以用于NAT转换,也可以用于数据过滤
4、灰色部分为路由处理

5、PRE_ROUTING链主要用于对进入到接口的数据包进行DNAT(目的地址转换)
6、LOCAL_IN链主要用于对进入本机的数据过滤
7、IP_PORWARD链主要用于对转发数据过滤
8、LOCAL_OUT链主要用于对本机发出的数据包过滤和DNAT(目的地址转换)
9、POST_ROUTING链主要用于对数据准备发出前进行SNAT(源地址转换)



信令从LAN侧到WAN侧的数据流向


1、SIP ALG在本机监听6060端口,在PRE_ROUTING链中增加如果收到的目的端口为5060、5061、
5062的数据包,则将该数据报重定向到本地LAN侧IP:6060,即如果从LAN侧收到数据包的目的
端口如果为5060、5061、5062,将数据报中IP头的目的地址改为LAN侧IP:6060。
2、从LAN口收到发往地址为公网软交换IP:5060数据,经过PRE_ROUTING链将目的地址转为本地。
3、在经过进入ROUTE处理时,因为目的地址为本地LAN侧IP:6060,则将数据流向LOCAL_IN。
4、在LOCAL_IN链中增加允许LAN侧目的端口6060的数据包进入,这样数据报就进入本机交给
监听在6060端口的SIP ALG来处理。
5、SIP ALG修改数据报,增加WAN侧的VIA头域,修改CONTACT地址为WAN侧地址,将Max-Forwards
头域进行递减,将SDP中媒体相关地址改为ALG媒体代理分配的WAN侧地址,最后将数据报通过
LOCAL_OUT、POST_ROUTING链从WAN侧送出。


信令从WAN侧到LAN侧的数据流向
媒体从LAN侧到WAN侧的数据流向
媒体从WAN侧到LAN侧的数据流向

这三种情况的数据报的目的地址都是设备本地地址,所以不需要在PRE_ROUTING链中做特殊处理
,仅需要在LOCAL_IN链中加入允许指定数据报的进入规则即可。



五、BCM SIP ALG功能实现

A、SIP ALG启动


SIP ALG启动依赖于两个方面,一个是确保WEB配置页面“应用”->“高级NAT配置”->“ALG配置”中的“启用SIP”选项开启,第二个就是要确保有路由模式的INTERNET连接,并且该连接开启NAT选项,仅处于已连接状态。满足这两个条件,SIP ALG进程才会启动,否则SIP ALG进程将立即停止,如ALG进程已经启动,但网络接口断开后,则ALG进程退出。

1、在WEB页面修改ALG参数时,会给SSK发出CMS_MSG_SIP_ALG_EXT_UPDATE消息,SSK收到这个消息后,调用processSipAlgExternalUpdate函数,来更新一个全局标记变量,记载有外部环境修改ALG的配置,这个全局标记变量后面会用到。

2、在ssk_main函数的死循环中,使用checkWanLinkAndUpdateForSipAlg函数定时检测各WAN口状态,及在上面小节介绍的外部更新标记变量,如果WAN口的数量发生变动,或者任意WAN口的网络状态发生变化,则将网络更新标记记为TRUE,如果网络更新标记或外部更新标记任意一个为TRUE,则触发ALG更新操作,调用SipAlgUpdate函数。

3、SipAlgUpdate函数首先从MDM中读取ALG开关状态,及需要重定向的端口配置,根据开关变量来确定关闭Alg,还是开启Alg.

4、如果WEB页面开关已经开启,则调用processSipAlgStart函数启动Alg。在processSipAlgStart函数中首先判断Alg运行情况,如果已经开启则关闭,否则确定有UP的
WAN口后,调用sendStartSipAlgMsgToSmd启动Alg。

5、在sendStartSipAlgMsgToSmd函数中,首先调用sipAlgStartPre做一些启用之前的操作,ALG主进程启动时需要从一个配置文件中读取相关配置信息,在sipAlgStartPre函数里主要就是构建这个配置文件,并加入一些iptables规则,加iptables规则是为了保证数据可以正常的进入到ALG进程中,这块可以参考iptables相关资料,及上一章讲的数据流向来加深理解。之后调用cmsMsg_sendAndGetReply给SMD发送消息,让SMD把ALG进程拉起。SMD如何拉起ALG进程在这里就不讲解了,这个是BCM 4.X架构代码比较重要的东西,内容比较多,大家可以学习一下smd_init、smd_main两个函数,来了解核心调度模块SMD是如何拉进程的。

6、SIP ALG主进程启动后首先执行main函数,在main函数主要做如下操作:
6.1、Sigemptyset函数设置信号回调
6.2、make_default_config函数设置默认参数
6.3、read_config函数从指定默认文件路径读取全局配置信息
6.4、secure_enviroment检测如果是root用户运行,根据配置改变用户ID及根目录
6.5、根据是否配置daemonize来fork一个独立进程进行alg,目前alg启动关闭由SMD控制,配置文件中将daemonize已置为0,否则SMD无法控制alg 关闭
6.6、将进程ID写到哪定位置
6.7、rtpproxy_init函数初始化RTP代理服务器,启动RTP代理主线程
6.8、parser_init函数对osip协议栈的解析器模块初始化
6.9、sipsock_listen_mult启动sip信令套接口
6.10、 register_init如果注册文件存在,则读取注册文件,生成url映射表。url映射表在alg信令转发中非常重要,是否成功处理非注册请求及一些地址替换都是根据url映射表来处理的。这个注册文件在上电时是不存在的,当一个NAT下设备通过ALG注册成功后会自动生成该文件,该ALG正常退出后,该文件中有效数据也会清空,该函数的主要作用就是在ALG异常退出的情况下保证ALG再次开启时可以恢复之前的url映射表。
6.11、进入ALG主循环处理函数,该主循环处理函数中主要处理:监听SIP信令,URL映射表的老化,检测WAN口IP地址变动,当有SIP数据包到达,则进行SIP信令处理。


B、SIP ALG注册信令处理


NAT下设备发出注册请求
1、sipsock_read读取数据
2、accesslist_check有效访问列表检测
3、security_check_raw简单的数据合法校验
4、osip_message_init、osip_message_parse使用osip协议栈的解析器进行消息解析,用于后
面使用osip协议栈对数据的修改及操作。
5、 security_check_sip对解析后的指定字段进行简单校验。
6、检查Max-Forwards,如果小于1则返回错误
7、check_vialoop检测是否产生消息环回,如果有则返回错误
8、检测是否注册请求消息,如果是则进行下面处理
9、检测收到注册请求消息的URL是否是发给ALG的,还是发给公网SIP服务器的,在这里一般都是发向公网SIP服务器,所以我们只看发往公网SIP服务器的流程。
10、register_client,这里根据注册信息从URL映射表获取一个可用的条目并进行填充,URL映射表最大条目数为9,表明ALG仅能同时处理9个NAT下设备,映射表各成员的取值如下:
Active:这里直接写为TRUR,表示条目已经有效

Expires:该条目老化时间,还记上面讲主循环时,有一个URL老化处理,就是用的这个值,该值 当前取自当前系统时间 + 2秒,该值在收到注册200应答后会重新更新,这里取一个2秒是为了确保后面不再有任何消息时,将这条新的URL快速老化。
true_url:取自注册请求中的contact地址,就是NAT下私网设备的地址
masq_url:取自配置文件中的outbound_if地址,就是ALG设备的WAN口地址
reg_url:取自注册请求中的to头域地址,就是SIP服务器地址
11、proxy_request进行请求处理,修改消息contact头域为自身WAN口地址,将Max-Forwards头域值递减,如果有Record-Route头域则检测是否含有自身地址,并删除,添加一个via头域为自身WAN口地址,将修改后的数据包从WAN口创建的socket发送出去,目的IP取自最初数据报中IP头的目的地址,目的端口取自请求URL中的端口

SIP服务器发出注册应答
1、收到数据包后,前面流程同收到注册请求一样,在后面的讲解中不再写出这些步骤,直接从使用OSIP协议栈解析出消息来讲解。
2、判断如果是应答消息,调用proxy_response函数
3、在URL映射表中查找哪条的true_url与数据包原始发送地址相同,如果不相同,则意味着这个响应是从WAN侧发来的
4、删除含有WAN侧地址的VIA头域
5、如果收到是200 OK的注册响应,则更新对应URL映射表中的expires值,取值为(当前系统时间 + 应答消息中expires值 + 30秒),同时将URL映射表中表数据写入本地注册文件,还记的这个注册文件有什么用吗?在之前讲主循环的时候可以找到。
6、恢复contact值为LAN侧私网设备地址
7、将修改后的数据包从LAN侧发送出去,目的地址取自应答消息中的VIA头域值 。


C、SIP ALG呼叫信令处理


NAT设备发出INVITE
1、判断如果消息是请求消息,则调用proxy_request函数
2、在URL映射表中查找哪条的true_url与数据包原始发送地址相同,如果相同,则意味着这个请求是从LAN侧发来的
3、如果在第2步没有找到,则在URL映射表中查找哪条的masq_url或reg_url与请求url相同,如果相同,则意味这个请求是从WAN侧发来的
4、如果在第3步没有找到,则在URL映射表中查找哪条的masq_url或reg_url与To头域相同,如果相同,则意味这个请求是从WAN侧发来的
5、如果到这步还不确定请求是从哪发来的,则回应408错误应答,URL映射表在这里很关键。
6、修改消息中contact头域值为WAN口地址
7、修改SDP中媒体地址为WAN口地址,媒体端口为媒体代理分配的端口号,在这里调用rtp_start_fwd函数将媒体转发所需要的必要参数写入媒体转发列表中。
8、将Max-Forwards头域值递减
9、删除Record-Routes头域含有自身的地址
10、添加VIA头域为WAN口地址
11、将修改后的消息从WAN口发送出去,目的IP取自最初数据报中IP头的目的地址,目的端口取自请求URL中的端口


软交换发出含有SDP的200响应
1、判断如果消息是响应消息,则调用proxy_response函数
2、在URL映射表中查找哪条的true_url与数据包原始发送地址相同,如果不相同,则意味着这个响应是从WAN侧发来的
3、删除含有WAN侧地址的VIA头域
4、收到200的invite应答,修改SDP中媒体地址为LAN口地址,媒体端口为媒体代理分配的端口号,在这里调用rtp_start_fwd函数将媒体转发所需要的必要参数写入媒体转发列表中。这时侯媒体代理已经知道了两边的媒体信息,如果双方发送媒体包,媒体代理就可以正常的进行媒体转发处理。
5、将修改好的消息从LAN侧发出,目的地址取自应答消息中的VIA头域值。

刚才介绍的信令处理是NAT下设备做主叫的情况下,NAT下设备做被叫的情况这里就不介绍了,感兴趣的同事可以从代码中来了解。


D、SIP ALG媒体处理


1、媒体代理初始化
rtpproxy_init函数执行媒体代理的初始化,主要创建了一个媒体代理线程rtpproxy_main,该线程主要负责RTP及RTCP的代理转发,及媒体代理列表的老化(判断有效的套接口列表项,如果最后媒体处理时间+老化时间已经小于当前时间,则认为已经没有媒体需要处理,则会复位该列表条目)。

2、向媒体代理列表中添加转发条目
收到INVITE及1XX、2XX协带SDP,则调用rtp_start_fwd函数向媒体代理列表中加入转发条目,并在本地WAN侧及LAN侧创建媒体套接口,用于媒体代理。其中传入一些重要参数信息。
Callid:SIP消息中的callid值,用于转发时关联双向媒体
client_id:客户端标识,取自SIP消息contact头域,用于转发时关联双向媒体
Direction:媒体条目方向,用于转发时关联双向媒体
media_stream_no:在SDP消息中media行的个数索引,用于转发时关联双向媒体
local_ipaddr、local_port:媒体代理自身地址和分配的端口
remote_ipaddr、remote_port:SDP中媒体地址

3、媒体转发处理
当主被叫媒体信息都加入转发条目时,媒体代理线程函数执行如下:
3.1、判断转发条目中RTP接收套接口是否收到数据,如果收到数据则继续执行
3.2、判断转发条目中RTP发送套接口是否有效,如果发送套接口无效,则在代理列表中进行遍历查找,查找条件为Callid相同、 client_id不同、 Direction不同、 media_stream_no相同的转发条目项,如果找到,则将当前条目的发送套接口设置为已查找条目的接收套接口。
3.3、使用当前条目中有效的RTP发送套接口将媒体数据发出,目的地址为转发条目记载的remote_ipaddr和remote_port
3.4、更新当前转发条目及关联条目的时间戳,以免转发条目被老化。
3.5、后面RTCP的处理基本相同,这里就不介绍了。

4、媒体转发停止
当出现如下情况下,媒体转发停止,复位转发条目:
A、媒体转发时发送媒体失败
B、转发条目老化
C、RTP代理关闭

D、WAN口IP发生变动
E、收到任意一方发送BYE或CANCEL
F、收到4xx、5xx、6xx应答

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值