PJNATH 关于NAT穿越的简介
NAT和NAT穿越简介
NAT(网络地址转换)是一种机制,其中设备对数据包的TCP/IP地址/端口号进行修改,并将IP地址从一个领域映射到另一个领域(通常从私有IP地址映射到公共IP地址,反之亦然)。这是通过NAT设备在将出站数据包从内部主机转发到互联网时在NAT的公共侧分配临时端口号来实现的,在某个预定义的时间内保持该映射,并将在该公共端口上从互联网接收的入站数据包转发回内部主机。
安装NAT设备主要是为了通过允许多个主机共享公共/互联网地址来缓解IPv4地址空间的耗尽。同样由于其映射性质(即映射只能通过来自内部主机的传输来创建),即使IPv4地址耗尽不是问题(例如,当家里只有一个主机时),也优选安装NAT设备,以为内部主机提供某种安全/屏蔽,使其免受来自互联网的威胁。
尽管NAT为内部网络提供了一些屏蔽,但必须区分NAT解决方案和防火墙解决方案。NAT不是防火墙解决方案。防火墙是一种旨在实施组织安全策略的安全解决方案,而NAT是一种允许多个主机使用单个公共IP地址的连接解决方案。可以理解的是,这两种功能有时很难分离,因为许多(通常是消费类)产品声称使用同一设备同时实现这两个功能,并简单地将设备标记为NAT框。但我们确实想明确这一区别,因为PJNATH是一个NAT穿越助手,而不是防火墙绕过解决方案。
NAT穿越问题
虽然NAT适用于典型的客户端-服务器通信(如网络和电子邮件),但由于总是由客户端发起会话,通常客户端不需要长时间保持连接,因此安装NAT会给对等通信(如VoIP)带来重大问题。下面将更详细地解释这些问题。
对等地址问题
在VoIP中,通常我们希望媒体(音频和视频)直接在客户端之间流动,因为中继成本很高(既有服务提供商的带宽成本,也有中继带来的额外延迟)。为了做到这一点,每个客户端通过VoIP信令路径将其媒体传输地址发送给另一个客户端,并且另一方将其媒体发送到该传输地址。
问题就在这里。如果客户端软件不知道NAT,那么它将把它的私有IP地址发送到另一个客户端,而另一个客户将无法将媒体发送到该地址。
传统上,这是通过使用STUN来解决的。利用这种机制,客户端首先通过查询STUN服务器来找出其公共IP地址/端口,然后将该公共地址而不是其私有地址发送给另一个客户端。当双方都使用这种机制时,他们可以向这些地址发送媒体包,从而在NAT中创建映射(也称为打开“洞”,因此这种机制也被普遍称为“打孔”),然后双方可以相互通信。
但这一机制并不是在所有情况下都有效,下文将对此进行解释。
“发夹”行为
发夹是一种行为,当NAT设备检测到数据包的(公共IP地址)目的地实际上是为内部主机(主机B)创建的映射IP地址时,它会将数据包从内部网络中的主机(让我们称之为主机a)转发回同一内部网络中的其他主机(主机B)。这是NAT的理想行为,但不幸的是,并非所有NAT设备都支持这一点。
如果没有这种行为,同一NAT后面的两个(内部)主机将无法相互通信,如果它们相互交换它们的公共地址(由上面的STUN解析)。
对称行为
NAT设备的行为并不一致,人们一直试图将它们的行为分为不同的类别。根据RFC 3489,传统上NAT设备分为全锥型、受限锥型、端口受限锥型和对称型http://www.ietf.org/rfc/rfc3489.txt第5节。一种更新的分类方法,如RFC 4787所解释的http://www.ietf.org/rfc/rfc4787.txt,将NAT行为类型分为两个属性:映射行为属性和过滤行为属性。每个属性可以是三种类型之一:端点无关、地址相关或地址和端口相关。通过这种新的分类方法,对称NAT实际上是一种地址和端口相关的映射NAT。
在这些类型中,对称类型是最难处理的类型。问题是因为NAT为到STUN服务器的通信和到其他(外部)主机的通信分配了不同的映射(同一内部主机的),所以由一个主机通知给另一个主机的IP地址/端口对接收方来说没有意义,因为这不是NAT设备创建的实际IP地址/端口映射。结果是,当接收方主机试图将数据包发送到此地址时,NAT设备会丢弃数据包,因为它不将数据包的发送方识别为发送到此地址的“授权”主机。
对此有两种解决方案。首先,我们可以通过将媒体传输切换到媒体包的源地址来使客户端更智能。这将起作用,因为通常客户端使用一种众所周知的被称为对称RTP的技术,即它们使用一个套接字来发送和接收RTP/媒体包。我们还在PJMEDIA媒体传输中使用此机制。但这种解决方案只有在对称NAT后面的客户端没有与对称NAT或端口受限NAT后面的其他客户端通信时才有效。
第二种解决方案是使用媒体中继,但如上所述,无论是在服务提供商的带宽成本还是中继引入的额外延迟方面,中继都是昂贵的。
绑定超时
当NAT设备创建绑定(公私IP地址映射)时,它会关联一个计时器。计时器用于在与之关联的绑定没有活动/流量时将其销毁。正因为如此,希望保持绑定打开的NAT感知应用程序必须定期发送出站数据包,这是一种称为保持活动的机制,否则它将最终失去绑定,无法接收来自互联网的传入数据包。
NAT穿越解决方案
旧STUN(RFC 3489)
由RFC 3489定义的原始STUN(通过网络地址转换器(NAT)的用户数据报协议(UDP)的简单遍历)http://www.ietf.org/rfc/rfc3489.txt(2003年出版,但这项工作早在2001年就开始了)旨在为上述NAT连接问题提供一个独立的、基于标准的解决方案。它配备了NAT类型检测算法和方法来对NAT进行打孔,以使流量通过,并已被证明在穿越多种类型的NAT时非常成功,因此它作为一种简单有效的NAT穿越解决方案而广受欢迎。
但从那时起,IETF的聪明人就意识到,仅靠STUN是不够的。除了STUN解决方案无法解决对称到对称或端口受限连接的性质外,人们还发现NAT行为可能会随着不同流量(或同一流量超时)而变化,因此得出结论,NAT类型检测可能会产生不可靠的结果,因此不应过多依赖它。
正因为如此,STUN将其努力转向了不同的战略。它现在不再试图提供独立的解决方案,而是提供一个部分解决方案和框架,以在此基础上构建其他(基于STUN的)协议,如TURN和ICE。
STUN/STUNbis(RFC 5389)
NAT会话遍历实用程序(STUN)是旧STUN的进一步发展。虽然它仍然为客户端提供了一种向STUN服务器查询其公共/映射地址的机制,但它已经反对使用NAT类型检测,现在它充当了在其之上构建其他协议(如TURN和ICE)的框架。
旧TURN
早在2001年11月就开始了基于标准的穿越使用中继NAT(TURN),这是(旧的)STUN完成解决方案的补充方法。最初的想法是主机使用STUN来检测NAT类型,当发现NAT类型是对称的时,它将使用TURN来中继流量。但如上所述,这种方法被认为是不可靠的,现在使用TURN的首选方式(也是一种新的TURN规范)是将其与ICE相结合。
TURN
Traversal Using Relays around NAT(TURN)是TURN的最新发展。虽然协议细节发生了很大变化,但目标仍然相同,即为应用程序提供中继控制。如上所述,优选地,TURN应该与ICE一起使用,因为中继在带宽和延迟方面都是昂贵的,因此它应该被用作最后的手段。
B2BUA方法
SIP背对背用户代理(B2BUA)是一个位于SIP流量中间的SIP实体,在两个呼叫段上充当SIP用户代理。拥有B2BUA的主要原因是能够提供呼叫(例如计费、执行策略)并帮助客户端穿越NAT。通常情况下,B2BUA会配备媒体中继,否则就不会很有用了。
属于这一类别的产品包括SIP会话边界控制器(SBC),而Asterisk等PBX在技术上也是B2BUA。
B2BUA在帮助NAT穿越方面的好处是,它不需要对客户端进行任何修改即可使其通过NAT。由于它基本上是一个中继,所以它应该能够成功地穿越对称NAT。
然而,由于它是一个中继,通常的中继缺点适用,即带宽和延迟问题。更重要的是,由于B2BUA在任一呼叫支路中充当用户代理(即,它在一个支路上终止SIP信令/呼叫,尽管它在另一支路上创建另一个呼叫),因此它也可能引入端到端SIP信令的一些问题。
ALG方法
现在,许多NAT设备(如消费者ADSL路由器)都配备了智能设备来检查和“修复”VoIP流量,以帮助其穿越NAT。此功能称为应用层网关(ALG)智能。这个想法是,既然NAT设备知道映射,它还不如尝试修复应用程序流量,这样流量就可以更好地穿越NAT。例如,执行的一些技巧包括用发送数据包的主机的映射公共地址/端口替换SIP/SDP数据包中的私有IP地址/端口。
尽管许多人声称它很有用,但事实上,这给我们带来的问题比解决问题更多。太多这样的设备破坏了SIP信令,在更高级的情况下,破坏了ICE协商。我们过去遇到的一些糟糕情况的例子:
- NAT设备更改了SIP响应消息中的Via地址/端口字段,使响应无法通过SIP RFC定义的SIP响应验证。
- 在其他情况下,SIP响应的Via标头中的修改对SIP服务器隐藏了重要信息,即SIP服务器看到的客户端的实际IP地址/端口。
- REGISTER请求/响应的联系人URI中的修改使客户端无法检测到其注册的绑定。
- SDP中IP地址/端口的修改会导致ICE协商失败,且ICE状态不匹配。
- ALG处理本身的复杂性似乎导致设备在管理地址绑定时表现错误(例如,它为客户端发送的第二个数据包创建了新的绑定,即使前一个数据包是几秒钟前发送的,或者它只是将入站数据包发送到错误的主机)。
我们花了很多人月的时间来解决这些ALG(错误)功能引起的问题,因为它增加了问题的复杂性,而不是解决问题,所以一般来说,我们根本不喜欢这种方法,更希望它消失。
通用即插即用
**通用即插即用(UPnP)**是一组控制网络设备的协议规范,其规范之一是控制NAT设备。使用该协议,客户端可以指示NAT设备在NAT的公共端打开一个端口,并使用该端口进行通信。UPnP由于其简单性而广受欢迎,人们可以预期它将在大多数NAT设备上可用。
UPnP的缺点是,由于它在通信中使用多播,它将只允许客户端控制同一多播域中的一个NAT设备。虽然这在家庭安装中通常不是问题(人们通常只有一个NAT路由器),但如果客户端在级联路由器安装之后,它将不起作用。更多的uPnP由于缺乏身份验证而存在严重的安全问题,它可能不是组织首选的解决方案。
自2.13版本起,PJNATH支持uPnP。
其他解决方案
NAT穿越的其他解决方案包括:SOCKS,自SOCKS5以来支持UDP协议。
ICE解决方案-更难工作的协议
IETF正在对一种新的协议进行标准化(在撰写本文时,该协议处于工作组最后一次呼叫/WGLC阶段),称为交互式连接建立(ICE)。ICE是客户端NAT穿越解决方案库中的终极武器,因为它承诺,如果两个客户端确实有一条通信路径,那么ICE就会找到这条路径。如果客户端可以通信的路径不止一条,ICE将使用最好/最有效的路径。
ICE的工作原理是将几种协议(如STUN和TURN)组合在一起,并为通信提供几种候选路径,从而最大限度地提高成功的机会,但同时也有能力对候选进行优先排序,因此更昂贵的替代方案(即中继)只会在其他方案失败时作为最后手段。ICE谈判过程包括几个阶段:
- 候选收集,客户端找出所有可能用于通信的地址。它可以找到三种类型的候选者:表示其物理NIC的主机候选者、从STUN解析的地址的服务器反射候选者和客户端从TURN中继器分配的地址的中继器候选者。
- 优先考虑这些候选人。通常,中继候选者的优先级最低,因为它是最昂贵的。
- 对这些候选者进行编码,将其发送到远程对等方,并与offer-answer进行协商。
- 对候选者进行配对,其中它将每个本地候选者与从远程对等端接收的每个远程候选者进行配对。
- 检查每个候选对的连接性。
- 得出结论。由于检查了所有可能的路径组合,如果有通信路径,ICE会找到它。
ICE有很多好处:
- 它是基于标准的。
- 它在STUN工作的地方工作(以及更多)
- 与独立的STUN解决方案不同,它解决了棘手的问题,因为它还提供了候选主机。
- 与中继解决方案一样,它也适用于对称NAT。但与普通中继不同的是,中继只是最后的手段,从而最大限度地减少了中继的带宽和延迟问题。
- 它为提供和检查候选地址提供了一个通用框架。虽然ICE核心标准只谈到使用STUN和TURN,但实现者可以在ICE中添加更多类型的候选者,例如TCP或HTTP中继上的UDP,甚至uPnP候选者,这可以对远程对等体透明地进行,因此即使远程对等体不支持这些,它也是兼容和可用的。
- 它还增加了一些安全性,特别是针对DoS攻击,因为在使用媒体地址之前必须确认媒体地址。
话虽如此,ICE是一个需要实现的复杂协议,这使得互操作性成为一个问题,在撰写本文时,我们还没有看到它的许多实现。幸运的是,PJNATH是第一个因此更成熟的ICE实现之一,于2007年年中首次发布,我们一直在定期的SIP互操作性测试(SIPit)活动中测试我们的实现,所以希望我们也是最稳定的之一。
PJNATH-有效NAT穿越解决方案的构建块
PJSIP NAT Helper(PJNATH)是一个库,包含基于标准的NAT穿越解决方案的实现。PJNATH可以用作软件的独立库,也可以使用PJSUA-LIB库,这是一个非常高级的库,将PJSIP、PJMEDIA和PJNATH集成到易于使用的API中。
PJNATH具有以下特点:
- STUN框架和实现,提供了现成的STUN感知套接字和框架来实现更高级别的基于STUN的协议,如TURN和ICE。
- NAT类型检测,用于故障排除。
- TURN实施(包括TCP)
- ICE实施(包括Trickle ICE)
- uPnP实施
参考
https://docs.pjsip.org/en/latest/api/pjnath/intro.html#
http://www.52im.net/thread-50-1-1.html