p2p小结(二):NAT

NAT即:Network Address Translation,是一种网络地址转换技术。该技术最初被用于简化重定向IP网络流量的相关工作,后来作为应对IPv4地址枯竭的关键技术被广泛使用,现在的NAT技术确切地说是NAPT,早期的Basic NAT只能做一对一的地址转换,意义不大,下面提到的NAT,如未做特殊说明,都是指NAPT

普遍的做法是将带有NAT功能的路由器部署在局域网的出口处,该路由器拥有ISP分配的一个公有IP,所有要外出的IP包都会由NAT转换为这个公有IP,然后再投递出去,同样,从外部返回的IP包也会经由NAT转换地址后再进入局域网。这样,只需一个公有IP就可以实现多台主机同时上网,从而大大减少了对公有IP的需求。

NAT所谓的“地址转换”,实际上是通过修改IP包协议首部中携带的信息实现的,当NAT收到外出的IP包时,首先去找这个数据包对应的session,如果找不到的话就新建一个,然后将IP首部中的源IP地址修改为ISP分配的公有IP,将TCP/UDP首部中的源端口号修改为一个由NAT产的端口号(这个“端口号”并非TCP/UDP的端口号,TCP/UDP端口号用来标识系统中的进程,这个“端口号”用来标识session,它是NAT产生的一个ID),然后将数据包发出去。当NAT收到来自外部的IP包时,首先也是去查询该数据包所属的session,然后从这个session中获取对端主机的地址,也就是局域网主机的私有IP,将这个IP包的目的IP改为该私有IP,将目的端口号改为对应的端口号,最后将其投递到局域网内。这就是地址转换的基本过程。另外,由于修改了首部中携带的数据,还需要对校验和(IP首部校验和TCP校验和UDP校验和)进行重新计算。

上面提到的session是NAT中的一个概念,可以把session理解为“连接”,这个“连接”是一个宽泛的描述,强调一种关联关系,这个“连接”可能基于TCPUDP等协议。只有建立了session的主机之间才能进行通信,这是NAT的基本设定。session可以被定义(定义依赖于具体的实现,实际的定义可能并非如此)为这样一个元组:(inside-private-ip,inside-private-port,nat-public-ip,nat-public-port,outside-public-ip,outside-public-port),即:NAT以内主机的私有IP,NAT以内主机的私有端口,NAT的公有IP,NAT的公有端口,NAT以外主机的公有IP,NAT以外主机的公有端口,上面的写法太冗长,把单词缩写一下inside/i,nat/n,outside/o,private/pri,public/pub,该元组简记为:(i-pri-ip,i-pri-port,n-pub-ip,n-pub-port,o-pub-ip,o-pub-port),后面在描述不同类型NAT的时候会使用定义中的字段。

下图给出了NAT的分类,Basic NAT最早出现,也最不实用,NAPT是对Basic NAT的升级,可以处理多对一的地址转换。NAPT有两种,Cone NATSymmetric NAT,这两者之间的区别简单地说就是:Cone NAT中的一个session可以关联多个外部主机,一个session对多个外部主机,形状就像锥子一样;而Symmetric NAT中一个session只能关联唯一的外部主机,一个session对一个外部主机,就是所谓的对称。另外,根据对外来数据包的不同限制,Cone NAT又有三个细分,这三个类型加上Symmetric NAT是常见的四类NAT,下面详细说明:
Full Cone NAT:完全锥形NAT,也就是无限制的锥形NAT,所谓的“无限制”体现在NAT对某个session的外来数据包的IP和端口号不做任何限制,即:session建立后,来自任意IP和端口的外部数据包都能通过该session而被转发到内部主机:

  • 内 -> 外:NAT收到来自内部的包后,检索“i-pri-ip == 源IP”且“i-pri-port == 源端口号”的session,若找不到,则新建session,确定session后,根据session中的信息修改数据包:将源IP置为n-pub-ip,源端口号置为n-pub-port,重新计算校验和,最后将数据包投递到外网。

  • 外 -> 内:NAT收到来自外部的包后,检索“n-pub-port == 目的端口号”的session,若找不到,则丢弃该数据包,否则,根据session中的信息修改数据包:目的IP置为i-pri-ip,目的端口置为i-pri-port,重新计算校验和,最后将数据包投递到内网。

