我使用一台 HPE Juniper EX2200-C-12p 作为我的交换机,一台 Lenovo M710q 作为我的路由器,后者只有一个网口。

是这样,我之前的网络使用一台 Raspberry 4b 4GB 作为我的路由器,使用一台没有任何带 VLAN 特性的普通交换机(TPLINK SG1008+)。作为代价,我的整个子网被暴露在了我所连接的校园网里;同时我网络的可审计性十分差劲,以至于我明明所有设备、线缆、端口都支持千兆及以上的带宽,然而多数时候我仍然会遇到「一些链路上被迫以百兆的速度进行链路协商」之类的问题,然而却没有很好的手段去观测、审计这样的现象。同时,整个子网被暴露在校园网中的行为似乎触发某些二层网络的禁忌,这使得我的 AP(一台 WNDR3700v4)完全无法正常工作。

由于我一直没能有多网口的小型设备,因此我听从我朋友的建议,购入了这台 HPE Juniper EX2200-C-12p。这是一台用于桌面的个人小型管理型交换机,无风扇,其软件已经 EOL——不过我并不在意。该设备有带 PoE 供电的版本,不过我暂且不需要。该设备的手册已经被 Juniper 归档,「扫入历史的垃圾堆里」1。我将手册下载,并且喂给 Agent,生成了 ex2200.skill。我对网络配置所知甚少,所以我很需要 LLM 的帮忙。

我今天费了一天的工夫将我的网络配置了起来。现在我的网络是一个很典型的「通过管理型交换机而使用单臂路由作为主路由进行拨号和流量审计」的结构。具体的配置流程我已经传到 wold9168/ex2200-c-conf 上。我接下来主要讲述一些我配置过程中遇到的琐碎事情,以及我对三层交换机认识的加深。

在此特别感谢我的朋友一通和zry。感谢这两位朋友持之以恒的相助。他们在过去两个月里为我投入了总计十余小时在向我演示三层交换机的配置以及对我问题的解答上。

先来理解三层交换机!

我先将最有价值的内容放在最前。一定有对网络理解不甚深入的朋友同我一样,对三层交换机充满这样或者那样的错误理解,以至于配置三层交换机的时候手足无措。

(我们这里讨论的三层交换机与管理型交换机是一个东西。)

二层交换机和 VLAN 的基本概念

物理三层交换机由两个网元组成:一个是路由器,甚至更具体一点而言,使用其英文称呼 Router 会更准确一些2;一个是二层交换机(L2 Switch)。

物理三层交换机的物理接口要和其内部的 Router 或者二层交换机建立联系,这个联系可以是三层的,也可以是二层的。连到前者就算三层,连到后者就算二层。这种联系就像接了一根网线一样。配置 VLAN 相当于将物理接口连到二层交换机的某个带 VLAN 的接口上。我们先来介绍这个二层交换机,这个二层交换机总是带 VLAN 特性。

VLAN 的概念是好理解的。一些二层流量,被打了 802.1Q tag,被称为 tagged 流量;与普通流量相区分,普通流量便称为 untagged 流量。所谓 VLAN 是一个二层特性,二层虚拟机将带有属于对应 VLAN,因而持有对应 tag 的流量在物理的交换机上交换,发生交换的物理端口在交换机的管理面板上被分配给这些 VLAN。

VLAN 有三种接口:Access、Trunk 和 Hybrid。Hybrid 是基于交换机的软件支持,把 Access 和 Trunk 强行捏到一起,用得比较少,我也没去学。一般的网络管理只用理解 Access 和 Trunk 两种接口就行。

  • Access 接口:一个 Access 接口只能属于一个 VLAN,这个 VLAN 的 ID 称为这个接口的 PVID。接口连接的所有设备都默认属于这个VLAN。
  • Trunk 接口:一个 Trunk 接口可以属于多个 VLAN。Trunk 接口一般用于与支持 802.1Q 的设备交互,尤其是在交换机、单臂路由之间进行数据通信。

我们想象,VLAN 的本质是允许对二层流量的数据帧进行封装,这种封装是以为这些数据帧打上 tag 的形式进行的。这些 tag 即对应 VLAN 的 ID。二层交换机通过这些 tag 来区分流量归属的网络。不同 VLAN 的端口之间相当于两台彼此独立的交换机,必须用网络设备相连。我们正是为了让网络之间彼此隔离才划定 VLAN——网络之间彼此隔离意味着不同 VLAN 下的设备无法直接通信,而必须经由跨 VLAN 的那些设备转发其流量才能与不同 VLAN 的设备通信。这些跨 VLAN 设备的存在为我们审计这些 VLAN 之间的流量提供了条件。

