Dual WAN with PCC preventing failover

I got my first RouterOS devices recently: a CCR2004-16G-2S+ and a CRS309-1G-8S±IN. I was prepared for a steep learning curve and I’m very happy with what I’ve got. The only issue is with these dual WANs. I set up failover first, per https://help.mikrotik.com/docs/spaces/ROS/pages/26476608/Failover+WAN+Backup. That worked fine. Next, I upgraded it to load balancing via PCC as shown in the manual. That also worked fine with both connections up, or with one either disabled or physically disconnected.

Where it didn’t work correctly is when first one connection (say, isp1) then the other (isp2) was knocked out by a storm recently. isp2 came up within 24 hours, whereas isp1 took days. For as long as isp2 was up and isp1 was down, I practically couldn’t access anything outside my network unless I kept the isp1 interface disabled (or, I assume, physically disconnected). I verified that the gateway itself was inaccessible (ISP IPs anonymized here):

[shiv@ccr2004] > /tool/ping address="8.8.8.8" interface="ether1" count=3
  SEQ HOST                                     SIZE TTL TIME       STATUS
    0 10.1.1.5                              84  64 262ms222us host unreachable
    1 8.8.8.8                                                      timeout
    2 8.8.8.8                                                      timeout
    sent=3 received=0 packet-loss=100%

[shiv@ccr2004] > /tool/ping address="10.1.1.1" interface="ether1" count=3
  SEQ HOST                                     SIZE TTL TIME       STATUS
    0 10.1.1.1                                                 timeout
    1 10.1.1.5                              84  64 71ms338us  host unreachable
    2 10.1.1.1                                                 timeout
    sent=3 received=0 packet-loss=100%

My inference is that packets were still being sent over that connection due to the classifier and the fallback routes weren’t being honoured for some reason, but then I’m completely new at this. I’d be grateful for any help figuring this out. Here are all the relevant parts (as far as I know) of my configuration, again with anonymized IPs:

# 2025-05-11 17:06:37 by RouterOS 7.18.2
# software id = WQLK-A9G0
#
# model = CCR2004-16G-2S+
/interface list
add name=LAN
add name=WAN
/interface list member
add interface=ether6 list=LAN
add interface=ether11 list=LAN
add interface=ether5 list=LAN
add interface=ether8 list=LAN
add interface=ether4 list=LAN
add interface=ether13 list=LAN
add interface=ether12 list=LAN
add interface=ether7 list=LAN
add interface=ether10 list=LAN
add interface=ether16 list=LAN
add interface=ether14 list=LAN
add interface=ether9 list=LAN
add interface=ether1 list=WAN
add interface=ether2 list=WAN
add interface=ether3 list=LAN

/ip route
add check-gateway=none disabled=no distance=2 dst-address=0.0.0.0/0 gateway=11.2.1.1 routing-table=main scope=30 suppress-hw-offload=no \
    target-scope=10
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=10.1.1.1 routing-table=main suppress-hw-offload=no
add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=10.1.1.1 routing-table=to_isp1 scope=30 suppress-hw-offload=no \
    target-scope=10
add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=11.2.1.1 routing-table=to_isp2 scope=30 suppress-hw-offload=\
    no target-scope=10

/ip address
add address=10.1.1.5/20 interface=ether1 network=10.1.1.0
add address=11.2.1.2/30 interface=ether2 network=11.2.1.0

/ip firewall filter
add action=accept chain=input comment="accept established,related,untracked" connection-state=established,related,untracked in-interface-list=WAN
add action=accept chain=forward connection-state=established,related,untracked
add action=drop chain=forward comment="drop invalid" connection-state=invalid
add action=accept chain=forward comment="allow dstnat" connection-nat-state=dstnat
add action=drop chain=input comment="drop invalid" connection-state=invalid in-interface-list=WAN
add action=accept chain=input comment="accept ICMP" in-interface-list=WAN protocol=icmp
add action=accept chain=input comment="allow SSH" disabled=yes in-interface-list=WAN port=22 protocol=tcp
add action=drop chain=input comment="block everything else" in-interface-list=WAN
/ip firewall mangle
add action=mark-connection chain=output comment="classify output (1)" connection-mark=no-mark connection-state=new new-connection-mark=balance1 \
    passthrough=no per-connection-classifier=both-addresses-and-ports:2/1
add action=mark-connection chain=input comment="mark incoming (isp1)" connection-state=new in-interface=ether1 new-connection-mark=fromisp1
add action=mark-connection chain=input comment="mark incoming (isp2)" connection-state=new in-interface=ether2 new-connection-mark=\
    fromisp2
add action=mark-connection chain=prerouting comment="classify prerouting (0)" connection-mark=no-mark connection-state=new dst-address-type=!local \
    in-interface=lan new-connection-mark=balance0 per-connection-classifier=both-addresses-and-ports:2/0
add action=mark-connection chain=prerouting comment="classify prerouting (1)" connection-mark=no-mark connection-state=new dst-address-type=!local \
    in-interface=lan new-connection-mark=balance1 per-connection-classifier=both-addresses-and-ports:2/1
add action=accept chain=prerouting comment="accept prerouting" dst-address=10.1.1.0/20 in-interface=lan
add action=accept chain=prerouting comment="accept prerouting" dst-address=11.2.1.0/30 in-interface=lan
add action=mark-routing chain=prerouting comment="balance prerouting (isp1)" connection-mark=balance0 in-interface=lan new-routing-mark=to_isp1
add action=mark-routing chain=prerouting comment="balance prerouting (isp2)" connection-mark=balance1 in-interface=lan new-routing-mark=\
    to_isp2
add action=mark-connection chain=output comment="classify output (0)" connection-mark=no-mark connection-state=new new-connection-mark=balance0 \
    per-connection-classifier=both-addresses-and-ports:2/0
add action=mark-routing chain=output comment="balance output (isp1)" connection-mark=balance0 new-routing-mark=to_isp1
add action=mark-routing chain=output comment="balance output (isp2)" connection-mark=balance1 new-routing-mark=to_isp2
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1
add action=masquerade chain=srcnat out-interface=ether2

/routing table
add disabled=no fib name=to_isp1
add disabled=no fib name=to_isp2

