【学习VPN之路】IP网络包路由原理

131 阅读12分钟

1. 路由分类

  • 本地内核路由: IP数据包在发送和接收后,都需要经过本机的路由到达本机的处理IP包的应用程序。
    • 决定一个 IP 包应该发往哪个本地网卡(如 TUN、ETH),这由本机的路由表控制。
  • 网络路径路由: 当IP数据包从本机发送以后,IP包需要借助各种网络设备路由到目标机器。
    • 决定一个从网卡发出去的数据包,如何在互联网或局域网中跳转、转发,最终到达目标 IP。这里包括NET技术。

2. 本地内核路由

2.1. 过程

一个应用程序的IP数据包发送过程中,需要知道应该被哪个网卡发送出去?操作系统会根据目标IP地址查找路由表, ****定位到匹配的路由条目,根据匹配的路由条目内的对应的网卡名称,定位到网卡,比如是A网卡,A网卡的地址是10.2.7.1。然后操作系统会将应用程序发送的IP包封装成A网卡要求的格式,比如IP源地址是A网卡的地址10.2.7.1。

➜  ~ route -n get default #获取默认路由条目
   route to: default
destination: default
       mask: default
    gateway: 192.168.3.1
  interface: en0
  • route to: default:表示你正在查询的路由目标是 default,即所有不在本地路由表中的目的地址(0.0.0.0/0)。
  • destination: default:路由目标(destination)是 default,和 route to 一致,表示默认路由。
  • mask: default:掩码是 default,等价于 0.0.0.0,表示没有具体匹配,也就是说这是最低优先级的“兜底路由”。
  • gateway: 192.168.3.1:网关(下一跳)是 192.168.3.1,即所有不匹配其它规则的 IP 包,都会通过这个网关发送出去。
  • interface: en0:使用的网络接口是 en0,即这条默认路由是走 en0 网卡出去的,通常是你的 Wi-Fi(在 Mac 上)。

2.2. 例子1

🧱 环境设定

你的电脑有如下网络配置:

网络属性
本机 IP 地址192.168.3.123
子网掩码255.255.255.0
默认网关192.168.3.1
网卡名称en0(Wi-Fi)
路由表默认条目0.0.0.0/0 → 192.168.3.1 via en0

目标 IP:比如你访问 8.8.8.8(Google 的 DNS)

