Software VLANs, static leases, and IPv6

I'm running into numerous issues trying to set up VLANs, static IP addresses and IPv6 in OpenWRT r16076-5a3562cd1d for the NanoPi R2S.

I have created software VLAN VLAN2VPN that I wish to route traffic through my Wireguard tunnel. I assigned it an IPv4 192.168.2.0/24 subnet and IPv6-PD of fdc2:9aea:13b1:2::1/64. To prevent IPv6 leaks I have disabled global IPv6 addressing on the VLAN2VPN VLAN with ip6class 'local'.

My complete /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 '64'
    option ipaddr '192.168.1.1'
    option ip6ifaceid '::1'
    option ip6hint '1'

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 'VLAN2VPN'
    option proto 'static'
    option type 'bridge'
    option ipaddr '192.168.2.1'
    option netmask '255.255.255.0'
    option ip6assign '64'
    option ip6hint '2'
    option ip6ifaceid '::1'
    option ifname 'eth0 eth0.2'
    option ip6class 'local'
    list dns '1.1.1.1'

config interface 'wg0'
    option proto 'wireguard'
    option private_key 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    option listen_port '51820'
    list addresses '10.1.1.1/24'

config wireguard_wg0
    option description 'Home VPN'
    option public_key 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    option route_allowed_ips '1'
    option endpoint_host 'xxx.xx.xx.xxx'
    option endpoint_port '1443'
    option persistent_keepalive '25'
    list allowed_ips '10.1.1.0/24'
    list allowed_ips 'fdc2:9aea:13b1:2::1/64'
    list allowed_ips '192.168.2.0/24'

I assigned my test device a static IP address in the 192.168.2.5 and a host ID of 5, I'm assuming this means it will receive an IPv6 address of fdc2:9aea:13b1:2::5/128.

/etc/config/dhcp:

config host
    option name 'test'
    option dns '1'
    option mac '5C:17:CF:19:3C:E1'
    option hostid '5'
    option ip '192.168.2.5'

Problem #1: Static leases do not work when assigning device to VLAN: For some reason my test device is being assigned an IP address from the default DHCP server assigning addresses for the LAN 192.168.1.0/24 subnet by default and not the static lease. I've worked around this by assigning the 192.168.2.5 IP address manually on the device. This allows it to join the 192.168.2.0/24 subnet, but I don't want to have to make modifications on every device because I cannot assign static IPs from the VLAN. Note: Assigning static leases works fine when assigning static IPs from the 192.168.1.0/24 LAN subnet. DHCP overriding the static assignment only happens on the VLANs.

Problem #2: After I add a device to the VLAN by manually assigning the IP on the device, it still receives global IPv6 addresses from my ISP even though these aren't exposed by the interface! What?! Does SLAAC not care about isolated VLANs?

Problem #3: I have added the VLAN subnet and IPv6 prefix to the allowed_ips WireGuard setting. I have no idea if this is the correct way to route traffic from specific vlans over the WireGuard tunnel, but it makes sense to me. I cannot find this information anywhere online, anyone that has gotten close to the answer ends up using vpn-policy-routing, which is something I'm trying to avoid because it causes a host of DNS timeout issues when trying to split DMZ and VPN traffic over a dual stack native connection and IPv4-only VPN. I do have an IPv6 Wireguard tunnel available that I test with on occasion, but I'm fine sending packets from fdc2:9aea:13b1:2::1/64 to the aether for now until I rectify the other more fundamental issues.

Thank you.

First problem is that you have bridged lan (eth0) with vlan2vpn (eth0.2)
Second problem is that wireguard is layer 3 protocol, not layer 2, so you can route, not bridge.

1 Like

I was only trying to bridge the vlan and lan (WireGuard is routed via allowed_ips) so not sure if that applies, but I have removed the bridge from my vlan configuration. I thought that it may at least fix the rogue DHCP, but unfortunately I am running into the exact same problems.

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 '64'
	option ipaddr '192.168.1.1'
	option ip6ifaceid '::1'
	option ip6hint '1'

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 'VLAN2VPN'
	option proto 'static'
	option ifname 'eth0.2'
	option ipaddr '192.168.2.1'
	option netmask '255.255.255.0'
	list dns '1.1.1.1'
	option ip6assign '64'
	option ip6hint '2'
	option ip6ifaceid '::1'
	option ip6class 'local'

config interface 'wg0'
	option proto 'wireguard'
	option private_key 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
	option listen_port '51820'
	list addresses '10.1.1.1/24'

config wireguard_wg0
	option description 'Home wireguard'
	option public_key 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	option route_allowed_ips '1'
	option endpoint_host '1xxx.xx.xx.xxx'
	option endpoint_port '1443'
	option persistent_keepalive '25'
	list allowed_ips '10.1.1.0/24'
	list allowed_ips 'fdc2:9aea:13b1:2::1/64'
	list allowed_ips '192.168.2.0/24'

Edit: I've also enabled DHCP for the VLAN interface, although I wasn't sure if that was strictly necessary if I'm manually assigning IPs. Regardless, it didn't work.