Access 接口可以与一个发出和接收 untagged 流量的设备相连。因为 Access 接口会自动将流量打上其对应的 Tag。可以说 Access 接口是一个 VLAN 系统的门禁,tag 是门票,流量是游客:流量通过 Access 接口的时候就像游客买票进入「VLAN 景区」,等到流量从这个 VLAN 系统出来,对应的 tag 就被拿掉——就像游客的门票被拿掉副券一样。即,Access 接口对二层流量进行封装和拆装,使其成为 VLAN 的流量或者由 VLAN 流量变为普通的 untagged 流量。

Trunk 接口则不会做这个封装拆装的工作,相应地,我们被允许在 Trunk 接口上同时传输多个 VLAN 下的流量。

在二层交换机上,我们可以指定一个物理接口为 Access 接口(绑定到单个 VLAN 上,通常用于连接不负责 VLAN 拆包的客户端和传入 untagged 流量的上层网络)或者 Trunk 接口(绑定到多个 VLAN 上,通常用于连接其他能处理 VLAN tag 的设备,例如单臂路由、交换机等)。这样我们就可以实现不同接口其上流量的隔离。一个新构建的 VLAN 里,arp 包将在整个 VLAN 上广播,而不会广播到不归属于该 VLAN 的接口上。

对于二层交换机,我们仍然可以将我们对其接口的理解建立在其前面板(带网络接口的一面)的物理形态上。这点与三层交换机是相区分的。

三层交换机与 VLANIF

重复一遍,三层交换机由一个 Router 和一个二层交换机组成。对于三层交换机而言,我们就不能简单地将其前面板对应到网络的逻辑结构上了。

三层交换机的每个物理接口均被我们通过交换机的管理软件,接入到其内的一个二层交换机上。当你对接口的 VLAN 进行配置的时候,你本质上是对该二层交换机以及「二层交换机到三层交换机前面板的物理接口的这段链路」进行配置。这个配置过程是易于理解的。

真正难以理解的是 VLANIF,VLANIF 是三层交换机的专属,它允许你为一个 VLAN 分配一个子网,该子网有一个IP,以及有对应的掩码。看起来就像你在电脑上为设备配置网络一般。

VLANIF 的全称是 VLAN Interface,我们需要站在三层交换机内部那个 Router 的角度上去理解它的称呼,而不能认为 VLAN Interface 是 VLAN 的某种特殊机制或者二层交换机上的特殊接口。VLAN Interface 是存在于三层交换机内 Router 上的虚拟接口,该虚拟接口一定是被接入到一个 VLAN 中的,并将三层交换机的路由能力应用到该二层交换机上。

三层交换机的 VLAN 以其 VLANIF 指定的 IP 为网关,与 VLAN 外的其他 VLAN 以及上级网络进行通信,这样的通信直接经过该三层交换机内的 Router,并受该 Router 的路由规则、ACL等规则的影响。用户因而得以在该 Router 上对流量进行路由、审计。顺带一提,对于我使用的 Juniper EX2200-C-12p 而言,VLANIF 的这个 IP 上同时还托管着该交换机的管理面板和 SSH。

我们先前提到:「我们正是为了让网络之间彼此隔离才划定 VLAN——网络之间彼此隔离意味着不同 VLAN 下的设备无法直接通信,而必须经由跨 VLAN 的那些设备转发其流量才能与不同 VLAN 的设备通信。这些跨 VLAN 设备的存在为我们审计这些 VLAN 之间的流量提供了条件。」实际上,三层交换机正是将这些跨 VLAN 的设备整合为了这个内部的 Router,交换机的路由规则工作在这个 Router 里。不过与商品概念的路由器3不同的是,该 Router 一般不带 NAT 功能和拨号功能。

没有创建 VLANIF 的话,相当于是这个 VLAN 没有连到一个三层交换机,那么该三层交换机的功能边界完全等价于一个二层交换机。

