面试题 / 网络与协议

ARP与NAT

ARP

每当我们学习一个新的网络协议的时候,都要把他结合到 OSI 七层模型中,或者是 TCP/IP 协议栈中来学习,一是要学习该协议在整个网络协议栈中的位置,二是要学习该协议解决了什么问题,地位如何?三是要学习该协议的工作原理,以及一些更深入的细节。

ARP 协议,可以说是在协议栈中属于一个偏底层的、非常重要的、又非常简单的通信协议。

开始阅读这篇文章之前,你可以先看看下面几个问题:

  1. ARP 协议在协议栈中的位置? ARP 协议在协议栈中的位置非常重要,在理解了它的工作原理之后,也很难说它到底是网络层协议,还是链路层协议,因为它恰恰串联起了网络层和链路层。国外的大部分教程通常将 ARP 协议放在网络层。
  2. ARP 协议解决了什么问题,地位如何? ARP 协议,全称 地址解析协议(Address Resolution Protocol),它解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
  3. ARP 工作原理? 只希望大家记住几个关键词:ARP 表、广播问询、单播响应

MAC 地址

在介绍 ARP 协议之前,有必要介绍一下 MAC 地址。

MAC 地址的全称是 媒体访问控制地址(Media Access Control Address)。如果说,互联网中每一个资源都由 IP 地址唯一标识(IP 协议内容),那么一切网络设备都由 MAC 地址唯一标识。

路由器的背面就会注明 MAC 位址

可以理解为,MAC 地址是一个网络设备真正的身份证号,IP 地址只是一种不重复的定位方式(比如说住在某省某市某街道的张三,这种逻辑定位是 IP 地址,他的身份证号才是他的 MAC 地址),也可以理解为 MAC 地址是身份证号,IP 地址是邮政地址。MAC 地址也有一些别称,如 LAN 地址、物理地址、以太网地址等。

还有一点要知道的是,不仅仅是网络资源才有 IP 地址,网络设备也有 IP 地址,比如路由器。但从结构上说,路由器等网络设备的作用是组成一个网络,而且通常是内网,所以它们使用的 IP 地址通常是内网 IP,内网的设备在与内网以外的设备进行通信时,需要用到 NAT 协议。

MAC 地址的长度为 6 字节(48 比特),地址空间大小有 280 万亿之多($2^{48}$),MAC 地址由 IEEE 统一管理与分配,理论上,一个网络设备中的网卡上的 MAC 地址是永久的。不同的网卡生产商从 IEEE 那里购买自己的 MAC 地址空间(MAC 的前 24 比特),也就是前 24 比特由 IEEE 统一管理,保证不会重复。而后 24 比特,由各家生产商自己管理,同样保证生产的两块网卡的 MAC 地址不会重复。

MAC 地址具有可携带性、永久性,身份证号永久地标识一个人的身份,不论他到哪里都不会改变。而 IP 地址不具有这些性质,当一台设备更换了网络,它的 IP 地址也就可能发生改变,也就是它在互联网中的定位发生了变化。

最后,记住,MAC 地址有一个特殊地址:FF-FF-FF-FF-FF-FF(全 1 地址),该地址表示广播地址。

ARP 协议工作原理

ARP 协议工作时有一个大前提,那就是 ARP 表

在一个局域网内,每个网络设备都自己维护了一个 ARP 表,ARP 表记录了某些其他网络设备的 IP 地址-MAC 地址映射关系,该映射关系以 <IP, MAC, TTL> 三元组的形式存储。其中,TTL 为该映射关系的生存周期,典型值为 20 分钟,超过该时间,该条目将被丢弃。

ARP 的工作原理将分两种场景讨论:

  1. 同一局域网内的 MAC 寻址
  2. 从一个局域网到另一个局域网中的网络设备的寻址

同一局域网内的 MAC 寻址

假设当前有如下场景:IP 地址为137.196.7.23的主机 A,想要给同一局域网内的 IP 地址为137.196.7.14主机 B,发送 IP 数据报文。

再次强调,当主机发送 IP 数据报文时(网络层),仅知道目的地的 IP 地址,并不清楚目的地的 MAC 地址,而 ARP 协议就是解决这一问题的。

