VLAN(Virtual Local Area Network),它将一个物理的 LAN 在逻辑上划分成多个广播域,即多个 VLAN。单个 VLAN 内的主机间二层互通,可以直接通信,而 VLAN 之间不能直接互通。这个能力对于流量管理、提高安全性都非常有用,也是在物理网络或虚拟网络中都很常使用的功能。
VLAN 原理
基于对 Linux Bridge 的学习,我们对交换机的行为可以有一个初步的理解,当交换机在接收到数据帧时,一般有三种处理:
- 直接转发:当收到的数据帧的 Dst MAC 在转发表中可以查到,并且对应的出端口和入端口不一致时,直接向出端口转发;
- 丢弃:当收到的数据帧的 Dst MAC 在转发表中可以查到,并且对应的出端口和入端口一致时,直接丢弃数据帧;
- 泛洪:当收到的数据帧的 Dst MAC 是单播地址,但是在转发表中查找不到时,或 Dst MAC 是组播、广播地址时,数据帧向除输入端口外的其它端口复制并发送;
我们刚才提及 VLAN 的能力,是单个 VLAN 内的主机间二层互通,可以直接通信,而 VLAN 之间不能直接互通
,所以我们大致可以猜测,VLAN 的划分会影响到数据帧的转发和泛洪,即在入端口接受到数据帧后,不再简单的根据 Dst MAC 判断转发丢弃或泛洪,还会同时再读取数据帧中的 VLAN 标签,决定对该帧的处理逻辑。
我们先看一下以太网帧的格式(其中在 12 字节的 MAC 地址之后的 2 字节到底是 Length 还是 Type,与以太网帧格式的不同版本有关,大家可以自行查阅相关资料):
[ 6B ][ 6B ][ 2B ][42~1500B][4B ]
[Destination Address][Source Address][Length/Type][ Data ][CRC]
而 IEEE 802.1q 标准对以太网帧的格式进行了修改,加入了 4B 的 VLAN 标签(IEEE 802.1q Tag):
[ 6B ][ 6B ][ 4B ][ 2B ][42~1500B][4B ]
[Destination Address][Source Address][802.1q Tag][Length/Type][ Data ][CRC]
展开看下 VLAN 标签的这 4 个字节中包含了什么内容:
- Type:2 字节,标识帧类型,取值为 0x8100;
- PRI:2 位,表示帧的优先级,值越大优先级越高,在交换机拥塞时,会先发送高优先级的帧;
- CFI:1 位,表示 MAC 地址是否为经典地址;
- VID:12 位,表示 VLAN ID,取值范围为 0 ~ 4095,其中 0 和 4095 为保留的 VLAN ID,不能使用;
好,假设我们自己就是交换机,当我的 ifindex 为 0 的端口接收到带 VLAN 标签的数据帧时,我们会怎么解析这个帧?
- 先读取 6 字节,记录为 Dst MAC;
- 再读取 6 字节,记录为 Src MAC;
- 再读取 2 字节,这里的判断就会稍微复杂一点,首先基于以太网帧的不同格式,这个字段可能为 Length 或 Type,当其值小于或等于 1500 时,该字段代表 Length,因为 Data 的长度是不会超过 1500 B 的;反之,当其值大于 1500 时,该字段代表 Type,如 0x0800 代表该帧为 IP 协议帧,0x0806 代表该帧为 ARP 协议帧,而如果恰好取值为 0x8100,则代表该帧是带 VLAN 标签的帧;假设此处我们接收到的是带 VLAN 标签的帧,此时:
- 再读取读取 2 字节,记录下该帧对应的优先级、VLAN ID 等信息;
- 再继续读取 2 字节,这里我们读取到的又是 Length 或 Type 信息,乍一看与刚才的读取的 2 字节的 0x8100 Type 信息似乎有冲突,但其实刚才读到的只是以太网帧中附加的 VLAN 标签里的 Type 信息,而这里读到的才是真正标识后续 Data 中数据帧类型的 Type 信息;
当解析完该帧后,我们会如何转发这个帧?
如上是大致的处理流程,实际处理逻辑与交换机的端口的配置有关,主要分为 Access 口和 Trunk 口。
- Access 口一般用于交换机与主机的互联,当接收到不带 VLAN 标签的报文时,接收并打上默认的 VLAN 标签,当接收到带 VLAN 标签的数据帧时,帧内的 VLAN ID 必须与默认的 VLAN ID 相同才接受,否则丢弃该数据帧。
- 而 Trunk 口一般用于交换机与交换机间的互联(如果同一台主机创建多个 VLAN 子接口,那它与交换机的互联也需要走 Trunk 口),这类型的口可以自由的设定允许通过多个 VLAN ID,这些 VLAN ID 可以与端口默认的 VLAN ID 相同,也可以不同。
好,对于 VLAN 的概念的讲解先告一段落,我们通过实践来加深对 VLAN 的理解。
VLAN 实践
我们本次的实践使用 GNS3 网络模拟器来进行,具体的安装步骤相对比较复杂,网上有不少教程大家可以慢慢折腾一下。
VLAN 隔离
网络拓扑如下所示:
对 ESW1 和 ESW2 的配置如下:
# ESW1
ESW1# configure terminal
ESW1# vlan 10
ESW1(config-vlan)# ex
ESW1# vlan 20
ESW1(config-vlan)# ex
ESW1(config)# interface fastEthernet1/0
ESW1(config-if)# switchport mode access
ESW1(config-if)# switchport access vlan 10
ESW1(config-if)# ex
ESW1(config)# interface fastEthernet1/1
ESW1(config-if)# switchport mode access
ESW1(config-if)# switchport access vlan 20
ESW1(config-if)# ex
ESW1(config)# interface fastEthernet1/2
ESW1(config-if)# switchport mode trunk
ESW1(config-if)# switchport trunk encapsulation dot1q
ESW1(config-if)# ex
# ESW2
ESW2# configure terminal
ESW2# vlan 10
ESW2(config-vlan)# ex
ESW2# vlan 20
ESW2(config-vlan)# ex
ESW2(config)# interface fastEthernet1/0
ESW2(config-if)# switchport mode access
ESW2(config-if)# switchport access vlan 10
ESW2(config-if)# ex
ESW2(config)# interface fastEthernet1/1
ESW2(config-if)# switchport mode access
ESW2(config-if)# switchport access vlan 20
ESW2(config-if)# ex
ESW2(config)# interface fastEthernet1/2
ESW2(config-if)# switchport mode trunk
ESW2(config-if)# switchport trunk encapsulation dot1q
ESW2(config-if)# ex
对 PC1 ~ PC4 的配置如下:
# PC1
PC1> ip 192.168.10.1/24
# PC2
PC2> ip 192.168.10.2/24
# PC3
PC3> ip 192.168.10.3/24
# PC4
PC4> ip 192.168.10.4/24
配置完成后,我们观察下网络的表现,首先通过 PC1 ping PC3,他们都处在 VLAN 10,是可以正常 ping 通:
- PC1 -> ESW1:此时从 PC1 发出的 ICMP request 报文,并没有携带任何 VLAN 标签,在进入 ESW1 的 access 口时,会打上默认的 VLAN ID 10;
- ESW1 -> ESW2:ESW1 发现当前的 ICMP request 数据帧包含 VLAN ID 为 10 的 Tag,检查自己另外两个口,仅 trunk 口允许 VLAN ID 10 通过,因此将该数据帧转发至 trunk 口。抓包可以看到此时从 trunk 口发出的 ICMP request 数据帧已经携带了 VLAN Tag;
- ESW2 -> PC3:ESW2 的 trunk 口也允许 VLAN ID 10 通过,因此会接收该数据帧,然后将其转发到 access 10 的口,当数据帧从 access 出去时,默认会进行 Untag 的动作,所以此时在 ESW2 和 PC3 间抓包,看到数据帧已经不带任何 VLAN 标签;
此时我们再观察下跨 VLAN 通信的表现,通过 PC1 ping PC4,此时无法正常 ping 通:
从 PC1 开始到 ESW2 跟刚才的逻辑差不多,这里不再解释,我们重点看一下,当带 VLAN ID 为 10 的 ARP 数据帧到达 ESW2 时,ESW2 只会向 access 10 的口转发数据帧,这是为什么 ESW2 -> PC4 之间抓包没有任何 ARP 包的原因,同时也解释了交换机这侧通过 VLAN 标签可以将物理 LAN 隔离成几个虚拟 LAN 的原因,因为从二层开始跨 VLAN 就已经无法互通了。
VLAN 三层打通
通过刚才的实验,我们知道 VLAN 间可以隔离二层广播域,这里我们再实验下如何在三层通过 VLANIF 打通 VLAN 间的网络,网络拓扑如下:
对 ESW1 ~ ESW3 的配置如下:
# ESW1
ESW1# configure terminal
ESW1# vlan 10
ESW1(config-vlan)# ex
ESW1# vlan 20
ESW1(config-vlan)# ex
ESW1(config)# interface fastEthernet1/0
ESW1(config-if)# switchport mode access
ESW1(config-if)# switchport access vlan 10
ESW1(config-if)# ex
ESW1(config)# interface fastEthernet1/1
ESW1(config-if)# switchport mode access
ESW1(config-if)# switchport access vlan 20
ESW1(config-if)# ex
ESW1(config)# interface fastEthernet1/2
ESW1(config-if)# switchport mode trunk
ESW1(config-if)# switchport trunk encapsulation dot1q
ESW1(config-if)# ex
# ESW2
ESW2# configure terminal
ESW2# vlan 10
ESW2(config-vlan)# ex
ESW2# vlan 20
ESW2(config-vlan)# ex
ESW2(config)# interface fastEthernet1/0
ESW2(config-if)# switchport mode access
ESW2(config-if)# switchport access vlan 10
ESW2(config-if)# ex
ESW2(config)# interface fastEthernet1/1
ESW2(config-if)# switchport mode access
ESW2(config-if)# switchport access vlan 20
ESW2(config-if)# ex
ESW2(config)# interface fastEthernet1/2
ESW2(config-if)# switchport mode trunk
ESW2(config-if)# switchport trunk encapsulation dot1q
ESW2(config-if)# ex
# ESW3
ESW3# configure terminal
ESW3# vlan 10
ESW3(config-vlan)# ex
ESW3# vlan 20
ESW3(config-vlan)# ex
ESW3(config)# ip routing
ESW3(config)# interface fastEthernet1/1
ESW3(config-if)# switchport mode trunk
ESW3(config-if)# switchport trunk encapsulation dot1q
ESW3(config-if)# ex
ESW3(config)# interface fastEthernet1/2
ESW3(config-if)# switchport mode trunk
ESW3(config-if)# switchport trunk encapsulation dot1q
ESW3(config-if)# ex
ESW3(config)# interface vlan 10
ESW3(config-if)# ip address 192.168.10.254 255.255.255.0
ESW3(config-if)# ex
ESW3(config)# interface vlan 20
ESW3(config-if)# ip address 192.168.20.254 255.255.255.0
ESW3(config-if)# ex
ESW3(config)# end
ESW3# show ip route connected
C 192.168.10.0/24 is directly connected Vlan10
C 192.168.20.0/24 is directly connected Vlan20
对 PC1 ~ PC4 的配置如下:
# PC1
PC1> ip 192.168.10.1/24 192.168.10.254
# PC2
PC2> ip 192.168.20.1/24 192.168.20.254
# PC3
PC3> ip 192.168.10.2/24 192.168.10.254
# PC4
PC4> ip 192.168.20.2/24 192.168.20.254
基于之前的学习,我们知道 PC1 到 PC3 以及 PC2 到 PC4 之间肯定是互通的(处在同一二层,且在同一子网),所以这里我们主要看下 PC1 到 PC4 是如何互通的:
- PC1 -> ESW1:跟之前一样,PC1 发起 ICMP request 数据帧,不带任何 VLAN 标签;
- ESW1 -> ESW3:此时的数据帧已经经过 ESW1 的 access 10 口,所以被打上了默认的 VLAN ID 10,ESW1 的 trunk 口允许 VLAN 10 通过,所以直接转发到 ESW3;
- ESW3 -> ESW2:ESW3 的 trunk 口接收到数据帧,由于 VLAN ID 也在允许范围内,所以会处理该帧,在解析时会发现该数据帧是发送给自己的(PC1 的网关是 192.168.10.254,对应 ESW3 中的 vlanif 10 的逻辑接口),所以会将 ICMP request 数据帧原本的二层的以太网帧头的部分丢弃,并解析其三层报文,发现其 Dst IP 是 192.168.20.2,于是查看自己的路由表,对应上
192.168.20.0/24 is directly connected Vlan20
这条记录,知道这个报文要发往 vlanif 20 这个逻辑接口,所以在重新组装以太网帧头时,除 Dst MAC 和 Src MAC 外,还会打上 VLAN ID 20 的标签,所以在 ESW3 -> ESW2 间的抓包点,我们可以看到 VLAN ID 已经从 10 变成了 20; - ESW2 -> PC4:直接向 VLAN ID 相同的 access 20 口转发数据帧;