Create multiple SSIDs with different wireguard interfaces

I want to have two or more different Wi-fi access points (SSIDs) that connect to different wireguard interface so that they have different IP address. I have it "almost" working but have issue that only the SSID which is associated with the wireguard Restarted last is working.

Below is my setup:
Devices: I have created two Bridge device -- br-lan1 and br-lan2 which are associated with different virtual eth0.
Interfaces:
Lan1 and Lan2 which are configured with above created Devices
wg1 and wg2 with different private, public key and peers
Firewall: Created such that Lan1 uses wg1 and Lan2 uses wg2
SSID: Two SSIDs. SSID1 with Lan1 network and SSID2 with Lan2 network.

Now, when I connect with SSID1 from my laptop, it shows expected wireguard IP address BUT when I connect with SSID2, it fails. Then, I restarted wg2 and then SSID2 shows expected IP but now if I connect with SSID1, that fails. Now, to make SSID1 work I have to restart wg1 so both SSIDs are not working at the same time.
I did some other tests too and based on my observation, the SSID associated with wireguard interface Restarted last is only working.

Really appreciate your help on this. Thanks.

You're going to need policy based routing to achieve your goal, but let's first review the basic config as it is now.

Does your goal include ethernet connectivity on a per-port > specific WG interface, or is it wifi only?

Please copy the output of the following commands and post it here using the "Preformatted text </> " button:
grafik
Remember to redact passwords, MAC addresses and any public IP addresses you may have:

cat /etc/config/network
cat /etc/config/wireless
cat /etc/config/dhcp
cat /etc/config/firewall

Thanks, I'm looking to connect devices via Wifi and each Wifi will be connected to different network/WG interface so a different IP address.

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

config globals 'globals'
        option ula_prefix '<IPV6>::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth0.1'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option ipaddr '192.168.33.1'

config device
        option name 'eth0.2'
        option macaddr '<MacAddress>'

config interface 'wan'
        option device 'eth0.2'
        option proto 'dhcp'
        option peerdns '0'
        list dns '<VPN's Public DNS Server>'

config interface 'wan6'
        option device 'eth0.2'
        option proto 'dhcpv6'
        option reqaddress 'try'
        option reqprefix 'auto'
        option peerdns '0'
        list dns '<VPN's Public DNS Server>'

config switch
        option name 'switch0'
        option reset '1'
        option enable_vlan '1'

config switch_vlan
        option device 'switch0'
        option vlan '1'
        option vid '1'
        option ports '0t 2t 4 5'

config switch_vlan
        option device 'switch0'
        option vlan '2'
        option ports '0t 1'
        option vid '2'

config interface 'wg'
        option proto 'wireguard'
        list addresses '10.64.90.154/32'
        option force_link '1'
        option peerdns '0'
        list dns '<VPN's Public DNS Server>'
        option private_key '<MyPrivateKey1>'

config wireguard_wg
        option public_key '<MyPublicKey1>'
        list allowed_ips '0.0.0.0/0'
        option route_allowed_ips '1'
        option endpoint_host '<IP Address1 of this interface that I will connect to>'
        option endpoint_port '51820'
        option description 'Location1'
        option disabled '1'

config interface 'lan_new'
        option proto 'static'
        list ipaddr '192.168.44.1/24'
        option ip6assign '60'
        option device 'br-lanNew'

config interface 'WGNEW'
        option proto 'wireguard'
        option force_link '1'
        option peerdns '0'
        list dns '<VPN's Public DNS Server>'
        option private_key '<MyPrivateKey2>'
        list addresses '10.64.250.114/32'

config wireguard_WGNEW
        option description 'Location2'
        option public_key '<MyPublicKey2>'
        list allowed_ips '0.0.0.0/0'
        option route_allowed_ips '1'
        option endpoint_host '<IP Address2 of this interface that I will connect to>'
        option endpoint_port '51820'

config device
        option type 'bridge'
        option name 'br-lanNew'
        list ports 'eth0.3'
        option mtu '1500'
        option mtu6 '1500'

config switch_vlan
        option device 'switch0'
        option vlan '3'
        option vid '3'
        option ports '0t 2t'
config wifi-device 'radio0'
        option type 'mac80211'
        option path 'pci0000:00/0000:00:00.0'
        option band '5g'
        option htmode 'VHT40'
        option channel 'auto'
        option cell_density '0'

config wifi-iface 'default_radio0'
        option device 'radio0'
        option network 'lan'
        option mode 'ap'
        option ssid '<SSID1>'
        option key '<SSID1Password>'
        option encryption 'sae-mixed'

