In my previous Dual-WAN failover article, I moved from a TP-Link ER605 (slowest device ever) to a MikroTik hEX S. That setup worked, but it also sent me down the usual rabbit hole of buying increasingly specialised router hardware for a problem which does not actually need it.

Repeatable infrastructure should depend on open networking standards and replaceable commodity hardware, not a particular router model, vendor GUI, or temporarily available development board.

This is the next iteration: a repeatable Dual-WAN failover router made from a one-port SBC and a TP-Link TL-SG105E managed Ethernet switch.

Yes, one Ethernet port is enough.

The TL-SG105E handles the VLAN magic. It separates the two WANs and the LAN, while a single 802.1Q trunk to the SBC carries all three networks as tagged VLANs. Linux sees three logical interfaces and routes between them normally. This old arrangement is usually called a router-on-a-stick.

No expensive, unobtainium MediaTek SBC is required. No power-hungry N150 box is required either. If a modest Raspberry Pi or another well-supported SBC is already sitting in a drawer, it can do this job.

The hardware detour

I have now tried the three obvious routes.

The TP-Link ER605 was the slowest of the lot. It was slow to boot, slow to react, and failover was slow enough to defeat the point of having a backup connection. To put it bluntly, the ER605 sucks for this job. It has a nice list of features on the box, but the actual experience is an unresponsive little appliance at the most important moment.

The MikroTik hEX S is much more capable, and the configuration from my earlier article does work. RouterOS, however, is deeply non-intuitive. Some of it is commands, some of it is WebFig, and some of it is clicky-clicky work to remove ports from the default bridge or attach them to an interface list. RouterOS is powerful, but I never feel that the final state is obvious from looking at the configuration.

This is also where the supposed friendliness of a GUI falls apart. Figuring out which page contains a setting, which checkbox quietly changes another setting, and what state the device finally ended up in is much harder than thinking through the problem and typing a few CLI commands. Commands are easy to read, review, save, diff and run again; a trail of clicks is none of those things.

OpenWrt seems like the natural answer for a Raspberry Pi, but OpenWrt-on-RPi is not maintained as a first-class appliance experience in the same way as a purpose-built OpenWrt router. To be precise, the OpenWrt bcm27xx page calls the target fully supported and official images do exist. I am talking about the complete Pi-specific integration, documentation and upgrade experience, not the absence of downloadable builds. I do not want this router to depend on a router-specific distribution or on the quality of one board target's integration.

The hardware situation makes this worse. The OpenWrt One and other attractive OpenWrt-compatible devices can be difficult to buy, expensive by the time they reach me, or already obsolete when I need another unit. A setup is not really repeatable if its first instruction is to hunt for one particular router revision on the used market.

That is why I would avoid building repeatable infrastructure around OpenWrt. Learning standard Linux interfaces, VLANs, policy routing, nftables and systemd produces reusable skills as well as reusable configuration. The next router can be a different Raspberry Pi, another ordinary ARM SBC, or even a small x86 machine without having to relearn a router distribution or find exactly compatible hardware. The same knowledge also transfers to servers, firewalls, VPN gateways, containers and cloud networks. Learning a vendor GUI mostly teaches me how to operate that vendor GUI.

Plain Debian or Raspberry Pi OS Lite has boring packages, normal systemd units, normal logs, normal upgrades, and configuration files which I can copy to another ARM or x86 machine. Boring is exactly what I want in a router.

What repeatable means here

I should be able to rebuild this router today using parts which are actually available locally. I should also be able to replace the SBC with a different Linux machine, re-run the configuration, inspect the resulting state, and understand every important routing decision without reconstructing a sequence of GUI clicks.

Availability matters more than appliance purity. The best router is not the most fashionable supported board on a compatibility list; it is the one I can repair or reproduce when the Internet is down. An open software stack tied to unobtainable hardware is not operationally open.

The central idea

The physical layout looks like this:

 Fibre router/ONT ---- untagged VLAN 10 --+
                                          |
 4G/5G backup router -- untagged VLAN 20 -+-- TP-Link TL-SG105E
                                          |        |
 LAN / Wi-Fi AP ------- untagged VLAN 30 -+        +-- tagged VLANs 10,20,30
                                                               |
                                                        one-port SBC

Enable 802.1Q VLAN in the TL-SG105E Web UI, create VLANs 10, 20 and 30, and configure the ports like this. TP-Link's 802.1Q configuration guide shows the same tagged/untagged and PVID controls.