为了达成这一目标,主机 A 将不得不通过 ARP 协议来获取主机 B 的 MAC 地址,并将 IP 报文封装成链路层帧,发送到下一跳上。在该局域网内,关于此将按照时间顺序,依次发生如下事件:

  1. 主机 A 检索自己的 ARP 表,发现 ARP 表中并无主机 B 的 IP 地址对应的映射条目,也就无从知道主机 B 的 MAC 地址。

  2. 主机 A 将构造一个 ARP 查询分组,并将其广播到所在的局域网中。

    ARP 分组是一种特殊报文,ARP 分组有两类,一种是查询分组,另一种是响应分组,它们具有相同的格式,均包含了发送和接收的 IP 地址、发送和接收的 MAC 地址。当然了,查询分组中,发送的 IP 地址,即为主机 A 的 IP 地址,接收的 IP 地址即为主机 B 的 IP 地址,发送的 MAC 地址也是主机 A 的 MAC 地址,但接收的 MAC 地址绝不会是主机 B 的 MAC 地址(因为这正是我们要问询的!),而是一个特殊值——FF-FF-FF-FF-FF-FF,之前说过,该 MAC 地址是广播地址,也就是说,查询分组将广播给该局域网内的所有设备。

  3. 主机 A 构造的查询分组将在该局域网内广播,理论上,每一个设备都会收到该分组,并检查查询分组的接收 IP 地址是否为自己的 IP 地址,如果是,说明查询分组已经到达了主机 B,否则,该查询分组对当前设备无效,丢弃之。

  4. 主机 B 收到了查询分组之后,验证是对自己的问询,接着构造一个 ARP 响应分组,该分组的目的地只有一个——主机 A,发送给主机 A。同时,主机 B 提取查询分组中的 IP 地址和 MAC 地址信息,在自己的 ARP 表中构造一条主机 A 的 IP-MAC 映射记录。

    ARP 响应分组具有和 ARP 查询分组相同的构造,不同的是,发送和接受的 IP 地址恰恰相反,发送的 MAC 地址为发送者本身,目标 MAC 地址为查询分组的发送者,也就是说,ARP 响应分组只有一个目的地,而非广播。

  5. 主机 A 终将收到主机 B 的响应分组,提取出该分组中的 IP 地址和 MAC 地址后,构造映射信息,加入到自己的 ARP 表中。

在整个过程中,有几点需要补充说明的是:

  1. 主机 A 想要给主机 B 发送 IP 数据报,如果主机 B 的 IP-MAC 映射信息已经存在于主机 A 的 ARP 表中,那么主机 A 无需广播,只需提取 MAC 地址并构造链路层帧发送即可。
  2. ARP 表中的映射信息是有生存周期的,典型值为 20 分钟。
  3. 目标主机接收到了问询主机构造的问询报文后,将先把问询主机的 IP-MAC 映射存进自己的 ARP 表中,这样才能获取到响应的目标 MAC 地址,顺利的发送响应分组。

总结来说,ARP 协议是一个广播问询,单播响应协议。

不同局域网内的 MAC 寻址

更复杂的情况是,发送主机 A 和接收主机 B 不在同一个子网中,假设一个一般场景,两台主机所在的子网由一台路由器联通。这里需要注意的是,一般情况下,我们说网络设备都有一个 IP 地址和一个 MAC 地址,这里说的网络设备,更严谨的说法应该是一个接口。路由器作为互联设备,具有多个接口,每个接口同样也应该具备不重复的 IP 地址和 MAC 地址。因此,在讨论 ARP 表时,路由器的多个接口都各自维护一个 ARP 表,而非一个路由器只维护一个 ARP 表。

接下来,回顾同一子网内的 MAC 寻址,如果主机 A 发送一个广播问询分组,那么 A 所在的子网内所有设备(接口)都将会捕获该分组,因为该分组的目的 IP 与发送主机 A 的 IP 在同一个子网中。但是当目的 IP 与 A 不在同一子网时,A 所在子网内将不会有设备成功接收该分组。那么,主机 A 应该发送怎样的查询分组呢?整个过程按照时间顺序发生的事件如下:

  1. 主机 A 查询 ARP 表,期望寻找到目标路由器的本子网接口的 MAC 地址。

    目标路由器指的是,根据目的主机 B 的 IP 地址,分析出 B 所在的子网,能够把报文转发到 B 所在子网的那个路由器。

  2. 主机 A 未能找到目标路由器的本子网接口的 MAC 地址,将采用 ARP 协议,问询到该 MAC 地址,由于目标接口与主机 A 在同一个子网内,该过程与同一局域网内的 MAC 寻址相同。

  3. 主机 A 获取到目标接口的 MAC 地址,先构造 IP 数据报,其中源 IP 是 A 的 IP 地址,目的 IP 地址是 B 的 IP 地址,再构造链路层帧,其中源 MAC 地址是 A 的 MAC 地址,目的 MAC 地址是本子网内与路由器连接的接口的 MAC 地址。主机 A 将把这个链路层帧,以单播的方式,发送给目标接口。

  4. 目标接口接收到了主机 A 发过来的链路层帧,解析,根据目的 IP 地址,查询转发表,将该 IP 数据报转发到与主机 B 所在子网相连的接口上。

    到此,该帧已经从主机 A 所在的子网,转移到了主机 B 所在的子网了。

  5. 路由器接口查询 ARP 表,期望寻找到主机 B 的 MAC 地址。

  6. 路由器接口如未能找到主机 B 的 MAC 地址,将采用 ARP 协议,广播问询,单播响应,获取到主机 B 的 MAC 地址。

  7. 路由器接口将对 IP 数据报重新封装成链路层帧,目标 MAC 地址为主机 B 的 MAC 地址,单播发送,直到目的地。

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}$)。因此,实际上,SOHO 子网中的 IP 地址是“相对的”,这在一定程度上也缓解了 IPv4 地址的分配压力。

