本文转自
http://www.cnblogs.com/ishang/p/3810382.html
http://www.cnblogs.com/ishangs/p/3816689.html
作者: 大雪先生


术语/缩略语表:

  • NAT(Network Address Translation)协议, 维基百科 http://en.wikipedia.org/wiki/Network_address_translation
  • STUN(Session Traversal Utilities for NAT)协议, http://tools.ietf.org/html/rfc5389
  • TURN(Traversal Using Relay NAT)协议, http://tools.ietf.org/html/rfc5766
  • SIP(Session Initiation Protocol), http://tools.ietf.org/html/rfc3261
  • SDP(Session Description Protocol), http://tools.ietf.org/html/rfc4566
  • ICE(Interactive Connectivity Establishment), https://tools.ietf.org/html/rfc5245
    ICE4J: https://github.com/jitsi/ice4j

四种NAT组网方式:

  1. Full-cone NAT
  2. Address-restricted-cone NAT
  3. Port-restricted cone NAT
  4. Symmetric NAT

以下为正文


1. 说明

本文详细描述了基于STUN系列协议实现的P2P SIP电话过程,其中涉及到了SIP信令的交互,P2P的原理,以及STUN、TURN、ICE的协议交互

本文所提到的各个服务单元的交互均使用UDP,不涉及TCP的打洞及其他和TCP相关的操作。

本文假设通信双方均没有防火墙对协议以及端口的限制。

本文不涉及客户端的资源的发布与查找。

本文适用于有一定基础的读者,比如说知道NAT设备的不同类型及其特点、知道 STUN / TURN / ICE 协议的基本概念、知道SIP协议的相关交互流程等。

本文力求严谨,但难免有疏漏之处,敬请谅解,欢迎批评指正。

本文大致可分为4个部分:

  • 第一部分,解释了穿越和打洞的概念以及STUN系列协议穿越的特点
  • 第二部分,STUN、TURN协议的工作原理及其作用,详细介绍了relay端口的分配、消息的接受与发送、STUN头的添加与去除
  • 第三部分,ICE协议的工作原理及其作用,详细介绍了ICE的打洞原理、两种打洞方式(regular nomination和aggressive nomination)、Peer Reflexive Candidates 的概念与发现过程
  • 第四部分,ICE在P2P SIP中的应用,详细讲解了SIP的信令交互流程与媒体建立流程。

2. 打洞和穿越的概念

有人将穿越打洞认为是一个概念,其实这也无伤大雅,在与其他人交流讨论的时候不产生歧义就好。严格来说,是先打洞,后穿越。

由于NAT的特性(请查阅NAT的几种不同类型的各自特点),一个位于外界的主机是不可能向内网主机直接建立连接的。要想实现外界主机与内网主机的交互,那么 “我(内部主机)在我自己的NAT设备上先打一个洞,然后使得你(外界主机)的数据能经过这个洞穿越过来”。

当我们打开电脑,连上网络,打开几个不同网站的时候,打洞和穿越时时刻刻都在发生着。你打开http://www.baidu.com的时候,你就在自己的NAT上打了一个洞,这个洞只允许baidu.com的80端口的数据穿越回来。如果没有你先打的洞,baidu.com是不可能成功给你发消息的。

(时刻记住一个概念,打洞是为了能让对方的数据过来。)

3. P2P中的打洞和穿越

既然打洞和穿越实时都在发生着,那么在client/server模型的网络编程中为什么很少提及打洞和穿越的概念,却在P2P通信中反复提及呢?

首先,在cs模型的网络编程中,服务器都架设在公网,服务器端不用打洞(服务端不用为客户端打洞,客户端的数据也能过来),客户端就能向服务器发送请求。

其次,client向服务器发送请求时,client的打洞和服务器响应的穿越是自动实现的。

最后,明确一点的是,C-S模型中,打洞是单方向的,即只需客户端打洞。

而在P2P网络编程中,通信的双方A和B既要当服务器,又要当客户端。因此打洞是双方的:A在自己的NAT上为B打一个洞,让B的数据能过来;B在自己的NAT上为A打一个洞,让A的数据能过来;

AB双方的打洞的操作得由我们自己完成,所以不得不提及穿越打洞的概念。

理解了“P2P通信中,打洞是双方的”这一点,也就理解了ICE的一半。

4. 使用STUN系列协议穿越的特点

在知道NAT的几种类型和每种类型的限制后,就是针对性的解决这些问题实现NAT的穿越。

