noiile
上篇文章着重讲了穿越NAT的技术原理。现在主要讲下如何部署。
我们知道STUN可以穿越除Symmetric之外的其他三种类型的NAT。Symmetric类型的NAT需要借助一个ALG来解决。
虽然ALG能够解决所有类型的NAT问题,但是如果所有呼叫的媒体通信都需要通过ALG来代理中转的话,势必给ALG带来十分重的负担,甚至影响语音通信的质量,照成延时或其他QoS的问题。
所以提出一个问题,如何将ALG的负担减至最小。
可以将NAT的类型分成Symmetric和Asymmetric两大类。所以网络通信会有以下几种结构:
caller callee
Asymmetric ßà Asymmetric
Symmetric ßà Asymmetric
Asymmetric ßà Symmetric
Symmetric ßà Symmetric
第一种情况,通过STUN可以很容易解决。
第二三种情况,虽然STUN解决不了,但是也可以通过非ALG的手段来解决。Symmetric类型的NAT只能接收来自它请求的IP地址和端口。比如A是Symmetric类型,B是非Symmetric类型。B能在自己的SDP里面填写正确的IP地址和端口(这里说的正确是指能真正联系到B的IP地址和端口),但是A不能,因为端口是当A发第一个包至B时由NAT Server动态分配一个端口。所以B必然不能通过A的SDP信息发包至A,但当B收到来自A发过来的RTP包时,它就可以从RTP包的IP包头中获知A的NAT Server的IP地址和端口。因此,B再重新修改它的Socket,将目标地址和端口该为来自A的RTP包的IP包头中的地址和端口。通过这样,也能解决这一类型的通话问题。
也就是说,只有第四种情况是非得通过ALG来解决的。
所以要根据通话双方的NAT类型来选择是否要经过ALG。
但是如何获知呼叫双方的NAT类型呢?
假设所有UA都支持STUN,可以检测出自己的NAT类型。
发起方可以在INVITE消息里面加上个NAT-Type的头域,指明自己是什么类型的NAT。
然后,要求每个SIP UA向自己的注册服务器注册时提供自己的NAT类型。
这样,当INVITE抵达目标UA的proxy时,就可以获知双方的NAT类型,得出是属于四种情况中的哪一种。
因此,由目标UA的proxy来决定是否需要经过ALG来中转。当目标UA的proxy收到个Incoming INVITE Message时,它判断呼叫双方的NAT类型。当双方NAT类型都是属于Symmetric时,则请求ALG进行RTP中转。属于其他类型则忽略。