LabHub
学习 学习路径 课程

网络基础 — 在 Linux 虚拟机里动手

是不是邻居 — 地址、掩码、ARP

在 LabHub 中继续学习

一句话总结

发送数据包之前,内核作出的第一个判断是“对方是否位于同一子网”。如果相同,就通过 ARP 直接询问对方的 MAC;如果不同,就发往网关的 MAC。一个 mask bit 就决定了这条分岔路径。

概念图: 位于何处 · 网关的 MAC · mask 输入错误。 · IP 重复。

为什么需要这些知识

IP 地址是表示设备位于何处的逻辑地址,实际传送 frame 的则是写入 NIC 的 MAC 地址,二者没有任何关联。因此,要向连接在同一条链路、即同一个 L2 的设备发送数据,就必须询问“拥有这个 IP 的设备,MAC 是什么?”这就是 ARP。响应会暂时保存在邻居表,也就是 ARP cache 中。

问题在于不在同一条链路上的目标。广播无法跨越链路,因此不能通过 ARP 找到。内核会先用 mask 判断“是否属于同一子网”;如果不是,就在路由表中查找网关,并使用网关的 MAC 构造 frame。网关必须位于同一子网的原因就在这里——内核必须能够询问它的 MAC。

它是如何运作的

假设从 192.168.1.77/25192.168.1.130 发送数据。/25 表示前 25 bit 是网络部分,因此在 128 处分界。77 位于 0–127 block,130 位于 128–255 block,二者属于不同子网,所以内核会查找网关。如果把同样两个地址设为 /24,它们就属于同一个 block,内核会通过 ARP 直接询问。地址完全没有改变,仅一个 mask bit 就让路径彻底不同。

192.168.1.77 与 192.168.1.130 的前 24 bit 相同,最后一个 octet 的首个 bit 分别为 0 和 1。按 /24 查看时属于同一子网,因此通过 ARP 直接询问对方 MAC;按 /25 查看时,该 bit 也属于网络部分,二者属于不同子网,所以发往网关的 MAC

ARP 请求的目标 MAC 是 ff:ff:ff:ff:ff:ff,因此属于广播。只有认出自身 IP 的主机会用单播响应。内核把响应写入邻居表,状态设为 REACHABLE;暂时未使用后改为 STALE,下次使用时再确认。如果用 nud permanent 写入静态条目,内核就不会更新它。因此,一旦填入错误 MAC,IP 和路由看似都正常,通信却会悄然中断。对方 NIC 只会认为“这不是发给我的”并丢弃,不会返回任何错误。

在实际工作中会是什么样

mask 输入错误。 新服务器本应设置 /24,却写成了 /16。同一个 /24 内通信正常,但发送到相邻网段,即同一 /16 下的另一个 /24 时,内核会认为目标“在同一子网”,于是发送 ARP,却得不到响应。本可经过网关到达的数据包,却因尝试直接寻找目标而失败。症状是“只有部分网段无法访问”,线索则是 ip neigh 中不断积累 FAILED 条目。

IP 重复。 两台设备使用同一 IP 时,会收到两份 ARP 响应,后到者获胜。通信会时通时断。只要捕捉到邻居表中的 MAC 持续变化,就能看出原因。

经常混淆的地址

子网内并非所有地址都能分配给主机。在 192.168.1.0/24 中,.0 是网络地址,.255 是广播地址,均不能分配给主机,因此可用地址不是 256 个,而是 254 个。mask 越窄,这种损失越明显。/30 的 4 个地址中只有 2 个可用,所以过去常用于连接两台路由器。如今该场景会使用 /31:协议明确规定点对点链路不需要广播,因此两个地址都能分配给主机。

有些网段具有固定含义,仅凭症状就能推测原因。

网段 含义 看到它时说明什么
127.0.0.0/8 本机 不会发往外部。服务只绑定这里时,其他主机无法访问
169.254.0.0/16 link-local DHCP 失败后自行分配的地址。典型症状是有地址却无法通信
10/8·172.16/12·192.168/16 私有网段 无法原样访问互联网,路径中必然存在 NAT
224.0.0.0/4 multicast 只有订阅特定 group 的主机才能收到

一个 interface 也可以配置多个地址。此时,出站数据包的源地址由内核选择。 默认规则是“选择与目标位于同一子网的地址中的第一个”。因此,如果对方 firewall 只允许特定源地址,现象可能看起来像有时通过、有时被阻断。运行 ip route get <상대 주소>,即可直接看到内核实际会选择的源地址和路径。与其猜测,不如使用这条命令确认。

最后,最好了解 ARP 的两种变体。Gratuitous ARP 是在无人询问时主动声明“这个 IP 属于我的 MAC”,常用于把 virtual IP 转移到另一台设备时,立即更新周边邻居表。故障切换后,流量仍在一段时间内持续发往故障设备,通常是因为没有发出该通知,或通知被中间 switch 过滤。Proxy ARP 则是由路由器代替其他 IP 作出响应。它看似方便,却会让人难以追踪究竟是哪台设备回复,严重妨碍根因调查。

下一次实操要做什么

你将使用 ip -brip -j 读取 interface 与地址,用 ipcalc 和 Python 计算子网,并尝试给 dummy interface 配置地址。随后,用 veth 连接两个 namespace,通过 tcpdump 捕获 ARP 请求和响应,再向静态条目写入错误 MAC,亲眼观察通信中断。