config wifi-iface 'wifinet2'
        option device 'radio0'
        option mode 'ap'
        option ssid '<SSID2>'
        option encryption 'sae-mixed'
        option key '<SSID2Password>'
        option network 'lan_new'
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 ednspacket_max '1232'
        list server '10.64.0.1'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option dhcpv6 'server'
        option ra 'server'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
        list dhcp_option '6,10.64.0.1'

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 dhcp 'lan_new'
        option interface 'lan_new'
        option start '100'
        option limit '150'
        option leasetime '12h'
        list dhcp_option '6,10.64.0.1'
        option ra 'server'
        list ra_flags 'managed-config'
        list ra_flags 'other-config'
        option ra_mtu '1500'
        option ra_hoplimit '64'
        option dhcpv6 'server'
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 output 'ACCEPT'
        option masq '1'
        option mtu_fix '1'
        option input 'REJECT'
        option forward 'REJECT'
        list network 'wan'
        list network 'wan6'

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 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 zone
        option name 'WGZONE'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'wg'

config forwarding
        option src 'lan'
        option dest 'WGZONE'

config zone
        option name 'lan_newF'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan_new'

config zone
        option name 'WGNEWZONE'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'WGNEW'

config forwarding
        option src 'lan_newF'
        option dest 'WGNEWZONE'

If you are not trying to connect the lan_new network to physical ethernet, you do not need to have eth0.3 included in the br-lanNew bridge and you don't need to define the VLAN on the switch (nor do you need to give it a physical port). That said, port 2 is currently a trunk (VLANs 2 and 3, both tagged), so whatever is downstream of this must be VLAN aware (i.e. a managed switch or an AP with VLAN capabilities).

You can remove the two dns related lines... they don't do anything here (same will be true on your WGNEW interface

Keep in mind that the DNS server defined here (10.64.0.1) is unreachable until the WG tunnel is established. This means that you will have difficulty resolving key things such as the NTP time server addresses and the address of your endpoint hosts (assuming they are domain names rather than IP addresses) -- these two things could cause your WG connections to fail to be established, creating a no-internet situation.

Same deal with the DHCP option 6 that you are sending to the hosts on lan and lan_new. That may not be an issue if they are never used without VPN, but something to keep in mind.

The only other comment about your config is that it is considered best practice to have network names and firewall zones all in lowercase. The real critical thing is that everything is consistent (which it is currently) since these things are case-sensitive. It's not a big deal to leave it as it is, but in the future you might just stick with lowercase.

Everything else looks fine. But you need to use Policy Based Routing to ensure that each network goes over the correct tunnel. Currently, one tunnel will take precedence, and one network will appear to have no internet connectivity.

1 Like

Thanks for your insights.

I being new to this, my intention was to create a new lan network which I will use with new wg. That's why I created eth0.3 so that it's completely on a different virtual network. Then create a new SSID with this lan_new.

I copied them from the VPN instructions so they are there. Maybe it's just redundant, I will remove them.

I don't understand this completely. Could you please clarify. The behavior is same that you mentioned, only in some cases the tunnel is established i.e. if the SSID associated with wireguard interface Restarted last the tunnel is being established else no.
I did traceroute and in case of failure, it errors out as "Destination protocol unreachable"

Yes, this is exactly what's happening. The wg interface restarted last is taking the precedence and I'm not able to understand why is that. Unfortunately, I'm still not sure of the reason. Could you provide more explanation.

I did try it earlier and it was working but I found there were leaks when I restarted the routing service i.e. while it was restarting it use to point to other wg interface than the one defined in pbr. I didn't test more but based on this I believe same could happen while restarting router or other services too.
That being said, is there any suggested approach for pbr for my scenario: Route all traffic by default to wg1 and only the devices defined in pbr should route to wg2.

Thanks again!! :slight_smile:

Sure. But I am still missing part of the info... I'll ask the question in a slightly different way so that we are on the same page:

  • Will you be using the network with both wired and wireless devices? Or will it be wireless only?

Yes... in fact, I just discussed the time issue here and here. Let me know if that makes sense now...

Yup... exactly as expected. In the simplified view, there is a routing table that has some basic rules about how to route traffic to other networks (and the internet). When you establish a WG connection with 0.0.0.0/0 in the allowed IPs field (and route allowed IPs enabled), that basically says "send everything through this tunnel" and it takes over the default route. So if you start a WG connection, it does exactly that. When you start a second WG connection, it then takes over from the first. Policy based routing is the solution to that because it allows you to specify the routing rules with more granularity.

This may have been due to errors in the PBR configuration, or maybe not a fully complete set of rules. Since you'll need this technique to achieve your goal, just post your PBR config for review and you should get the help you need.

1 Like

All the devices will be using these networks using wireless connections only.

So, you meant that due to no connection there could be incorrect time on router which could create more issues.

Thanks, this makes sense now and was something that I was struggling with to understand. Though I did notice this in IP routing table while troubleshooting but wasn't sure why it's happening.
I just noticed with policy routing it created other tables pbr_wg and pbr_WGNEW with Target as 0.0.0.0/0 so I think that's why it works with pbr.
That being said, I assume there's no way what I'm trying will work without pbr since allowed IP in both interfaces is 0.0.0.0/0. Is that correct?