最容易想到的就是,能不能在NAT上做一下手脚,让它能识别出我特有的协议,从而不限制我特有的协议,这就是ALG的初衷。ALG(应用层网关),有两个功能,一个是修改自己“认识的”协议中相关字段的内网地址为外网地址;另一个是,允许自己“认识的”协议直接穿透,而不需要打洞;

可以认为ALG的能力是NAT的一个插件,插上什么协议类型的插件,NAT就能辨别什么类型的协议,继而对相应类型的协议做相关操作。常用的应用有FTP、DNS、ICMP、SIP等。在VOIP中,如果使用ALG的话,可以实现通信双方的直接媒体通信,但是不足之处就是需要NAT支持SIP,这就不适合像skype类型的应用。

还有一种成熟的穿越技术:UPnP,它的想法跟ALG有点类似,也是在NAT上做了手脚。当内网的主机启动UPnP程序的时候,就会在NAT上产生 “映射端口”与UPnP程序的端口一一映射,而且不会被回收。从外部来的消息,只要是发送到“映射端口”的,直接就会送至内网的UPnP程序。像我们平常用到的迅雷、电骡等,这种方式也不用打洞,但缺点就是需要应用程序、操作系统以及NAT支持UPnP,同样不适用于skype类型的应用。

使用STUN/TURN/ICE最大的好处充分利用NAT的特性,不需要操作系统支持、不需要对现有的NAT设备做改变就能实现穿越。

最后需要说明的一点就是,没有不好的技术,只有不适合的技术。

5. STUN/ TURN/ICE协议的关系

  • 简单来说,STUN的目的是为了进行P2P通信,通过提供反射地址(Server Reflexive Address)这种能力来使双方可以进行P2P通信,但是依赖NAT类型的不同,这种方式是有失败的概率的:比如双方都为对称型NAT或者一方为对称型,另一方为端口限制型。

    因为有失败的可能性,所以单纯的依赖STUN协议提供的反射地址的话,需要事先探测出双方的NAT类型,假如发现是对称型的NAT,那么就不打洞了,而是直接中转。目前网络类型纷繁复杂,STUN协议在5389的时候去掉了NAT类型的判断的能力,因为越来越多的实践发现,在多层NAT下,类型的探测不总是有效的。而使用ICE的时候,不需要事先探测NAT类型。

    STUN还有一个作用是为ICE提供支持(对Binding的扩展)。

  • TURN协议的目的是为了保证通信双方百分之百能进行通信,就是在只知道反射地址而打洞失败的情况下的一种补充方案-----使用中继,使用中继方式百分之百能使得双方进行通信,只不过已经不是P2P的了,而且伴随而来的是转发效率的问题。不过这不要紧,因为该协议的目的就是保证双方肯定能通信,损失效率来保证了连性。

  • ICE协议的目的就是综合以上两种方案,通过通信双方互相发探测包,找出一种最合理,最廉价的可行路径。ICE首先探测内网地址,再探测STUN提供的反射地址,最后探测TURN协议的中继地址,反正最终目的就是探出一条路,内网地址不行用反射地址,反射地址不行,最后不得已情况下那就用中继地址。

一般来说,目前的TURN服务器通常也实现了STUN协议,所以可以称之为TURN服务器或者是STUN 服务器。

如果说一个服务器是STUN服务器,那么该服务器可能是纯的STUN(RFC 5389)服务器,也可能是一个TURN(RFC 5766)服务器,也可能是两者都实现了的服务器。本文以下图中所说的STUN服务器,均为实现了STUN和TURN的服务器。

未完。。。。待续。。。。

第二部分:STUN/TURN/ICE协议在P2P SIP中的应用(二)

本文为原创,转载请注明以下内容:
  名称:STUN/TURN/ICE协议在P2P SIP中的应用(一)
  作者:大雪先生
  链接:http://www.cnblogs.com/ishang/p/3810382.html

6. STUN协议(RFC 5389)

6.1 为什么会用到STUN协议

首先要明确的概念是:STUN协议没有穿越的能力,它只是为穿越提供反射地址(Server Reflexive Address)。在双方进行通讯的时候,我们双方的目的地址可以分别为对方的反射地址,但是反射地址不能穿越成功的时候(NAT类型为对称类型的时候),必须使用TURN。

