ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

从应用到网卡:图解跨网络传输与IP/MAC地址分工

从应用到网卡:图解跨网络传输与IP/MAC地址分工

网络这块东西,刚上手的时候最容易犯的一个毛病,就是把它当成一门“背诵课”——IP 地址长什么样、MAC 地址多少位、数据包怎么封装,背得滚瓜烂熟,可一旦让你画一张“两台机器隔着好几个网段通信,数据到底怎么走的”图,脑子立马就空了。我自己当年也是这样,书翻了三遍,真到抓包看流量的时候还是一脸懵。后来带过几个新人,发现大家卡的地方高度一致:不是记不住概念,而是脑子里没有一张“从应用到网卡”的完整路径图,尤其是中间那层“软件虚拟层”到底干了什么,几乎没人讲得清楚。

这篇东西就是想把这件事捋顺。核心讲三块:跨网络传输的大致过程配上图解思路、IP 地址到底是个什么东西、以及 IP 和 MAC 这两个地址为什么非得同时存在。适合刚学网络基础的同学,也适合工作几年但一直没把底层链路想明白的开发者——尤其是做后端、做容器、做虚拟化相关工作的,软件虚拟层这块绕不过去。我会尽量用“数据从你键盘敲下去,到对面屏幕亮起来”这条主线串起来,中间该停的地方停下来讲原理,该给参数的地方给具体数字,能画图的地方用文字把图“讲”出来,你照着在纸上画一遍,基本就通了。

1. 先把“跨网络”这件事拆成四段路来看

很多人一上来就啃 OSI 七层模型,啃完还是不知道数据怎么走。我的建议是先别管分层,先把一次跨网络通信想象成“寄快递”,分成四段路,每段路的“交接方式”都不一样,这样理解起来会顺很多。

1.1 四段路的分段逻辑:为什么必须切开看

假设你在 A 城市的一台电脑上,要访问 B 城市某台服务器上的一个网页。这中间物理上可能隔了十几台路由器、若干交换机。如果把它当成一整条路来看,你会觉得“数据包怎么知道该往哪拐”这个问题无解。但切成四段就清楚了:

  • 第一段:本机内部,从浏览器进程到本机网卡,这一段根本没出机器,走的是操作系统内部的软件栈;
  • 第二段:本机到本网关,也就是你所在局域网内,从你的网卡到路由器的 LAN 口;
  • 第三段:网关到对端网关,这一段跨了多个网络,是真正意义上的“跨网络”,经过一堆路由器逐跳转发;
  • 第四段:对端网关到目标主机,进入对方局域网,最后送到服务器网卡。

这么切的好处是:每一段只关心“下一跳是谁”,不需要知道全程。这跟寄快递一模一样——你只需要写清楚收件地址,快递员只负责送到下一个中转站,中转站再决定下一站,没人需要记住从你家到收件人手里的完整路线。逐跳转发(hop-by-hop)这个思想,是整个互联网能扩展到今天这个规模的根本原因,也是理解跨网络传输的第一把钥匙。

我见过不少人纠结“路由器怎么知道整个互联网的拓扑”,其实它根本不知道,也不需要知道。它只看目标 IP,查自己的路由表,找到“去这个网段该从哪个口出去、下一跳是谁”,然后把包扔出去就完事了。这个认知一旦建立,后面所有内容都会顺。

1.2 每一段路上“地址”扮演的角色不一样

四段路切开了,接下来要理解一个关键点:不同路段用的“地址”不是同一个东西。这就像寄快递,包裹上写的是最终收件地址(相当于 IP),但快递员在分拣中心之间传递时,靠的是每个中转站自己的内部编号和交接单(相当于 MAC 在局域网内的作用)。

具体来说:

路段主要使用的地址作用范围谁负责解析
本机内部无(走本地回环或直接系统调用)进程到网卡操作系统协议栈
本机到网关MAC 地址(局域网内)同一广播域ARP
网关到对端网关IP 地址(逐跳变化的是 MAC,IP 不变)跨网段路由表
对端网关到主机MAC 地址(局域网内)同一广播域ARP

这张表是整篇文章的骨架,建议你抄下来。它说明了一个特别容易被忽略的事实:IP 地址在整条路上基本不变(NAT 场景除外),而 MAC 地址每经过一个三层设备就会换一次。为什么?因为 MAC 只在局域网内有效,出了这个广播域就没意义了,所以每到一个新局域网,必须换成那个局域网内能识别的 MAC。这个点在后面第 4 节还会展开,这里先埋个伏笔。