一台接入到一个 VLAN 的设备,其应以 VLANIF 指定的 IP 为网关:流量从客户端发出,在本 VLAN 的流量直接通过交换机的交换,在本 VLAN 的设备内传播;而如果流量指向本 VLAN 子网外的设备,那么该流量的下一跳就是 VLANIF(流量进入三层交换机内的 Router)。Router 接收到流量以后,如果流量指向该 Router 的接口(VLANIF)所连接的 VLAN,那么该 Router 可以将流量直接通过对应 VLAN 所连接着的 VLANIF 将流量扔到对应 VLAN 中的设备;如果流量指向外层的网络,那么流量就需要通过该 Router 连向上级网络的接口出去。

如果我们设置一条路由规则:0.0.0.0 → VLANIF10 → 192.168.10.2(简化记法,意为「所有流量经由 VLANIF10 发往下一跳 192.168.10.2」),那么所有未被现有路由规则路由的流量(0.0.0.0),都将通过VLANIF10这个 VLANIF,被导向 192.168.10.2

我们可以设置另一个独立的 VLAN(比如 VLAN 9),让 VLAN 9 与 192.168.10.2 设备相连,同时将上级网络到该三层交换机的接口设置为 VLAN 9 的 Access 接口。VLAN 9 中仅有两个设备彼此连接,即上级网络与192.168.10.2的连接。这样仅负责两个设备连接的网络,我们一般为其分配一个/30子网,并称之为 Peer。

分配/30子网是因为/30子网里有四个 IP,一个 IP 用作网络号,一个 IP 用作广播,剩下两个 IP 分别被分配到该 VLAN 连接的两个设备上。

192.168.10.2 这台设备设置一个路由,这个路由是 0.0.0.0 eno1.9 <上级网络的网关>eno1.9指的是在 eno1 网口4上发送或者接收 VLAN 9 流量。那么这样,以客户端(192.168.12.10,处于 VLAN 12 中,VLAN 12 被分配了 192.168.12.0/24 的网段以及 192.168.12.1 的 VLANIF)到公网(8.8.8.8)的访问为例,我们就会得到这样一个链路:

  • 192.168.12.10 产生到 8.8.8.8 的 L3 流量。
  • 该 L3 流量的目标 IP 不归属于 VLAN 12 的网段,所以根据 192.168.12.10 的默认路由规则(0.0.0.0 eno1 192.168.12.1),该流量被打到三层交换机的 Router 上。
  • 由于 Router 有 0.0.0.0 VLANIF10 192.168.10.2 的规则,因此该 L3 流量将被直接路由到 192.168.10.2 上。
    • 顺带一提,Router 一般默认会有一个 VLAN10 VLANIF10 direct的路由规则,随对应 VLANIF 的创建而创建。该路由规则允许将以 VLAN 10 为目的的流量直接通过 VLANIF10 发送出去。这允许用户通过 VLAN 12 的 VLANIF12,籍由 Router,连接到 VLAN 10 上的设备。当然,你都走 Router 过了,那么你自然可以在 Router 上对这样的流量设置 ACL 或者各种奇怪的规则,甚至于更简单粗暴一点——你直接将所有这样的流量的下一条都设置为某个设备,以让该设备对这部分流量施以审计,或者直接丢弃以隔绝两者。
  • 192.168.10.2 接收到流量了。它根据自己的路由规则 0.0.0.0 eno1.9 <上级网络的网关>,将流量通过 eno1 发送出去,打上了 VLAN 9 的 tag。该流量的下一跳将是上级网络的网关。
  • 流量从与上级网络相连的 VLAN 9 Access 接口上走出的时候,对应的 tag 被移除。之后网络系统里发生的事情就与我们的 VLAN 无关了!

以上结构正是我所采用的结构,192.168.10.2 正是我的主路由。我通过该路由对整个子网与公网的通信流量进行审计、观测、代理,并通过该主路由进行 PPPoE 拨号。

多交换机的情况

多交换机的情况稍微复杂一点。

我们先明确一下,不同交换机之间可以通过 Trunk 接口来互传 VLAN 流量。这使得他们之间相同 ID 的 VLAN 在逻辑上被认为是同一个 VLAN。

但是逻辑上相同的 VLAN 只能有一个 VLAN IF,或者说只有一个 VLAN IF 是有意义的:VLAN IF 只能在一台交换机上应用,更严谨的说,VLAN IF 在 VLAN 中扮演的角色是一个路由器,在一个子网里也只能有一个 VLAN IF 作为网关。我们可以起两个 VLAN IF,这就相当于一个子网里有两个路由器,那这两个路由器里也只能有一个来扮演网关的角色,至于另一个——它就没什么用了。

