有两个措辞几乎相同的需求:把每个 VPN 客户端放进选定的 VLAN,或者让现有的 VLAN 中继穿过 VPN。它们是不同的产品。OpenVPN 内置的 VLAN 感知模式是面向第一种需求的交换机模型,并不是透明标签传输的同义词。选错会得到一套看起来配置完成、却悄悄丢弃你真正在意帧的设计。

VLAN 感知模式实际构建了什么

在仅用于服务器的 TAP 部署中启用 vlan-tagging 后,守护进程会把自身的 TAP 设备和每个已连接的客户端建模为内部交换机的端口。客户端端口是无标签的,其 VLAN 归属通过服务器上按客户端设置的 vlan-pvid 上下文指定,而不是由客户端发送的任何内容决定。这正是该模型的全部意义:成员关系是服务器端针对已认证对端作出的决定。客户端配置里没有任何东西需要知道自己属于哪个 VLAN。

服务器的 TAP 一侧通过 vlan-accept 获得自己的带标签或无标签接收策略。该交换机内部的转发只在相同的 VID 之间进行,即使设置了 client-to-client 也是如此,因此分属不同 VLAN 的两个客户端即使都连到服务器,也无法经由服务器互相到达。

这个模型是接入端口模型。离开客户端的帧不带标签,归属由服务器依据身份强制施加。要求笔记本自己给流量打标签,等于要求另一套设计。

分配必须依据已认证的客户端身份,而不是客户端自我申报的值。省略分配也不是隔离状态:客户端会落到默认 PVID,所以缺少 ccd 条目是一个无声的策略决定,而不是中立的。

透明中继反而要求什么

要把已经带标签的帧端到端搬运,第一步是关掉 VLAN 感知处理。交换机模型与保留标签是互斥的替代方案,同时开启等于让一个特性去做另一个特性的工作。

关掉只是开始。每一端的网桥和物理交换端口必须就会允许哪些 VLAN、哪个标签是本征标签、以及如何处理无标签帧达成一致。扩展一条不加限制的中继,暴露出来的广播域远比你原本想连接的两个多得多。

帧的大小需要单独的预算。带标签的以太网帧加上封装后,比人们从教程里抄来的有效载荷数字更大;一条曾适用于路由隧道的 MTU,并不能证明中继路径可用。

决定答案的三个条件

第一,客户端平台到底支不支持 TAP?Android 和 iOS 不支持,macOS 的支持也有限,所以一支移动用户队伍无论 VLAN 怎么安排,都排除了两种 TAP 设计。TUN 的路由会话承载的是 IP 包,而不是以太网帧,服务器端的任何 VLAN 配置都改变不了这一点。设计拓扑前先核查用户队伍,因为这个条件无法绕过。它也是最常在交换机工作做完之后才被发现的条件。

第二,VLAN 由谁分配?如果答案是「由服务器按谁通过了认证来分配」,交换机模型就合适。如果答案是「由现有交换基础设施分配,标签已经存在」,那就需要中继设计。

第三,网络应当有多大范围可达。交换机模型在构造上把每个客户端留在同一个 VLAN 里。中继设计是一座网桥,而配置错误的网桥会把本该彼此隔离的广播域连在一起。

检验你做出的选择

接入一个应当位于允许 VLAN 的客户端,再接入一个不应当的,然后从真实端点而不是服务器本身去测试。服务器侧可达只能证明网桥或交换机存在,并不能证明客户端落进了哪个 VLAN。

ip -d link show tap0
bridge vlan show

在服务器上,第二条命令会显示每个网桥端口的 VLAN 成员关系,包括端口是否带标签。在排查第二层以上的任何问题之前,先把它和你原本的分配对照一下。

记录这套部署用的是两种设计中的哪一种。只写「VLAN 感知」的备注含义模糊,下一位工程师会按自己最先学到的那种去理解。OpenVPN 的 VLAN 参考文档定义了交换机行为以及按客户端的上下文,是确认你正在运行哪种模型的最短路径。

相关文章