1.3 用“寄快递”类比把封装和解封装串起来

数据往下走的时候要一层层“套信封”,往上走的时候要一层层“拆信封”,这就是封装和解封装。还是用快递类比:

你写一封信(应用层数据),装进信封写上收件地址(加 TCP/UDP 头,形成段),再装进快递袋贴上运单(加 IP 头,形成包),最后装进车厢(加 MAC 头,形成帧)发出去。到了每个中转站,工作人员拆开外层车厢看看运单(拆 MAC 头,看 IP),决定下一站,然后重新装车(换新 MAC 头)继续发。只有到了最终收件人手里,才会把信封拆开读到信的内容(一路拆到应用层)。

这个类比里有个细节值得强调:中转站只拆到“运单”这一层,不会拆信封。对应到网络里,路由器只处理到 IP 层,不会去动 TCP 头和里面的应用数据。这就是为什么端到端的可靠性(比如 TCP 重传)必须由两端自己保证,中间设备帮不上忙。理解了这一点,你就能明白为什么“网络层不保证可靠交付”这句话不是缺陷,而是设计上的取舍——把复杂性放在两端,中间设备才能做得简单、跑得快。

2. 软件虚拟层:数据在出网卡之前到底经历了什么

这一段是很多人最模糊的地方。大家知道“应用发数据、网卡发帧”,但中间那一大坨软件到底干了啥,说不清楚。我把它叫“软件虚拟层”,是因为这一层里全是“虚拟”出来的东西——虚拟的接口、虚拟的缓冲区、虚拟的连接状态,物理上你什么都看不到,但每一步都实实在在影响着性能和排错。

2.1 从 socket 到协议栈:一次 write 调用背后的动作序列

你在代码里写一句send()或者write(),看起来是一个动作,实际上内核里跑了一长串。以 TCP 为例,大致是这样:

  1. 应用把数据拷进内核的发送缓冲区。注意,write()返回成功不代表数据发出去了,只代表拷进缓冲区了。这是新手最容易误解的点,也是“为什么程序显示发送成功但对面没收到”的常见原因。
  2. TCP 层给数据分段、加头。根据 MSS(最大报文段长度)切分,加上源端口、目的端口、序列号、确认号、窗口大小等字段。
  3. IP 层加 IP 头。填源 IP、目的 IP、TTL、协议号等。这里要做一件关键的事:查路由表决定从哪个网卡出去、下一跳是谁。
  4. 查 ARP 缓存拿下一跳的 MAC。如果缓存里没有,就要先发 ARP 请求(这个后面细讲)。
  5. 链路层加 MAC 头,形成帧。
  6. 交给网卡驱动,驱动把帧塞进网卡的发送环形缓冲区(ring buffer),触发 DMA,网卡硬件真正把电信号/光信号打到线路上。

这一串动作里,第 3 步和第 4 步是“软件虚拟层”的核心。路由表决定了“往哪走”,ARP 决定了“交给谁”。这两个表都是纯软件维护的,你在ip route和arp -a里看到的就是它们。我排查网络问题时,第一步永远是看这两个表,十有八九问题就出在这儿。

提示:write()返回的是“拷进缓冲区的字节数”,不是“对端收到的字节数”。要确认对端收到,必须靠应用层的确认机制,别指望系统调用给你保证。

2.2 路由表:软件层怎么决定“下一跳”

路由表这个东西,说白了就是一张“目的地 → 出口”的对照表。Linux 上用ip route看,典型输出长这样:

default via 192.168.1.1 dev eth0 proto static 192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.100 10.0.0.0/8 via 192.168.1.1 dev eth0

怎么读?内核收到一个包,拿目的 IP 去匹配,遵循最长前缀匹配原则。比如目的 IP 是10.2.3.4,它会匹配到10.0.0.0/8这条(前缀长度 8),走网关192.168.1.1;如果目的 IP 是192.168.1.50,匹配192.168.1.0/24(前缀长度 24),直接走 eth0,不经过网关;如果都不匹配,就走default(前缀长度 0,最短,所以是兜底)。

这里有个实操中特别容易踩的坑:多条路由前缀长度相同时,看 metric(度量值),小的优先。我遇到过一台机器配了两条默认路由,metric 一样,结果流量随机走两个网关,时通时不通,排查了半天才发现是路由冲突。所以配路由时,要么保证 metric 有区分,要么就别配重复的。

