noiile的专栏

不爽,千万别骂我

原创 SIP穿越NAT&FireWall解决方案收藏

新一篇: 编码心得:为什么我的单件(Singleton)对象会有两个地址呢? | 旧一篇: 我的IT历程(中)

SIP从私网到公网会遇到什么样的问题呢?

包的地址转换。

SIP消息里面的SIP地址转换。

SIP消息里面的SDP中的RTP地址转换。

 

网络现存结构复杂,SIP服务提供商并不一定是NETWORK提供商,很难要求客户只能使用某种方式的NAT&FireWall。如何找出一种可以满足各种网络的SIP应用解决方案呢?

 

NATFirewall的基本原理

首先,NAT的几种方式:

Full Cone当一台私网内的主机向公网发一个包,其本地地址和端口是{A:B}NAT会将其私有地址{A:B}转换成公网地址{X:Y}并绑定。任何包都可以通过地址{X:Y}送到该主机的{A:B}地址上,NAT会将任何发送到{X:Y}incoming包的地址{X:Y}转换成{A:B}

 

Partial/Restricted Cone当一台私网内的主机向公网发一个包,其本地地址和断口是{A:B}NAT会将其私有地址{A:B}转换成公网地址{X:Y}并绑定。任何包都可以通过地址{X:Y}送到该主机的{A:B}地址上,但是,NAT只为第一个发往{X:Y}的包绑定成{A:B}|{X:Y}<->{C:D},其中{C:D}是那个包的源地址和端口。也就是说,只有来自{C:D}的包才能于主机{A:B}通信。

PartialRestricted Cone的区别是Partial只绑定incoming packet IP地址,而Restricted Cone会绑定incoming packetIP地址和端口。也就是上面描述的那种情况。

 

Symmetric Cone当一台私网内的主机向公网某台主机发送一个包,{A:B}à{C:D}NAT会将其地址{A:B}转换成{X:Y},并为其绑定成{A:B}|{X:Y}<->{C:D}NAT只接受来自{C:D}incoming packet,将它转给{A:B}。也就是说,如果私网内的主机要向外面发送一个包,它必须要知道对方的公网IP和端口。但如果对方也是处于一个私网内,它就很难获知对方的公网IP和端口。

 

由此可见,Symmetric Cone条件最严格,Partial/Restricted Cone次之,Full Cone条件最不严格。

 

下面再看看Firewall的基本策略:

l         Firewall会判断所有的包是来自内部(Inside)还是外部(Outside)

l         一般,允许所有来自inside的包发出去。

l         一般,允许来自Outside的包发进来,但这个连接必须是由Inside发起的。

l         一般,禁止所有连接由Outside发起的包发进来。

l         一般,firewall会允许几个信任的outside主机,他们可以发起建立连接,并发包进来。

 

所有NATFirewall都是对于TCP/IP层以下进行处理和过滤的,而SIP应用的地址是在应用层。所以必须采用其他的途径来解决这一问题。

针对不同的NAT类型,可以有不同的解决方案。

l         UPnP

l         External Query

l         STUN

l         ALG

其中前3种都是由SIP Client(包括UAProxy)通过某种手段或协议在INVITE之前获取自己的公网地址和端口。需要SIP Client提供额外支持,并且也不适应所有的NAT方式。

ALG(Application Layer Gateway)适应所有NAT方式,并不需要SIP Client做任何额外的支持。它对Application层的SIP信令进行处理和修改,从而做到透明转换地址。

下面针对一个案例详细描述ALG的解决方案。

 

SIP ALG解决方案


ALG修改SIP消息里面的SIP地址和端口和SDP消息里面的RTP地址和端口,其中RTP地址和端口要向RTP Proxy请求获得,RTP Proxy分配自己的一个空闲的地址和端口,并和这个Call保持映射关系。并为分配给呼叫双方的地址和端口进行绑定,这样,呼叫双方的RTP连接地址都是RTP Proxy,由RTP Proxy经过中转,发至真正的目的地。

假设,有两个SIP Client要进行通信,AdaBob,他们分别位于自己的Nat Server后面:

其中两台NAT Server都是Symmetric Cone方式。

其信令流程如下:

1.         Ada发起信令,Invite Bob

IP Packet IP Address:

From: 192.168.1.10:5060

To: 128.97.41.56:5060 (SIP ALG)

SIP Msg IP Address:

From: 192.168.1.10:5060

To: 128.97.41.56:5060

SDP Body IP Address for RTP:

192.168.1.10:10024

 

2.         经过NAT ServerNAT将其私有地址转换成公网地址,并绑定,由于是采用Symmetric Cone方式,所以还绑定目的的IP地址。

{192.168.1.10:5060}|{128.96.41.1:5678}<->{128.97.41.56:5060}

IP Packet IP Address:

From: 128.96.41.1:5678

To: 128.97.41.56:5060 (SIP ALG)

SIP Msg IP Address:

From: 192.168.1.10:5060

To: 128.97.41.56:5060

SDP Body IP Address for RTP:

192.168.1.10:10024

 

3.         SIP ALG接受到该INVITE,发现其包的IP地址和SIP IP地址不同,就判断其是经过NAT,于是就将其相关的SIP IP地址修改。

并检查它的Body中是否是包含SDP信息,如果是,且有RTP地址,SIP ALG就会去向RTP Proxy请求一个公网RTP地址来代替原有的RTP地址。

IP Packet IP Address:

From: 128.97.41.56:5060

To: 128.96.63.25:5566

SIP Msg IP Address:

From: 128.96.41.1:5678

To: 128.96.63.25:5566(下一跳的地址)

SDP Body IP Address for RTP:

128.97.44.5:3000

 

