Build two VLANs on one wire and read the tag

short · 45 min · Objective 2.2

Task

Create two VLANs on a single Linux bridge, put a host in each, prove they cannot reach one another, then capture a tagged frame and read the 802.1Q header. The tag is four bytes, and seeing them is what makes trunking concrete.

Steps

  1. Create a VLAN-aware bridge: sudo ip link add br0 type bridge vlan_filtering 1 and bring it up.
  2. Create two namespaces with veth pairs into the bridge. Put h1's bridge port in VLAN 10 as untagged, and h2's in VLAN 20 as untagged: sudo bridge vlan add dev veth1 vid 10 pvid 10 untagged, and the same for veth2 with vid 20.
  3. Address both hosts in the same IP subnet — 10.10.0.1/24 and 10.10.0.2/24 — which is the point: same subnet, different VLANs.
  4. Ping from h1 to h2. It fails, and it fails at layer 2 rather than layer 3. Confirm with ip neigh show in h1: the ARP entry stays incomplete, because the ARP broadcast never crossed the VLAN boundary.
  5. Now create a trunk. Add a third veth carrying both VLANs tagged (sudo bridge vlan add dev veth3 vid 10 and vid 20), and capture on it while pinging. Read the VLAN ID out of the captured frame.

Verify

bridge vlan show
sudo ip netns exec h1 ping -c 2 -W 1 10.10.0.2; echo "exit $?"
sudo ip netns exec h1 ip neigh show 10.10.0.2
sudo tcpdump -i veth3 -n -e -c 5 vlan

bridge vlan show must list veth1 in VLAN 10 and veth2 in VLAN 20. The ping must fail with an incomplete ARP entry. And the tcpdump on the trunk must print vlan 10 or vlan 20 in the frame header — that is the 802.1Q tag, observed.

Notes

Two hosts in the same IP subnet that cannot reach each other is the clearest demonstration there is that VLANs operate below IP. No routing is involved and no firewall is involved; the frame simply is not forwarded.

Note what the native VLAN does. A trunk carries one VLAN untagged — the native VLAN — and every other VLAN tagged. A native VLAN mismatch between two switches silently merges two VLANs, which is both a connectivity fault and a security hole, and it is why hardening guidance says to set the native VLAN to an unused ID.

The 4-byte tag also explains the "giants" counter from domain 5: a switch that does not account for it sees a maximum-size tagged frame as oversized.