还有一个概念叫“直连路由”,就是上面192.168.1.0/24 dev eth0这种,是网卡配了 IP 之后内核自动生成的,scope 是 link,表示“这个网段我直接能到,不用网关”。这类路由你一般不用手动配,但排查时要知道它存在,因为它优先级往往很高。

2.3 ARP:IP 到 MAC 的那次“广播喊话”

路由表告诉你“下一跳的 IP 是 192.168.1.1”,但网卡发帧需要的是 MAC 地址,这中间的转换就靠 ARP。过程很朴素:

  1. 本机广播一个 ARP 请求:“谁是 192.168.1.1?把你的 MAC 告诉我。”这个包的目的 MAC 是全 F(ff:ff:ff:ff:ff:ff),局域网内所有设备都能收到。
  2. 目标设备单播回复:“我是,我的 MAC 是 xx:xx:xx:xx:xx:xx。”
  3. 本机把这条映射存进 ARP 缓存,一段时间内不再重复问。

用arp -a或ip neigh能看到缓存。这里有几个实战经验值得说:

  • ARP 缓存有老化时间,Linux 默认大概几十秒到几分钟(具体看内核参数gc_stale_time等)。缓存过期后要重新 ARP,这会造成短暂延迟,高频通信场景下影响不大,但极端低延迟场景要留意。
  • ARP 是局域网内广播,跨网段问不到。所以如果你发现“能 ping 通网关但 ping 不通同网段另一台机器”,八成是 ARP 出问题了,先清缓存试试(ip neigh flush all)。
  • 免费 ARP(Gratuitous ARP)常用于 IP 冲突检测和主备切换,设备上线时主动广播自己的 IP-MAC 映射,通知大家更新缓存。做高可用的时候这个概念很重要。

2.4 虚拟网卡、网桥、命名空间:容器场景下的“软件虚拟层”长什么样

如果你做容器或者虚拟化,上面这套“软件虚拟层”会更复杂一层,因为网卡本身都是虚拟的。典型结构是:物理网卡 → 网桥(bridge)→ veth pair(一对虚拟网线)→ 容器内的虚拟网卡。数据从容器出来,先走 veth 到网桥,网桥再根据 MAC 决定转发到哪个口,最后从物理网卡出去。

这里的关键认知是:虚拟网卡和物理网卡在协议栈看来没区别,一样有 MAC、一样参与 ARP、一样查路由表。所以你在容器里ip route、arp -a看到的,和物理机上是同一套逻辑。区别只在于“线”是软件模拟的,转发靠的是网桥的软件交换逻辑,而不是硬件交换芯片。

这也解释了一个常见现象:容器网络性能不如物理机,瓶颈往往不在协议栈,而在 veth 和网桥这一段的软件转发开销,以及可能的多次内存拷贝。优化方向通常是减少拷贝(比如用零拷贝技术)、或者绕过网桥直接走路由。这些属于进阶内容,但底层逻辑还是那句话——软件虚拟层干的活,本质是把“物理上要做的事”用软件重新实现一遍,理解了物理链路,虚拟链路就不难。

3. IP 地址:不是“门牌号”那么简单

“IP 地址就像门牌号”——这个比喻流传太广,但它其实误导了很多人。门牌号是固定的、唯一的,而 IP 地址是分层的、可变的、甚至可以是共享的。把 IP 理解成“分层定位系统”更准确,它同时承担了“标识一台主机”和“帮助路由器定位网段”两个职责,这两个职责的张力,正是很多网络设计的根源。

3.1 点分十进制背后的二进制结构

192.168.1.100这个写法叫点分十进制,本质是 32 位二进制,每 8 位一组转成十进制用点隔开。所以:

192 . 168 . 1 . 100 11000000 . 10101000 . 00000001 . 01100100

为什么要懂二进制?因为子网掩码、网段计算、CIDR 表示法全都建立在二进制之上。比如192.168.1.100/24,这个/24表示前 24 位是网络位,后 8 位是主机位。网络地址就是把主机位全置 0:192.168.1.0;广播地址是主机位全置 1:192.168.1.255;可用主机范围是192.168.1.1到192.168.1.254,共 254 个。