cat /var/etc/dnsmasq.conf.cfg01411c

conf-file=/etc/dnsmasq.conf
dhcp-authoritative
domain-needed
localise-queries
read-ethers
enable-ubus
expand-hosts
bind-dynamic
local-service
dhcp-sequential-ip
edns-packet-max=1232
domain=lan
server=/lan/
dhcp-leasefile=/tmp/dhcp.leases
resolv-file=/tmp/resolv.conf.d/resolv.conf.auto
stop-dns-rebind
rebind-localhost-ok
dhcp-broadcast=tag:needs-broadcast
addn-hosts=/tmp/hosts
conf-dir=/tmp/dnsmasq.d
user=dnsmasq
group=dnsmasq
dhcp-host=5F:17:CD:19:3C:E4,192.168.2.5,phone
dhcp-ignore-names=tag:dhcp_bogus_hostname
conf-file=/usr/share/dnsmasq/dhcpbogushostname.conf
bogus-priv
conf-file=/usr/share/dnsmasq/rfc6761.conf
dhcp-range=set:lan,192.168.1.100,192.168.1.249,255.255.255.0,12h
no-dhcp-interface=eth1
dhcp-range=set:VLAN2VPN,192.168.2.100,static,255.255.255.0,12h

Edit 2: I have tried routing the vpn firewall zone to LAN in hopes of getting static leases working on the VLAN subnet:

config defaults
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option synflood_protect '1'

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

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 'wg0'

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

config rule
	option name 'Allow-DHCP-Renew'
	option src 'wan'
	option proto 'udp'
	option dest_port '68'
	option target 'ACCEPT'
	option family 'ipv4'

config rule
	option name 'Allow-Ping'
	option src 'wan'
	option proto 'icmp'
	option icmp_type 'echo-request'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-IGMP'
	option src 'wan'
	option proto 'igmp'
	option family 'ipv4'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCPv6'
	option src 'wan'
	option proto 'udp'
	option src_ip 'fc00::/6'
	option dest_ip 'fc00::/6'
	option dest_port '546'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-MLD'
	option src 'wan'
	option proto 'icmp'
	option src_ip 'fe80::/10'
	list icmp_type '130/0'
	list icmp_type '131/0'
	list icmp_type '132/0'
	list icmp_type '143/0'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Input'
	option src 'wan'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	list icmp_type 'router-solicitation'
	list icmp_type 'neighbour-solicitation'
	list icmp_type 'router-advertisement'
	list icmp_type 'neighbour-advertisement'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-ICMPv6-Forward'
	option src 'wan'
	option dest '*'
	option proto 'icmp'
	list icmp_type 'echo-request'
	list icmp_type 'echo-reply'
	list icmp_type 'destination-unreachable'
	list icmp_type 'packet-too-big'
	list icmp_type 'time-exceeded'
	list icmp_type 'bad-header'
	list icmp_type 'unknown-header-type'
	option limit '1000/sec'
	option family 'ipv6'
	option target 'ACCEPT'

config rule
	option name 'Allow-IPSec-ESP'
	option src 'wan'
	option dest 'lan'
	option proto 'esp'
	option target 'ACCEPT'

config rule
	option name 'Allow-ISAKMP'
	option src 'wan'
	option dest 'lan'
	option dest_port '500'
	option proto 'udp'
	option target 'ACCEPT'

config include
	option path '/etc/firewall.user'

config include 'miniupnpd'
	option type 'script'
	option path '/usr/share/miniupnpd/firewall.include'
	option family 'any'
	option reload '1'

config zone
	option name 'vpn'
	option input 'ACCEPT'
	option output 'ACCEPT'
	list network 'VLAN2VPN'
	option forward 'REJECT'

config forwarding
	option src 'vpn'
	option dest 'lan'

config forwarding
	option src 'lan'
	option dest 'vpn'

Still no dice, my client is still pulling a dynamic 192.168.1.100/24 address even after clearing /tmp/dhcp.leases and restarting the client.

That is not correct. Allowed IPs are the IPs that are allowed on the peer. Which means that on this side you want the ::/0 and on the other side you can have the fdc2:9aea:13b1:2::/64. The same applies for the IPv4 addresses.

1 Like

Thank you for the clarification re: WireGuard. I will fix the configuration. Unfortunately I need to get these static leases working first so I can get my devices onto the software VLAN before I can start addressing the WireGuard issues.

Why is dnsmasq not reserving static leases on the 802.1q VLAN subnet?

uci export dhcp; netstat -lnp | grep 67 ?

1 Like
package dhcp

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option localservice '1'
	option sequential_ip '1'
	option ednspacket_max '1232'

config dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dhcpv6 'server'
	option ra_slaac '1'
	list ra_flags 'managed-config'
	list ra_flags 'other-config'
	option ra_management '1'
	option ra 'server'

config dhcp 'wan'
	option interface 'wan'
	option ignore '1'