Below is the output of cat /etc/config/pbr

config pbr 'config'
        option verbosity '2'
        option resolver_set 'none'
        option ipv6_enabled '0'
        list ignored_interface 'vpnserver'
        list ignored_interface 'wgserver'
        option boot_timeout '30'
        option rule_create_option 'add'
        option procd_reload_delay '1'
        option webui_show_ignore_target '0'
        list webui_supported_protocol 'all'
        list webui_supported_protocol 'tcp'
        list webui_supported_protocol 'udp'
        list webui_supported_protocol 'tcp udp'
        list webui_supported_protocol 'icmp'
        option enabled '1'
        option strict_enforcement '1'

config policy
        option name 'WireGuard Server'
        option interface 'wan'
        option src_port '51820'
        option chain 'output'
        option proto 'udp'
        option enabled '0'

config policy
        option interface 'WGNEW'
        option name 'Phone1'
        option src_addr '<MacAddress of Phone1>'

config policy
        option name 'Phone2'
        option src_addr '<MacAddress of Phone2>'
        option interface 'wg'

This does work as expected but what I noticed is in case of pbr if I make changes in routing service and Restart it. It leaks the IP while being restarted.
E.g.: Let's say I Restarted interface WGNEW and tunnel is established. Phone2 in above policy will connect correctly via interface wg but if I restart routing service it will route via WGNEW and leak that IP. Though it's quick and does correct itself after service has started back but even a small connection leak is an issue for my use case. Moreover, since it leaks while Restarting routing service, I think it could also leak while restarting other Network artifacts.

Additional question for PBR, is there any rule priority that takes place? I want to setup Wifi that all devices should connect via WGNEW interface and only the devices that are defined in routing policies should connect via wg interface.

Based on this, you do not need to create VLANs on the switch (i.e. eth0.3).
Your bridges can simply omit the list ports line.

Chicken or egg... if the time is not correct when the tunnel attempts to start, it will not be able to establish a connection. But at the same time, it will effectively make it impossible for the router to get any internet connection (since it would all be going through the tunnel), and therefore the time cannot ever be sync'd because WG has attempted to start but failed and is now blocking connectivity.

It is plausible that PBR could resolve this issue insofar as to ensure that the router still uses the regular wan, but that's just theory for now. The common soluition is to wait for NTP to complete successfully and then start the tunnel.

Correct.

I'm not sure why that would happen... but theoretically a pretty rare event.

Theoretically yes, but I'm not an expert on PBR. That said, your thread title suggests that you were aiming to create 2 SSIDs for this purpose. Rather than trying to identify individual devices, it seemed as if you would just ensure that said devices connect to the desired wifi network. Has that plan changed? Or is there a problem with it?

1 Like

Done. Tested and it works. Do these bridges connect to internet via wan? I just followed VPN provided instructions earlier so wasn't sure, that's why created eth0.3 too.

That's interesting. I didn't know that. Thanks for providing more information on that.

It's still the desired end solution I'm looking for. My main intention for 2 SSIDs was so that I can connect different devices to different SSIDs and keeping them on separated wg/IP network. So, in a way, almost all devices will be on SSID1 except few on SSID2 so that there's never an IP leak scenario. The issue was that even though I created two SSIDs they weren't working at the same time due to what you mentioned for the allowed IPs 0.0.0.0/0 in both wireguard interfaces so that didn't work as expected.

Due to above issue and based on what you suggested, I'm trying to go with pbr route and implement same functionality that all devices should connected via wg interface unless they are specified in pbr to connect via WGNEW interface. I couldn't find exact rules similar to what I'm looking for but I read that I might have to implement policies based on subnet. I will try that now.

If you had asked in the pbr support thread you would have received a faster reply. Enable secure_reload.

1 Like

Thanks, I looked on that here and added to my config. Is the below correct, I have added option secure_reload '1' to pbr 'config':

config pbr 'config'
        option verbosity '2'
        option resolver_set 'none'
        option ipv6_enabled '0'
        list ignored_interface 'vpnserver'
        list ignored_interface 'wgserver'
        option boot_timeout '30'
        option rule_create_option 'add'
        option procd_reload_delay '1'
        option webui_show_ignore_target '0'
        list webui_supported_protocol 'all'
        list webui_supported_protocol 'tcp'
        list webui_supported_protocol 'udp'
        list webui_supported_protocol 'tcp udp'
        list webui_supported_protocol 'icmp'
        option enabled '1'
        option strict_enforcement '1'
        option secure_reload '1'

Edited:

I tried the above mentioned setting for option secure_reload '1' and it doesn't work. I see same IP leak behavior as before. Is my syntax correct or do I need to modify it somewhere else?

Actually, I forgot that it's enabled by default. README has instructions on what to do if things are not working as expected.