这个计算看着简单,但实际排错时特别有用。我见过有人把两台机器配成192.168.1.10/24和192.168.1.200/25,看着都在 192.168.1 段,实际/25的网段是192.168.1.128到192.168.1.255,跟/24的192.168.1.0到192.168.1.127根本不是一个网段,互相 ping 不通太正常了。判断两台机器是否同网段,不能只看前三段数字,必须用掩码算。

3.2 私有地址、公网地址与 NAT 的现实妥协

IPv4 地址只有 32 位,理论上约 43 亿个,早就不够用了。解决办法之一是划出一批私有地址,只在内部网络使用,不直接在公网上路由:

地址段范围常见用途
A 类私有10.0.0.0/8大型内网、云上 VPC
B 类私有172.16.0.0/12中型网络、容器网络常用
C 类私有192.168.0.0/16家庭、小型办公网络

私有地址要访问公网,必须经过 NAT(网络地址转换),把私有源 IP 换成公网 IP。这就引出一个重要认知:IP 地址在整条路上“基本不变”这个说法,在 NAT 场景下要打折扣。经过 NAT 设备时,源 IP 会被改写,回来的包再被改回去。所以严格说,端到端的 IP 在 NAT 环境下并不是真正端到端的,这也是为什么有些 P2P 应用在 NAT 后面会出问题。

做开发的同学尤其要注意:如果你在代码里依赖“对端看到的源 IP 就是我本机 IP”,在 NAT 环境下这个假设不成立。日志里记录的客户端 IP 可能是 NAT 设备的地址,真实客户端 IP 要靠应用层透传(比如 HTTP 头里的转发字段)。这个坑我踩过不止一次。

3.3 子网划分的实际算法:手算一遍就再也不会忘

光看公式容易忘,手算一遍最扎实。假设给你172.16.8.0/22,要划分成能容纳 500 台主机的子网,怎么算?

先看/22有多少主机位:32 - 22 = 10 位,主机数 2^10 - 2 = 1022 个。要 500 台,需要 2^n - 2 ≥ 500,n 至少 9(2^9 - 2 = 510)。所以主机位留 9 位,网络位就是 32 - 9 = 23 位,即/23。

/22能切成两个/23:

  • 172.16.8.0/23:范围172.16.8.0到172.16.9.255
  • 172.16.10.0/23:范围172.16.10.0到172.16.11.255

每个/23有 510 个可用地址,满足 500 台需求。这个手算过程建议你自己拿几个网段练几遍,练到看到/22就能条件反射出“1022 个地址、能切两个 /23”,排错时速度会快很多。

注意:主机数计算永远要减 2,因为网络地址和广播地址不能分配给主机。这个“减 2”在点对点链路(/31)和单主机(/32)场景下有例外,但常规子网划分记住减 2 就行。

3.4 特殊地址清单:排错时能救命的那几个

有几个特殊 IP 段,平时不显眼,出问题时全靠它们定位:

  • 127.0.0.0/8:回环地址,127.0.0.1最常用。ping 它通,说明本机协议栈正常;不通,说明协议栈或网卡驱动有问题,跟外部网络无关。这是排查的第一步。
  • 0.0.0.0:表示“本机所有地址”或“未指定”。服务监听0.0.0.0表示监听所有网卡;路由表里的0.0.0.0/0就是默认路由。
  • 169.254.0.0/16:链路本地地址。如果你看到机器拿到这个段的 IP,基本可以断定 DHCP 没拿到地址,是自动分配的兜底地址,网络大概率不通。
  • 255.255.255.255:受限广播地址,只在本地网段广播,不跨路由器。

我排查“机器上不了网”的标准流程就是:先 ping127.0.0.1确认协议栈,再看 IP 是不是169.254段(DHCP 问题),再看路由表有没有默认路由,最后看 ARP 和 DNS。这套流程走下来,八成问题当场定位。

4. IP 与 MAC:为什么两个地址缺一不可

这是被问得最多的问题之一:“既然 IP 能定位主机,为什么还要 MAC?直接用 IP 通信不行吗?”这个问题问得好,答案藏在“分层”和“解耦”这两个词里。理解了这一层,你对网络设计的理解会上一个台阶。

4.1 从“谁负责送到”看两个地址的分工

先给结论:IP 负责“最终送到哪”,MAC 负责“这一跳交给谁”。两者职责完全不同,不能互相替代。

