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 port | Connected device | VLANs | PVID |
|---|---|---|---|
| 1 | Primary ISP router | VLAN 10 untagged | 10 |
| 2 | Backup 4G/5G router | VLAN 20 untagged | 20 |
| 3 | LAN switch, mesh unit, or AP | VLAN 30 untagged | 30 |
| 4 (optional) | Another LAN device | VLAN 30 untagged | 30 |
| 5 | SBC Ethernet port | VLANs 10, 20 and 30 tagged | 1 (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:
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.20andeth0.30VLAN 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-failoverservice.
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:
- Unplug the primary WAN cable from switch port 1.
- Leave the cable connected but power off the fibre router.
- Restore the primary and confirm that traffic returns to it.
- Power off the backup router while the primary is healthy.
- Power off both upstream routers and confirm that the LAN itself still works.
- 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:
| Measurement | Sensible test |
|---|---|
| Idle power | SBC and TL-SG105E together, measured at the wall after boot |
| Routed throughput | Sustained iperf3 traffic through the VLAN trunk |
| Cold-boot recovery | Power-on until a LAN client can reach the Internet |
| WAN1 failure detection | Time from disconnecting WAN1 until WAN2 carries traffic |
| WAN1 failback | Time from restoring WAN1 until it becomes active again |
| Disruption | Lost 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.