Always post the complete export (anonymized of course), as the issue is typically caused by something you do not assume to be related.

In what you’ve posted, the routing tables to_isp1 and to_isp2 are defined but empty; as you say the load distribution was working well while both WAN connections were available, I assume you just forgot to copy those routes, not that they do not exist at all.

In any case, if you want load distribution and failover to work together, rename the routing tables (in your head is enough) from to_isp1 and to_isp2 to prefer_isp1 and prefer_isp2 and modify them accordingly, i.e. add the route via ISP 2 as the backup (higher distance) one into table prefer_isp1 and the route via ISP 1 as the backup one into table prefer_isp2. This way, the router will use the uplink chosen by PCC if it is available and the other one if it is not.

Thanks for the quick reply.

I understand. I was just worried about a (relatively) large anonymized configuration obscuring the relevant parts of it. In fact:

In what you’ve posted, the routing tables > to_isp1 > and > to_isp2 > are defined but empty; as you say the load distribution was working well while both WAN connections were available, I assume you just forgot to copy those routes, not that they do not exist at all.

Do the ones under /ip route not count? My understanding from the PCC manual page is that the routes only need to be defined there and not under /routing as well.

In any case, if you want load distribution and failover to work together, rename the routing tables (in your head is enough) from > to_isp1 > and > to_isp2 > to > prefer_isp1 > and > prefer_isp2 > and modify them accordingly, i.e. add the route via ISP 2 as the backup (higher > distance> ) one into table > prefer_isp1 > and the route via ISP 1 as the backup one into table > prefer_isp2> . This way, the router will use the uplink chosen by PCC if it is available and the other one if it is not.

Thank you very much! I can’t reproduce the exact failure I had earlier but, after modifying my configuration as you describe, I briefly removed the WAN cable from one modem and verified that nothing obvious had gone wrong. I’ll assume that’s fixed it.

I did wonder if this was what I needed to do, but I could have sworn I read somewhere that the main routing table would be used as a fallback. (Which makes no sense now that I think about it.)

Of course they do, I have missed the routing-table column for the last two routes, and not only that. I was somehow tuned to the fallback approach that is based on recursive next-hop search.

In the config above, you have two default routes with different distance in table main, and one default route in each of to_isp1 and to_isp2. Whereas you use check-gateway=ping to make the routes in the latter two tables only available if the gateway is reachable, both the routes in main are not subject to such check, so for them to be eligible for becoming active, it is enough that the respective WAN interface is up. So if the uplink from the ISP router or something in the ISP network is broken but the ISP router itself stays up, pinging the gateway on that modem itself gives you a “false positive” result - the route checked this way is active even though the path to the internet is not transparent.

When using the recursive next hop search approach, the gateway of the default routes is a virtual one - typically, it is some “immortal” public IP address (often called “canary” one), towards which a dedicated /32 route via the actual gateway is configured, and the scope and target-scope parameters of these two routes allow the default one to use the /32 one recursively. In this setup, the default route actually uses the local gateway as specified using the /32 route, but the check-gateway=ping of the default route pings the virtual one, so if the path to it is broken anywhere, the default route becomes inactive.

(And since I’ve seen check-gateway=ping only on two routes and four routes in total, I’ve concluded it is this fairly popular setup without inspecting the rest of the parameters in detail).



That’s actually correct - if the routing is told to use a particular table but no active route to the destination is currently available in that table, the routing indeed retries using table main (unless explicitly instructed not to do so using a routing rule). So yes, it is also a possible solution - if WAN1 fails and therefore routing table to_isp1 becomes effectively empty, the router uses main instead, so you don’t need the lower priority routes in to_ispX that I have suggested above. But in your current configuration the default route via WAN1 is only supervised using check-gateway=ping in table to_isp1 whereas in main, the default route via WAN1 remains active unless the interface is physically down (and similarly for WAN2). So even if the gateway on WAN1 modem stops responding but the interface remains up, using main, the packets are nevertheless routed via WAN1 and therefore get nowhere.

Post your updated latest config for review when ready
/export file=anynameyouwish ( minus router serial number, any public WANIP information, keys)

I see. That explains part of it. I’m sorry to say I don’t understand the ‘recursive next hop search’ approach, but I hope that’s something I’ll learn in time.

That’s actually correct - if the routing is told to use a particular table but no active route to the destination is currently available in that table, the routing indeed retries using table > main > (unless explicitly instructed not to do so using a routing rule).

Oh, that’s surprising. What rule would I need to prevent falling back to main? I intend to set up a dedicated VLAN for each WAN, to facilitate both troubleshooting and tracking connectivity, so I assume I’ll need a table per WAN with that rule at the end.

So yes, it is also a possible solution - if WAN1 fails and therefore routing table > to_isp1 > becomes effectively empty, the router uses > main > instead, so you don’t need the lower priority routes in > to_ispX > that I have suggested above. But in your current configuration the default route via WAN1 is only supervised using > check-gateway=ping > in table > to_isp1 > whereas in > main> , the default route via WAN1 remains active unless the interface is physically down (and similarly for WAN2). So even if the gateway on WAN1 modem stops responding but the interface remains up, using > main> , the packets are nevertheless routed via WAN1 and therefore get nowhere.

That makes sense. I’ve updated all my routes to use check-gateway=ping.

Thanks again for the explanations and the help so far. I’ll share my anonymized configuration as anav suggested for review in the following post.

Here it is (with anonymized names and IPs, mostly):

# 2025-05-18 16:35:36 by RouterOS 7.18.2
# software id = WQLK-A9G0
#
# model = CCR2004-16G-2S+
/interface bridge
add admin-mac=11:22:33:44:55:66 auto-mac=no name=lan protocol-mode=none \
    vlan-filtering=yes
