当主机只有私有IP,没有公网IP的时候,如果想要连接到因特网,就需要使用NAT(Network Address Translation,网络地址转换)或PAT(Port Address Translation,端口地址转换)技术。
使用NAT上网时,需要在 连接局域网和因特网的 路由器上安装NAT软件,并且NAT路由器至少要有一个公网IP。当内网主机和因特网通信时,由NAT负责将(私有IP,私有Port)转换成(NAT公网IP,NAT公网Port);当外部网络发来回应消息时,NAT还要负责将(NAT公网IP,NAT公网Port)转换回(私有IP,私有Port),并进行转发。NAT使用session记录这个映射关系。
NAT分为三类:
静态NAT:内网IP和公网IP是一对一的,一直不变的
动态NAT:适用于公网IP略少于内网IP的场景。将内网IP转换成公网IP时,公网IP是随机的,不确定的
NAPT(Network Address Port Translation,也叫PAT):不仅会对源IP地址进行转换,还会对源端口进行转换,通过端口多路复用的方式,内网的所有主机可以共享一个公网IP地址。NAPT不仅可以最大程度的节约公网IP地址,还可以隐藏内部主机的端口,有效避免来自Internet的攻击。==目前应用最多的就是NAPT==
NAPT分为Cone NAPT(锥形NAPT)和Symmetric NAPT(对称NAPT)。
Cone NAPT又分为:
目前最常见的,应该是Port Restricted Cone NAPT(端口限制锥形NAPT)。它也是要穿透的目标。
这里只分析NAPT。
1,判断NAPT是Cone NAPT,还是Symmetric NAPT,Symmetric NAPT是无法穿透的
建立两个公网UDP Server,其中,Server1绑定(IP1,Port1),Server2绑定(IP2,Port2)。然后内网主机分别向这两个Server发送数据,Server收到的数据包的源地址就是(NATIP,NATPort),Server只需要把这个数据包的源地址进行序列化,然后发送到 该源地址 即可,NAT会将响应包转发给内网主机,最终内网主机就能拿到NAT转换后的IP地址和端口了。如果两次转换得到的IP地址和端口都相同,则说明是Cone NAPT,否则是Symmetric NAPT。
2,穿透Port Restricted Cone NAPT
如果程序能够穿透Port Restricted Cone NAPT,那么肯定能穿透Full Cone NAPT、Restricted Cone NAPT。
建立一个用于协调的公网UDP Server
假设有两个Client:
ClientA首先发送请求给Server。告知:Server转告ClientB(NATB-IP-B,NATB-Port-B),ClientA(NATA-IP-A,NATA-PORT-A)想要和它进行通信
ClientB向ClientA(NATA-IP-A,NATA-PORT-A)发送一个UDP数据包。该数据包到达NATA时,会被丢弃,因为ClientA没有和ClientB通信过。但是NATB会记住:ClientB(IP-B,Port-B)曾经向ClientA(NATA-IP-A,NATA-PORT-A)发送过报文,因此,以后以(NATA-IP-A,NATA-PORT-A)为源地址和源端口的数据包,会被NATB转发给ClientB(IP-B,Port-B)(也就是,ClientB为ClientA(NATA-IP-A,NATA-PORT-A)在NATB上打了个洞)
ClientB为ClientA(NATA-IP-A,NATA-PORT-A)在NATB上打完洞之后,需要通过Server转告ClientA(NATA-IP-A,NATA-PORT-A):==洞已经为你打好,你可以跟我通信了==
ClientA收到Server的转告之后,会向ClientB(NATB-IP-B,NATB-Port-B)发起通信,数据包到达NATB时,NATB会将数据包转发给ClientB(IP-B,Port-B)。并且NATA会记住:ClientA(IP-A,Port-A)曾经向ClientB(NATB-IP-B,NATB-Port-B)发送过报文,因此,以后以(NATB-IP-B,NATB-Port-B)为源地址和源端口的数据包,会被NATA转发给ClientA(IP-A,Port-A)(也就是,ClientA为ClientB(NATB-IP-B,NATB-Port-B)在NATA上打了个洞)