Files
cs-note/hhs/NETWORK/02-链路层/05-VLAN与Trunk.md
T
2026-05-27 23:01:37 +08:00

12 KiB
Raw Blame History

tags, create time
tags create time
计算机网络
VLAN
802.1Q
Trunk
Access端口
2026-05-17 23:30

VLAN 与 Trunk

概述

VLAN(Virtual Local Area Network,虚拟局域网)允许在一台物理交换机上创建多个逻辑隔离的广播域。它是现代数据中心和办公网络的基本组织单元。

[!QUESTION] 为什么需要 VLAN? 一台万兆交换机的 MAC 表通常限制在几万条以内,加上广播泛洪带来的开销,单广播域超过 2000 台主机会显著降低性能。VLAN 将大网络划分为多个小广播域,就像在一栋大楼里用防火墙隔出多个独立办公室——同一楼层但互不干扰。

IEEE 802.1Q Tag 结构

不带 VLAN 的 Ethernet II 帧

┌──────────┬──────────┬──────┬─────────────┬──────┐
│ Dest MAC │ Src MAC  │Type  │   Payload    │ FCS  │
│  6 bytes │  6 bytes │ 2B   │  46-1500 B   │ 4 B  │
│          │          │0x0800│              │      │
└──────────┴──────────┴──────┴─────────────┴──────┘
           ←── 14 ──→       ←──MTU──→     ←── 4 ──→
           Header                    Payload   Tail

带 802.1Q Tag 的帧

┌──────────┬──────────┬──────┬──────┬──────────┬─────────────┬──────┐
│ Dest MAC │ Src MAC  │ TPID │ TCI  │Org.EType │   Payload    │ FCS  │
│  6 bytes │  6 bytes │ 2B   │ 2B   │  2B      │  46-1500 B   │ 4 B  │
│          │          │0x8100│ VID  │ 0x0800   │              │      │
└──────────┴──────────┴──────┴──────┴──────────┴─────────────┴──────┘
           ←── 14 ──→ │←4 Tag→│ ←───── 4+MTU ─────→    ←── 4 ──→
                      ↑ 新增 4-byte Tag

[!important] TPID 替换了 EtherType TPID(0x8100)占据了原帧中 EtherType 的位置,原 EtherType(如 0x0800)被后移到 TCI 之后、Payload 之前。交换机通过识别 TPID=0x8100 来判断这是一帧 802.1Q 标记帧。

TCI (Tag Control Information) 位图

Bit 15-13         Bit 12        Bit 11-0
─────────────────────────────────────────
PCP (优先级)     |  DEI/CFI     |  VID (VLAN ID)
  (3 bits)       |  (1 bit)     |  (12 bits)
字段 大小 取值范围 说明
PCP 3 bit 0–7 Priority Code Point,QoS 优先级(见下表)
DEI 1 bit 0 或 1 Drop Eligible Indicator,指示该帧在拥塞时可被丢弃。在 802.1Q-2011 前称为 CFI(Canonical Format Indicator),传统以太网固定为 0
VID 12 bit 0–4095 VLAN Identifier,实际可用 1–4094(0 仅用于优先级帧,4095 保留)

PCP 优先级对照

PCP 用途 典型场景
1 Background 后台低优先级的备份任务
0 Best Effort(默认) 普通数据流量,大多数业务的默认值
2 Spare 预留,可用于自定义业务
3 Excellent Effort 关键业务数据(如 ERP、数据库同步)
4 Video 视频流(≤100ms 延迟要求)
5 Voice 语音通话 VoIP(≤10ms 延迟,流控标记)
6 Internetwork Control 路由协议等网络控制报文
7 Network Control STP、LLDP 等二层协议,不能被丢弃

[!question] 为什么 PCP 0(Best Effort)不是最低优先级? 这是 IEEE 802.1Q 历史遗留设计。PCP 1 的 "Background" 比默认更"低",用于非紧急的大块传输(如备份),避免抢占默认业务的带宽。实际部署中 PCP 0 和 1 的区别不大,重点应关注 PCP 4–7。

VLAN 端口类型

