Skip to content

WireGuard with VLAN Bridge

WireGuard on RouterOS is a Layer 3 (routed) tunnel. It carries IP packets, not Ethernet frames, which means it cannot be inserted into a VLAN-filtering bridge the same way a physical Ethernet port can. Understanding this distinction is essential before designing any WireGuard + VLAN topology.

Two valid integration designs exist:

DesignWhen to use
Routed VLANs over WireGuardRemote sites or road warriors need IP access to one or more local VLANs. Traffic is routed, not bridged, across the tunnel. This is the recommended approach.
L2 extension (EoIP over WireGuard)Two sites must share the same broadcast domain (e.g., same VLAN/subnet must span physical locations). Use EoIP or VXLAN as the L2 carrier inside the WireGuard underlay, then bridge that interface.

  • RouterOS 7.1 or later (WireGuard support added in 7.1)
  • Existing VLAN-filtering bridge on the LAN side (see Bridge VLAN Filtering)
  • WAN interface with a public or reachable IP address
  • UDP reachability between WireGuard endpoints on the configured listen-port
  • Basic familiarity with /interface bridge vlan and /ip firewall filter

Section titled “Design 1 — Routed VLANs over WireGuard (Recommended)”

In this design, WireGuard remains a pure L3 tunnel. VLAN subnets on the LAN side are routed across the tunnel using allowed-address and static routes. The VLAN bridge and WireGuard are independent — the bridge handles L2 switching and VLAN segmentation locally; WireGuard is the encrypted pipe to remote peers.

┌─────────────────────────────────┐ ┌────────────────────────────┐
│ Site A (RouterOS) │ │ Remote peer / road warrior│
│ │ │ │
│ VLAN 10 (192.168.10.0/24) │ WG tun │ Peer address: 10.0.0.2 │
│ VLAN 20 (192.168.20.0/24) ────┼───────────┼──► gets access to VLAN 10 │
│ │ │ via allowed-address │
│ wg1 endpoint: 10.0.0.1/30 │ │ │
└─────────────────────────────────┘ └────────────────────────────┘
/interface bridge
add name=br1 vlan-filtering=yes protocol-mode=rstp
/interface bridge port
add bridge=br1 interface=ether2 pvid=10 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged
add bridge=br1 interface=ether3 pvid=20 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-tagged
add bridge=br1 interface=ether4 ingress-filtering=yes frame-types=admit-only-vlan-tagged
/interface bridge vlan
add bridge=br1 vlan-ids=10 tagged=br1,ether4 untagged=ether2
add bridge=br1 vlan-ids=20 tagged=br1,ether4 untagged=ether3

Step 2 — Create VLAN Interfaces and Assign IPs

Section titled “Step 2 — Create VLAN Interfaces and Assign IPs”
/interface vlan
add name=vlan10 interface=br1 vlan-id=10
add name=vlan20 interface=br1 vlan-id=20
/ip address
add address=192.168.10.1/24 interface=vlan10
add address=192.168.20.1/24 interface=vlan20
/interface wireguard
add name=wg1 listen-port=13231 mtu=1420

After creation, retrieve the generated public key:

/interface wireguard print

Assign a point-to-point tunnel address:

/ip address
add address=10.0.0.1/30 interface=wg1

Add each remote peer with allowed-address covering the VLAN subnets the peer should reach:

/interface wireguard peers
add interface=wg1 \
public-key="<PEER_PUBLIC_KEY>" \
allowed-address=10.0.0.2/32,192.168.10.0/24 \
endpoint-address=203.0.113.50 \
endpoint-port=13231 \
persistent-keepalive=25s
  • 10.0.0.2/32 — the peer’s tunnel IP
  • 192.168.10.0/24 — the remote subnet the peer can originate (for road warriors, omit this and use a /32 per peer)
/ip route
add dst-address=192.168.10.0/24 gateway=wg1

For road warriors (no fixed remote subnet), the allowed-address=/32 entry is sufficient — RouterOS automatically creates a host route for each peer.

/ip firewall filter
# Allow WireGuard handshake from WAN
add chain=input action=accept protocol=udp dst-port=13231 in-interface-list=WAN comment="WireGuard UDP"
# Allow established/related (include if not already present in your ruleset)
add chain=input action=accept connection-state=established,related
# Allow routed traffic from WG peers to specific VLANs
add chain=forward action=accept in-interface=wg1 dst-address=192.168.10.0/24 comment="WG to VLAN10"
# Drop everything else from WG peers (explicit deny)
add chain=forward action=drop in-interface=wg1 comment="WG default deny"

Design 2 — L2 Extension (EoIP over WireGuard)

Section titled “Design 2 — L2 Extension (EoIP over WireGuard)”

Use this design only when both sites must share the same L2 broadcast domain (same VLAN ID and subnet span both physical locations). EoIP provides the Ethernet encapsulation; WireGuard provides the encrypted, authenticated underlay.