本文所说的STUN协议指的是RFC-5389 ,RFC-5389已经移除了NAT类型探测的能力(RFC-3489定义了NAT类型探测的能力),STUN协议主要有2个功能

  • 功能1: 让一个位于NAT后的客户端得到自己的公网地址(反射地址,Server Reflexive Address),该功能通过向服务端发送一个 Binding请求,服务端返回一个success response消息来完成。success response消息中包含一个叫做XOR-MAPPED-ADDRESS的属性,该属性的值就是“反射地址”经过异或后的值

  • 功能2: 在ICE(Interactive Connectivity Establishment交互式连接建立)时,STUN协议被用于探测双方的连通性。该功能也是通过向对方客户端发送Binding消息,对方响应该请求实现。需要说明一点的是,在ICE交互时的Binding消息与功能1中所说的Binding消息不一样。ICE添加了几个新的属性,从而扩展了Binding消息:PRIORITY, USE-CANDIDATE, ICE-CONTROLLED, ICE-CONTROLLING。这种扩展了的Binding消息,只会用在ICE的探测中。

6.2 STUN协议的工作原理

A. 客户端用于得到自己的外网地址(反射地址,Server Reflexive Address),如下图所示:

a) 客户端A向STUN Port发送Binding请求(图中绿色部分)

b) STUN服务器接收到客户端A的Binding请求,它能得到该请求的源地址与端口(该地址和端口就是经过NAT映射过的),将该地址和端口记为Server Reflexive Address。

c) STUN服务器发送response响应,在response响应中携将Server Reflexive Address经过异或后填入XOR-MAPPED-ADDRESS属性。

d) 客户端A接受到STUN服务器的response后,就知道了自己的外网地址(反射地址,Server Reflexive Address)。

B. 在ICE(交互式连接建立)是,用于双方的连通性探测。

在ICE打洞探测的时候再详细介绍

7 TURN协议

7.1 为什么会用到TURN协议

前面也提到过,TURN协议是STUN 协议的有效补充,在使用反射地址(Server Reflexive Address)穿越方式失败的时候才会用到TURN。

简单的说就是,TURN协议使用中转的方式实现位于两个不同NAT后的客户端通信。TURN协议为每个连接到该服务器的客户端都分配一个公网地址(Relayed Address),该Relayed地址专门为该客户端中转消息。

该方法是实现位于两个不同NAT后的客户端通信的一个方式(其他方式还有p2p)。

该方法的优点是:不管NAT是什么类型(NAT类型分为:全锥形、地址限制锥形、端口限制锥形、对称型),都可以通过这种方式实现两个客户端的通信。

TURN中继转发的弊端有两个:

  1. 如果通信两端传输的数据量过大(比如客户端之间传输的是音视频),那么每个数据包都要经过TURN服务器的转发,那么会造成数据的丢失以及传送时延的增加;
  2. 成本问题,如果每两个客户端之间的通信都要经过TURN转发,那么在客户端到达一定规模后(十万上百万),需要架设大量的TURN服务器。这在成本上是无法承受的。所以才有了使用P2P方式。需要说明的有一点,双方可以进行点对点的直接通信,不是因为它们之间采用点对点通信后丢包和时延的问题就能解决(P2P方式同样也可能存在比较大的丢包),而是成本问题。

所以这种使用TURN协议中转的方式只会用在双方通信交互内容数据量较少的情况下。

7.2 TURN协议的工作原理

本节描述了TURN协议的大体工作原理,与RFC 5766有一定的出入,了解了此工作原理再去看RFC 5766 会事半功倍。本节介绍不涉及到RFC 5766中提到的,CreatePermission、ChannelBind操作。

7.2.1 Allocate请求

客户端通过发送Allocate请求给STUN服务器,从而让STUN服务器为A用户开启一个relay端口。

a) 客户端A向STUN Port发送Allocate请求(图中绿色部分)

b) STUN服务器接收到客户端A的Allocate请求,服务器一看是Allocate请求,则根据relay端口分配策略为A分配一个端口。

c) 服务器发送response成功响应。在该response中包含XOR-RELAYED-ADDRESS属性。该属性值就是A的relay端口的异或结果。

d) 客户端接收到response后,就知道了自己的relay地址。该relay地址是个公网地址,可以看作是客户端A在公网上的一个代理,任何想要联系A的客户端,只要将数据发送到A的relay地址就可以了,具体的转发原理请看下一小节。

7.2.2 Relay端口消息的转发

任何想要联系客户端A的人,只要知道客户端A的relay地址就可以了。

7.2.2.1 A的Relay端口接受其他客户端的消息

如上图所示:因为客户端A位于NAT后,所以其他客户端无法和A建立直接的通信。但是客户端A在STUN服务器上申请了一个端口(上图中:A的relay端口),其他客户端想要和A通信,那么只需要将信息发送到“A的relay端口”,STUN服务器会将从relay端口接收到的信息通过STUN Port发送给A。

7.2.2.2 A的响应消息原路返回

A应答其他客户端发来的消息的时候,是通过原路返回的。

7.2.2.3 思考