/interface ethernet
set [ find default-name=ether1 ] comment=isp1
set [ find default-name=ether2 ] comment=isp2
set [ find default-name=ether14 ] comment="Budh (backup)"
set [ find default-name=sfp-sfpplus1 ] comment="Budh 1"
set [ find default-name=sfp-sfpplus2 ] comment="Budh 2"
/interface wireguard
add listen-port=12345 mtu=1420 name=wireguard2
add listen-port=12346 mtu=1420 name=wireguard3
add listen-port=12347 mtu=1420 name=wireguard1
/interface vlan
add interface=lan name=vlan1 vlan-id=101
add interface=lan name=vlan2 vlan-id=102
add interface=lan name=vlan3 vlan-id=103
add interface=lan name=vlan4 vlan-id=104
add interface=lan name=vlan5 vlan-id=105
add interface=lan name=vlan6 vlan-id=106
add interface=lan name=vlan7 vlan-id=107
add interface=lan name=vlan8 vlan-id=108
add interface=lan name=vlan9 vlan-id=109
/interface bonding
add comment=Budh mode=802.3ad name=budh slaves=sfp-sfpplus1,sfp-sfpplus2 \
    transmit-hash-policy=layer-2-and-3
/interface list
add name=LAN
add name=WAN
/ip pool
add name=lan ranges=1.2.1.2-1.2.1.254
add name=vlan_vlan9 ranges=1.2.109.2-1.2.109.254
add name=vlan_vlan3 ranges=1.2.103.2-1.2.103.254
add name=vlan_vlan2 ranges=1.2.102.2-1.2.102.254
add name=vlan_vlan4 ranges=1.2.104.2-1.2.104.254
add name=vlan_vlan6 ranges=1.2.106.2-1.2.106.254
add name=vlan_vlan7 ranges=1.2.107.2-1.2.107.254
add name=vlan_vlan8 ranges=1.2.108.2-1.2.108.254
add name=vlan_vlan5 ranges=1.2.105.2-1.2.105.254
/ip dhcp-server
add address-pool=lan interface=lan name=lan_dhcp
add address-pool=vlan_vlan4 interface=vlan4 name=vlan_vlan4_dhcp
add address-pool=vlan_vlan3 interface=vlan3 name=vlan_vlan3_dhcp
add address-pool=vlan_vlan5 interface=vlan5 name=vlan_vlan5_dhcp
add address-pool=vlan_vlan7 interface=vlan7 name=vlan_vlan7_dhcp
add address-pool=vlan_vlan6 interface=vlan6 name=\
    vlan_vlan6_dhcp
add address-pool=vlan_vlan2 interface=vlan2 name=vlan_vlan2_dhcp
add address-pool=vlan_vlan9 interface=vlan9 name=vlan_vlan9_dhcp
add address-pool=vlan_vlan8 interface=vlan8 name=vlan_vlan8_dhcp
/port
set 0 name=serial0
/queue type
add cake-diffserv=besteffort cake-nat=yes cake-rtt=10ms cake-rtt-scheme=metro \
    kind=cake name=cake-tx
add cake-diffserv=besteffort cake-nat=yes cake-rtt=10ms cake-rtt-scheme=metro \
    kind=cake name=cake-rx
/queue simple
add max-limit=1G/1G name=isp2-cake queue=cake-rx/cake-tx target=ether2
add max-limit=1G/1G name=isp1-cake queue=cake-rx/cake-tx target=ether1
/routing table
add disabled=no fib name=prefer_isp1
add disabled=no fib name=prefer_isp2
/system logging action
set 3 src-address=1.2.1.1
add name=alloy remote=1.2.1.10 remote-log-format=syslog remote-port=515 \
    remote-protocol=tcp syslog-facility=syslog syslog-time-format=iso8601 \
    target=remote
/user group
add name=metrics policy="read,api,!local,!telnet,!ssh,!ftp,!reboot,!write,!pol\
    icy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon,!rest-api"
/interface bridge port
add bridge=lan interface=ether5
add bridge=lan interface=ether6
add bridge=lan interface=ether11
add bridge=lan interface=ether16
add bridge=lan interface=ether7
# This backup cable is not plugged in except if required in an emergency.
add bridge=lan comment="Budh (backup)" interface=ether14
add bridge=lan interface=ether12
add bridge=lan interface=ether10
add bridge=lan interface=ether9
add bridge=lan interface=ether13
add bridge=lan interface=ether4
add bridge=lan interface=ether8
add bridge=lan interface=ether3
add bridge=lan interface=budh
/ip neighbor discovery-settings
set discover-interface-list=LAN
/interface bridge vlan
add bridge=lan untagged="ether7,ether8,ether9,ether14,ether11,ether10,ether12,\
    ether13,ether6,ether4,ether5" vlan-ids=1
add bridge=lan comment="vlan1 (101)" vlan-ids=101
add bridge=lan comment="vlan5 (105)" tagged=LAN vlan-ids=105
add bridge=lan comment="vlan3 (103)" tagged=LAN vlan-ids=103
add bridge=lan comment="vlan4 (104)" tagged=LAN vlan-ids=104
add bridge=lan comment="vlan2 (102)" tagged=LAN vlan-ids=102
add bridge=lan comment="vlan6 (106)" tagged=LAN vlan-ids=106
add bridge=lan comment="vlan8 (108)" tagged=LAN vlan-ids=108
add bridge=lan comment="vlan7 (107)" tagged=LAN vlan-ids=107
add bridge=lan comment="vlan9 (109)" tagged=LAN vlan-ids=109
/interface list member
add interface=ether6 list=LAN
add interface=ether11 list=LAN
add interface=ether5 list=LAN
add interface=ether8 list=LAN
add interface=ether4 list=LAN
add interface=ether13 list=LAN
add interface=ether12 list=LAN
add interface=ether7 list=LAN
add interface=ether10 list=LAN
add interface=ether16 list=LAN
add interface=ether14 list=LAN
add interface=ether9 list=LAN
add interface=wireguard2 list=LAN
add interface=wireguard1 list=LAN
add interface=wireguard3 list=LAN
add interface=ether1 list=WAN
add interface=ether2 list=WAN
add interface=ether3 list=LAN
add interface=budh list=LAN
/interface ovpn-server server
add mac-address=22:33:44:55:66:77 name=ovpn-server1
/interface wireguard peers
# redacted
/ip address
add address=1.2.1.1/24 interface=lan network=1.2.1.0/24
add address=1.3.2.1/24 interface=wireguard2 network=1.3.2.0/24
add address=1.3.3.1/24 interface=wireguard3 network=1.3.3.0/24
add address=1.3.1.1/24 interface=wireguard1 network=1.3.1.0/24
add address=10.1.1.5/20 interface=ether1 network=10.1.1.0
add address=11.2.1.2/30 interface=ether2 network=11.2.1.0
add address=1.2.104.1/24 interface=vlan4 network=1.2.104.0/24
add address=1.2.108.1/24 interface=vlan8 network=1.2.108.0/24
add address=1.2.103.1/24 interface=vlan3 network=1.2.103.0/24
add address=1.2.102.1/24 interface=vlan2 network=1.2.102.0/24
add address=1.2.107.1/24 interface=vlan7 network=1.2.107.0/24
add address=1.2.106.1/24 interface=vlan6 network=1.2.106.0/24
add address=1.2.105.1/24 interface=vlan5 network=1.2.105.0/24
add address=1.2.109.1/24 interface=vlan9 network=1.2.109.0/24
# Not part of the bridge:
add address=192.168.88.1/24 interface=ether15 network=192.168.88.0
/ip dhcp-server lease
# redacted
/ip dhcp-server network
add address=1.2.1.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.1.1
add address=1.2.103.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.103.1
add address=1.2.104.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.104.1
add address=1.2.102.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.102.1
add address=1.2.102.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.108.1
add address=1.2.109.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=1.2.109.1
add address=1.2.107.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=1.2.107.1
add address=1.2.106.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=1.2.106.1
add address=1.2.105.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=\
    1.2.105.1
