WireGuard with VLAN Bridge
WireGuard with VLAN Bridge
Section titled “WireGuard with VLAN Bridge”Overview
Section titled “Overview”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:
| Design | When to use |
|---|---|
| Routed VLANs over WireGuard | Remote 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. |
Prerequisites
Section titled “Prerequisites”- 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 vlanand/ip firewall filter
Design 1 — Routed VLANs over WireGuard (Recommended)
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.
Topology
Section titled “Topology” ┌─────────────────────────────────┐ ┌────────────────────────────┐ │ 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 │ │ │ └─────────────────────────────────┘ └────────────────────────────┘Step 1 — Create the VLAN Bridge
Section titled “Step 1 — Create the VLAN Bridge”/interface bridgeadd name=br1 vlan-filtering=yes protocol-mode=rstp
/interface bridge portadd bridge=br1 interface=ether2 pvid=10 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-taggedadd bridge=br1 interface=ether3 pvid=20 ingress-filtering=yes frame-types=admit-only-untagged-and-priority-taggedadd bridge=br1 interface=ether4 ingress-filtering=yes frame-types=admit-only-vlan-tagged
/interface bridge vlanadd bridge=br1 vlan-ids=10 tagged=br1,ether4 untagged=ether2add bridge=br1 vlan-ids=20 tagged=br1,ether4 untagged=ether3Step 2 — Create VLAN Interfaces and Assign IPs
Section titled “Step 2 — Create VLAN Interfaces and Assign IPs”/interface vlanadd name=vlan10 interface=br1 vlan-id=10add name=vlan20 interface=br1 vlan-id=20
/ip addressadd address=192.168.10.1/24 interface=vlan10add address=192.168.20.1/24 interface=vlan20Step 3 — Create the WireGuard Interface
Section titled “Step 3 — Create the WireGuard Interface”/interface wireguardadd name=wg1 listen-port=13231 mtu=1420After creation, retrieve the generated public key:
/interface wireguard printAssign a point-to-point tunnel address:
/ip addressadd address=10.0.0.1/30 interface=wg1Step 4 — Add Peers
Section titled “Step 4 — Add Peers”Add each remote peer with allowed-address covering the VLAN subnets the peer should reach:
/interface wireguard peersadd 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=25s10.0.0.2/32— the peer’s tunnel IP192.168.10.0/24— the remote subnet the peer can originate (for road warriors, omit this and use a /32 per peer)
Step 5 — Add Routes
Section titled “Step 5 — Add Routes”/ip routeadd dst-address=192.168.10.0/24 gateway=wg1For road warriors (no fixed remote subnet), the allowed-address=/32 entry is sufficient — RouterOS automatically creates a host route for each peer.
Step 6 — Firewall Rules
Section titled “Step 6 — Firewall Rules”/ip firewall filter# Allow WireGuard handshake from WANadd 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 VLANsadd 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.
Step 1 — Establish WireGuard Underlay
Section titled “Step 1 — Establish WireGuard Underlay”Configure WireGuard as in Design 1 (Steps 1–4), but allow only the tunnel endpoints in allowed-address:
/interface wireguard peersadd 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=25sStep 2 — Create EoIP Tunnel over WireGuard
Section titled “Step 2 — Create EoIP Tunnel over WireGuard”/interface eoipadd name=eoip1 remote-address=10.0.0.2 tunnel-id=100 mtu=1400Step 3 — Add EoIP Interface to the Bridge
Section titled “Step 3 — Add EoIP Interface to the Bridge”/interface bridge portadd bridge=br1 interface=eoip1 ingress-filtering=yes pvid=30Add VLAN table entry for the shared VLAN:
/interface bridge vlanadd bridge=br1 vlan-ids=30 tagged=br1 untagged=eoip1Both 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 peersadd 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 peersadd 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 filteradd 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 onlyadd 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"NAT for Internet Access (Road Warriors)
Section titled “NAT for Internet Access (Road Warriors)”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 natadd chain=srcnat out-interface-list=WAN src-address=10.0.1.0/24 action=masquerade comment="WG road warriors → WAN"Verification
Section titled “Verification”Check WireGuard handshake and traffic counters
Section titled “Check WireGuard handshake and traffic counters”/interface wireguard peers print detailLook 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=wg1Confirm bridge VLAN table is correct
Section titled “Confirm bridge VLAN table is correct”/interface bridge vlan print detail/interface bridge port print detailCheck firewall counters
Section titled “Check firewall counters”/ip firewall filter print stats where comment~"WG"Check logs
Section titled “Check logs”/log print where message~"wireguard"Test connectivity
Section titled “Test connectivity”# 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=4Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
No handshake (last-handshake is empty) | Firewall input rule for UDP 13231 on WAN; check remote endpoint address/port |
| Handshake OK but no traffic flows | allowed-address must include the source IP of traffic; check routes |
| Bridge VLAN traffic missing after adding EoIP | Verify mtu on EoIP ≤ WireGuard MTU minus 20 bytes; check bridge VLAN table entries |
| Road warrior can reach wrong VLAN | Tighten firewall forward chain rules; confirm allowed-address does not overlap peers |
| High CPU on forwarding path | WireGuard has no hardware offload; all crypto is CPU-bound. Consider a device with a hardware crypto engine. |
| L2-over-WG drops packets intermittently | Check for MTU/fragmentation: lower EoIP MTU; enable TCP MSS clamping on the WG interface |
| Firewall rules not matching bridged traffic | Enable 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 rules | Add a pre-FastTrack accept rule for WG source subnets (see firewall note above) |
TCP MSS Clamping (for EoIP/L2 design)
Section titled “TCP MSS Clamping (for EoIP/L2 design)”/ip firewall mangleadd chain=forward action=change-mss new-mss=clamp-to-pmtu protocol=tcp tcp-flags=syn out-interface=wg1