Switch portConnected deviceVLANsPVID
1Primary ISP routerVLAN 10 untagged10
2Backup 4G/5G routerVLAN 20 untagged20
3LAN switch, mesh unit, or APVLAN 30 untagged30
4 (optional)Another LAN deviceVLAN 30 untagged30
5SBC Ethernet portVLANs 10, 20 and 30 tagged1 (unused)

Port 5 can retain the default PVID because the SBC sends tagged traffic on the trunk. Make each port a member only of the VLANs it needs; in particular, do not leave the WAN and LAN ports joined as untagged members of the default VLAN 1. Put the switch's management interface on VLAN 30 where the hardware revision permits it, and save the configuration. The management page must not be reachable from either WAN.

The installer configures Linux, not the managed switch: configure and save the TL-SG105E VLANs first, because that switch is what safely turns one Ethernet port into three isolated networks.

There is no USB Ethernet adapter here. There are no separate physical WAN ports on the SBC. The TL-SG105E supplies the port isolation, and Linux supplies the routing.

Assumptions

The two upstream routers already perform the ISP-specific work. Both WAN VLANs use DHCP, so the script learns their addresses and gateways instead of baking my home subnets into the setup. The LAN is deliberately fixed:

eth0.10 (VLAN 10): primary WAN, DHCP
eth0.20 (VLAN 20): secondary WAN, DHCP
eth0.30 (VLAN 30): LAN, 192.168.10.1/24

The setup assumes Raspberry Pi OS or Debian with NetworkManager and a physical Ethernet interface named eth0. It was written for a Raspberry Pi 3B+ or 4 and a TP-Link TL-SG105E, although nothing in the idea is specific to those models. Check the interface name with ip link and adjust the variables if your board calls it something else.

This article deliberately covers IPv4 only. The installer disables IPv6 on the three VLAN profiles until proper IPv6 prefix delegation and failover are configured.

The ideal SBC

The ideal board for this job would have reliable, built-in eMMC rather than depending on a removable microSD card. Routers are appliances: storage should tolerate unattended reboots and power interruptions without turning the next boot into a filesystem-repair exercise.

Once the router is configured and tested, the whole Linux root filesystem should be made read-only. Runtime state such as /run, /tmp, logs, DHCP leases and NetworkManager state can live in tmpfs or in a disposable overlay. Updates then become a deliberate maintenance operation: temporarily make the root writable, update and test it, and return it to read-only mode.

This is an end-state, not something to enable before running the installer. The setup script needs to install packages and write configuration first. A read-only root plus eMMC does not eliminate the need for backups, but it makes the finished router much more appliance-like and far less vulnerable to an untimely power cut.

The repeatable part

The complete setup is in one readable installer, published from static/files/dualwan-router.sh:

Download dualwan-router.sh

Put the file on the SBC, inspect it, and run it locally:

chmod +x dualwan-router.sh
sudo ./dualwan-router.sh

Do not launch it through the same Ethernet port which is about to become the VLAN trunk. Use a keyboard and display, serial console, or temporary Wi-Fi connection. Also avoid Wi-Fi on 192.168.1.0/24 when one of the WAN routers uses that subnet.

The installer does all of the otherwise tedious work:

  • installs NetworkManager, dnsmasq, nftables and the normal Linux routing tools;
  • creates the eth0.10, eth0.20 and eth0.30 VLAN profiles;
  • obtains both WAN configurations over DHCP but prevents NetworkManager from choosing a default route;
  • enables IPv4 forwarding, disables strict reverse-path filtering, and turns off ICMP redirects;
  • supplies LAN DHCP and DNS on 192.168.10.0/24;
  • installs a default-deny nftables firewall and NAT for both WANs; and
  • installs and enables the dualwan-failover service.

It backs up files which it replaces under /root/dualwan-router-backups/ and is designed to be re-run. It does replace /etc/nftables.conf, so this should be a dedicated router rather than an SBC already hosting an elaborate firewall.

The Wi-Fi mesh or access point belongs on VLAN 30 and should run in AP/bridge mode. There should be only one DHCP server on the LAN: dnsmasq on the SBC.

How the failover works

A cable can remain up while an ISP is broken beyond its gateway, so carrier state alone is not a health check. The service obtains each WAN's current address and gateway from NetworkManager, constructs a source-specific policy routing table, and then tests that path directly.

