UDP打洞相关经验

几年前做过一个简单的nat 打洞的项目, 当时自己做了个简单的总结。 希望对你有些帮助。
p2p有很多种, 有些是利用supernode, 有些是nat 打洞, 有些是两者结合。 下面说的p2p专指nat打洞。




P2P通信技术由于根据不同的网络环境,可能采取不同的策略。优秀的P2P通信软件,在做通信
之前,首先都要检测自己目前所处的网络环境。检测网络环境的内容包括:
[1] 正确获得软件运行的主机器的合法IP,因为在有时候主机器存在多个网络接口,包括VPN等
虚拟接口。而正确拿到一个有效的网络接口,是整个通信的必要条件。
[2] 判断自己的本地IP是不是有合法的IP(用户直接暴露在公网络上,例如通过主机器拨ADSL
上网的用户).一般会采用STUN协议来识别自己是不是直接暴露在公网上。
[3] 如果没有和法的IP,那自己处在网络中什么位置(是在一层NAT后面,还是在多层NAT后面,
这个信息对于P2P通信十分有用,不过往往由于目前的Firewall的存在,很难获得十分准确的
距离NAT的位置)
[4] 如果自己没有Public IP,那自己的本地通信地址对应的Nat上的映射地址也必须知道
(这个往往是通过STUN协议来获得,说白了就是让外面的Server帮忙看一下我的NAT给我映射什
么地址了。这个信息也是p2p通信所必须有的信息。)
[5] 看看我的NAT是不是支持类似UPNP的服务(这个服务能够让NAT后面的用户在NAT上订阅一个
永远属于自己的IPORT,目前一般市面上的小路又器等设备都默认支持这个服务,这个服务可
以说是给P2P通信开了一个后门).


如果想正确的获得上面这些信息,就是通过基本的SOCKET通信技术来实现了。


当环境检测完备之后,我们对每个用户都有个整体的概念,当然是拥有PUBLIC IP的用户对我门
来讲是更友好一些了。哈哈。不过我们的目的不是仅仅处理拥有PUBLIC IP的用户。我们主要是
想处理两个在NAT后面的用户能够通信。所以针对上面的3种情况,我们统一对待。因为最麻烦的
NAT转发情况我们都能处理正确了。那比较容易的反向代理与直接通信,就更能正常工作了。


这里我要声明一下,由于前面我说过,P2P通信无论怎么实现,都不可能实现100%的成功率。目前
锯某些权威的报告统计,比较好的实现也仅仅在80%成功率左右。所以大多数实现P2P通信的软件,
都必须考虑一个问题,就是当通信双方无论如何都无法直接通信的情况下,是否对这样的两个用户
提供服务。如果对这样的用户也提供服务,那就只有两种办法来解决,一种是运营商用自己的带
宽为这样的用户做中转。还有种比较下流的办法,就是前面我说的。用其他的有PUBLIC IP的用户
作为SUPER NODE,偷用用户的带宽做中转。当然,这部分中转技术不在我们这里讨论的范围内。


假使现在有两个QQ的用户A,B(QQ的实现不一定是我下面所说的这样,我只是用QQ做个比喻)
当用户A想与用户B进行语音聊天的时候,A通过QQ的信令,向B用户发送语音聊天的请求。当用户
B接到这个请求后,他有权利决定是否同意这个请求,如果B同意了A的请求,则在最开始的几秒钟,
A与B都是把语音数据发送到QQ的某一个转发SERVER上去(这个转发Server可能是QQ公司自己的,
也可能是某个A或者B附近的具有PUBLIC IP的QQ用户), 然后A与B自然第一时间就能听到声音了,
不过这个过程的同时,A与B的QQ Client同时还要做大量的路径的可连接性检测工作。(当A请求B
的时候,在A的请求信令中,会相应的把A自己的相关地址信息都带给B,同样当B回答A同意的时候,
也会把自己的地址信息同样带给A。一般VOIP的软件会采用SDP这样的协议来描述这样的信息,
具体请参见RFC DRAFT ICE。). 连接检测工作的步骤,如下:


首先分清两个过程:印脚印过程与打洞过程


[印脚印过程]
        所谓印脚印过程就是每个Client都试图在其自己的网关上留下自己曾经
        去过对方网关的地址的事实。往往通过发送一个目的地址为对方网关地址的报文来实现,
        但这个报文不能到达对方的网关,因为很多NAT与FIREWALL的策略是只有出去的UDP会话,
        其外面的对应地址的UDP报文才能够回来。这里要十分注意。这个留脚印的报文最多只能
        发送到对应的网关的下一个路有器。因为目前很多Firewall回根据端口不可到达的ICMP
        消息,来拒绝该端口上的后续消息。也就是说,如果一开始A的留脚印报文直接发送到B的
        网络关上了,而这个时候B还没有在自己网关上留下自己的对于A的网关的脚印的时候,
        B的网关会自动回复A的网络关一个端口不可到达的ICMP消息。而当这个消息到达A的网
        关后,A的网关的FIREWALL就会把B的网关的上的对应IP:PORT记录成黑名单里去。。而随
        后当B试图经过自己的网关向A的网关发送打洞消息的时候,是无论如何都不可能发进来的。
        因为A的FIREWALL会拒绝这个请求。所以可以通过设置IPTTL来控制这个报文的生命周期。
        这个也是我们为什么要知道Client做在主机器距离自己的网关的距离的原因。一般发送
        这个印脚印报文的TTL为距离网关的TTL的长度+1。当然,如果这个报文一离开自己的网
        关就下一跳就是对方网关机器,那只能认倒霉吧。本次P2P通信多半不能成功。


[打洞过程]
        所谓打洞过程,就是Client通过自己的网关,向对方网关对应的地址发送报
        文,其目的是让对方网关把这个报文转发给对方Client.一般该过程会在印脚印过程之后
        发生。如果引脚印过程是成功的。那该过程一般也会成功。这里我没有讨论具体打洞过


        程中的细节,实际根据NAT的类型不同,其打洞时候也会有很多细致的工作要做。


[p2p通信的逻辑步骤]
        假如A距离其自己的Gateway NAT的距离为1 (单位为IP TTL),
        B距离其自己的Gateway Nat 的距离是2. 则在连接检测的开始阶段。A与B都首先试图在自
        己的网关NAT上留下从自己到对方网关的脚印。假如A与B都分别成功的在自己的网关上留
        下了自己去对方网关对应地址的脚印。则接下来的步骤就是AB两个人都分别向对方的地址
        进行打洞。如果双方都收到了对方的打洞消息。则对应都给了自己的回复。则得出
        A<--->A'GATEWAY<--->B'GATEWAY<--->B是可以直接通信的。这个时候就可以切换媒体数据
        到底这条路径上进行传输了。也就基本实现了P2P。


想做到打洞率超过80%的p2p, 还是很复杂的, 除了需要了解主流的路由器的nat逻辑外,

还需要的基础理论知道包括:STUN, TURN, ICE, TUNNEL, VPN, NAT, FIREWALL, UPNP等等等等


本文摘录自 http://bbs.chinaunix.net/thread-1427081-1-1.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值