打个比方:你要从北京寄一份文件到广州某公司。收件地址(IP)写的是“广州市某区某路某号某公司”,这个地址在整个运输过程中不变,快递公司靠它决定最终送到哪。但文件在运输途中,从北京分拣中心到石家庄中转站、再到郑州中转站,每一段都是“北京站交给石家庄站的车”“石家庄站交给郑州站的车”,这个“交给谁”是每一跳临时决定的,相当于 MAC。你不可能在收件地址里写清楚“先交给石家庄站再交给郑州站”,因为路线可能变、中转站可能调整,写死了反而僵化。

对应到网络:IP 是端到端的逻辑地址,跨越整个网络不变(NAT 除外);MAC 是链路层的物理地址,只在当前局域网有效,每过一跳就换。用 IP 做端到端定位,用 MAC 做逐跳交付,各司其职,这是分层设计的精髓。

4.2 如果只有 MAC 会怎样:一个思想实验

假设我们不用 IP,只用 MAC 通信,会发生什么?

MAC 地址是 48 位,理论上全球唯一,看起来“直接用 MAC 定位”也行。但问题在于:MAC 地址没有层次结构。IP 地址是分层的(网络位 + 主机位),路由器可以只看网络位就把整个网段“打包”处理,路由表能压缩到几十万条覆盖全球。而 MAC 是扁平的,48 位里没有“你在哪个区域”的信息,路由器要转发就得记住全球每一台设备的 MAC,路由表会爆炸到不可维护。

更致命的是,MAC 地址跟硬件绑定,换网卡就换 MAC,设备移动位置 MAC 也不变,但网络拓扑变了,扁平地址根本无法表达“位置”。所以纯 MAC 通信在规模上根本行不通。这个思想实验说明:地址必须分层,才能支撑大规模网络。IP 的分层设计不是随便定的,是被规模逼出来的。

4.3 一次完整转发中两个地址的变化轨迹

把前面所有内容串起来,看一个包从 A 到 B 的完整轨迹,重点盯 IP 和 MAC 的变化:

阶段源 IP目的 IP源 MAC目的 MAC
A 发出A 的 IPB 的 IPA 的 MAC网关1 的 MAC
网关1 转发A 的 IPB 的 IP网关1 的 MAC网关2 的 MAC
网关2 转发A 的 IPB 的 IP网关2 的 MAC网关3 的 MAC
到达 B 网段A 的 IPB 的 MAC网关N 的 MACB 的 MAC

看这张表,规律一目了然:IP 从头到尾不变,MAC 每跳都换。这就是“端到端不变、逐跳变化”的直观体现。抓包的时候如果你在多个网段同时抓,会看到同一个包的 IP 头完全一样,但 MAC 头每段都不同,这就是最直接的证据。

这里补充一个细节:TTL 字段每经过一个路由器减 1,减到 0 就丢弃并回 ICMP 超时。这个机制防止包在网络里无限循环。traceroute就是利用 TTL 逐跳递增、收集每跳返回的 ICMP 超时包,从而画出路径的。理解了 TTL,你就理解了 traceroute 的原理,也理解了为什么“网络环路”会导致包被丢弃而不是永远转圈。

4.4 常见误解澄清:MAC 唯一不等于 MAC 不可改

最后澄清几个高频误解,这些在面试和实际排错里都容易翻车:

  • “MAC 地址全球唯一,所以不能改”:错。MAC 唯一性靠厂商自觉分配,软件层面完全可以改(网卡驱动支持的话),这叫 MAC 地址伪造。虚拟化环境里 MAC 更是随便配。唯一性只是“约定”,不是“物理定律”。
  • “同网段通信不需要 IP”:错。同网段通信虽然最终靠 MAC 交付,但发送方仍要用 IP 判断“是否同网段”(拿目的 IP 和自己的掩码算),判断完才决定是直接 ARP 目的 IP 还是 ARP 网关。IP 在这里承担的是“判断逻辑”,不是“交付手段”。
  • “交换机看 IP,路由器看 MAC”:反了。二层交换机看 MAC 转发,三层路由器看 IP 转发。这个基础别搞混。
  • “IP 地址能唯一标识一台设备”:不完全对。NAT 后面一堆设备共享一个公网 IP,负载均衡后面一个 VIP 对应多台机器。IP 标识的是“网络位置”,不是“设备身份”。

5. 把整条链路画在纸上:一份可复现的图解思路