问题1: STUN服务器为什么不直接从A的relay端口把数据转发给A呢(如下图所示)?而非要从STUN端口发送?

问题1

问题2: 客户端A的响应消息在原路返回的时候,A的响应消息是先发送到了STUN Port,然后再经由A的relay Port发出的。那么A的relay Port是怎么知道它要把数据发送到哪呢?

   答案请看7.2.4 和 7.2.5

7.2.3 Refresh请求

STUN服务器给客户端A分配的relay地址都具有一定的有效时长,可能是30秒或者1分钟或者几十分钟。客户端如果需要STUN服务器一直为它开启这个端口,就需要定时的向STUN服务器发送请求,该请求用刷新relay端口的剩余时间。

在标准的TURN(RFC 5766)协议中,客户端A向STUN服务器发送Allocate请求,STUN服务器在响应消息中添加了一个“LifeTime”的属性,该属性表示relay的存活时间。 客户端需要在relay的存活时间内周期性的调用REFRESH请求,服务端接收到REFRESH请求后,刷新剩余时间;当REFRESH请求中的lifetime属性为0时,说明是客户端主动要求关闭relay地址。

7.2.4 STUN端口的保活

由于与STUN服务器通信使用的是UDP,所以为了保持一个长连接,需要客户端周期性的向STUN服务器的STUN Port发送心跳包。

周期性心跳包的目的就是,使得NAT设备对客户端A的反射地址(Server Reflexive Address)一直有效。使得从STUN Port发送的数据能通过A的反射地址到达A。此处不理解的可以查阅“NAT 类型的分类以及NAT的作用”。

此处解释了,7.2.2.3中的第一个问题,因为客户端A没有和relay Port保活,又由于NAT的特性,数据直接通过relay port转发给A时,NAT直接就丢弃了,所以A是收不到的。所以数据必须经过STUN服务器的STUN Port发送。

7.2.5 Relay转发的时候添加STUN头(Send和Data请求)

将7.2.2.1、 7.2.2.2合并到一起就是:

如上图所示是B主动给A发消息:“Hello”,A回应“Hi”的过程。

  • 序号1、2、3、4、5为B的发送请求(蓝色箭头方向);

  • 序号6、7、8、9、10为A的回应,原路返回(绿色箭头方向)。

注意:在“Hello”发送的过程中,1、2阶段时,发送的数据为裸的UDP数据。在4、5过程中,是被STUN协议包装过的“Hello”,称之为Data indication。

同样在“Hi”发送的过程中,6、7阶段为被STUN协议包装过的“Hi”,称之为Send indication,9、10是裸的UDP数据。

在4、5阶段,由于数据是从STUN Port转发下来的,为了能够让客户端A知道这个包是哪个客户端发来的,所以,STUN 协议对“Hello”进行了重新的包装,最主要的就是添加了一个XOR-PEER-ADDRESS属性,由裸数据包装成STUN协议的过程,我们称之为添加了STUN头。XOR-PEER-ADDRESS的内容就是客户端B的反射地址(Server Reflexive Address)。

在6、7阶段,A的响应原路返回,为了能够让A的relay port知道最终发往哪个客户端,因此也为“Hi”添加了STUN头,也是添加了XOR-PEER-ADDRESS属性,内容就是客户端B的反射地址(Server Reflexive Address)。这样A的relay port就知道“Hi”的目的地址。

第3阶段是:从A的relay端口收到数据,添加STUN头后,最后从STUN Port 发出的过程。

第8阶段是:从STUN Port 接收到带STUN 头的数据,去掉STUN头,最后从A的relay端口发出的过程。

此处解释了7.2.2.3 的第二个问题。

客户端B主动发送信息给A的交互流程如上图所示,那么客户端A主动发送信息给客户端B的交互流程是怎样的呢,你能画出来吗?

要知道客户端A主动发消息给客户端B,应该将消息发往客户端B的relay port哦。。

7.2.6 使用TURN协议的必要性

要想实现消息的中转,必须使用TURN协议吗?答案当然是否定的。

TURN协议只是一种公认的,标准的协议。我们当然可以实现自己的协议,但是已经有人对标准的TURN协议进行了实现(比如pjproject,它实现了STUN、TURN、ICE、SIP),我们为什么不拿来就用呢?

在拿来就用的过程中,肯定会对已经实现的标准做一定的改动。但这关系不大,实现我们所关注的功能即可。

本文为原创,转载请注明以下内容:

名称:STUN/TURN/ICE协议在P2P SIP中的应用(二)

作者:大雪先生

链接:http://www.cnblogs.com/ishangs/p/3816689.html