/ip dns
set servers=8.8.8.8,8.8.4.4
/ip firewall filter
add action=accept chain=input dst-port=12345 protocol=udp
add action=accept chain=input dst-port=12346 protocol=udp
add action=accept chain=input dst-port=12347 protocol=udp
add action=accept chain=input comment="accept established,related,untracked" \
    connection-state=established,related,untracked in-interface-list=WAN
add action=accept chain=forward connection-state=\
    established,related,untracked
add action=drop chain=forward comment="drop invalid" connection-state=invalid
add action=accept chain=forward comment="allow dstnat" connection-nat-state=\
    dstnat
add action=drop chain=input comment="drop invalid" connection-state=invalid \
    in-interface-list=WAN
add action=accept chain=input comment="accept ICMP" in-interface-list=WAN \
    protocol=icmp
add action=accept chain=input comment="allow SSH" disabled=yes \
    in-interface-list=WAN port=22 protocol=tcp
add action=drop chain=input comment="block everything else" \
    in-interface-list=WAN
/ip firewall mangle
add action=mark-connection chain=output comment="classify output (1)" \
    connection-mark=no-mark connection-state=new new-connection-mark=balance1 \
    passthrough=no per-connection-classifier=both-addresses-and-ports:2/1
add action=mark-connection chain=input comment="mark incoming (isp1)" \
    connection-state=new in-interface=ether1 new-connection-mark=fromisp1
add action=mark-connection chain=input comment="mark incoming (isp2)" \
    connection-state=new in-interface=ether2 new-connection-mark=\
    fromisp2
add action=mark-connection chain=prerouting comment="classify prerouting (0)" \
    connection-mark=no-mark connection-state=new dst-address-type=!local \
    in-interface=lan new-connection-mark=balance0 per-connection-classifier=\
    both-addresses-and-ports:2/0
add action=mark-connection chain=prerouting comment="classify prerouting (1)" \
    connection-mark=no-mark connection-state=new dst-address-type=!local \
    in-interface=lan new-connection-mark=balance1 per-connection-classifier=\
    both-addresses-and-ports:2/1
add action=accept chain=prerouting comment="accept prerouting" dst-address=\
    10.1.1.0/20 in-interface=lan
add action=accept chain=prerouting comment="accept prerouting" dst-address=\
    11.2.1.0/30 in-interface=lan
add action=mark-routing chain=prerouting comment="balance prerouting (isp1)" \
    connection-mark=balance0 in-interface=lan new-routing-mark=prefer_isp1
add action=mark-routing chain=prerouting comment=\
    "balance prerouting (isp2)" connection-mark=balance1 in-interface=\
    lan new-routing-mark=prefer_isp2
add action=mark-connection chain=output comment="classify output (0)" \
    connection-mark=no-mark connection-state=new new-connection-mark=balance0 \
    per-connection-classifier=both-addresses-and-ports:2/0
add action=mark-routing chain=output comment="balance output (isp1)" \
    connection-mark=balance0 new-routing-mark=prefer_isp1
add action=mark-routing chain=output comment="balance output (isp2)" \
    connection-mark=balance1 new-routing-mark=prefer_isp2
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1
add action=masquerade chain=srcnat out-interface=ether2
/ip route
add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    10.1.1.1 routing-table=prefer_isp1 scope=30 suppress-hw-offload=no \
    target-scope=10
add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    11.2.1.1 routing-table=prefer_isp2 scope=30 \
    suppress-hw-offload=no target-scope=10
add check-gateway=ping disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\
    11.2.1.1 routing-table=prefer_isp1 scope=30 suppress-hw-offload=no \
    target-scope=10
add check-gateway=ping disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\
    10.1.1.1 routing-table=prefer_isp2 scope=30 \
    suppress-hw-offload=no target-scope=10
add check-gateway=ping distance=2 dst-address=0.0.0.0/0 gateway=11.2.1.1 \
    routing-table=main scope=30 target-scope=10
add check-gateway=ping distance=1 dst-address=0.0.0.0/0 gateway=10.1.1.1 \
    routing-table=main scope=30 target-scope=10
/ip service
set telnet disabled=yes
set ftp disabled=yes
set www disabled=yes
set www-ssl address=1.2.1.0/24,1.2.103.0/24 certificate=ccr2004 \
    disabled=no tls-version=only-1.2
set api disabled=yes
set winbox disabled=yes
set api-ssl address="1.2.1.0/24" certificate=ccr2004 tls-version=\
    only-1.2
/ip ssh
set always-allow-password-login=yes host-key-size=4096 strong-crypto=yes
/system clock
set time-zone-name=Asia/Kolkata
/system identity
set name=ccr2004
/system logging
add action=alloy topics=wireguard
add action=alloy topics=certificate
add action=alloy topics=route
add action=alloy topics=bridge
add action=alloy topics=error
add action=alloy topics=warning
add action=alloy topics=firewall
add action=alloy topics=queue
add action=alloy topics=interface
add action=alloy topics=info
add action=alloy topics=critical
add action=alloy topics=dhcp
add action=alloy topics=health
/system note
set note="\
    \n      ----------------------------------------\
    \n      |\
    \n      | Managed by Ansible\
    \n      |\
    \n      ----------------------------------------\
    \n      |\
    \n      | You are logged into ccr2004\
    \n      |\
    \n      ----------------------------------------"