前面讲了一堆概念,最后落到“怎么画一张自己能看懂的图”。我不给你现成的图,而是给你一套画图的方法,你照着画一遍,比看十张图都管用。这也是我带新人时最常用的训练方式。

5.1 画图前的准备:先确定三个要素

动手画之前,先把三个要素定下来,否则画出来是乱的:

  1. 拓扑:几台主机、几个网段、几个路由器。建议从最简单的开始——两台主机、两个网段、一个路由器,先把这条链路画透。
  2. 地址规划:每个网段用什么 IP 段,每台设备的 IP、网关、MAC 都标上。地址一定要具体,别写“A 的 IP”这种占位符,写192.168.1.10这种真实值,画的时候才有代入感。
  3. 通信方向:明确是“A 访问 B”,单向画,别一会儿正向一会儿反向,容易乱。

我建议用纸笔画,别一上来就用工具。纸笔慢,但慢的过程就是思考的过程。等你能在纸上流畅画出来,再用工具画就水到渠成了。

5.2 分层画法:一张图分三层叠上去

我的画法是分三层,从下往上叠:

  • 第一层画物理拓扑:主机、交换机、路由器、连线,标上接口。这一层只关心“谁和谁连着”。
  • 第二层画地址:在每个设备旁边标 IP、MAC、网关。这一层把第 3 节的地址知识用上。
  • 第三层画数据流:用箭头标出包从 A 出发,经过哪些设备,每个设备上 IP 和 MAC 怎么变。这一层把第 4 节的转发轨迹用上。

三层叠完,一张完整的图就有了。关键是每一层只关注一件事,别混着画,混着画必乱。这个方法和软件设计里的“关注点分离”是一个道理,画图也一样。

5.3 用文字把图“讲”出来:一个具体例子

假设拓扑是:主机 A(192.168.1.10/24,MACAA:AA)→ 路由器 R1(LAN 口192.168.1.1,MACR1L;WAN 口10.0.0.1,MACR1W)→ 路由器 R2(WAN 口10.0.0.2,MACR2W;LAN 口192.168.2.1,MACR2L)→ 主机 B(192.168.2.20/24,MACBB:BB)。A 要访问 B。

数据流这样走:

  1. A 拿目的 IP192.168.2.20和自己的掩码/24算,发现不同网段,决定走网关192.168.1.1。
  2. A 查 ARP 拿192.168.1.1的 MAC(R1L),封装帧:源 IP192.168.1.10,目的 IP192.168.2.20,源 MACAA:AA,目的 MACR1L,发出去。
  3. R1 收到,拆帧看目的 IP192.168.2.20,查路由表,下一跳是10.0.0.2。重新封装:源 IP 不变,目的 IP 不变,源 MAC 换成R1W,目的 MAC 换成R2W(ARP 得到),从 WAN 口发出。
  4. R2 收到,拆帧看目的 IP192.168.2.20,发现是直连网段,ARP 拿 B 的 MAC(BB:BB)。重新封装:源 IP 不变,目的 IP 不变,源 MAC 换成R2L,目的 MAC 换成BB:BB,从 LAN 口发出。
  5. B 收到,拆帧,目的 MAC 是自己,目的 IP 是自己,往上递交给协议栈处理。

你把这个过程在纸上画一遍,每个设备旁边标上“进什么帧、出什么帧”,IP 和 MAC 的变化就一目了然了。画完你会发现,整个过程里 IP 一次没变,MAC 换了三次(A→R1、R1→R2、R2→B),跟第 4 节的表格完全对得上。

5.4 画完之后的自检清单

图画完,用这几个问题自检,能答上来说明你真懂了:

  • 如果 A 的 ARP 缓存里没有网关的 MAC,第一步会发生什么?(答:先广播 ARP 请求)
  • 如果 R1 的路由表里没有去192.168.2.0/24的路由,包会怎样?(答:走默认路由或丢弃,取决于配置)
  • 如果 B 的网关配错了,A 能 ping 通 B 吗?(答:去程能到,回程回不来,表现为单向不通)
  • 如果中间某台设备的 MTU 较小,会发生什么?(答:可能分片,或触发 PMTUD,表现为大包不通小包通)

这几个问题覆盖了 ARP、路由、网关、MTU 四个高频故障点,能答上来,说明你对整条链路的理解是完整的,不是零散记忆。

6. 几个我踩过的坑和对应的排查手法

