Phase 0 你看懂了数据包穿过哪几层。Phase 1 换挡:在一台 Linux 上,亲手把这些东西造出来、调出来。第一站是认全"网卡"——但你很快会发现,Linux 里绝大多数"网卡"根本不是硬件。其中 veth 和 bridge 你在 Phase 0 其实已经用过了(0.3 的 namespace 实验、0.2 的 br-lan),这章把它们连同 eth/wlan/lo/vlan/tun·tap 一并讲清。
网络接口(Network Interface):内核暴露的"收发数据包的端点"。它可能对应一块物理网卡,也可能纯粹是软件造出来的——内核一视同仁。
1接口:内核眼里的网卡
这是 Phase 1 第一个要扭转的直觉:你以为"网卡 = 那块插网线的硬件",但内核眼里,接口只是一个有名字、能进出数据包的对象。物理网卡是接口,环回是接口,你后面要造的 bridge、veth、隧道全是接口。先列出本机所有接口:
ip link show # 列出全部接口
ip -br link # 紧凑视图(一行一个,看名字+状态最方便)
每个接口都有:一个名字(eth0、wlan0、lo…)、一个 index(内核内部编号)、一组状态标志(UP / DOWN / LOWER_UP…)、MTU(0.2 那个 1500),以及大多数都有一个 MAC 地址(也是 0.2)。
最简单的接口是 lo(loopback,环回):每台机器都有,发给它的包永远留在本机、不出网卡。127.0.0.1 和 ::1 就绑在它上面。你 curl localhost,包在 lo 上转一圈就回来了,根本不碰物理网卡——这也是本机服务间通信飞快的原因。回想 0.3 的 namespace 实验:每个 namespace 我都单独 ip link set lo up,正因为每个网络命名空间有自己独立的 lo。
它是内核提供的一个"虚拟端点",看着像真设备,数据却根本不出内核。这正是后面所有虚拟接口的共同气质——名字和真网卡一样,背后没有硬件。
2物理接口:eth 与 wlan
eth(以太网)和 wlan(Wi-Fi)是少数真正接硬件的接口,直接连着网卡驱动。各有一个硬件 MAC(0.2);eth 收发以太网帧,wlan 收发 802.11 帧但对上层伪装成以太网。
命名上有新旧两套:传统是 eth0 / wlan0;现代 systemd 用可预测命名(predictable naming)——enp3s0(en=ethernet,p3=PCI 总线 3,s0=插槽 0)、wlp2s0(wl=wireless lan)。好处是插拔、重启后名字不变。
ip link set eth0 up # 启用接口(就是 Phase 0 实验里的 set ... up)
ip link set eth0 down # 禁用
ethtool eth0 # 有线物理层细节:速率、双工、连接状态
iw dev # 无线接口与连接信息(Wi-Fi)
路由器的物理口(一个 WAN 口、几个 LAN 口)就是这些 eth 接口。但 0.2 学过,LAN 那几个口背后被桥成一个 br-lan——也就是路由器把多个物理 eth 接口"绑"进了一个 bridge。OpenWRT 新版用 DSA(Distributed Switch Architecture)把交换芯片的每个口暴露成独立 eth 接口(lan1、lan2…),再按需桥接——正是 1.1 这些接口类型在真实路由器里的样子。下一节就讲 bridge。
3bridge 与 veth:虚拟布线的两件基本元件
这是 Phase 1 真正打开局面的一节。有两件软件元件,合起来你就能在一台机器上搭出任意网络拓扑:
- bridge = 内核里的一台软件交换机:把多个接口"插"进它,这些接口就成了同一个二层网段,像接在同一台交换机上。
- veth = 一对虚拟网线:总是成对出现,从一端进的包从另一端出。
bridge:软件交换机
回想 0.2:交换机在二层按 MAC 转发帧,br-lan 把路由器多个 LAN 口并成一个广播域。Linux bridge 就是这台交换机的软件版。
sudo ip link add br0 type bridge # 造一个 bridge,叫 br0
sudo ip link set br0 up
sudo ip link set eth1 master br0 # 把 eth1 插进 br0(eth1 成为 br0 的一个口)
ip link show master br0 # 看谁插在 br0 上
bridge link # 看桥的端口
veth:成对的虚拟网线
回想 0.3:namespace 实验里,我用 ip link add v-h1 type veth peer name v-r1 造了一对 veth,两端分别塞进不同 namespace,当作连接它们的网线。veth 永远成对,从一端进的包从另一端出——天生用来"连接两个隔离的网络域"。
sudo ip link add veth-a type veth peer name veth-b # 造一对:a、b 是一根线的两头
sudo ip link set veth-b master br0 # 例如把一端插上 br0
# 另一端可以塞进某个 namespace(0.3 那样),或留在本机
bridge 当交换机、veth 当网线、namespace(0.3,1.4 细讲)当主机——三件凑齐,就能在一台机器上搭任意拓扑。你 docker run 起一个容器,Docker 背后做的正是:建一个 namespace,造一对 veth,一端进容器、一端插上 docker0 这个 bridge。你 Phase 0 手动跑的那套 netns + veth,就是容器网络的本质。
一台 OpenWRT 路由器的 br-lan 就是这一节的 bridge:把 lan1、lan2、lan3 这些 eth 接口 master br-lan,它们就成了同一个二层网段,LAN 口之间二层互通。你在 /etc/config/network 写的 bridge device + ports,netifd 翻译成的正是这几条 ip link add … type bridge + ip link set … master。
4VLAN:一条线切多个网段
VLAN(802.1Q)在以太网帧头插一个 4 字节的 VLAN tag,带一个 VLAN ID(1–4094)。同一条物理线上,不同 VLAN ID 的帧互相看不见——逻辑上等于多台独立交换机。回想 0.2 的以太网帧:这个 tag 就插在源 MAC 和类型字段之间。
为什么有用:家里一根网线 / 一台交换机,想隔离出 LAN / Guest / IoT 三个网段(各自的访问策略),不必拉三条线,打 VLAN 标签即可。在 Linux 上造 VLAN 子接口:
# 在 eth0 上造一个 VLAN 10 的子接口
sudo ip link add link eth0 name eth0.10 type vlan id 10
sudo ip link set eth0.10 up
# eth0.10 收发的帧都带 VLAN tag 10;eth0 本身还能同时跑别的 VLAN
命名约定 eth0.10 = eth0 上的 VLAN 10。
这正是路由器做 LAN / Guest / IoT 隔离的底层手段:一个口插交换机,交换机按 VLAN 分,路由器在不同 VLAN 子接口上跑不同网段 + 不同防火墙策略。本课程后面 1.3 的"三 VLAN 家庭防火墙"专题、2.7 的 VLAN 隔离都靠它;OpenWRT 的 DSA 也是用 VLAN 在交换芯片里划隔离。
5tun/tap:用户空间的网卡
前面的接口,包都在内核里流转。tun/tap不同:它在内核和某个用户态程序之间架了个口子,把进出这个接口的包交给程序处理。两种模式:
- tap:工作在二层,收发完整以太网帧(像一块虚拟网卡);
- tun:工作在三层,收发 IP 包(没有以太网头)。
谁用它:VPN。一个 VPN 程序创建一个 tun 接口,系统把要走 VPN 的 IP 包路由到 tun;VPN 程序从 tun "读出"这些包,加密后通过普通 socket 发给对端;对端解密、写回它的 tun。OpenVPN 是这个模式;WireGuard 在内核里实现,但对外同样呈现一个 tun 风格的接口 wg0。
ip link show type wireguard # WireGuard 接口(1.6 隧道技术细讲)
sudo ip tuntap add dev tun0 mode tun # 通用 tun(一般由 VPN 程序自动建)
内核往里写 IP 包,你的程序从里读;你的程序往里写,内核当成"收到的包"处理。VPN 的本质,就是把这些包在用户态加密后,套进另一条普通连接里发走。理解了 tun,你就理解了几乎所有 VPN 的工作方式。
路由器上的 WireGuard / OpenVPN(本课程 3.4 的 WireGuard mesh、2.7 的透明代理)都基于 tun 风格接口。你给路由器配一个 wg0,把要走隧道的流量路由过去——又回到了"接口 + 路由表"这套 Phase 0 的基本盘:一切流量调度,最后都落到"从哪个接口出、查哪条路由"。
本章小结
- 接口是内核抽象,不一定是硬件;
ip link列出全部。 - lo:本机环回,localhost 流量不出网卡;每个 namespace 各有一个。
- eth / wlan:真接硬件;现代用可预测命名(
enp3s0/wlp2s0)。 - bridge(软件交换机,把接口
master进去)+ veth(成对虚拟网线)+ namespace = 在一台机器上搭任意拓扑,也是容器网络的底层积木。 - VLAN:帧里打 tag,一条线跑多个隔离网段(LAN/Guest/IoT)。
- tun/tap:内核把包交给用户态程序,VPN 的基础(tun=三层,tap=二层)。
动手练习
- 跑
ip -br link,给你机器上每个接口归类:哪些是物理(eth/wlan)、哪些是虚拟(lo/docker0/veth/…)?有没有docker0这种 bridge? - 造一对 veth、一个 bridge,把 veth 一端插上 bridge(
ip link add+master),用bridge link确认插上了;做完用ip link del清理。 - 思考题:你
curl http://127.0.0.1:3000访问本机服务,这个包经过物理网卡吗?走的是哪个接口?(回想 lo。) - 进阶:若装了 Docker,跑
ip link找docker0(一个 bridge)和若干 veth;docker run一个容器后再看,多了什么?把它和 0.3 的 namespace + veth 实验对应起来。