config odhcpd 'odhcpd'
	option maindhcp '0'
	option leasefile '/tmp/hosts/odhcpd'
	option leasetrigger '/usr/sbin/odhcpd-update'
	option loglevel '4'

config host
	option dns '1'
	option mac '5C:17:CF:19:3C:E1'
	option hostid '5'
	option name 'test'
	option ip '192.168.2.5'

config dhcp 'VLAN2VPN'
	option interface 'VLAN2VPN'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option dynamicdhcp '0'
	option ra 'server'
	option dhcpv6 'server'
	option ra_management '1'
	option ra_default '1'
	option force '1'

udp        0      0 0.0.0.0:67              0.0.0.0:*                           23241/dnsmasq

Edit: I should also mention that downstream of eth0 is a dumb wireless AP running OpenWRT with a '1' VLAN tag on the CPU, but untagged ports. I'm not sure if this affects the ability to assign devices downstream of the switch to the VLAN on the upstream router:

You haven't got any port configured for vlan 2.
Trunk port to the NanoPi should be tagged for both vlans.
I suggest you enable tagging on lan interface too on NanoPi, vlan1 if you want.
Then on the dumbAP split the ports to be untagged on vlan1 and vlan2.

1 Like

Thanks @trendy. I'm beginning to understand my confusion here. I thought that I would be able to use software VLANs to segment my network without a hardware switch in the mix. I guess that this is not possible. As most of my clients are wireless I believe that the best option would be to create virtual SSIDs on my dumb AP that correspond to the desired VLANs that I am creating on the trunk'd NanoPi, correct? I was hoping to not have to mess with the wireless topology, but if I need a hardware switch involved to do VLANs it may be the most flexible option. I'm trying to avoid L3 IPv6 leaks, specifically Android devices with SLAAC, which is why I shifted from vpn-policy-routing to VLANs.

Back to the drawing board.

Yes

You don't need one, the dumbAP running OpenWrt can tag vlans as well.

1 Like

@trendy, thanks so much for the help, I've created the VLANs and fixed the static IP assignment on the new subnet. Getting closer!

Switch:

VLAN 1 is untagged on the trunk port (LAN 4) for default traffic. I created VLANs 2-4 and tied each to a different SSID.

Router:

/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 proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '192.168.1.1'
	option ip6assign '64'
	option ip6ifaceid '::1'
	option ifname 'eth1'

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

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

config interface 'vpn'
	option proto 'static'
	option type 'bridge'
	option ipaddr '192.168.2.1'
	option netmask '255.255.255.0'
	list dns '1.1.1.1'
	option ifname 'eth1 eth1.2'

Thus far I've only created a VLAN interface for VLAN ID 2 just as a test. I also disabled IPv6 assignment on VLAN 2 to prevent any IPv6 leaks on VPN devices (I could never get this to work right with vpn-policy-routing). I bridged the VLAN to the untagged LAN interface so I can still communicate between the two networks:

$ ping 192.168.2.5
PING 192.168.2.5 (192.168.2.5) 56(84) bytes of data.
64 bytes from 192.168.2.5: icmp_seq=1 ttl=63 time=102 ms

(I don't know why my pings are so high on my LAN, bad cable, wifi interference?)

The next step is to route everything in VLAN 2 over the Wireguard interface. You mentioned earlier:

That is not correct. Allowed IPs are the IPs that are allowed on the peer. Which means that on this side you want the ::/0 and on the other side you can have the fdc2:9aea:13b1:2::/64. The same applies for the IPv4 addresses.

Let's forget about IPv6 for now and focus on routing only IPv4 traffic from the VLAN 2 iface (subnet 192.168.2.0/24). I'm not quite sure what you mean "the other side." Assuming this is a commercial VPN I won't be able to change their settings. How would I selectively route only traffic from 192.168.2.0/24 over Wireguard? The information I've found is to replace the default 0.0.0.0/0 with 192.168.2.0/24 for allowed_ips, but apparently that is incorrect? Thank you!

Again you have bridged the lan (eth1) with the vpn (eth1 eth1.2)
Also you cannot have the same IPs on 2 different devices. The dumbAP doesn't need an IP on the vpn interface, leave it unmanaged.

Use policy based routing and firewall rules to prevent other IPs from accessing the wireguard tunnel.

1 Like

I was under the misconception that vlan needed to be bridged to lan in order to access it, I see now that it is handled by the firewall, and I removed the bridge to eth1.

Sorry if it was not clear, that was my router config.

This is the vlan setup on the switch:

:+1:

Is it working fine now?

Yes, vpn-policy-routing works perfectly too now in IPv4-only mode, I'm no longer running into timeouts and packet loss. I'm using wan as the default route and made a vpn-policy-rule to send the 192.168.2.0/24 (vpn vlan 2) subnet to the wireguard interface. Works great. I'm not sure if I'll be able to connect to the router through wireguard without setting the default route to the wireguard interface, however. And I'll probably need to play with my ddns settings to grab both IPs, but VLANs are working!

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.