For each WAN it checks the local gateway, verifies that a route lookup selects the intended interface, and requires replies from at least two of three public targets: 1.1.1.1, 8.8.8.8 and 9.9.9.9. Use different probe addresses if your ISP filters ICMP.

WAN1 always wins when both paths are healthy. If WAN1 fails, the service makes WAN2 the one default route; when WAN1 returns, it becomes the default again. The dedicated tables mean a probe for WAN2 still leaves through WAN2 while WAN1 is active. They also avoid confusing one provider's test with the other provider's result.

Existing NAT sessions normally break when the public path changes. That is unavoidable failover, not load balancing. Browsers and most applications reconnect by themselves; a long-running SSH session usually does not.

Test the failure, not just the configuration

First inspect the logical interfaces, rules and routes:

nmcli device status
ip -4 rule show
ip -4 route show
ip -4 route show table 101
ip -4 route show table 102
sudo nft list ruleset
systemctl status dualwan-failover

From a LAN client, keep a ping and a download running. Then test these cases separately:

  1. Unplug the primary WAN cable from switch port 1.
  2. Leave the cable connected but power off the fibre router.
  3. Restore the primary and confirm that traffic returns to it.
  4. Power off the backup router while the primary is healthy.
  5. Power off both upstream routers and confirm that the LAN itself still works.
  6. Reboot the SBC and the managed switch together.

Watch decisions live with:

journalctl -fu dualwan-failover

Also verify the external address before and after failover from a LAN client. A route table which looks correct is not the same thing as a tested failure path.

Measure it

The case becomes much stronger with measurements, not just a successful configuration screen. These are the numbers worth recording for this setup and for any appliance being considered as an alternative:

MeasurementSensible test
Idle powerSBC and TL-SG105E together, measured at the wall after boot
Routed throughputSustained iperf3 traffic through the VLAN trunk
Cold-boot recoveryPower-on until a LAN client can reach the Internet
WAN1 failure detectionTime from disconnecting WAN1 until WAN2 carries traffic
WAN1 failbackTime from restoring WAN1 until it becomes active again
DisruptionLost pings and broken sessions during failover and failback

I would rather publish those results than repeat a maximum throughput number from a product page. They expose slow booting, optimistic routing claims, excessive power use and unstable failback immediately. I will add the complete results after repeating each test enough times to make them meaningful.

Why this is the sensible version

The router has one replaceable computer, one TL-SG105E, and no vendor controller. The network layout fits in a small table. The entire router configuration is text, so it can be kept in Git, copied to another SBC, and reviewed after an upgrade.

Separating switching from routing also improves repairability. The TL-SG105E does VLAN isolation and the SBC does Linux routing; either can be replaced without replacing the other. A conventional Dual-WAN router is a single point of failure too, but it combines both jobs in one model-specific box. Here the failure domains, configuration and possible replacements are all visible.

A gigabit full-duplex trunk can receive a packet from a WAN VLAN and transmit it back on the LAN VLAN at the same time. The one cable is therefore not automatically a half-gigabit bottleneck. Actual throughput depends on the SBC's Ethernet implementation, CPU, MTU, and packet sizes, so test it with iperf3 instead of believing a board specification. In practice, a Raspberry Pi 4 can touch around 880 Mbps here without even trying hard or requiring elaborate tuning. That is already generous for many home connections; an older board may be enough for a slower fibre or 4G link.

For power, the Cuzor UPS is the best and most reliable option I have found for this kind of installation. It is a practical way to keep the Raspberry Pi, TL-SG105E and other small networking devices alive through short power cuts and power transitions. Dual-WAN is not very useful if both links disappear because the router reboots during a mains glitch.

There are two real cautions. The switch and SBC each remain a single point of failure, so keep configuration backups and power both from the same UPS. A spare TL-SG105E or pre-imaged SD card is also cheap insurance. VLAN separation is a security boundary only when the switch is configured correctly: never mix an untagged WAN and LAN on the same port, and never expose the switch management interface to VLAN 10 or VLAN 20.

That is the whole point of this iteration: Dual-WAN failover is a small Linux routing problem. It does not justify a slow ER605, a clicky-clicky RouterOS configuration, an exotic MediaTek router board, or an overpowered N150 mini PC. One Ethernet port, three VLANs, and boring configuration files are enough.