穿越NAT的意义: NAT是为了节省IP地址而设计的,但它隐藏了内网机器的地址,“意外”起到了安全的做用。对外不可见,不透明的内部网络也与互联网的“公平”应用,“相互共享”的思想所不容,尤为是P2P网络中“相互服务”的宗旨,因此穿越NAT,让众多内部网络的机器也参与到P2P网络中的大集体中来,一直是P2P开发者的所但愿的。穿越NAT须要借助外部的支持,说白了就是“内外勾结”,骗过NAT。不少P2P网络成功地实现了这一目标,但仍是有一些“遗憾”---并不是全部的状况下均可以。因为客户端是主动登陆P2P网络才可穿越,因此P2P的方式也没有违背企业的内部管理原则,毕竟“自由世界”的加入都是自觉自愿的。 NAT原理: NAT(Network Address Translation)网络地址转换/网络地址翻译。 工做原理:NAT主要的经过对数据包头的地址替换来完成内网计算机访问外网服务的。当内部机器要访问外部网络时,NAT设备把内部的IP1与端口号1(网络层地址与传输层地址),转换成NAT的外部IP2与新的端口号2,再送给外部网络,数据返回时,再把目的为IP2:端口2的数据包替换为IP1:端口1,送给内网机器。若通信协议的内容中有IP地址的传递,如FTP协议,NAT在翻译时还要注意数据包内涉及协议地址交互的地方也要替换,不然协议就会出现地址混乱。在NAT设备中维护了这个要替换地址的映射表,并根据内部计算机的通信需求维护该表。外部网络来数据包可否进入NAT,主要是看是否已经有可映射的表项,若没有就会丢弃。 NAT的外部公网地址能够是一个IP,也能够是一个网段,造成地址池。NAT还能够把某个外网地址直接影射给内网的某个服务器,让外网的用户能够直接访问到这台服务器。NAT的工做的隐藏内网的机器,但容许内网主动打开到外网的通信“通道”,也就是创建映射表项。 NAT给P2P带来的问题是:NAT只容许单方面发起链接,通信的双方不是平等的,P2P网络的基础有了问题,具体的表现为: 内网主机IP是私有的,外部主机看不到,也没法主动发起链接 即便知道了内网IP,但NAT会丢弃没有在影射表的数据包 内网主机能够做为客户端访问外网,但不能做为服务器提供服务 当两个主机都位于各自的NAT以后,要实现P2P的链接,就不只是谁主动的问题,而是如何解决在两个NAT上同时有对方映射表项的问题。 STUN协议(IETF RFC 3489): STUN协议是一种通道协议,能够做为正式通信前的通路创建,它采用的是用户终端干预的一种方法,能够解决应用协议内部传递IP地址给NAT带来的麻烦。用户经过其余方法获得其地址对应在NAT出口上的对外地址,而后在报文负载中所描述的地址信息就直接填写NAT上对外地址,而不是内网的私有IP,这样报文的内容在通过NAT时就按普通的NAT流程转换报文头部的IP地址便可,负载内的IP地址信息无需再修改。利用STUN的思路能够穿越NAT。STUN协议是客户端/服务器协议,分两种请求方式:一是UDP发送的绑定请求(Binding Requests),二是TCP发送的秘密请求(Shared Secret Requests)。绑定请求用于肯定NAT分配的绑定地址。 STUN标准中,根据内部终端的地址(P:p)到NAT出口的公网地址(A:b)的影射方式,把NAT分为四种类型: 1. Full Cone:来自相同的内部地址的请求消息映射为相同的外部地址,与外部地址(目的地址)无关。映射关系为P:p↔A:b,任何外部主机可经过(A:b)发送到数据到(P:p)上。 2. Restricted Cone:来自相同的内部地址的请求消息映射为相同的外部地址,返回的数据只接受该内部节点曾发数据的那个目的计算机地址X。映射关系为P:p↔A:b↔X,只有来自X的数据包才可经过(A:b)发送到数据到(P:p)上。 3. Port Restricted Cone:来自相同的内部地址的请求消息映射为相同的外部地址,返回的数据只接受该内部节点曾发数据的那个目的地址X:x。映射关系为P:p↔A:b↔X:x,只有来自X:x的数据包才可经过(A:b)发送到数据到(P:p)上。 4. Symmetric(对称) NAT:只有来自相同的内部地址(P:p),而且发送到同一个地址(X:x) 的请求消息,才被映射为相同的外部地址(A:b),返回的数据只接受该内部节点曾发数据的那个目的地址X:x。映射关系为P:p↔A:b↔X:x,当(P:p)访问(Y:y)时,映射为P:p↔B:c↔Y:y。 P2P利用STUN穿越NAT: 位于NAT后面终端A与B要穿越NAT直接通信,能够借助在公网上的第三者Server来帮助。 穿越NAT的状况分为为两种方式: 一、一方在NAT以后,一方在公网上。这种状况相对简单,只要让NAT以后的终端先发起通信,NAT就没有做用了,它能够从Server上取得另外一个Peer的地址,主动链接,回来的数据包就能够方便地穿越NAT。 二、双方都在NAT以后,链接的成功与否与两个NAT的类型有关。主要的思路的先经过终端与Server的链接,得到两个终端在NAT外部的地址(IP与端口号),再由终端向对方的外部地址发邀请包,获取本身与对方通信的外部地址,俗称为“打洞”。关键是获取了NAT外部映射的地址,就能够发包直接沟通,创建链接。但当一方是对称型,另外一方是Port Restricted或对称型时,没法有效获取外部地址,邀请包没法到达对方,也就没法穿越NAT。具体的分析能够根据两个NAT的类型分红若干状况分析,这里给通常的穿越例子。 实例:UDP穿越NAT: A登陆Server,NAT A分配端口11000,Server获得A的地址为100.10.10.10:11000 B登陆Server,NAT B分配端口22000,Server获得B的地址为200.20.20.20:22000 此时B会把直接来自A的包丢弃,因此要在NAT B上打一个方向为A的洞,那么A就能够向200.20.20.20:22000发送数据了 打洞的指令来自Server。B向A的地址100.10.10.10:11000发一个UDP报文,被NAT A丢弃,但在NAT B上创建映射记录,NAT B不在丢弃来自A的报文。 Server通知A能够通信,A发起数据UDP包给B,NAT B放行,B收到A的包,双方开始通信 注:如果对称NAT,当B向A打洞的端口要从新分配(NAT A不会再分配11000端口),B没法获取这个端口,因此不适用本方法。 实例:TCP穿越NAT: A登陆Server,NAT A分配端口11000,Server获得A的地址为100.10.10.10:11000 B登陆Server,NAT B分配端口22000,Server获得B的地址为200.20.20.20:22000 A向B发送TCP数据包SYN:192.168.10.11:1234=>200.20.20.20:22000,在NAT A上打洞 B向A发送TCP数据包SYN:192.168.20.22:1234=>100.10.10.10:11000,在NAT B上打洞 通道创建,A与B三次握手创建TCP链接