端口类型 Access Trunk Hybrid(Huawei/H3C)
允许 VLAN 1 个(PVID) 多个 多个(可配置)
入栈标签 接收不带标签 → 打上 PVID 所有到达的帧保持标签 根据配置决定
出栈标签 发送时剥离标签 发送时保留标签(除 PVID) 按每 VLAN 配置
使用场景 接 PC/打印机/AP 交换机互联、接路由器 灵活混合

Access 端口示例

flowchart LR
    PC["PC (无标签帧)"] -->|"发裸帧"| A["Access Port<br/>PVID = 10"]
    A -->|"打上 Tag 10"| S["Switch 内部 VLAN 10 域"]
    S -->|"移除 Tag"| B["Access Port<br/>PVID = 10"]
    B -->|"发裸帧"| GW["网关 Router"]
    
    style A fill:#DDA0DD,color:#000
    style B fill:#DDA0DD,color:#000

Access 端口对主机透明——主机看到的仍是普通以太网帧,完全不知道 VLAN 的存在。

Trunk 端口示例

flowchart LR
    SW1["Switch A"] -->|"Trunk<br/>携带多个 VID"| SW2["Switch B"]
    
    Note over SW1,SW2: VLAN 10 流量: EtherType=0x8100, VID=10<br/>VLAN 20 流量: EtherType=0x8100, VID=20
    
    style SW1 fill:#98FB98,color:#000
    style SW2 fill:#98FB98,color:#000

Native VLAN(本征 VLAN)

Trunk 端口上有一个特殊概念:Native VLAN,默认为 VLAN 1。

flowchart LR
    UH["不带标签的主机"] -->|"裸帧(无 Tag)"| TR["Trunk 端口"]
    TH["带 Tag 的主机"] -->|"Tag 帧(VID=10)"| TR
    TR -->|"识别为 Native VLAN"| NV["VLAN 1 域"]
    TR -->|"按 VID 转发"| V10["VLAN 10 域"]
    
    style NV fill:#FFD700,color:#000
    style V10 fill:#87CEEB,color:#000

工作规则:

  • 入方向:Trunk 端口收到不带标签的帧时,自动归入 Native VLAN
  • 出方向:属于 Native VLAN 的帧在发出时剥离标签(对端看到的是裸帧)

[!warning] Native VLAN 必须两端一致 如果 Trunk 两端交换机的 Native VLAN 设置不一致(一端是 VLAN 1,另一端是 VLAN 2),会导致:

  1. 流量被错误转发到非预期 VLAN
  2. 成为 VLAN Hopping 攻击的入口(见下一节)

Router-on-a-Stick(单臂路由)

当路由器只有一个物理接口时,可以通过子接口 + VLAN 实现多个 VLAN 间路由:

        VLAN 10              VLAN 20
    ┌──────────┐        ┌──────────┐
    │ 192.168.10.x /24 │    │ 192.168.20.x /24 │
    └──────┬───┘        └──────┬───┘
           │                   │
         Access              Access
           │                   │
    ┌──────┴───────────────────┴───┐
    │            Switch             │
    │   Trunk Port (eth0.10 & .20) │
    └──────┬───────────────────┬───┘
           │ 子接口 eth0.10    │ 子接口 eth0.20
           ▼                   ▼
    ┌─────────────────┐  ┌─────────────────┐
    │ Router            │  │ Router            │
    │ eth0.10: 192.168.10.1/24 │  │ eth0.20: 192.168.20.1/24 │
    └─────────────────┘  └─────────────────┘

[!warning] 单臂路由的性能瓶颈 所有 VLAN 间的流量都经过同一个物理接口进出(先入后出),相当于双倍带宽占用。对于万兆环境,建议使用三层交换机做硬件 VLAN 间路由。

配置示例

Linux Bridge 上的 VLAN

# 创建 vlan interface
ip link add link eth0 name eth0.10 type vlan id 10
ip link add link eth0 name eth0.20 type vlan id 20

# 设置 IP 并启用
ip addr add 192.168.10.1/24 dev eth0.10
ip addr add 192.168.20.1/24 dev eth0.20
ip link set eth0.10 up
ip link set eth0.20 up

