在真实的嵌入式产品——尤其是多网口网关、工业路由器、车载中央网关、边缘计算设备中,我们经常会面临一个更复杂的需求:让多张网卡、多个网段、多个应用互相隔离,互不干扰,甚至拥有完全独立的网络栈。
传统的做法是用路由表、策略路由、VLAN 划分来实现隔离,但这种方式配置复杂、容易出错、权限无法完全分开。而 Linux 内核提供了一种更轻量、更干净、更彻底的隔离方案,也是现代容器、虚拟化、多云接入、多链路复用的底层基础——网络命名空间(Network Namespace,简称 netns)。
很多嵌入式工程师会误以为“网络命名空间是容器才用的技术”,这是一个非常普遍的误区。在嵌入式场景里,netns 几乎是高级网络产品的标配:4G/5G 多路拨号、多 WAN 叠加、管理网口安全隔离、应用与系统网络分离、虚拟路由功能,全部依赖这项技术。本文参考Bootlin资料进行总结归纳。
一、为什么嵌入式设备需要网络命名空间?
在单网卡、单 IP 的简单设备里,我们确实不需要网络命名空间。但只要设备进入多网口、多链路、多网段的场景,传统共享网络栈的问题立刻暴露出来。
举几个最常见的嵌入式产品痛点:
一台工业网关,有 eth0 网口、eth1 网口、wwan0 4G 上网卡。如果三张网卡共用同一个网络命名空间,就会共用同一张路由表。系统很可能把默认路由指向 eth0 或 wwan0,导致外网不通、内网冲突、路由表混乱。
再比如,设备需要提供一个独立的“调试管理网口”,不允许业务程序访问,也不允许被外部扫描。如果共享网络栈,即使配置了 iptables,也依然存在越权访问的风险。
还有更复杂的场景:多路 4G 拨号叠加。每张模组都需要独立的 DNS、独立的默认路由、独立的 iptables 规则,共享网络栈根本无法实现。
容器与边缘应用场景就更不用说了,一个运行在设备上的第三方应用,绝对不允许它随意修改系统的网卡、路由、ARP 表,否则会导致整个设备崩溃。
这些问题的本质只有一个:所有网络资源都在同一个空间里,彼此无法彻底隔离。
而网络命名空间要解决的,就是这件事:让系统内可以同时运行多套完全独立的网络栈,每套网络栈都有自己的网卡、IP、路由、ARP 表、防火墙、端口范围,互相看不见、摸不着、干扰不到。
它不是虚拟化,不是虚拟机,而是内核级别的轻量级资源隔离。几乎没有 CPU 开销,几乎没有内存开销,是嵌入式设备最理想的“网络虚拟化”方案。
二、网络命名空间到底是什么?内核如何实现?
从用户视角看,网络命名空间就像是给系统“多开了几套网络环境”。
从内核视角看,它的实现非常优雅:Linux 内核把所有和网络相关的全局变量、全局结构,全部封装进一个统一的结构体——struct net。每个 struct net 就是一个独立的网络命名空间。
当系统启动时,内核会自动创建一个初始命名空间,叫做 init_net。我们平时登录设备看到的所有网卡、IP、路由,全都属于 init_net。
当我们使用 ip netns add ns1 创建新的命名空间时,内核会复制一份全新的、干净的网络环境:
关键在于:每个命名空间是完全独立的实例,彼此之间没有共享状态。
一个进程可以加入某个命名空间,此后它看到的网络环境就完全限定在这个空间里。它无法访问其他命名空间的网卡,无法读取其他命名空间的路由,甚至无法探测到其他命名空间里开启的端口。
三、网络命名空间最核心的规则
网络命名空间最核心的规则:
第一条规则:一个网络设备(net_device)只能属于一个命名空间。 一张网卡,不管是物理的 eth0,还是虚拟的 veth、vlan、bridge,它在任何时刻都只属于一个命名空间。不能共享,不能跨空间映射。
第二条规则:不同命名空间可以拥有完全相同的 IP 地址、相同的网卡名、相同的端口,而不会冲突。 因为它们是完全隔离的协议栈。
第三条规则:默认情况下,命名空间之间完全不通。 内核不会自动转发,不会自动互通,没有任何“隐形通道”。
第四条规则:要让两个命名空间通信,必须建立一条“虚拟网线”连接它们。 这条虚拟网线,就是 Linux 虚拟网络里极其重要的设备——veth pair。
第五条规则:物理网卡可以随意在命名空间之间移动。 你可以把 eth1 从初始命名空间移到 ns1,再移到 ns2,整个过程不需要重启网卡,不需要重新加载驱动。
这五条规则,构成了 Linux 网络隔离的全部基础。
四、veth pair:命名空间之间的虚拟网线
如果说命名空间是“独立房间”,那 veth pair 就是连接房间的“管道”。
veth(Virtual Ethernet)是一种成对出现的虚拟设备,你永远无法只创建一个 veth,必须创建一对。它的行为非常简单: 数据从 veth0 进,就一定会从 veth1 出;数据从 veth1 进,就一定会从 veth0 出。
就像一根虚拟网线,两端各插一个网卡。
它的真正价值,在于两端可以放在不同的命名空间里。
这是 Linux 所有跨命名空间通信方案的基础:容器、Kubernetes、多网段互通、虚拟路由,全都离不开它。
在嵌入式设备里,你不需要每次都手动写复杂的命令,只要理解:veth 只负责转发,不修改数据,不做 NAT,不做路由,它就是一根透明的网线。
五、命名空间的实际意义:嵌入式多网口隔离神器
在嵌入式产品里,网络命名空间是真正解决工程难题的工具。
- 最典型的应用是 4G/5G 模组完全隔离。 很多网关会同时插多张 4G/5G 模块,每张模组都需要拨号、获取独立 IP、独立路由、独立 DNS。如果不使用 netns,多张模组会互相抢占默认路由,导致网络异常。把每张模组单独放入一个命名空间,就能实现完全隔离。
- 第二个典型场景:管理口与业务口隔离。 把调试网口放在单独的命名空间,只允许特定进程访问,业务程序完全看不到这张网卡,极大提升安全性。
- 第三个场景:多WAN 叠加/多链路负载均衡。 每个 WAN 一个命名空间,各自拨号、各自路由、互不干扰,再通过策略路由实现流量分流。
- 第四个场景:容器/边缘应用。 每个应用一个命名空间,不能访问内部 LAN,只能访问 WAN,保证系统安全。
六、命名空间与 net_device 的关系
我们在第三篇讲过 struct net_device 是 Linux 网络设备的统一抽象。它内部有一个成员,指向它所属的命名空间 struct net。
当你执行:
ip link set eth1 netns ns1
内核做的事情非常简单: 把 eth1 对应的 net_device 从原来的 init_net 移到 ns1 对应的 struct net 中。
移动完成后:
这也是为什么物理网卡可以自由移动——因为它只是改变了所属的网络空间实例,驱动、硬件、DMA 完全不受影响。
七、命名空间与网桥、VLAN、子接口的关系
很多工程师会疑惑:如果我把一张网卡放进命名空间,那基于它的 VLAN、子接口、网桥端口会怎样?
答案很明确:从属关系跟随主设备。
例如 eth0.10 是 eth0 的 VLAN 子接口,如果你把 eth0 移入命名空间,eth0.10 也会跟着进去。
网桥同理:一个网口加入网桥后,如果把网口移入另一个命名空间,它会自动脱离网桥,进入新命名空间。
这是 Linux 网络设备模型的统一逻辑,也是整个网络栈稳定、可预测的原因。
八、总结
到这里,我们完整地梳理了网络命名空间的内核逻辑、隔离模型、设备归属、通信机制以及在嵌入式设备中的真实价值。
它不是容器的附属技术,而是 Linux 网络最基础、最强大、最实用的隔离机制。理解它,你就能真正搭建稳定、干净、安全、可扩展的嵌入式网络架构。
它让多网卡不再冲突,让多链路不再混乱,让隔离不再依赖复杂的 iptables,让设备稳定性大幅提升。