/system routerboard settings
set enter-setup-on=delete-key
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN
/tool netwatch
add host=8.8.8.8 interval=5s name=watch_isp2 src-address=11.2.1.2 \
    type=icmp
add host=8.8.8.8 interval=5s name=watch_isp1 src-address=10.1.1.5 type=\
    icmp

No need to be sorry, the matter is a bit complex and not really well explained in an accessible language, the usual given reference is this:
http://forum.mikrotik.com/t/advanced-routing-failover-without-scripting/136599/1
but check this thread, hopefully it will help you:
http://forum.mikrotik.com/t/primary-gateway-with-static-ip-address-not-activating/183380/1
starting from here:
http://forum.mikrotik.com/t/primary-gateway-with-static-ip-address-not-activating/183380/1
AND links given there.

The horrible nomenclature you have decided to call your bridge lan, is not wrong but not a good idea… VERY confusing!

You should read this reference… your vlans are WRONG!
http://forum.mikrotik.com/t/using-routeros-to-vlan-your-network/126489/1
Once you have vlans, there should be no dhcp by the bridge, and thus no subnets associated with the bridge.

Interface list should contain the vlans, not etheports!!!

If you redact wireguard peers then one cannot see the errors and from the rest of the crappy config, there are most likely errors.
Do not enter endpoint address, any keys, the rest is not an issue.

What is your expectation of wireguard, to come in a specific WAN??
Are you hosting wireguard or only using third party servers?

Much appreciated, thank you. I’ll take a look once I’ve sorted out my, er, crappy configuration.

Coming to anav’s reply:

Thanks for taking the time to look at this. In hindsight, that was a poor choice of name. What do you use? bridge1, BR1, etc.?

You should read this reference… > your vlans are WRONG!
http://forum.mikrotik.com/t/using-routeros-to-vlan-your-network/126489/1
Once you have vlans, there should be no dhcp by the bridge, and thus no subnets associated with the bridge.

That was a very informative thread. It makes sense conceptually, but I want to see if I’ve understood the rationale behind it.

So far, I’ve mostly been using VLANs as an organizational tool. The only form of inter-VLAN access control was the tagged/untagged list on each port. However, the linked thread explains how to use VLANs for segregation, including explicitly defining a separate ‘base’ VLAN (which I believe is an implicit default VLAN in my case) and blocking all except specific inter-VLAN routes. If I have a DHCP server on my bridge, though, I’m offering that DHCP configuration not just to the implicit VLAN but to everything connected. Have I got that right?

Interface list should contain the vlans, not etheports!!!

I was going to ask you to elaborate on this, but I think I see how that makes more sense in the context of isolation.

If you redact wireguard peers then one cannot see the errors and from the rest of the crappy config, there are most likely errors.
Do not enter endpoint address, any keys, the rest is not an issue.

Here you go (please excuse the peer names; this is the full list, and I use comments in the real configuration):

/interface wireguard peers
add allowed-address=1.4.2.9/30 interface=wireguard2 name=peer7 \
    persistent-keepalive=25s
add allowed-address=1.4.1.9/30 interface=wireguard1 name=\
    peer8 persistent-keepalive=25s
add allowed-address=1.4.2.13/30 interface=wireguard2 \
    name=peer9 persistent-keepalive=25s
add allowed-address=1.4.1.13/30 interface=wireguard1 name=\
    peer10 persistent-keepalive=25s
add allowed-address=1.4.3.9/30 interface=wireguard3 name=\
    peer11 persistent-keepalive=25s
add allowed-address=1.4.2.17/30 interface=\
    wireguard2 name=peer12 persistent-keepalive=25s



What is your expectation of wireguard, to come in a specific WAN??

No, any WAN. My devices have multiples of the same WG configuration for each WAN’s public IP.

Are you hosting wireguard or only using third party servers?

Hosting.

I (unfortunately) had the opportunity to test this again last week when one connection (isp1) was down for half a day and I’m sorry to report that I saw no change in behaviour. I still had the problem of only some clients working (which I’m guessing is because PCC put them on isp2) while others couldn’t reach the Internet (presumably because they were on isp1). I noticed that when I looked at the routes in the GUI or the CLI, I never saw the fallback route (via isp2) in prefer_isp1 become active while the primary route was inactive. Either both were active or both were inactive.

Given our earlier conversation about falling back to the main table, would it help to remove the fallbacks I later added to the prefer_ispN tables so that it falls back to the main table, which now has check_gateway=ping set on the routes?

As always, cannot comment without latest config.

Sure, that’s here: https://forum.mikrotik.com/posting.php?mode=quote&p=1145951&sid=900a78497a86c154cc39d1c392bb4e37#pr1143445

And in case it got lost in the shuffle, I answered your last set of questions here: https://forum.mikrotik.com/posting.php?mode=quote&p=1145951#pr1143621

Both useless links, moving on.

Yikes, sorry about that! I thought I was sharing the permalinks of the posts but I guess they’re different in the preview when composing a post. Let me reproduce my configuration from post #7 in this thread:

# 2025-05-18 16:35:36 by RouterOS 7.18.2
# software id = WQLK-A9G0
#
# model = CCR2004-16G-2S+
/interface bridge
add admin-mac=11:22:33:44:55:66 auto-mac=no name=lan protocol-mode=none \
    vlan-filtering=yes