# 查看
$ ip -d link show type vlan
4: eth0.10@eth0: <BROADCAST,MULTICAST,UP> mtu 1500 ...
    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff promiscuity 0
    vlan protocol 802.1Q id 10 reassemble 0

Docker 中利用 VLAN

[!warning] Docker bridge 网络 ≠ VLAN docker network create --driver bridge 创建的是隔离的 Linux 网桥,不会在帧上打 802.1Q Tag。它在逻辑上类似"独立广播域",但不是真正的 VLAN。 要让容器接入真实 VLAN,需使用 macvlan 或 ipvlan 驱动:

# docker-compose.yml — 容器直接接入物理 VLAN
services:
  web-vlan10:
    image: nginx
    networks:
      office_net:
        ipv4_address: 192.168.10.10

  app-vlan20:
    image: app:latest
    networks:
      server_net:
        ipv4_address: 192.168.20.10

networks:
  office_net:
    driver: macvlan
    driver_opts:
      parent: eth0.10    # 宿主机 VLAN 子接口
    ipam:
      config:
        - subnet: 192.168.10.0/24
          gateway: 192.168.10.1
  server_net:
    driver: macvlan
    driver_opts:
      parent: eth0.20
    ipam:
      config:
        - subnet: 192.168.20.0/24
          gateway: 192.168.20.1

容器通过 macvlan 驱动直接收发带 802.1Q 标签的帧,与物理网络中的 VLAN 设备无缝互通。

VLAN 边界与跨 Switch

sequenceDiagram
    participant SW1 as Switch-A
    participant Link as 交换机间链路
    participant SW2 as Switch-B
    
    SW1->>Link: Frame {EtherType:0x8100, VID:10}
    Note over Link: Trunk 链路保持 802.1Q Tag
    SW2->>SW2: 收到 → 识别 VID=10 → 在 VLAN 10 内转发
    SW2->>SW2: 查 MAC 表 → 仅从同 VLAN 端口发出

核心要点: VLAN 信息随 802.1Q Tag 穿过 Trunk 链路传递到下一台交换机。每台交换机根据自己的 VLAN 数据库独立处理。

VLAN Hopping 攻击与防御

VLAN Hopping 是通过协议漏洞非法访问其他 VLAN 的二层攻击,主要有两种方式:

攻击一:Double Tagging(双标签攻击)

sequenceDiagram
    participant A as 攻击者 (VLAN 10)
    participant S as Switch
    participant V as VLAN 20 目标主机
    
    A->>S: 外层 Tag VID=1 (Native VLAN)<br/>内层 Tag VID=20 (目标 VLAN)
    S->>S: 剥离外层 Tag (Native VLAN=1)
    S->>V: 帧到达 VLAN 20!(内层 Tag 未被检查)

原理:攻击者发送双标签帧,外层使用 Native VLAN ID。Switch 剥离外层 Tag 后,内层 Tag 暴露,帧被转发到目标 VLAN。此攻击单向,且需要攻击者在 Native VLAN 中。

[!important] 防御:将 Native VLAN 设为未使用的 VLAN(如 VLAN 999),并确认所有 Trunk 端口都显式允许所需的 VLAN(不要用 allowed vlan all)

攻击二:DTP 欺骗

若端口启用了 DTP(Dynamic Trunking Protocol),攻击者可伪装成交换机,诱使端口切换为 Trunk 模式,从而访问所有 VLAN。

防御:在所有接入端口上关闭 DTP 自动协商:

# Cisco: 关闭 DTP
switchport nonegotiate
# Huawei: 关闭自动协商
undo negotiation auto

最佳实践

项目 建议
VLAN ID 分配 管理 VLAN=1(不建议,安全风险),业务 VLAN ≥ 10
Native VLAN 修改默认 native VLAN(避免用 1),防 VLAN Hopping
VLAN 数量 单台交换机支持最大 4094 个 VLAN
Inter-VLAN 路由 >10 个 VLAN 用三层交换机而非单臂路由
安全 未使用的端口划入"黑洞 VLAN"(无 IP 段),关闭 DTP(Dynamic Trunking Protocol,Cisco 私有自动协商协议)

关联笔记