4.         因为Bob不断的向SIP ALG发送注册包,所以,它的NAT Server始终为它保留着这么个绑定,{10.0.0.12:5060}|{128.96.63.25:5566}<->{128.97.41.56:5060}。所以,由SIP ALG发出的INVITEBob能收到。

Bob返回200 OK,包含SDP信息。

IP Packet IP Address:

From: 10.0.0.12:5060

To: 128.97.41.56:5060

SIP Msg IP Address:

From: 10.0.0.12:5060

To: 128.97.41.56:5060(下一跳的地址)

SDP Body IP Address for RTP:

10.0.0.12:10002

 

5.         NAT Server将其包的IP地址修改。发往SIP ALG

 

6.         SIP ALG接受到该200 OK,发现其包的IP地址和SIP IP地址不同,就判断其是经过NAT,于是就将其相关的SIP IP地址修改。

并检查它的Body中是否是包含SDP信息,如果是,且有RTP地址,SIP ALG就会去向RTP Proxy请求一个公网RTP地址来代替原有的RTP地址。

IP Packet IP Address:

From: 128.96.63.25:5566

To: 128.96.41.1:5678

SIP Msg IP Address:

From: 128.96.63.25:5566

To: 128.96.41.1:5678(下一跳的地址)

SDP Body IP Address for RTP:

128.97.44.5:3002

 

7.         此时,RTP Proxy为这个Session保持着这么个连接绑定

{128.97.44.5:3000|128.97.44.5:3002}

 

8.         Ada收到200 OK,它认为对方的RTP地址是128.97.44.5:3002。将与其建立连接。

Bob认为对方的RTP地址是128.97.44.5:3000。将与其建立连接。

 

9.         RTP Proxy3002端口收到包,它可以从包地址获得AdaRTP公网IP

RTP Proxy3000端口收到包,它可以从包地址获得BobRTP公网IP

从而,RTP Proxy会将3002端口收到的包转发到BobRTP公网IP

同样,RTP Proxy会将3000端口收到的包转发到AdaRTP公网IP

 

这样,一个通话的连接就成功建立。

SIP ALG的部署

因为无论如何,都需要所有RTP包经过RTP Proxy,所以所有的MS都要有修改SDP的能力,而只有SIP ALG需要有修改SIP消息的能力。让用户配置自己的Proxy是什么,避免公网的SIP Client也经过SIP ALG,造成没必要的消耗。

补充

如果SIP ALG发现INVITE包的地址和SIP地址是一致的话,它将不对这个包进行修改,它认为这个包是来自公网,或者SIP Client具备了穿越NAT的能力。但它会修改其SDPIP地址。

ISSUE:

1.       如果SDP描述的是单工工作的话,RTP连接无法建立,因为RTP proxy始终无法知道沉默方的RTP公网IP

2.       每次建立RTP连接,某一方的RTP包可能会丢掉若干个,直到RTP proxy获知另一方的RTP公网IP

3.       是否应该强制任何RTP包都要经过RTP Proxy,无论它们都是来自公网,可以直接连接。我想是的,因为主叫方是不知道被叫方的网络环境的。

4.       如果多个RTP Proxy进行均衡,如何保证为主叫方分配IPProxy和为被叫方分配IPProxy是一致的呢?(它们必须是同一台Proxy

可以增加一个header,比如RTP proxy,这个header只有SIP ALG认识。

5.       如果SIP消息加密,就无法修改其SIPIP地址。

 

 

参考

“SIP, NAT, and Firewalls”, Fredrik Thernelius, May 2000

“Cisco - VoIP Traversal of NAT and Firewall”,  Cisco Systems, Inc.

 

(Noiile)

 

 

 

发表于 @ 2004年09月24日 13:07:00|评论(loading...)|编辑

新一篇: 编码心得:为什么我的单件(Singleton)对象会有两个地址呢? | 旧一篇: 我的IT历程(中)

评论

#IOKE 发表于2004-10-25 10:40:00  IP:
TrackBack来自《SIP穿越NAT》

Ping Back来自:blog.csdn.net
#ioke 发表于2004-10-25 10:36:00  IP: 211.160.21.*
把你这篇文章搬到我那里去了,呵呵,谢谢。允许吗?
#noiile 发表于2004-11-04 16:52:00  IP: 218.20.251.*
当然可以。呵呵。如果你也是关注该领域的,可以常交流。
#RedMaple 发表于2005-02-05 15:06:00  IP: 222.136.63.*
有研究安全中间件穿越NAT的么?
另:
防火墙一般会对内部往外的连接放行,如果不呢,或者只允许相应的某些连接,如http报文可以通过,其他不行呢?

另外,我想请问一下实际的情况:防火墙是否常用于保护端设备或者类似的概念

#RedMaple 发表于2005-02-05 15:33:00  IP: 222.136.63.*
另外在实际部署时由于ALG的存在,使得这种方案只能是某种程度上的透明,即还要设定PROXY,对于内网用户来说。

还有几个问题:
1 在实际中我们考虑多级NAT么?
2 在例子中,Ada知道bob的公网连接地址,这一点如何知道?
#RedMaple 发表于2005-02-05 15:41:00  IP: 222.136.63.*
我的地址:
myfri2001@126.com,多多交流
http://blog.csdn.net/hr_wyk/
#noiile 发表于2005-02-06 21:44:00  IP: 59.32.253.*
这篇文章是针对SIP应用的,因此有几个前提条件:
1.支持SIP应用,意味着你的gateway/firewall开放5060端口给SIP消息
2.SIP User agent必须要知道Proxy Server的地址,也就是本文说的ALG.
#kidtty 发表于2007-04-23 23:30:10  IP: 221.215.176.*
非常感谢你的讲解,请问Far-end NAT和Near-end NAT有什么区别?谢谢
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © noiile