/interface ethernet
set [ find default-name=ether1 ] comment=isp1
set [ find default-name=ether2 ] comment=isp2
set [ find default-name=ether14 ] comment="Budh (backup)"
set [ find default-name=sfp-sfpplus1 ] comment="Budh 1"
set [ find default-name=sfp-sfpplus2 ] comment="Budh 2"
/interface wireguard
add listen-port=12345 mtu=1420 name=wireguard2
add listen-port=12346 mtu=1420 name=wireguard3
add listen-port=12347 mtu=1420 name=wireguard1
/interface vlan
add interface=lan name=vlan1 vlan-id=101
add interface=lan name=vlan2 vlan-id=102
add interface=lan name=vlan3 vlan-id=103
add interface=lan name=vlan4 vlan-id=104
add interface=lan name=vlan5 vlan-id=105
add interface=lan name=vlan6 vlan-id=106
add interface=lan name=vlan7 vlan-id=107
add interface=lan name=vlan8 vlan-id=108
add interface=lan name=vlan9 vlan-id=109
/interface bonding
add comment=Budh mode=802.3ad name=budh slaves=sfp-sfpplus1,sfp-sfpplus2 \
    transmit-hash-policy=layer-2-and-3
/interface list
add name=LAN
add name=WAN
/ip pool
add name=lan ranges=1.2.1.2-1.2.1.254
add name=vlan_vlan9 ranges=1.2.109.2-1.2.109.254
add name=vlan_vlan3 ranges=1.2.103.2-1.2.103.254
add name=vlan_vlan2 ranges=1.2.102.2-1.2.102.254
add name=vlan_vlan4 ranges=1.2.104.2-1.2.104.254
add name=vlan_vlan6 ranges=1.2.106.2-1.2.106.254
add name=vlan_vlan7 ranges=1.2.107.2-1.2.107.254
add name=vlan_vlan8 ranges=1.2.108.2-1.2.108.254
add name=vlan_vlan5 ranges=1.2.105.2-1.2.105.254
/ip dhcp-server
add address-pool=lan interface=lan name=lan_dhcp
add address-pool=vlan_vlan4 interface=vlan4 name=vlan_vlan4_dhcp
add address-pool=vlan_vlan3 interface=vlan3 name=vlan_vlan3_dhcp
add address-pool=vlan_vlan5 interface=vlan5 name=vlan_vlan5_dhcp
add address-pool=vlan_vlan7 interface=vlan7 name=vlan_vlan7_dhcp
add address-pool=vlan_vlan6 interface=vlan6 name=\
    vlan_vlan6_dhcp
add address-pool=vlan_vlan2 interface=vlan2 name=vlan_vlan2_dhcp
add address-pool=vlan_vlan9 interface=vlan9 name=vlan_vlan9_dhcp
add address-pool=vlan_vlan8 interface=vlan8 name=vlan_vlan8_dhcp
/port
set 0 name=serial0
/queue type
add cake-diffserv=besteffort cake-nat=yes cake-rtt=10ms cake-rtt-scheme=metro \
    kind=cake name=cake-tx
add cake-diffserv=besteffort cake-nat=yes cake-rtt=10ms cake-rtt-scheme=metro \
    kind=cake name=cake-rx
/queue simple
add max-limit=1G/1G name=isp2-cake queue=cake-rx/cake-tx target=ether2
add max-limit=1G/1G name=isp1-cake queue=cake-rx/cake-tx target=ether1
/routing table
add disabled=no fib name=prefer_isp1
add disabled=no fib name=prefer_isp2
/system logging action
set 3 src-address=1.2.1.1
add name=alloy remote=1.2.1.10 remote-log-format=syslog remote-port=515 \
    remote-protocol=tcp syslog-facility=syslog syslog-time-format=iso8601 \
    target=remote
/user group
add name=metrics policy="read,api,!local,!telnet,!ssh,!ftp,!reboot,!write,!pol\
    icy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon,!rest-api"
/interface bridge port
add bridge=lan interface=ether5
add bridge=lan interface=ether6
add bridge=lan interface=ether11
add bridge=lan interface=ether16
add bridge=lan interface=ether7
# This backup cable is not plugged in except if required in an emergency.
add bridge=lan comment="Budh (backup)" interface=ether14
add bridge=lan interface=ether12
add bridge=lan interface=ether10
add bridge=lan interface=ether9
add bridge=lan interface=ether13
add bridge=lan interface=ether4
add bridge=lan interface=ether8
add bridge=lan interface=ether3
add bridge=lan interface=budh
/ip neighbor discovery-settings
set discover-interface-list=LAN
/interface bridge vlan
add bridge=lan untagged="ether7,ether8,ether9,ether14,ether11,ether10,ether12,\
    ether13,ether6,ether4,ether5" vlan-ids=1
add bridge=lan comment="vlan1 (101)" vlan-ids=101
add bridge=lan comment="vlan5 (105)" tagged=LAN vlan-ids=105
add bridge=lan comment="vlan3 (103)" tagged=LAN vlan-ids=103
add bridge=lan comment="vlan4 (104)" tagged=LAN vlan-ids=104
add bridge=lan comment="vlan2 (102)" tagged=LAN vlan-ids=102
add bridge=lan comment="vlan6 (106)" tagged=LAN vlan-ids=106
add bridge=lan comment="vlan8 (108)" tagged=LAN vlan-ids=108
add bridge=lan comment="vlan7 (107)" tagged=LAN vlan-ids=107
add bridge=lan comment="vlan9 (109)" tagged=LAN vlan-ids=109
/interface list member
add interface=ether6 list=LAN
add interface=ether11 list=LAN
add interface=ether5 list=LAN
add interface=ether8 list=LAN
add interface=ether4 list=LAN
add interface=ether13 list=LAN
add interface=ether12 list=LAN
add interface=ether7 list=LAN
add interface=ether10 list=LAN
add interface=ether16 list=LAN
add interface=ether14 list=LAN
add interface=ether9 list=LAN
add interface=wireguard2 list=LAN
add interface=wireguard1 list=LAN
add interface=wireguard3 list=LAN
add interface=ether1 list=WAN
add interface=ether2 list=WAN
add interface=ether3 list=LAN
add interface=budh list=LAN
/interface ovpn-server server
add mac-address=22:33:44:55:66:77 name=ovpn-server1
/interface wireguard peers
# redacted
/ip address
add address=1.2.1.1/24 interface=lan network=1.2.1.0/24
add address=1.3.2.1/24 interface=wireguard2 network=1.3.2.0/24
add address=1.3.3.1/24 interface=wireguard3 network=1.3.3.0/24
add address=1.3.1.1/24 interface=wireguard1 network=1.3.1.0/24
add address=10.1.1.5/20 interface=ether1 network=10.1.1.0
add address=11.2.1.2/30 interface=ether2 network=11.2.1.0
add address=1.2.104.1/24 interface=vlan4 network=1.2.104.0/24
add address=1.2.108.1/24 interface=vlan8 network=1.2.108.0/24
add address=1.2.103.1/24 interface=vlan3 network=1.2.103.0/24
add address=1.2.102.1/24 interface=vlan2 network=1.2.102.0/24
add address=1.2.107.1/24 interface=vlan7 network=1.2.107.0/24
add address=1.2.106.1/24 interface=vlan6 network=1.2.106.0/24
add address=1.2.105.1/24 interface=vlan5 network=1.2.105.0/24
add address=1.2.109.1/24 interface=vlan9 network=1.2.109.0/24
# Not part of the bridge:
add address=192.168.88.1/24 interface=ether15 network=192.168.88.0
/ip dhcp-server lease
# redacted
/ip dhcp-server network
add address=1.2.1.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.1.1
add address=1.2.103.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.103.1
add address=1.2.104.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.104.1
add address=1.2.102.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.102.1
add address=1.2.102.0/24/24 dns-server=1.2.1.7,1.2.1.8 gateway=1.2.108.1
add address=1.2.109.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=1.2.109.1
add address=1.2.107.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=1.2.107.1
add address=1.2.106.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=1.2.106.1
add address=1.2.105.0/24/24 dns-server=8.8.8.8,8.8.4.4 gateway=\
    1.2.105.1
