首先介绍下基础nat的四种方式,在进行nat转换的时候,我们在网关路由表上记录了映射关系,这个映射关系可以用六元祖表示

其中目标ip:目标port可以通配。可以分4种类型

1、全锥形 full cone:映射完成后的外网ip:外网port 可以被任何外网ip端口访问

2、ip 受限制:映射完成后只能目标ip能够访问

3、端口受限制:映射完成后,只能固定的目标ip和端口能够访问。

4、对称型:每次打洞都生成新的外网ip和端口,不能被外网主动访问。

nat穿透

局域网的A访问一个外部主机,这个主机返回A它的nat转换后的ip1 port1。另一个局域网B访问外部主机(stun),外部主机返回B被nat转换后的ip2,port2。A访问B,就是A去访问ip2,port2。B访问A,就是访问ip1,port1。

非对称与非对称:由于A(客户机)无论访问哪个主机,A的nat都是将它转换为ip1 port1(ip1 与port1都不会变化),因此A B都去访问stun,得到的ip与port不会变化。因此可以打洞。

一端对称,一端非对称:A(非对称Nat,且只能是ip不变,port变化的那种情况),一端非对称B,且只能是 full cone 或者ip受限。首先B访问A,B记录A的ip1(只要ip1的信息发过来,就能收到),B的数据必然被A的nat丢掉,但是A就可以访问B了

对称与对称:A去访问stun 得到的为Aip1 Aport1。B去访问stun,得到Bip1 Bport1。A去访问B, A net记录Bip1 Bport1, B去访问A,自身nat将其转换为BIp2, Bport2(Bip1,Bport1是访问stun得到的),但是A的洞只为Bip1,Bport1留着,Bip2,Bport2根本链接不上A,所以2个都改为对称Nat,根本没法打穿。

基于上述理论我们可以用go来测试我们的nat类型,为打洞做准备。

我们尝试链接stun服务器:

I,如果连接失败,说明不支持NAT;如果连接成功,说明支持NAT

II,同时切换ip和端口,如果返回的外网ip和端口都没有变,说明是完全锥形NAT;如果失败,说明不是

III,只切换ip能成功,但是II失败,说明是端口限制NAT;如果失败,说明是ip端口限制NAT,这三种形式的nat都可以打洞。