我们可以用 Peer 来协商多个交换机之间的流量,使得一台交换机上设置的 VLAN IF 能为另一台交换机所感知:假设一台交换机 A 有 VLANIF12(192.168.12.1),一台机器 B 有 VLANIF13(192.168.13.1)。那么 VLANIF13 对应的 192.168.13.1 拿到下级设备的流量以后:需要一个独立的 VLAN14(192.168.14.0/30)作为 Peer 来连接 A 和 B。为 A 连接到 VLAN 14 的接口分配 192.168.14.1,为 B 连接到 VLAN 14 的接口分配 192.168.14.2。那么,VLAN 13 的一个下级设备 192.168.13.2 向 VLAN 12 中的一个下级设备发送请求,其流量的路径就如下:192.168.13.2->192.168.13.1(设备 B 的 VLANIF13)->设备 B 上的一条0.0.0.0 VLANIF14 14.1规则->192.168.14.1(设备 A 与 VLAN 14 相连的接口)->192.168.12.1(设备 A 的 VLANIF12)->192.168.12.2(设备 A 中 VLAN 12 的一个下级设备)。

当然,流量在不跨越交换机的时候就不需要一个独立的 VLAN 14 作为 Peer 了。

这里展示的做法是一种原始的做法。实际上对于多交换机的环境,我们最好采用 OSPF 协议。不过这就超出了我们的讨论范围以及我的知识边界。

路由器配置的踩坑

我极其不希望使用 OpenWrt 及其衍生品。我觉得使用 init.d 管理服务的手感实在不如 systemd。我也没有尝试 RouterOS、VyOS、pfSense 这些产品的动力。我于是自己安装了一个 Debian 13 到我的 Lenovo M710q 上,尝试自己配置路由。(我其实更想用 Rocky Linux,但是 Debian 配置路由的博客好久以前就满天飞了。)

将一台 Debian 转为路由器只需要很少的几个步骤:

  • 配置路由表
  • 通过内核参数启用 IPv4 和 IPv6 流量的转发
  • 配置 DHCP

我对 DHCP 的知识保持一种极大的钝感,因此无法为您解答任何有关于此的问题。我建议您直接参阅我 wold9168/ex2200-c-conf 仓库中的做法。我还特意为 DHCPv6 的部分单独开了一个章节。至于 DHCPv4,我直接让三层交换机接管了 DHCPv4 工作,因而不必在这台 Debian 路由器上配置太多东西。

路由表的配置不劳多说,只须记得将配置持久化到文件里即可。我需要重点提及一下的是内核参数的问题。Debian 13 开机的时候似乎不再读取 /etc/sysctl.conf 中的内核参数(至少我使用的 Debian 13.5 不会),而是仅读取 /etc/sysctl.d/*.conf 中的内核参数。吊诡的是,你如果使用 sysctl -p 重新加载内核参数的话,该指令又会读取 /etc/sysctl.conf 中的内容。这点尤其需要注意一下。

我在这个环节里过于依赖 AI 了,所以直接看我的仓库好于听我在这里胡诌。我这里同样放出几篇我参考过的文章以飨读者:

我的 VLAN 划分

我参考了我的良师益友一通的 VLAN 划分,在他的设计里,VLAN 主要分为这样几个部分:

  • VLAN 10 是路由 VLAN,必须所有人都能访问
  • VLAN 11 是管理 VLAN
  • VLAN 12 是个人设备
    • 设备——VLAN 12——VLAN 10——路由器——外网
  • VLAN 13 是虚拟机和微服务使用

我则再加入一个 VLAN 9 以方便设备的上联:

  • VLAN 9 是中间 VLAN,用于与上级网络进行连接。默认上级网络流量不带任何tag
  • VLAN 10 是路由 VLAN,必须所有人都能访问
  • VLAN 11 是管理 VLAN
  • VLAN 12 是个人设备
    • 设备——VLAN 12——VLAN 10——路由器——外网
  • VLAN 13 是虚拟机和微服务使用
  1. https://www.juniper.net/documentation/us/en/internal/archives/topics/concept/ex-series-archives.html 

  2. 这里特意使用 Router 的称呼是因为这个 Router 很纯粹,只有路由的功能。我们一般所说的路由器可以有两种概念,一种是商品概念上的路由器,即作为商品售卖的,整合了 NAT、三层路由、二层交换等多种功能的一种综合性网络设备,一种是严格意义上的路由器,仅负责三层路由。这里是后者。 

  3. 见脚注2。 

  4. 随便举例的一个网口名称