P2P网络中,UDP穿越NAT方式主要有:中转方式(Relay)、反向连接(Connection Reversal)、UDP打洞(UDP Hole Punching)。
1.1中转方式
中转方式是最简单也是比较可靠的NAT穿越方法,它将P2P通信简单地转换为客户端/服务器通信模式。
假如有A和B两个客户端和一个公共服务器S,客户端位于各自的私有网络中,各自的NAT阻止任何其他客户端直接向其发起连接。中转方式就是A和B都有一个到S的UDP连接,A为了向B发送消息,A可以选择它已经建立的连接服务器S发送消息,然后S使用与B现存的连接向B转发消息,达到了A与B通信的目的
优点:只要客户端能够连接到服务器,中转就可以工作,是最有效的
缺点:消耗了服务器的处理能力和网络带宽,多了中转环节,节点间反应时间增加,效率最低
1.2反向连接
反向连接方式只适合仅有一个主机在NAT后面,另外的主机拥有合法公网IP地址的情况,这种方式的使用范围有明显的局限性。
假如有A和B两个客户端和一个公共服务器S,客户端A位于私有网络中,客户端B拥有合法的公网IP。如果A想要初始化一个到B的连接,直接连接就可以了,因为B没有在NAT后面,A的NAT认为这是一个外出的会话,不会阻拦。如果B想要初始化一个到A的连接,直接连接就会被A的NAT阻止,B通过服务器S向A发送连接请求,请求A反向连接到B。也就说说A可以直接连B,B要想连A,只需要通过服务器通知A,让A反向连接B
1.3UDP打洞
UDP打洞技术假定客户端A和B可以与公网服务器S建立UDP连接。当一个客户端登录到S之后,服务器S会记录下该客户端的两个endpoints(IP地址,UDP端口),一个是客户端的内网IP和端口,另一个是内网IP和端口经过NAT转换后的公网IP和端口。如果该客户端不是位于NAT设备后面,那么采用上述方法得到的两个endpoint值应该完全相同。
具体实现方法:假设两台内网PC, A和B想用端口40000通信,网关分别是NATA和NATB,服务器是S,配置如下:
A: 192.168.0.34 40000
NATA: 58.240.157.121 60020
B: 192.168.0.227 40000
NATB: 58.240.157.222 50030
S: 58.240.157.240 40000
打洞过程:
(1) A访问S,打一个洞,洞的指向为 A <---> S
(2) B访问S,打一个洞,洞的指向为 B<---> S
(3) S访问A,告诉它:B想访问A
(4) A访问B,洞的指向为A<--->B,B的路由器NATB收到数据包之后不会转发给B,而是丢弃,因为它认为这是来历不明的包
(5) B访问A, 洞的指向为B<->A, 因为A已经访问过B了,则A的路由NATA会把该包转发给A,此时A与B可以进行双向通信,打洞成功。
打洞的目的是为了告诉NAT,我要访问的IP是我"朋友",你不能阻拦它发过来的信息。比如第4步A通过发送这个包,告诉了NATA:B是我朋友;第5步B发送包给A,告诉了NATB:A是我朋友。最后NATA认识了B,而NATB认识了A,A与B终于实现了双向通信