转:NAT traversal 的概念相关推荐

  1. IPFS: NAT traversal(NAT穿越)

    IPFS是一个p2p网络,那么一定绕不开的一个问题就是NAT穿越.之前的文章里面也提到过IPFS网络连通性使用的ICE NAT穿越框架,本文简单介绍一下什么是NAT. 为什么有NAT技术? NAT主要 ...

  2. 关于 IMPP/XMPP/SIMPLE 这几种即时通讯协议和NAT traversal

    IM(Instant Messaging)正在被广泛地采用,特别是在公司与它们的客户互动联接方案上.为了解决即时通讯的标准问题,IETF成立了专门的工作小组,研究和开发与IM相关的协议. 目前IM有四 ...

  3. NAT和路由器 基本概念

    NAT(Network Address Translation, 网络地址转换)是1994年提出的.当在专用网内部的一些主机本来已经分配到了本地IP地址(即 仅在本专用网内使用的专用地址),但现在又想 ...

  4. NAT概念解释(不完全版,但不会搞错...)

    NAT 在计算器网络中,网络地址转换(Network Address Translation,缩写为NAT),也叫做网络掩蔽或者IP掩蔽(IP masquerading) 是一种IP数据包在通过路由器 ...

  5. nat端口限制_Cisco ASA 防火墙 NAT - 基本概念

    Cisco 的 NAT 从来都是谜之难用,无论是 IOS 还是 ASA.在这里专门集中整理了一下 ASA NAT 的一些概念和基础配置案例,仅限于基础部分,实在是没有精力去深究.( ASA versi ...

  6. NAT会话穿越应用程序(STUN)(RFC-5389)

    RFC文档链接 摘要 NAT会话穿越应用程序 (STUN) 是一种协议,在处理网络地址转换(Network Address Translator, NAT)穿越时充当其他协议的工具.终端可以使用它来确 ...

  7. 穿越NAT的p2p通信方法研究

    穿越NAT的p2p通信方法研究 日期:2008-12-08 来源:P2P网  作者:未知 字体:大 中 小 <script src="http://www.ppcn.net/ads/b ...

  8. TCP穿透主流商用NAT产品的主要技术研究

    [摘要]近些年,标准化社区已经开发出一些UDP穿透NAT/防火墙的技术(也就是,在NAT之后的主机之间建立UDP流).然而,由于TCP连接建立的不对称特点,TCP的NAT穿透要困难的多.最近,研究者们 ...

  9. NAT技术详解(网络地址转换)

    组织对不起,90年的事我瞒不住了--NAT(网络地址转换) NAT(Network Addresss Translation),网络地址转换,本质上是一种允许在互联网的不同地方重复使用相同的IP地址集 ...

最新文章

  1. 软件测试培训教程:pytest与unittest区别
  2. Windows+Python 3.6环境下安装PyQt4
  3. Nexus配置内部仓库
  4. ActionScript3学习笔记2-包
  5. 经典Android开发教程!这些新技术你们都知道吗?年薪超过80万!
  6. java基础篇——包
  7. 让input支持 ctrl v上传粘贴图片? 让input支持QQ截图或剪切板中的图像数据(Java实现保存)...
  8. 提交App中断出现 Cannot proceed with delivery an existing transporter instan
  9. java处理获取到的Elasticsearch数据
  10. Delphi 10.4.2 (RAD Studio 10.4.2 )安装教程图解
  11. java课堂点名和提问程序_Java程序设计作业.md
  12. [Linux] IOmeter 安装
  13. chrome突然无法复制粘贴了
  14. 自动窗宽窗位的一些思路
  15. passcode - pwnable
  16. 以美颜sdk为例,详解sdk接入流程
  17. Linux基础命令,个人笔记备份
  18. scrapy爬取斗图表情
  19. vue2.0,vue3.0 v-model数据双向绑定
  20. 【图像识别】基于matlab实现步态周期检测与步态角度特征

热门文章

  1. 计算机一级信息技术基础知识,计算机一级考试之信息技术基础.doc
  2. enter对应的keycode_vue 添加enter回车事件
  3. Linux:ubuntu 下安装软件,卸载,查看已经安装的软件
  4. cmake cache变量_反复研究好几遍,我才发现关于 CMake 变量还可以这样理解!
  5. 洛谷——P2006 赵神牛的游戏
  6. 快速生成HTML结构语法(HTML、CSS)
  7. 什么是联表查询?(深度刨析,建议收藏)
  8. 移动端h5 隐藏滑动滚动条
  9. 硬核干货!揭秘波士顿动力背后的专利技术
  10. 第十三章 线程安全与锁优化