/ip dns
set servers=8.8.8.8,8.8.4.4
/ip firewall filter
add action=accept chain=input dst-port=12345 protocol=udp
add action=accept chain=input dst-port=12346 protocol=udp
add action=accept chain=input dst-port=12347 protocol=udp
add action=accept chain=input comment="accept established,related,untracked" \
    connection-state=established,related,untracked in-interface-list=WAN
add action=accept chain=forward connection-state=\
    established,related,untracked
add action=drop chain=forward comment="drop invalid" connection-state=invalid
add action=accept chain=forward comment="allow dstnat" connection-nat-state=\
    dstnat
add action=drop chain=input comment="drop invalid" connection-state=invalid \
    in-interface-list=WAN
add action=accept chain=input comment="accept ICMP" in-interface-list=WAN \
    protocol=icmp
add action=accept chain=input comment="allow SSH" disabled=yes \
    in-interface-list=WAN port=22 protocol=tcp
add action=drop chain=input comment="block everything else" \
    in-interface-list=WAN
/ip firewall mangle
add action=mark-connection chain=output comment="classify output (1)" \
    connection-mark=no-mark connection-state=new new-connection-mark=balance1 \
    passthrough=no per-connection-classifier=both-addresses-and-ports:2/1
add action=mark-connection chain=input comment="mark incoming (isp1)" \
    connection-state=new in-interface=ether1 new-connection-mark=fromisp1
add action=mark-connection chain=input comment="mark incoming (isp2)" \
    connection-state=new in-interface=ether2 new-connection-mark=\
    fromisp2
add action=mark-connection chain=prerouting comment="classify prerouting (0)" \
    connection-mark=no-mark connection-state=new dst-address-type=!local \
    in-interface=lan new-connection-mark=balance0 per-connection-classifier=\
    both-addresses-and-ports:2/0
add action=mark-connection chain=prerouting comment="classify prerouting (1)" \
    connection-mark=no-mark connection-state=new dst-address-type=!local \
    in-interface=lan new-connection-mark=balance1 per-connection-classifier=\
    both-addresses-and-ports:2/1
add action=accept chain=prerouting comment="accept prerouting" dst-address=\
    10.1.1.0/20 in-interface=lan
add action=accept chain=prerouting comment="accept prerouting" dst-address=\
    11.2.1.0/30 in-interface=lan
add action=mark-routing chain=prerouting comment="balance prerouting (isp1)" \
    connection-mark=balance0 in-interface=lan new-routing-mark=prefer_isp1
add action=mark-routing chain=prerouting comment=\
    "balance prerouting (isp2)" connection-mark=balance1 in-interface=\
    lan new-routing-mark=prefer_isp2
add action=mark-connection chain=output comment="classify output (0)" \
    connection-mark=no-mark connection-state=new new-connection-mark=balance0 \
    per-connection-classifier=both-addresses-and-ports:2/0
add action=mark-routing chain=output comment="balance output (isp1)" \
    connection-mark=balance0 new-routing-mark=prefer_isp1
add action=mark-routing chain=output comment="balance output (isp2)" \
    connection-mark=balance1 new-routing-mark=prefer_isp2
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1
add action=masquerade chain=srcnat out-interface=ether2
/ip route
add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    10.1.1.1 routing-table=prefer_isp1 scope=30 suppress-hw-offload=no \
    target-scope=10
add check-gateway=ping disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
    11.2.1.1 routing-table=prefer_isp2 scope=30 \
    suppress-hw-offload=no target-scope=10
add check-gateway=ping disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\
    11.2.1.1 routing-table=prefer_isp1 scope=30 suppress-hw-offload=no \
    target-scope=10
add check-gateway=ping disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\
    10.1.1.1 routing-table=prefer_isp2 scope=30 \
    suppress-hw-offload=no target-scope=10
add check-gateway=ping distance=2 dst-address=0.0.0.0/0 gateway=11.2.1.1 \
    routing-table=main scope=30 target-scope=10
add check-gateway=ping distance=1 dst-address=0.0.0.0/0 gateway=10.1.1.1 \
    routing-table=main scope=30 target-scope=10
/ip service
set telnet disabled=yes
set ftp disabled=yes
set www disabled=yes
set www-ssl address=1.2.1.0/24,1.2.103.0/24 certificate=ccr2004 \
    disabled=no tls-version=only-1.2
set api disabled=yes
set winbox disabled=yes
set api-ssl address="1.2.1.0/24" certificate=ccr2004 tls-version=\
    only-1.2