Restricted Cone NAT:有(地址)限制的锥形NAT,在Full Cone NAT的基础上增加了对外来数据包的源IP的限制,即:session建立后,只有源IP地址与session中的o-pub-ip一致的外来数据包才能通过该session:

  • 内 -> 外:NAT收到来自内部的包后,检索“i-pri-ip == 源IP”且“i-pri-port == 源端口号”的session,若找不到,则新建session,确定session后,根据session中的信息修改数据包:源IP置为n-pub-ip,源端口号置为n-pub-port,重新计算校验和,最后将数据包投递到外网。

  • 外 -> 内:NAT收到来自外部的包后,检索“n-pub-port == 目的端口号”且“o-pub-ip == 源IP”的session,若找不到,则丢弃该数据包,否则,根据session中的信息修改数据包:目的IP置为i-pri-ip,目的端口置为i-pri-port,重新计算校验和,最后将数据包投递到内网。

Port Restricted Cone NAT:有端口限制的锥形NAT,在Restricted Cone NAT的基础上增加了对外来数据包的源端口号的限制,即:session建立后,只有源IP地址和源端口号与session中的o-pub-ip和o-pub-port都一致的外来数据包才能通过该session:

  • 内 -> 外:NAT收到来自内部的包后,检索“i-pri-ip == 源IP”且“i-pri-port == 源端口号”的session,若找不到,则新建session,确定session后,根据session中的信息修改数据包:源IP置为n-pub-ip,源端口号置为n-pub-port,重新计算校验和,最后将数据包投递到外网。

  • 外 -> 内:NAT收到来自外部的包后,检索“n-pub-port == 目的端口号”且“o-pub-ip == 源IP”且“o-pub-port == 源端口号”的session,若找不到,则丢弃该数据包,否则,根据session中的信息修改数据包:目的IP置为i-pri-ip,目的端口置为i-pri-port,重新计算校验和,最后将数据包投递到内网。

Symmetric NAT:对称形的NAT,是相对于锥形NAT来说的一种NAT类型,它与锥形NAT在处理外出数据包的逻辑上有所不同:锥形NAT收到一个要外出的包时,它会拿数据包的源IP地址和源端口号来匹配现有的session,若匹配不上,就创建新的session,而对称形的NAT则是拿该数据包的源IP地址、源端口号和目的IP,三个字段去匹配session,比锥形NAT多了一个“目的IP”字段。对外来数据包的限制规则是:session建立后,只有源IP地址与session中的o-pub-ip一致的外来数据包才能通过该session:

  • 内 -> 外:NAT收到来自内部的包后,检索“i-pri-ip == 源IP”且“i-pri-port == 源端口号”且“o-pub-ip == 目的IP”的session,若找不到,则新建session,确定session后,根据session中的信息修改数据包:源IP置为n-pub-ip,源端口号置为n-pub-port,重新计算校验和,最后将数据包投递到外网。

  • 外 -> 内:NAT收到来自外部的包后,检索“n-pub-port == 目的端口号”且“o-pub-ip == 源IP的session,若找不到,则丢弃该数据包,否则,根据session中的信息修改数据包,目的IP = i-pri-ip,目的端口 = i-pri-port,重新计算校验和,最后将数据包发到内网。

所谓的“锥形”和“对称形”大概是指某一内部主机的端口向可通信的外部主机端口发送数据包时所构成的图形,把NAT视为对称轴

目标端口号发生改变,不会产生新的session: 目标端口号发生改变,将会产生新的session:


References:


Prev-p2p小结(一):基本
Next-p2p小结(三):NAT穿越