VLAN(Virtual Local Area Network),它將(jiang)一個(ge)(ge)(ge)物(wu)理(li)的(de) LAN 在(zai)(zai)邏輯上劃分成多個(ge)(ge)(ge)廣播域,即(ji)多個(ge)(ge)(ge) VLAN。單個(ge)(ge)(ge) VLAN 內的(de)主機間二層互通(tong)(tong),可以直接通(tong)(tong)信,而(er) VLAN 之間不能(neng)直接互通(tong)(tong)。這個(ge)(ge)(ge)能(neng)力對于流量管理(li)、提高安全性都非常有用(yong),也是在(zai)(zai)物(wu)理(li)網絡或虛擬網絡中都很常使(shi)用(yong)的(de)功能(neng)。
VLAN 原理
基(ji)于對 Linux Bridge 的(de)學習,我們(men)對交換(huan)機(ji)(ji)的(de)行為可以有(you)一個初(chu)步的(de)理解,當交換(huan)機(ji)(ji)在(zai)接(jie)收到數(shu)據幀時,一般有(you)三種處理:
- 直接轉發:當收到的數據幀的 Dst MAC 在轉發表中可以查到,并且對應的出端口和入端口不一致時,直接向出端口轉發;
- 丟棄:當收到的數據幀的 Dst MAC 在轉發表中可以查到,并且對應的出端口和入端口一致時,直接丟棄數據幀;
- 泛洪:當收到的數據幀的 Dst MAC 是單播地址,但是在轉發表中查找不到時,或 Dst MAC 是組播、廣播地址時,數據幀向除輸入端口外的其它端口復制并發送;
我們剛才提及 VLAN 的能力,是單個 VLAN 內的主機間二層互通,可以直接通信,而 VLAN 之間不能直接互通,所以(yi)我們大致可(ke)以(yi)猜測,VLAN 的劃分會影(ying)響到(dao)(dao)數據(ju)(ju)幀(zhen)的轉發和泛洪,即在入端口接受到(dao)(dao)數據(ju)(ju)幀(zhen)后,不(bu)再簡單的根據(ju)(ju) Dst MAC 判斷轉發丟棄(qi)或泛洪,還會同時再讀取數據(ju)(ju)幀(zhen)中的 VLAN 標簽,決定對該幀(zhen)的處理邏輯。
我們(men)先看一下以太網幀(zhen)的格(ge)式(shi)(其中在 12 字(zi)(zi)節的 MAC 地址之(zhi)后(hou)的 2 字(zi)(zi)節到底是 Length 還是 Type,與以太網幀(zhen)格(ge)式(shi)的不(bu)同版本有關(guan),大(da)家可以自行查閱相關(guan)資料):
[ 6B ][ 6B ][ 2B ][42~1500B][4B ]
[Destination Address][Source Address][Length/Type][ Data ][CRC]
而 IEEE 802.1q 標(biao)(biao)準(zhun)對以太網幀的格式(shi)進行了修(xiu)改(gai),加入了 4B 的 VLAN 標(biao)(biao)簽(IEEE 802.1q Tag):
[ 6B ][ 6B ][ 4B ][ 2B ][42~1500B][4B ]
[Destination Address][Source Address][802.1q Tag][Length/Type][ Data ][CRC]
展開看(kan)下(xia) VLAN 標簽(qian)的這 4 個(ge)字(zi)節中包含了什么內容:
- Type:2 字節,標識幀類型,取值為 0x8100;
- PRI:2 位,表示幀的優先級,值越大優先級越高,在交換機擁塞時,會先發送高優先級的幀;
- CFI:1 位,表示 MAC 地址是否為經典地址;
- VID:12 位,表示 VLAN ID,取值范圍為 0 ~ 4095,其中 0 和 4095 為保留的 VLAN ID,不能使用;
好,假設我(wo)們自己就是交換(huan)機,當我(wo)的 ifindex 為(wei) 0 的端口接收到帶(dai) VLAN 標簽的數據幀(zhen)時,我(wo)們會怎么解(jie)析這個幀(zhen)?
- 先讀取 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 信息;
當解析完該幀后,我們會如何轉發這個幀?

如上是大致(zhi)的(de)處理流(liu)程(cheng),實際處理邏輯與交換機的(de)端口的(de)配置有關,主要分為(wei) Access 口和 Trunk 口。
- Access 口一般用于交換機與主機的互聯,當接收到不帶 VLAN 標簽的報文時,接收并打上默認的 VLAN 標簽,當接收到帶 VLAN 標簽的數據幀時,幀內的 VLAN ID 必須與默認的 VLAN ID 相同才接受,否則丟棄該數據幀。
- 而 Trunk 口一般用于交換機與交換機間的互聯(如果同一臺主機創建多個 VLAN 子接口,那它與交換機的互聯也需要走 Trunk 口),這類型的口可以自由的設定允許通過多個 VLAN ID,這些 VLAN ID 可以與端口默認的 VLAN ID 相同,也可以不同。
好,對(dui)于(yu) VLAN 的概念的講解先告一(yi)段(duan)落(luo),我們通過實踐來加深對(dui) VLAN 的理解。
VLAN 實踐
我們本次的(de)實(shi)踐(jian)使用 GNS3 網絡模擬器(qi)來(lai)進(jin)行,具體的(de)安裝步驟相對比較(jiao)復雜,網上有(you)不少教程大家可(ke)以慢慢折騰一下。
VLAN 隔離
網絡拓撲如下所示:

對 ESW1 和(he) ESW2 的配(pei)置如下:
# 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 的(de)配(pei)置如(ru)下:
# 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 跟(gen)剛才的邏輯差不多(duo),這(zhe)里(li)不再解釋(shi),我們重點看(kan)一下,當帶(dai) VLAN ID 為(wei)(wei)(wei) 10 的 ARP 數(shu)據幀(zhen)到達 ESW2 時(shi),ESW2 只會向 access 10 的口轉發(fa)數(shu)據幀(zhen),這(zhe)是為(wei)(wei)(wei)什(shen)么 ESW2 -> PC4 之間抓包(bao)沒(mei)有任何 ARP 包(bao)的原(yuan)因,同時(shi)也解釋(shi)了交換機這(zhe)側通(tong)過 VLAN 標簽可以將物(wu)理 LAN 隔離成幾個虛(xu)擬 LAN 的原(yuan)因,因為(wei)(wei)(wei)從二層開始跨 VLAN 就已(yi)經無法互通(tong)了。
VLAN 三層打通
通過剛才的實驗,我們知道 VLAN 間可以隔離二層廣播域,這里我們再實驗下如何在三層通過 VLANIF 打通 VLAN 間的網絡,網絡拓撲如下:

對 ESW1 ~ ESW3 的(de)配置如下:
# 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 的配置(zhi)如下:
# 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 口轉發數據幀;