How to use WireGuard for only a specific VLAN?

I am trying to route specific devices/traffic over a WireGuard interface. Until recently I was using an IPv4-only stack with vpn-policy-routing without any issues. However, my ISP has recently enabled IPv6 and I've run into some problems using vpn-policy-routing with a dual-stack ISP and IPv4-only WireGuard:

  1. IPv6 leaks with vpn-policy-routing. The default wireguard AllowedIPs configuration (0.0.0.0/24) from my Wireguard VPN indicates that it only supports IPv4. This meant that all of my new IPv6 traffic never made it through the wireguard tunnel and was instead routed straight to my ISP (hooray). To immediately remedy this I added all IPv6 addresses to the WireGuard AllowedIPs (option allowed_ips '::/0'). This worked for any devices using DHCPv6 but SLAAC devices like my Android phone would still get a public prefix from my ISP. To fix this, I added option ip6class local to the lan interface so that SLAAC devices would only receive a local IPv6 address and not a public one (effectively, IPv6 NAT).

  2. Split tunnel connectivity/timeout issues. While these changes fixed the leaks, they also led to all sorts of problems when browsing since my devices would still perform IPv6 dns lookups that led to nowhere (timeouts, delays, other weird problems). Perhaps this is an XY problem and I could fix the issue by disabling IPv6 completely, but it looks like I may need to do this on a per-device basis (for instance, systemd-resolved will perform OS-level IPv6 level lookups and must be disabled). Also, I would like to utilize IPv6 in my DMZ since it works fine when routed directly to my ISP.

To side-step this issue I decided it would be better to just implement layer 2 vlans that I could selectively route (bridge?) over WireGuard and/or my DMZ. I also wanted to do this in order to provision off IoT devices from the rest of my LAN as well as to have more granular control over DNS and organization.

Ideally, I want the default DMZ interface to connect directly to wan/wan6 and the new veth (802.1q tagged) to WireGuard + my DMZ LAN. In other words, I want everything on my LAN to be able to communicate, but only some of the devices to have direct access to the the internet via my ISP and other devices only through the WireGuard interface.

I know that adding a new iface eth0.2 will create a new vlan tagged 2, and I believe that I can also bridge this network with wireguard in one step using iface eth0 eth0.2 wireguard and option type 'bridge', so I took a stab at creating a new vlan 'vlan1vpn' you can see in my current /etc/config/network:

config interface 'loopback'
    option ifname 'lo'
    option proto 'static'
    option ipaddr '127.0.0.1'
    option netmask '255.0.0.0'

config globals 'globals'
    option ula_prefix 'fdc2:9aea:13b1::/48'

config interface 'lan'
    option type 'bridge'
    option ifname 'eth0'
    option proto 'static'
    option netmask '255.255.255.0'
    option ip6assign '60'
    option ipaddr '192.168.1.1'
    option ip6class 'local'

config interface 'vlan2vpn'
    option proto 'static'
    option type 'bridge'
    option ifname 'eth0 eth0.2 wireguard'
    option ipaddr '192.168.2.1'
    option netmask '255.255.255.0'
    list dns '1.1.1.1'
    option ip6assign '60'

config interface 'wan'
    option proto 'dhcp'
    option ifname 'eth1'

config interface 'wan6'
    option proto 'dhcpv6'
    option ifname 'eth1'
    option reqaddress 'try'
    option reqprefix '56'

config interface 'wireguard'
    option proto 'wireguard'
    option listen_port '51820'
    list addresses '10.1.128.101/24'
    option auto '0'
    option private_key 'xxxxxxxxxxxxxxxxxxxxx'

config wireguard_wireguard
    option route_allowed_ips '1'
    option endpoint_port '1443'
    option persistent_keepalive '25'
    option public_key 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
    option endpoint_host 'XXX.XX.XX.XXX'
    option description 'Wireguard'
    # Route everything
    #list allowed_ips '0.0.0.0/0'
    #list allowed_ips '::/0'
    # Route vlan1 and intra-vpn only
    list allowed_ips '192.168.2.0/24'
    list allowed_ips '10.1.128.0/24'


I figure that now I should be able to just assign static ips in the 192.168.2.0/24 subnet to tag them with a vlan tag of 2. Unfortunately, the first problem I run into is that the DHCPv4 server seems to clobber the static IP addresses I assign in the dnsmasq settings. I can still test this manually by setting static IPs on the devices manually (but they do not show up in the DHCP list in LUCI) Eventually I may even figure out how to manually assign ipv6 prefixes but I figure that OpenWRT can handle those automatically for now. The problem may also be tied to the firewall config:

/etc/config/firewall:

config zone
    option name 'lan'
    option input 'ACCEPT'
    option output 'ACCEPT'
    option forward 'ACCEPT'
    list network 'lan'
    list network 'vlan1vpn'

config zone
    option name 'wan'
    option input 'REJECT'
    option output 'ACCEPT'
    option forward 'REJECT'
    option masq '1'
    option mtu_fix '1'
    list network 'wan'
    list network 'wan6'
    list network 'wireguard'

config forwarding
    option src 'lan'
    option dest 'wan'

I'm not certain if I need to explicitly forward packets from the 192.168.2.0/24 subnet to the LAN or WireGuard interface.

Could anyone that has attempted to route specific vlans through wireguard without vpn-policy-routing or something similar help me out here? Or perhaps this is an XY problem and I'm overlooking something since my searches have been unproductive. Thanks!

I'm afraid, WireGuard won't work with bridging.
You can try a VPN provider that supports IPv6 inside the tunnel and enable IPv6 masquerading.

VPN-PBR has some IPv6-specific settings, but I have no native IPv6 to test it.
Policy-based routing can also be configured manually with IP rules and custom routing tables.

Disabling IPv6 delegation for a specific subnet/VLAN should be possible as well.
I recommend to troubleshoot the timeout/connectivity issues with Wireshark/tcpdump.

2 Likes