P2P之UDP穿透NAT的原理与实现之我见:
下面先强调3个概念, 非常重要,红字为重点
1.主机1想向主机2发送数据:从主机1开始——到NAT1——到外网——到NAT2,到了NAT2这里,主机1向主机2发送的数据就会丢弃了,为什么呢?NAT2在此时相当于一个防火墙,为了安全,对于主机1发送过来的数据会做丢弃处理。
这时候主机1想要和主机2通讯有两种方法:
1. 在路由上做端口映射,把通讯需要的端口映射到主机2(这个对于在内网玩过远控的人都知道吧)
2. 在NAT2处进行“打洞”,意思把通讯需要的端口在NAT上标记出来,让NAT知道访问这个端口就是要访问主机2(这个和端口映射的意思差不多)
2.那么我们如果想从外部发送一个数据报给居于内网的计算机有什么办法呢?首先,我们必须在此内网的NAT上打上一个“洞”(也就是在NAT上建立一个Session),这个洞不能由外部来打,只能由此内网内的被访问主机来打,而且这个洞是有方向的, 比如从内部某台主机(192.168.0.10)向外部的某个IP(219.237.60.1)发送一个UDP包,那么就在这个内网的NAT 设备上打了一个方向为219.237.60.1的“洞”(这就是称为UDPHolePunching的技术),以后219.237.60.1就可以通过这 个洞与内网的192.168.0.10联系了。(但是其他的IP不能利用这个洞)。
3.概念:私有地址/端口和公有地址/端口
我们知道,现在大部分网络采用的都是NAPT(Network Address/Port Translator)了,这个东东的作用是一个对外的对话在经过NAT之后IP地址和端口号都会被改写,在这里,我们把一次会话中客户自己认为在使用的IP地址和端口号称为私有地址/端口,而把经过NAPT之后被改写的IP地址和端口号称为公有地址/端口. 可以简单理解成:路由器192.168.0.1-255:端口就是私有, 连接公网IP的就是公有。
下面讲解下流程:
客户端首先得到自己的私有地址/终端,然后向server端发送登陆请求,server端在得到这个请求之后就可以知道这个client端的公有地址/终端,server会为每一个登陆的client保存它们的私有地址/端口和公有地址/端口.
OK,下面开始关键的打洞流程. 假设client A要向client B 对话, 但是A不知道B的地址,即使知道,根据NAT的原理,这个对话在第一次会被拒绝, 因为client B的NAT认为这是一个从没有过的外部发来的请求. 这个时候, A如果发现自己没有保存B的地址, 或者说发送给B的会话请求失败了,它会要求server端通知B向A打一个洞,这个B->A的会话意义在于它使NAT B认为A的地址/端口是可以通过(即已被认可)的地址/端口,这样A再向B发送对话的时候就不会再被NAT B拒绝了.简而言之,UDP打洞就是一个通过server保存下来的地址使得彼此之间能够直接通信的过程,server只管帮助建立连接,在建立间接之后就不再介入了。
为什么要C/S架构了,前面说过 洞不能由外部来打,只能由此内网内的被访问主机来打,还有方向性,所以用server做桥梁是比较好的。
总结一下这个过程:如果Client A想向Client B发送信息,那么Client A发送命令给Server S,请求ServerS 命令Client B 向Client A方向打洞。呵呵,是不是很绕口,不过没关系,理解原理了就清楚了,然后Client A就可以通过Client B的外网地址与Client B通信了。
个人学习总结 请不要转载
P2P之UDP穿透NAT的原理与实现之我见