SOHO 子网的“代理人”,也就是和外界的窗口,通常由路由器扮演。路由器的 LAN 一侧管理着一个小子网,而它的 WAN 接口才是真正参与到 Internet 中的接口,也就有一个“绝对唯一的地址”。NAT 协议,正是在 LAN 中的主机在与 LAN 外界通信时,起到了地址转换的关键作用。

细节

NAT 协议

假设当前场景如上图。中间是一个路由器,它的右侧组织了一个 LAN,网络号为10.0.0/24。LAN 侧接口的 IP 地址为10.0.0.4,并且该子网内有至少三台主机,分别是10.0.0.110.0.0.210.0.0.3。路由器的左侧连接的是 WAN,WAN 侧接口的 IP 地址为138.76.29.7

首先,针对以上信息,我们有如下事实需要说明:

  1. 路由器右侧子网的网络地址为 10.0.0.0/24(网络前缀 24 位,主机号占 8 位),三台主机地址以及路由器的 LAN 侧接口地址,均由 DHCP 协议规定。而且,该 DHCP 运行在路由器内部(路由器自维护一个小 DHCP 服务器),从而为子网内提供 DHCP 服务。
  2. 路由器的 WAN 侧接口地址同样由 DHCP 协议规定,但该地址是路由器从 ISP(网络服务提供商)处获得,也就是该 DHCP 通常运行在路由器所在区域的 DHCP 服务器上。

现在,路由器内部还运行着 NAT 协议,从而为 LAN-WAN 间通信提供地址转换服务。为此,一个很重要的结构是 NAT 转换表。为了说明 NAT 的运行细节,假设有以下请求发生:

  1. 主机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)。
  2. 10.0.0.4即路由器的 LAN 接口收到10.0.0.1的请求。路由器将为该请求指派一个新的源端口号,如5001,并将请求报文发送给 WAN 接口138.76.29.7。同时,在 NAT 转换表中记录一条转换记录138.76.29.7
    ——10.0.0.1
  3. 请求报文到达 WAN 接口,继续向目的主机128.119.40.186发送。

之后,将会有如下响应发生:

  1. 主机128.119.40.186收到请求,构造响应报文,并将其发送给目的地138.76.29.7:5001
  2. 响应报文到达路由器的 WAN 接口。路由器查询 NAT 转换表,发现138.76.29.7:5001在转换表中有记录,从而将其目的地址和目的端口转换成为10.0.0.1:3345,再发送到10.0.0.4上。
  3. 被转换的响应报文到达路由器的 LAN 接口,继而被转发至目的地10.0.0.1

LAN-WAN 间通信提供地址转换

🐛 修正(参见:issue#2009):上图第四步的 Dest 值应该为 10.0.0.1:3345 而不是~~138.76.29.7:5001~~,这里笔误了。

划重点

针对以上过程,有以下几个重点需要强调:

  1. 当请求报文到达路由器,并被指定了新端口号时,由于端口号有 16 位,因此,通常来说,一个路由器管理的 LAN 中的最大主机数 $≈65500$($2^{16}$ 的地址空间),但通常 SOHO 子网内不会有如此多的主机数量。
  2. 对于目的服务器来说,从来不知道“到底是哪个主机给我发送的请求”,它只知道是来自138.76.29.7:5001的路由器转发的请求。因此,可以说,路由器在 WAN 和 LAN 之间起到了屏蔽作用,所有内部主机发送到外部的报文,都具有同一个 IP 地址(不同的端口号),所有外部发送到内部的报文,也都只有一个目的地(不同端口号),是经过了 NAT 转换后,外部报文才得以正确地送达内部主机。
  3. 在报文穿过路由器,发生 NAT 转换时,如果 LAN 主机 IP 已经在 NAT 转换表中注册过了,则不需要路由器新指派端口,而是直接按照转换记录穿过路由器。同理,外部报文发送至内部时也如此。

总结 NAT 协议的特点,有以下几点:

  1. NAT 协议通过对 WAN 屏蔽 LAN,有效地缓解了 IPv4 地址分配压力。
  2. LAN 主机 IP 地址的变更,无需通告 WAN。
  3. WAN 的 ISP 变更接口地址时,无需通告 LAN 内主机。
  4. LAN 主机对 WAN 不可见,不可直接寻址,可以保证一定程度的安全性。

然而,NAT 协议由于其独特性,存在着一些争议。比如,可能你已经注意到了,NAT 协议在 LAN 以外,标识一个内部主机时,使用的是端口号,因为 IP 地址都是相同的。这种将端口号作为主机寻址的行为,可能会引发一些误会。此外,路由器作为网络层的设备,修改了传输层的分组内容(修改了源 IP 地址和端口号),同样是不规范的行为。但是,尽管如此,NAT 协议作为 IPv4 时代的产物,极大地方便了一些本来棘手的问题,一直被沿用至今。


来源引用