字节大佬含泪吐血总结系列之 NAT 协议详解(网络层)
字节大佬含泪吐血总结系列之 NAT 协议详解(网络层)
应用场景
NAT 协议(Network Address Translation) 的应用场景如同它的名称——网络地址转换,应用于内部网到外部网的地址转换过程中。具体地说,在一个小的子网(局域网,Local Area Network,LAN)内,各主机使用的是同一个 LAN 下的 IP 地址,但在该 LAN 以外,在广域网(Wide Area Network,WAN)中,需要一个统一的 IP 地址来标识该 LAN 在整个 Internet 上的位置。
这个场景其实不难理解。随着一个个小型办公室、家庭办公室(Small Office, Home Office, SOHO)的出现,为了管理这些 SOHO,一个个子网被设计出来,从而在整个 Internet 中的主机数量将非常庞大。如果每个主机都有一个“绝对唯一”的 IP 地址,那么 IPv4 地址的表达能力可能很快达到上限( 2 32 2^{32} 232)。因此,实际上,SOHO 子网中的 IP 地址是“相对的”,这在一定程度上也缓解了 IPv4 地址的分配压力。
SOHO 子网的“代理人”,也就是和外界的窗口,通常由路由器扮演。路由器的 LAN 一侧管理着一个小子网,而它的 WAN 接口才是真正参与到 Internet 中的接口,也就有一个“绝对唯一的地址”。NAT 协议,正是在 LAN 中的主机在与 LAN 外界通信时,起到了地址转换的关键作用。
细节
假设当前场景如上图。中间是一个路由器,它的右侧组织了一个 LAN,网络号为10.0.0/24
。LAN 侧接口的 IP 地址为10.0.0.4
,并且该子网内有至少三台主机,分别是10.0.0.1
,10.0.0.2
和10.0.0.3
。路由器的左侧连接的是 WAN,WAN 侧接口的 IP 地址为138.76.29.7
。
首先,针对以上信息,我们有如下事实需要说明:
- 路由器的右侧子网的网络号为
10.0.0/24
,主机号为10.0.0/8
,三台主机地址,以及路由器的 LAN 侧接口地址,均由 DHCP 协议规定。而且,该 DHCP 运行在路由器内部(路由器自维护一个小 DHCP 服务器),从而为子网内提供 DHCP 服务。 - 路由器的 WAN 侧接口地址同样由 DHCP 协议规定,但该地址是路由器从 ISP(网络服务提供商)处获得,也就是该 DHCP 通常运行在路由器所在区域的 DHCP 服务器上。
现在,路由器内部还运行着 NAT 协议,从而为 LAN-WAN 间通信提供地址转换服务。为此,一个很重要的结构是 NAT 转换表。为了说明 NAT 的运行细节,假设有以下请求发生:
- 主机
10.0.0.1
向 IP 地址为128.119.40.186
的 Web 服务器(端口 80)发送了 HTTP 请求(如请求页面)。此时,主机10.0.0.1
将随机指派一个端口,如3345
,作为本次请求的源端口号,将该请求发送到路由器中(目的地址将是128.119.40.186
,但会先到达10.0.0.4
)。 10.0.0.4
即路由器的 LAN 接口收到10.0.0.1
的请求。路由器将为该请求指派一个新的源端口号,如5001
,并将请求报文发送给 WAN 接口138.76.29.7
。同时,在 NAT 转换表中记录一条转换记录138.76.29.7:5001——10.0.0.1:3345。- 请求报文到达 WAN 接口,继续向目的主机
128.119.40.186
发送。
之后,将会有如下响应发生:
- 主机
128.119.40.186
收到请求,构造响应报文,并将其发送给目的地138.76.29.7:5001
。 - 响应报文到达路由器的 WAN 接口。路由器查询 NAT 转换表,发现
138.76.29.7:5001
在转换表中有记录,从而将其目的地址和目的端口转换成为10.0.0.1:3345
,再发送到10.0.0.4
上。 - 被转换的响应报文到达路由器的 LAN 接口,继而被转发至目的地
10.0.0.1
。
🐛 修正(参见:issue#2009):上图第四步的 Dest 值应该为 10.0.0.1:3345
而不是~~138.76.29.7:5001
~~,这里笔误了。
划重点
针对以上过程,有以下几个重点需要强调:
- 当请求报文到达路由器,并被指定了新端口号时,由于端口号有 16 位,因此,通常来说,一个路由器管理的 LAN 中的最大主机数 ≈ 65500 ≈65500 ≈65500( 2 16 2^{16} 216 的地址空间),但通常 SOHO 子网内不会有如此多的主机数量。
- 对于目的服务器来说,从来不知道“到底是哪个主机给我发送的请求”,它只知道是来自
138.76.29.7:5001
的路由器转发的请求。因此,可以说,**路由器在 WAN 和 LAN 之间起到了屏蔽作用,**所有内部主机发送到外部的报文,都具有同一个 IP 地址(不同的端口号),所有外部发送到内部的报文,也都只有一个目的地(不同端口号),是经过了 NAT 转换后,外部报文才得以正确地送达内部主机。 - 在报文穿过路由器,发生 NAT 转换时,如果 LAN 主机 IP 已经在 NAT 转换表中注册过了,则不需要路由器新指派端口,而是直接按照转换记录穿过路由器。同理,外部报文发送至内部时也如此。
总结 NAT 协议的特点,有以下几点:
- NAT 协议通过对 WAN 屏蔽 LAN,有效地缓解了 IPv4 地址分配压力。
- LAN 主机 IP 地址的变更,无需通告 WAN。
- WAN 的 ISP 变更接口地址时,无需通告 LAN 内主机。
- LAN 主机对 WAN 不可见,不可直接寻址,可以保证一定程度的安全性。
然而,NAT 协议由于其独特性,存在着一些争议。比如,可能你已经注意到了,**NAT 协议在 LAN 以外,标识一个内部主机时,使用的是端口号,因为 IP 地址都是相同的。**这种将端口号作为主机寻址的行为,可能会引发一些误会。此外,路由器作为网络层的设备,修改了传输层的分组内容(修改了源 IP 地址和端口号),同样是不规范的行为。但是,尽管如此,NAT 协议作为 IPv4 时代的产物,极大地方便了一些本来棘手的问题,一直被沿用至今。