L2 extension amplifies broadcast traffic across the WAN link. ARP, mDNS, and other broadcasts from all hosts on the VLAN cross the tunnel. Keep the shared L2 domain small (e.g., a single IoT or management VLAN) and use STP to prevent loops.

Configure WireGuard as in Design 1 (Steps 1–4), but allow only the tunnel endpoints in allowed-address:

/interface wireguard peers
add interface=wg1 \
public-key="<PEER_PUBLIC_KEY>" \
allowed-address=10.0.0.2/32 \
endpoint-address=203.0.113.50 \
endpoint-port=13231 \
persistent-keepalive=25s

Step 2 — Create EoIP Tunnel over WireGuard

Section titled “Step 2 — Create EoIP Tunnel over WireGuard”
/interface eoip
add name=eoip1 remote-address=10.0.0.2 tunnel-id=100 mtu=1400

Step 3 — Add EoIP Interface to the Bridge

Section titled “Step 3 — Add EoIP Interface to the Bridge”
/interface bridge port
add bridge=br1 interface=eoip1 ingress-filtering=yes pvid=30

Add VLAN table entry for the shared VLAN:

/interface bridge vlan
add bridge=br1 vlan-ids=30 tagged=br1 untagged=eoip1

Both sites must mirror this configuration with swapped WireGuard endpoint addresses and the same tunnel-id.


Road Warrior Pattern — Per-Peer VLAN Access

Section titled “Road Warrior Pattern — Per-Peer VLAN Access”

WireGuard has no native dynamic VLAN assignment (no 802.1X/RADIUS integration). Assign each road warrior to a VLAN by controlling their peer allowed-address and enforcing policy in the firewall:

# Peer 1 — trusted user → access VLAN 10
/interface wireguard peers
add interface=wg1 public-key="<USER1_KEY>" allowed-address=10.0.1.1/32 persistent-keepalive=25s
# Peer 2 — IoT device → access VLAN 30 only
/interface wireguard peers
add interface=wg1 public-key="<IOT_KEY>" allowed-address=10.0.1.2/32 persistent-keepalive=25s
# Firewall: peer 1 may reach VLAN 10
/ip firewall filter
add chain=forward action=accept src-address=10.0.1.1 dst-address=192.168.10.0/24 comment="User1→VLAN10"
# Firewall: IoT peer may reach VLAN 30 only
add chain=forward action=accept src-address=10.0.1.2 dst-address=192.168.30.0/24 comment="IoT→VLAN30"
add chain=forward action=drop in-interface=wg1 comment="WG default deny"

If road warrior peers should route internet traffic through the router (full-tunnel), add a masquerade rule and expand allowed-address to include 0.0.0.0/0 on the peer:

# On the peer client side: AllowedIPs = 0.0.0.0/0
# On the router: masquerade WG tunnel traffic leaving to WAN
/ip firewall nat
add chain=srcnat out-interface-list=WAN src-address=10.0.1.0/24 action=masquerade comment="WG road warriors → WAN"

Check WireGuard handshake and traffic counters

Section titled “Check WireGuard handshake and traffic counters”
/interface wireguard peers print detail

Look for last-handshake within the last ~180 seconds and non-zero rx/tx byte counts.

Verify routing table has VLAN and WG prefixes

Section titled “Verify routing table has VLAN and WG prefixes”
/ip route print where gateway=wg1
/interface bridge vlan print detail
/interface bridge port print detail
/ip firewall filter print stats where comment~"WG"
/log print where message~"wireguard"
# Ping from router to remote peer tunnel IP
/ping 10.0.0.2 interface=wg1 count=4
# Ping from router to remote VLAN host (if routed)
/ping 192.168.10.100 count=4

SymptomCheck
No handshake (last-handshake is empty)Firewall input rule for UDP 13231 on WAN; check remote endpoint address/port
Handshake OK but no traffic flowsallowed-address must include the source IP of traffic; check routes
Bridge VLAN traffic missing after adding EoIPVerify mtu on EoIP ≤ WireGuard MTU minus 20 bytes; check bridge VLAN table entries
Road warrior can reach wrong VLANTighten firewall forward chain rules; confirm allowed-address does not overlap peers
High CPU on forwarding pathWireGuard has no hardware offload; all crypto is CPU-bound. Consider a device with a hardware crypto engine.
L2-over-WG drops packets intermittentlyCheck for MTU/fragmentation: lower EoIP MTU; enable TCP MSS clamping on the WG interface
Firewall rules not matching bridged trafficEnable use-ip-firewall=yes and use-ip-firewall-for-vlan=yes on the bridge, or use /interface bridge filter for L2 traffic
FastTrack bypasses WG forward rulesAdd a pre-FastTrack accept rule for WG source subnets (see firewall note above)
/ip firewall mangle
add chain=forward action=change-mss new-mss=clamp-to-pmtu protocol=tcp tcp-flags=syn out-interface=wg1