Files
cs-note/hhs/NETWORK/02-链路层/05-VLAN与Trunk.md
T
2026-05-24 11:42:38 +08:00

209 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [计算机网络, VLAN, 802.1Q, Trunk, Access端口]
create time: 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 │Type │TPID │ TCI │ Payload │ FCS │
│ 6 bytes │ 6 bytes │ 2B │2B │ 2B │ 46-1500 B │ 4 B │
│ │ │0x0800│8100 │ VID │ │ │
└──────────┴──────────┴──────┴───┴──────┴─────────────┴──────┘
←── 14 ──→ │←──4──→│ ←──MTU──→ ←── 4 ──→
↑ 新增 4-byte Tag
```
### TCI (Tag Control Information) 位图
```
Bit 15 Bit 13-12 Bit 11-0
────────────────────────────────────
CFI | PCP (优先级) | VID (VLAN ID)
(1bit) | (3 bits) | (12 bits)
```
| 字段 | 大小 | 取值范围 | 说明 |
|------|------|---------|------|
| CFI | 1 bit | 0 或 1 | Canonical Format Indicator,传统以太网固定为 0 |
| PCP | 3 bit | 0–7 | Priority Code Point,QoS 优先级(见下表) |
| VID | 12 bit | 0–4095 | VLAN Identifier,**实际可用 1–4094** |
### PCP 优先级对照
| PCP | 用途 | 典型场景 |
|-----|------|---------|
| 0 | Best Effort | 普通数据流量 |
| 1 | Background | 后台低优先级的备份任务 |
| 2–3 | Excellent Effort | 文件传输等中等业务 |
| 4 | Critical Applications | 视频流会议 |
| 5 | Voice | 语音通话 VoIP(最高优先) |
| 6 | Network Control | 网络管理协议 |
| 7 | Reserved | 保留 |
## VLAN 端口类型
| 端口类型 | Access | Trunk | Hybrid(Huawei/H3C) |
|----------|--------|-------|---------------------|
| 允许 VLAN | 1 个(PVID) | 多个 | 多个(可配置) |
| 入栈标签 | 接收不带标签 → 打上 PVID | 所有到达的帧保持标签 | 根据配置决定 |
| 出栈标签 | 发送时剥离标签 | 发送时保留标签(除 PVID) | 按每 VLAN 配置 |
| 使用场景 | 接 PC/打印机/AP | 交换机互联、接路由器 | 灵活混合 |
### Access 端口示例
```mermaid
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 端口示例
```mermaid
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
```
## 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
```bash
# 创建 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
```yaml
# docker-compose.yml
services:
web:
networks:
frontend: # VLAN 10
ipv4_address: 192.168.10.10
backend: # VLAN 20
ipv4_address: 192.168.20.10
networks:
frontend:
driver: bridge
ipam:
config:
- subnet: 192.168.10.0/24
backend:
driver: bridge
ipam:
config:
- subnet: 192.168.20.0/24
```
## VLAN 边界与跨 Switch
```mermaid
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 ID 分配 | 管理 VLAN=1(不建议,安全风险),业务 VLAN ≥ 10 |
| Native VLAN | 修改默认 native VLAN(避免用 1),防 VLAN Hopping |
| VLAN 数量 | 单台交换机支持最大 4094 个 VLAN |
| Inter-VLAN 路由 | >10 个 VLAN 用三层交换机而非单臂路由 |
| 安全 | 未使用的端口划入"黑洞 VLAN"(无 IP 段),关闭 DTP 自动协商 |
## 关联笔记
- [[hhs/NETWORK/Ethernet帧结构]] — 802.1Q Tag 插入在 Ethertype 位置之前
- [[hhs/NETWORK/Switch与路由器]] — Switch 如何基于 VLAN 隔离广播域
- [[hhs/NETWORK/MAC地址与广播域]] — VLAN 缩小了广播域的规模