概念讲完,最后分享几个真实踩过的坑。这些坑教科书上不会写,但实际工作中遇到频率极高,尤其是做后端和运维的同学,早晚会碰上。

6.1 “能 ping 通 IP 但 ping 不通域名”:先分清楚是哪一层的问题

这个现象太常见了。ping IP 通,说明网络层及以下没问题——路由通、ARP 通、链路通。ping 域名不通,问题一定在 DNS 这一层。排查顺序:

  1. cat /etc/resolv.conf看 DNS 服务器配了没、配得对不对;
  2. nslookup 域名或dig 域名直接测 DNS 解析,看返回什么;
  3. 如果 DNS 服务器是内网的,确认到 DNS 服务器的路由通不通;
  4. 检查是不是防火墙拦了 53 端口。

我遇到过一次,resolv.conf里配的 DNS 服务器 IP 是旧的,早下线了,但系统一直没报错,只是解析超时后走备用,慢得让人抓狂。这种问题不看配置文件根本发现不了。

6.2 “同网段两台机器不通”:优先怀疑掩码和 ARP

同网段不通,比跨网段不通更让人困惑,因为“看起来应该通”。我的排查顺序是:

  • 先算掩码:拿两台机器的 IP 和掩码分别算网络地址,确认真的同网段。前面说过,/24和/25看着像同段,实际可能不同段。
  • 再看 ARP:ip neigh看有没有对方的 MAC 记录。没有的话,手动 ping 一下触发 ARP,再看有没有。如果 ARP 请求发了但没回应,可能是对方防火墙拦了 ARP,或者中间有隔离(比如交换机的端口隔离功能)。
  • 最后看交换机:如果是物理环境,确认两台机器接的交换机端口在同一个 VLAN。VLAN 配错导致“物理同网段、逻辑不同广播域”的情况,我见过不止一次。

6.3 “改完 IP 后时通时不通”:ARP 缓存没刷新

这个坑特别隐蔽。你给一台机器改了 IP,但同网段其他机器的 ARP 缓存里还留着旧 IP 对应的旧 MAC,或者旧 IP 对应的记录没清,导致流量发到错误的地方。表现就是“时通时不通”,因为有的机器缓存刷新了,有的没刷。

解决办法:改 IP 后,在相关机器上清 ARP 缓存(ip neigh flush all),或者等缓存自然老化。更彻底的做法是改 IP 时发免费 ARP 通知大家更新。这个细节在做服务器迁移、主备切换时特别重要,不做的话切换后会有几分钟的“抖动期”。

6.4 “大包不通小包通”:MTU 和分片问题

ping 小包通、大包不通,或者 SSH 能连上但传大文件卡死,八成是 MTU 问题。链路中某一段的 MTU 比端到端协商的小,大包被丢弃,而 ICMP 的“需要分片”消息又被防火墙拦了,导致发送方不知道要减小包,一直重传大包。

排查手法:用ping -s 1472 -M do 目标IP(1472 + 28 = 1500,即标准 MTU)逐步减小包大小,找到能通的最大值,就知道链路的实际 MTU 了。这个手法在跨运营商、走隧道(比如 IPsec、GRE)的场景下特别有用,因为隧道封装会增加开销,实际可用 MTU 比 1500 小。

提示:隧道场景下,TCP MSS 需要相应调小,否则会出现“握手成功但传数据卡死”的经典现象。这个坑在云上跨可用区通信时很常见。

6.5 排查的通用心法:从下往上,逐层排除

最后说个心法。网络排查最忌讳“猜”,正确做法是从下往上逐层排除:物理层(网线、网卡状态)→ 链路层(ARP、MAC)→ 网络层(IP、路由、ping)→ 传输层(端口、防火墙)→ 应用层(服务、配置)。每层用对应的工具验证,验证通过再往上走,别跳。

这套方法看着笨,但最可靠。我见过太多人一上来就怀疑应用代码,查了半天发现是网线没插好。逐层排除虽然慢一点,但不会漏,而且每排除一层,你就对这条链路多一分把握。排查完一次,把过程记下来,下次遇到类似问题,直接照着走,效率会越来越高。

这套东西说到底,核心就一句话:网络传输是分层的、逐跳的、地址是分工的。把这三件事想透,剩下的都是细节。图你自己画一遍,坑你自己踩一遍,比看多少篇文章都管用。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进