/ip ssh
set always-allow-password-login=yes host-key-size=4096 strong-crypto=yes
/system clock
set time-zone-name=Asia/Kolkata
/system identity
set name=ccr2004
/system logging
add action=alloy topics=wireguard
add action=alloy topics=certificate
add action=alloy topics=route
add action=alloy topics=bridge
add action=alloy topics=error
add action=alloy topics=warning
add action=alloy topics=firewall
add action=alloy topics=queue
add action=alloy topics=interface
add action=alloy topics=info
add action=alloy topics=critical
add action=alloy topics=dhcp
add action=alloy topics=health
/system note
set note="\
    \n      ----------------------------------------\
    \n      |\
    \n      | Managed by Ansible\
    \n      |\
    \n      ----------------------------------------\
    \n      |\
    \n      | You are logged into ccr2004\
    \n      |\
    \n      ----------------------------------------"
/system routerboard settings
set enter-setup-on=delete-key
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN
/tool netwatch
add host=8.8.8.8 interval=5s name=watch_isp2 src-address=11.2.1.2 \
    type=icmp
add host=8.8.8.8 interval=5s name=watch_isp1 src-address=10.1.1.5 type=\
    icmp

And quote my reply (which includes the WireGuard peers) to your post from post #10:

Yep, but that configuration is from 18-05-2025, thought you had changed something in the meantime.

Ditto, no effort to learn and incorporate the Ref on Vlans, moving on!

Right, I see what you mean. I’d already made the changes sindy suggested to the routes and tables by that point and this was the first opportunity I had to test their impact, so I haven’t changed anything in the interim. It’s still trying to send packets out the WAN connection that’s down, though.

As far as the VLANs go, I’m obviously keen to fix them too. All I want is to be sure I understand my mistakes first, otherwise I’ll end up doing the same thing again thanks to an incorrect mental model. Hence the question I asked two weeks ago (after reading the guide) that anav’s ignored twice. I’m therefore just focusing on the malfunctioning failover that I hopefully can do something about.

Not that I understand much of the VLANs and mangle and firewall filter rules you have, but generally speaking, it seems that your configuration (from 18-05-2025) is what I would call “a bloody mess of inconsistent and illogical names/comments, capable of confusing any reader, including you” :confused:

Examples:
The bridge is called “lan”. ← it is a bridge, call it “bridge” or “bridge1” or “br-main” or “pontevecchio” :open_mouth: but don’t use a different case (same) name as an interface-list (LAN).

ether14 has comment “Budh” BUT there is actually a bonding (what for?) of SFP1 and SFP2 with comment AND name “budh”

Names should be UNIQUE (and when possible self-explaining) comments should be either omitted (if unnecessary) or actually useful.

Interfaces are added to interface-lists in an order that can only come out as the result of dice throwing. :laughing:

There are quite a few entries that look like non-sequiturs or remnants of previous experiments.

Don’t be shy, if you have a VLAN 105, call it 105, NOT VLAN 5 (105)!

You have to understand that the simpler, more linear and ordered a configuration is, the easier it is to understand it BOTH for a stranger on an internet forum AND for the future you, that in three to six months time won’t be anymore capable of understanding why you made this (or that) setting.

Maybe useful, maybe not, try using my parser (shameless plug :wink: ):
http://forum.mikrotik.com/t/configuration-parser-spreadsheet/183922/1
http://forum.mikrotik.com/t/configuration-parser-spreadsheet/183922/1
if you get the hang of it, it is very handy to highlight this kind of mix-ups.

Since - set aside my occasional grumpiness - I am after all a good guy at heart, find attached a copy of the spreadsheet with your configuration loaded and a couple of *_check sheets added, but it is only a base for you to experiment with.
Config_Parser_Alpha_4_Aankhen.zip (207 KB)

Haha. That’s fair. I only started working with real routers (and any switches at all) in 2023, limited to TP-Link equipment, and this configuration is my attempt to translate what I had there into RouterOS. I think I can explain a few specific things, but overall, I’m not surprised it’s confusing, and I’d like to clean it up.

Examples:
The bridge is called “lan”. ← it is a bridge, call it “bridge” or “bridge1” or “br-main” or “pontevecchio” > :open_mouth: > but don’t use a different case (same) name as an interface-list (LAN).

Understood.

ether14 has comment “Budh” BUT there is actually a bonding (what for?) of SFP1 and SFP2 with > comment AND name > “budh”

Names should be UNIQUE (and when possible self-explaining) comments should be either omitted (if unnecessary) or actually useful.

I’ve been kicking myself for this since I first shared my configuration. It’s on my list of things to correct. The two SFP+ ports (which should be Budh 1 and Budh 2) are connected to my switch (Budh) in an LACP group. ether14 is a backup connection to Budh that I used while I was figuring out my configuration; I plug it in if I lock myself out of the LAG, which has happened… more than once.

Interfaces are added to interface-lists in an order that can only come out as the result of dice throwing. > :laughing:

That’s basically true! I’m not writing this configuration by hand but managing it via Terraform, and since the order isn’t significant for these lists, it adds the members in parallel.

There are quite a few entries that look like non-sequiturs or remnants of previous experiments.

Don’t be shy, if you have a VLAN 105, call it 105, NOT VLAN 5 (105)!

This is an artifact of the anonymization. Sorry about that. I have meaningful names for the VLANs in the real configuration, corresponding to names assigned to things like Wi-fi networks.

You have to understand that the simpler, more linear and ordered a configuration is, the easier it is to understand it BOTH for a stranger on an internet forum AND for the future you, that in three to six months time won’t be anymore capable of understanding why you made this (or that) setting.

That makes sense.

Maybe useful, maybe not, try using my parser (shameless plug > :wink: > ):
Configuration Parser Spreadsheet
Configuration Parser Spreadsheet
if you get the hang of it, it is very handy to highlight this kind of mix-ups.

Since - set aside my occasional grumpiness - I am after all a good guy at heart, find attached a copy of the spreadsheet with your configuration loaded and a couple of *_check sheets added, but it is only a base for you to experiment with.

This is great! Thank you for the links and the sheet. And thanks a lot for taking the time to look over the configuration and offer such friendly advice—left to myself, I wouldn’t have detected even a hint of grumpiness.

Apart from what you’ve highlighted, I now have a few major changes to make. First, I’ve been rethinking my dual WAN setup and I’m considering using failover instead for non-technical reasons, which would render my original question irrelevant. Second, I’m going to assume my understanding of the rationale behind the VLAN setups in the guide is correct and try reorganizing mine accordingly. Wish me luck!