🧭 过程

  1. 应用层发起请求
    你执行 ping 8.8.8.8,或者浏览器访问了某个外网网站。请求经过用户态的应用,进入内核网络栈。
  2. 内核构造 IP 包(还未封装)
    • 源地址暂未确定(操作系统稍后填充)
    • 目的地址:8.8.8.8
    • TCP/UDP 层也填入自己的端口等信息
  1. 内核查找路由表
    • 目标 IP 是 8.8.8.8,不在局域网内
    • 内核查到路由表里 default 路由是 0.0.0.0/0 → 192.168.3.1 via en0
    • 决定走 en0 网卡,并把网关设置为 192.168.3.1
  1. 确定源 IP
    • 因为要走 en0,内核从 en0 网卡配置中取出源 IP 填入包头:192.168.3.123
  1. 查找网关 MAC 地址
    • 为了发送数据帧,必须知道下一跳网关的 MAC
    • 内核在 ARP 缓存中查找 192.168.3.1 的 MAC(例如:aa:bb:cc:dd:ee:ff),没有的话就发 ARP 请求获取
  1. 封装以太网帧
    • 以太网头部:
      • 目的 MAC:aa:bb:cc:dd:ee:ff(网关)
      • 源 MAC:你的 en0 网卡的 MAC(比如:11:22:33:44:55:66
      • EtherType:0x0800 表示是 IPv4 包
    • 帧数据部分就是上面构造好的 IP 包
  1. 发出
    • 整个以太网帧通过 en0 发送出去
    • 到达路由器(192.168.3.1),由它继续转发

2.3. 例子2

2.3.1. 环境设定

  • 你在 macOS 上运行一个本地 TCP 服务监听在 127.0.0.1:5000。
  • 然后你用另一个进程发起连接:telnet 127.0.0.1 5000

这时候你发送的目标 IP 是 127.0.0.1,属于回环地址,操作系统会使用本地回环接口 lo0 来处理该包。数据包不会出网卡,也不会走网关,完全在本机的内核网络协议栈中流转。

我们来看一下系统的路由信息:

  ~ route -n get 127.0.0.1
   route to: 127.0.0.1
destination: 127.0.0.0
       mask: 255.0.0.0
    gateway: 127.0.0.1
  interface: lo0

字段解释:

  • route to: 127.0.0.1:表示我们查询的目标是 127.0.0.1
  • destination: 127.0.0.0:匹配的路由目标是 127.0.0.0,这是整个回环网段。
  • mask: 255.0.0.0:路由掩码为 /8,也就是 127.0.0.0 到 127.255.255.255 都走这个回环。
  • gateway: 127.0.0.1:下一跳是本机。
  • interface: lo0:数据包走的接口是 lo0,也就是回环接口。

说明:

  • 所有发往 127.0.0.1/8 网段的 IP 包都会被送入 lo0 这个回环设备。

2.3.2. 过程

  • 应用层:你执行 telnet 127.0.0.1 5000,TCP 建立连接。
  • 内核路由查找:目标 IP 为 127.0.0.1,在路由表中查找,匹配 127.0.0.0/8,接口为 lo0
  • IP 层封装:
    • 源 IP:也是 127.0.0.1(系统会自动使用回环地址作为源地址)
    • 目标 IP:127.0.0.1
  • 网络层决定走 lo0,包并不会实际发到物理网卡。
  • 最终数据在内核内部流转,直接转交给监听该地址的本地服务处理。

2.4. 例子3

2.4.1. 环境准备

  • 当前主机安装了一个使用 TUN 设备的 VPN 客户端(例如 WireGuard)。
  • TUN 虚拟网卡名为:utun3
  • VPN 服务器分配的虚拟 IP:10.7.0.2/32
  • VPN 虚拟网关地址:10.7.0.1
  • 目标:访问 Facebook 的 IP 地址 31.13.71.36,希望通过 VPN 走 utun3

2.4.2. 📊 路由表相关条目(部分)

$ netstat -rn -f inet
Destination        Gateway            Netif
default            192.168.3.1        en0
10.7.0.1/32        10.7.0.1           utun3
10.7.0.2/32        link#13            utun3
31.13.71.36/32     10.7.0.1           utun3

2.4.3. 📤 发包过程

  1. 应用程序(如 Safari)尝试访问 https://facebook.com,DNS 解析得到 IP 31.13.71.36
  2. 操作系统查找目标 IP 31.13.71.36 在路由表中对应的路由条目。
    • 命中路由条目:
31.13.71.36/32 -> 网关 10.7.0.1,接口 utun3
  1. 操作系统选择将此包交给 utun3 接口处理。
    • 源地址设置为 TUN 虚拟 IP:10.7.0.2
    • 目标地址为:31.13.71.36
  1. IP 包封装后进入 TUN 网卡 utun3,传给 VPN 应用(如 wireguard-go)
  2. VPN 应用将 IP 包加密封装为 UDP 数据包,发往真实公网 VPN 服务器地址
    • 源地址:en0 的公网地址(如 192.168.3.20)
    • 目标地址:VPN 服务器公网 IP(如 3.3.3.3:51820)
  1. 加密封装后的 UDP 包通过物理网卡 en0 发出

2.4.4. 📥 收包过程

  1. 从服务器返回的加密 UDP 包通过 en0 接收。
  2. WireGuard 监听端口接收到该包,解密得到原始 IP 数据包:
    • 源地址:31.13.71.36
    • 目标地址:10.7.0.2
  1. 内核将该 IP 包投递给目标地址 10.7.0.2 → 属于本地 utun3
  2. IP 层找到是本机的 IP(TUN IP),交由应用层处理。

3. 网络路径路由

这里要特别注意:路由器转发IP包,并接受外部IP,转发给路由器所在的内网机器。这个过程NET技术。是VPN技术里使用的重要技术

3.1. 定义

网络路径路由是指:当 IP 数据包从本机网卡发送出去后,经过路由器等网络设备,按路由协议和路由表规则,逐跳转发直到最终目标机器的过程。

换句话说,网络路径路由决定了:

  • 一个从本机网卡发出的数据包,
  • 如何通过互联网或局域网中的多个路由设备,
  • 逐层跳转(hop),
  • 最终抵达目的 IP 所在的主机或设备。

3.2. 作用

  • 指导数据包在复杂网络中“走哪条路”,跳过哪些中间设备。
  • 解决跨网段通信和多网络环境下的数据传递问题。
  • 让远程主机之间能够互相找到并通信。

3.3. 过程

  1. 本机发送数据包
    发送方应用发起数据包后,内核根据本地路由表确定哪个接口发出(如前面本地路由所述)。
  2. 本机封装以太网帧
    IP 包封装到链路层帧(如以太网帧),下一跳地址是网关(默认网关或特定路由的下一跳)。
  3. 数据包到达第一跳路由器
    第一个路由器收到数据包后:
    • 解封装链路层帧,读取 IP 包。
    • 查找自己的路由表,根据目的 IP 决定下一跳。
    • 重新封装链路层帧,发给下一跳。
  1. 多跳转发
    数据包在网络中多个路由器跳转,每跳都类似上述操作。
  2. 到达目标网络
    最后一个路由器根据目的 IP 找到目标设备所在的局域网,封装链路层帧发给目标设备。
  3. 目标设备接收处理
    目标设备收到数据包后,交由上层协议栈处理,最终交给目标应用。

3.4. 例子

局域网主机ping 外网 34.22.45.10。

Ping使用的是ICMP协议,ICMP协议底层是IP协议

3.4.1. 环境设定

  • 局域网主机:IP=192.168.1.100,子网掩码 = 255.255.255.0,默认网关 = 192.168.1.1(家用路由器 LAN 口 IP)。
  • 家用路由器
    • LAN 口:192.168.1.1(连接局域网);
    • WAN 口:203.0.113.5(公网 IP,由 ISP 分配),默认网关 = 203.0.113.1(ISP 上级路由器 IP)。
    • 路由表(简化):
目的网络子网掩码下一跳(网关)出口接口说明
192.168.1.0/24255.255.255.0直接连接LAN 口局域网内主机直接转发
0.0.0.0/0(默认)0.0.0.0203.0.113.1WAN 口所有外网流量走 ISP 网关
  • 外网目标 IP:34.22.45.10(假设位于公网,已联网)。

3.4.2. 过程

3.4.2.1. 步骤 1:主机生成 ICMP 请求包
  • 主机 192.168.1.100 的操作系统(如 Windows/Linux)生成ICMP Echo Request(请求包)
    • 数据链路层:暂未封装 MAC 地址(待后续填充);
    • 网络层(IP 头):
      • 源 IP=192.168.1.100,目的 IP=34.22.45.10;
      • 协议字段 = 1(表示 ICMP);
    • 传输层(ICMP):
      • 类型 = 8(Echo Request),代码 = 0,包含随机序列号和数据(如 “abc123”)。
3.4.2.2. 步骤 2:主机查询自身路由表,确定下一跳

主机发送前需判断 “34.22.45.10 是否在局域网内”,通过子网掩码计算

  • 局域网网段:192.168.1.0/24(192.168.1.0~192.168.1.255);
  • 34.22.45.10 不在该范围,因此需要通过默认网关转发。

查询主机路由表(简化):

目的网络子网掩码网关接口说明
192.168.1.0/24255.255.255.00.0.0.0本地网卡局域网内直接通信
0.0.0.0/00.0.0.0192.168.1.1本地网卡外网流量走默认网关

结论:34.22.45.10 匹配 “0.0.0.0/0”,下一跳是网关 192.168.1.1,通过本地网卡发送。

3.4.2.3. 步骤 3:主机查询 ARP 缓存,获取网关 MAC 地址

IP 包需封装成以太网帧(数据链路层),需知道网关 192.168.1.1 的 MAC 地址:

  • 主机查自身 ARP 缓存(记录 IP 与 MAC 的映射):
    • 若缓存中有 192.168.1.1 → MAC(如 aa:bb:cc:dd:ee:ff),直接使用;
    • 若没有,发送ARP 请求帧(广播):“谁有 192.168.1.1 的 IP?请回复我(192.168.1.100)的 MAC(ff:ee:dd:cc:bb:aa)”。
  • 路由器 LAN 口收到 ARP 请求,回复ARP 应答帧(单播):“192.168.1.1 的 MAC 是 aa:bb:cc:dd:ee:ff”。
  • 主机更新 ARP 缓存,记录 192.168.1.1 → aa:bb:cc:dd:ee:ff。
3.4.2.4. 步骤 4:主机发送封装后的 ICMP 请求包到路由器

主机将 ICMP 请求封装为以太网帧

  • 帧头:源 MAC=ff:ee:dd:cc:bb:aa(主机 MAC),目的 MAC=aa:bb:cc:dd:ee:ff(路由器 LAN 口 MAC),类型 = 0x0800(表示上层是 IP 协议);
  • 帧数据:IP 包(含 ICMP 请求);
  • 通过网线发送到路由器 LAN 口。
3.4.2.5. 步骤 5:路由器接收 IP 包,查询自身路由表

路由器 LAN 口收到帧后,解封装(去掉帧头),得到 IP 包(目的 IP=34.22.45.10),开始处理:

  1. 检查目的 IP 是否在局域网:34.22.45.10 不在 192.168.1.0/24,需转发到外网;
  2. 查询路由器路由表(见场景设定):
    • 34.22.45.10 匹配 “0.0.0.0/0”(默认路由),下一跳是 203.0.113.1(ISP 上级路由器),出口接口是 WAN 口;
  1. NAT 转换(关键!局域网 IP 需转换为 WAN 口公网 IP):
    • 路由器修改 IP 包的源 IP:从 192.168.1.100 → 203.0.113.5(自身 WAN 口 IP);
    • 记录 NAT 表项:192.168.1.100:ICMP(标识符=12345) → 203.0.113.5:ICMP(标识符=12345)(用于后续匹配响应)。
3.4.2.6. 步骤 6:路由器查询 WAN 口网关 MAC,转发到外网

路由器需将转换后的 IP 包通过 WAN 口发送到 ISP 网关 203.0.113.1:

  1. 查路由器 WAN 口的 ARP 缓存,获取 203.0.113.1 的 MAC(如 11:22:33:44:55:66);
  2. 封装以太网帧:
    • 源 MAC = 路由器 WAN 口 MAC(如 aa:bb:cc:11:22:33),目的 MAC=11:22:33:44:55:66;
    • 帧数据:转换后的 IP 包(源 IP=203.0.113.5,目的 IP=34.22.45.10,ICMP 请求);
  1. 通过 WAN 口发送到 ISP 上级路由器。
3.4.2.7. 步骤 7:外网路由器逐级转发,到达目标主机
  • ISP 上级路由器(203.0.113.1)收到包后,查询自身路由表,找到 34.22.45.10 所在网段的下一跳,继续转发;
  • 经过多级外网路由器(骨干网、目标网段网关),最终 ICMP 请求包到达 34.22.45.10 主机。
3.4.2.8. 步骤 8:目标主机处理 ICMP 请求,生成响应包

34.22.45.10 主机收到 ICMP 请求:

  • 解封装后发现是 ICMP Echo Request(Type=8),生成ICMP Echo Reply(Type=0)
  • 响应包的 IP 头:源 IP=34.22.45.10,目的 IP=203.0.113.5(路由器 WAN 口 IP);
  • 封装后按原路返回(通过目标主机的默认路由转发)。

3.4.3. 二、接收过程(ICMP 响应从目标主机返回局域网主机)

3.4.3.1. 步骤 9:响应包经外网返回家用路由器 WAN 口
  • 响应包沿 “目标主机→外网路由器→ISP 上级路由器” 反向路径转发,最终到达家用路由器 WAN 口;
  • 路由器 WAN 口收到帧,解封装得 IP 包(源 IP=34.22.45.10,目的 IP=203.0.113.5,ICMP 响应)。
3.4.3.2. 步骤 10:路由器查询 NAT 表,还原内网 IP

路由器处理响应包:

  1. 查 NAT 表,发现 “目的 IP=203.0.113.5,ICMP 标识符 = 12345” 对应内网主机 192.168.1.100;
  2. 修改 IP 包的目的 IP:从 203.0.113.5 → 192.168.1.100;
  3. 查询路由器路由表,确定 192.168.1.100 在局域网(192.168.1.0/24),下一跳是 “直接连接”,出口接口是 LAN 口。
3.4.3.3. 步骤 11:路由器查询主机 MAC,转发响应包到主机
  1. 路由器查 LAN 口 ARP 缓存,获取 192.168.1.100 的 MAC(ff:ee:dd:cc:bb:aa);
  2. 封装以太网帧:源 MAC = 路由器 LAN 口 MAC(aa:bb:cc:dd:ee:ff),目的 MAC=ff:ee:dd:cc:bb:aa;
  3. 通过 LAN 口发送到 192.168.1.100 主机。
3.4.3.4. 步骤 12:主机接收响应,完成 ping
  • 主机收到帧,解封装得 ICMP 响应包(Type=0);
  • 操作系统匹配到之前发送的 ping 请求,在终端显示 “Reply from 34.22.45.10: bytes=32 time=xxms TTL=xx”。

3.4.4. 关键总结

  1. 路由表作用:每台设备(主机、路由器)通过路由表决定 “IP 包该发给谁(下一跳)”,核心是 “最长前缀匹配”(精确网段优先于默认路由);
  2. ARP 作用:在数据链路层将 IP 地址转换为 MAC 地址,确保帧能正确送达物理设备;
  3. NAT 作用:家用路由器通过 NAT 将局域网私有 IP 转换为 WAN 口公网 IP,实现内网主机访问外网(同时解决公网 IP 不足问题);
  4. 双向对称性:请求和响应路径对称,反向过程是正向的 “镜像操作”(NAT 还原、路由反向查询)。

通过这个过程,可以清晰看到 “网络分层”(应用层→网络层→数据链路层)的协作,以及路由、ARP、NAT 在其中的关键作用。