NAT/STUN

1.RFC3489 - STUN

RFC 3489 《STUN – Simple Traversal of UDP Through NATs》(《简单的用UDP穿透NATs》)描述了一套用于使UDP穿过NAT的协议,本文并不关心STUN协议的实现,如STUN Client或Server。相反我们更关心作为STUN穿透对象的NAT。

NAT是为了解决网络地址资源的问题出现的一种折中办法,显然使用NAT并不如拥有一个专用的Internet地址来得方便,但是从另一个角度看,NAT也为网络提供了许多安全保障。NAT的实现细节是多种多样的,但总的来说,越开放的则越危险,越封闭的则越安全。

2.NAT 的划分

RFC3489中将NAT的实现分为四大类:

1.Full Cone NAT 完全锥形NAT

2.Restricted Cone NAT 限制锥形NAT(可以理解为IP限制)

3.Port Restricted Cone NAT 端口限制锥形NAT(IP+Port限制)

4.Symmetric NAT 对称NAT

其中完全锥形的穿透性最好,而对称形的安全性最高。

1.锥形NAT与对称NAT的区别

所谓锥形NAT是指:只要是从同一个内部地址和端口出来的包,无论目的地址是否相同,NAT都将它转换成同一个外部地址和端口。

“同一个外部地址和端口”与“无论目的地址是否相同”形成了一个类似锥形的网络结构,也是这一名称的由来。

反过来,不满足这一条件的即为对称NAT。

举个例子:

NAT内的主机A: IP记为A,使用端口1000

NAT网关: IP记为NAT,用于NAT的端口池假设为(5001-5999)

公网上的主机B: IP记为B,开放端口2000

公网上的主机C: IP记为C,开放端口3000

假设主机A先后访问主机B和C

1)如果是锥形NAT:

那么成功连接后,状态必然如下:

A(1000) ——> NAT(5001)——> B(2000)

A(1000) ——> NAT(5001)——> C(3000)

也就是说,只要是从A主机的1000端口发出的包,经过地址转换后的源端口一定相同。

2)如果是对称形NAT:

连接后,状态有可能(注意是可能,不是一定)如下:

A(1000) ——> NAT(5001)——> B(2000)

A(1000) ——> NAT(5002)——> C(3000)

两者的区别显而易见。

2.三种CONE NAT之间的区别

仍然以上面的网络环境为例:

假设A先与B建立了连接,

A(1000) ——> NAT(5001)———> B(2000)

1)Port Restricted Cone NAT

只有B(2000)发往NAT(5001)的数据包可以到达A(1000)

B(2000) ——> NAT(5001) ———> A(1000)

B(3000) ——> NAT(5001) —X—> A(1000)

C(2000) ——> NAT(5001) —X—> A(1000)

2)Restricted Cone NAT

只要是从B主机发往NAT(5001)的数据包都可以到达A(1000)

B(2000) ——> NAT(5001) ———> A(1000)

B(3000) ——> NAT(5001) ———> A(1000)

C(2000) ——> NAT(5001) —X—> A(1000)

3)Full Cone NAT

任意地址发往NAT(5001)的数据包都可以到达A(1000)

B(2000) ——> NAT(5001) ———> A(1000)

B(3000) ——> NAT(5001) ———> A(1000)

C(3000) ——> NAT(5001) ———> A(1000)

3.Linux的NAT

Linux的NAT“MASQUERADE”属于对称形NAT。

说明这一点只需要否定MASQUERADE为锥形NAT即可。

Linux在进行地址转换时,会遵循两个原则:

1、尽量不去修改源端口,也就是说,ip伪装后的源端口尽可能保持不变。

2、更为重要的是,ip伪装后必须保证伪装后的源地址/端口与目标地址/端口(即所谓的socket)唯一。

假设如下的情况:

内网有主机A和D,公网有主机B和C。

先后建立如下三条连接:

A(1000) ——> NAT(1000)——> B(2000)

D(1000) ——> NAT(1000)——> C(2000)

A(1000) ——> NAT(1001)——> C(2000)

可以看到,前两条连接遵循了原则1,并且不违背原则2

而第三条连接为了避免与第二条产生相同的socket而改变了源端口

比较第一和第三条连接,同样来自A(1000)的数据包在经过NAT后源端口分别变为了1000和1001。说明Linux的NAT是对称NAT。

4.对协议的支持

CONENAT要求原始源地址端口相同的数据包经过地址转换后,新源地址和端口也相同,换句话说,原始源地址端口不同的数据包,转换后的源地址和端口也一定不同。

那么,是不是Full Cone NAT的可穿透性一定比Symmetric NAT要好呢,或者说,通过Symmetric NAT可以建立的连接,如果换成Full Cone NAT是不是也一定能成功呢?

假设如下的情况:

内网有主机A和D,公网有主机B和C,某UDP协议服务端口为2000,并且要求客户端的源端口一定为1000。

1)如果A使用该协议访问B

A(1000) ——> NAT(1000)———> B(2000)

由于Linux有尽量不改变源端口的规则,因此在1000端口未被占用时,连接是可以正常建立的

如果此时D也需要访问B

D(1000) ——> NAT(1001)—X—> B(2000)

端口必须要改变了,否则将出现两个相同的socket,后续由B(2000)发往NAT(1000)的包将不知道是转发给A还是D。

于是B将因为客户端的源端口错误而拒绝连接。

在这种情况下,MASQUERADE与CONENAT的表现相同。

2)如果A连接B后,D也像C发起连接,而在此之后,A又向C发起连接

 ① A(1000) ——> NAT(1000)———> B(2000)

如果是MASQUERADE:

 ② D(1000) ——> NAT(1000)———> C(2000)

 ③ A(1000) ——> NAT(1001)—X—> C(2000)

如果是CONENAT:

 ② D(1000) ——> NAT(1001)—X—> C(2000)

 ③ A(1000) ——> NAT(1000)———> C(2000)

对于MASQUERADE来说,只要在没有重复的socket的情况下,总是坚持尽量不改变源端口的原则,因此第二条连接仍然采用源端口1000,而第三条连接为了避免重复的socket而改变了端口。

对于CONENAT,为了保证所有来自A(1000)的数据包均被转换为NAT(1000),因此D在向C发起连接时,即使不会产生重复的socket,但因为NAT的1000端口已经被A(1000)“占用”了,只好使用新的端口。

可以看出,不同的target产生不同的结果。我们也不能绝对的说,在任何时候,全锥形NAT的可穿透性都比对称NAT要好,比如上面的例子,如果只存在连接①和②,显然是对称形NAT要更适用。

因此,选择哪种NAT,除了对网络安全和普遍的可穿透性的考虑外,有时还需要根据具体应用来决定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值