I first tried Travelmate, but it caused CPU spikes. I then tried MultiWAN Manager, but it was slow, clunky and kept misconfiguring the connections.
So I scripted my own.
This script monitors for a certain SSID on radio0 (2.4 GHz). That SSID comes from a cell phone hotspot. If your main ISP goes down, you can feed data to/from your LAN through your cell phone’s hotspot.
The script monitors periodically (using the main 2.4GHz WiFi) for the TARGET_SSID. When the script sees the TARGET_SSID, it enables the wireless network which is set up to receive the cell phone hotspot WiFi signal; and when it no longer sees that TARGET_SSID, it disables that wireless network and its associated interface, and brings radio0 back up so the 2.4 GHz signal remains stable.
This is due to a bug that causes radio0 (2.4GHz) to go down and stay down after you stop the hotspot signal, usually requiring a manual restart of radio0. There’s also a bug wherein the wireless network set up to receive the hotspot signal loses the interface it’s assigned to when the hotspot WiFi is disabled… this script assigns that interface just before bringing up the wireless network set up to receive the hotspot signal.
DO NOT use radio1 (5GHz) for receiving a hotspot signal. It just doesn’t work. radio1 goes down when it tries, requiring a manual restart of radio1. Set your cellphone’s hotspot to only transmit on 2.4GHz.
Go to Network >> Interfaces. Click the “Add new interface” button.
Add new interface…: Name: Choose a name. I chose trm_wwan.
Add new interface…: Protocol: DHCP client
Add new interface…: Device: phy0-sta0
Click the “Create Interface” button.
Back in the list of interfaces, find the interface you just created, and click its “Edit” button.
Set up the new interface thusly:
General Settings: Protocol: DHCP client
General Settings: Device: phy0-sta0
General Settings: Disable this interface: unchecked
General Settings: Bring up on boot: unchecked
General Settings: Hostname to send when requesting DHCP: Send the hostname of this device
Advanced Settings: Force link: unchecked
Advanced Settings: Use broadcast flag: unchecked
Advanced Settings: Preferred client ID: Automatic
Advanced Settings: Client ID to send when requesting DHCP: blank
Advanced Settings: Vendor Class to send when requesting DHCP: blank
Advanced Settings: Use default gateway: checked
Advanced Settings: Use DNS servers advertised by peer: unchecked
Advanced Settings: Use custom DNS servers: 1.1.1.1; 1.0.0.1; 9.9.9.9; 149.112.112.112
Advanced Settings: DNS weight: 0
Advanced Settings: Use gateway metric: 100
Advanced Settings: Multi-Path TCP: Off
Advanced Settings: Override IPv4 routing table: blank
Advanced Settings: Override IPv6 routing table: blank
Advanced Settings: Delegate IPv6 prefixes: checked
Advanced Settings: IPv6 assignment length: disabled
Advanced Settings: IPv6 prefix filter: blank
Advanced Settings: IPv6 suffix: ::1
Advanced Settings: IPv6 preference: 0
Firewall Settings: Create/Assign firewall-zone: wan + wan6
DHCP Server: No DHCP Server configured for this interface.
Click the “Save” button.
Back at Network >> Interfaces, click the “Add new interface…” button again.
Add new interface…: Name: Choose a name. I chose trm_wwan6.
Add new interface…: Protocol: DHCPv6 client
Add new interface…: Device: Alias Interface: @{whatever you named the first interface}
Mine would be: Alias Interface: “@trm_wwan”
Click the “Create Interface” button.
Back in the list of interfaces, find the interface you just created, and click its “Edit” button.
Set up the new interface thusly:
General Settings: Protocol: DHCPv6 client
General Settings: Device: @{whatever you named the first interface}
Mine would be: @trm_wwan
General Settings: Disable this interface: unchecked
General Settings: Bring up on boot: checked
General Settings: Request IPv6-address: try
General Settings: Request IPv6-prefix: Automatic
General Settings: Extend prefix: unchecked
General Settings: Do not send a Release when restarting: checked
Advanced Settings: Force link: unchecked
Advanced Settings: Preferred client ID: Automatic
Advanced Settings: Client ID to send when requesting DHCP: blank
Advanced Settings: Use default gateway: checked
Advanced Settings: Use DNS servers advertised by peer: checked
Advanced Settings: DNS weight: 0
Advanced Settings: Use gateway metric: 100
Advanced Settings: Multi-Path TCP: Off
Advanced Settings: Override IPv4 routing table: blank
Advanced Settings: Override IPv6 routing table: blank
Advanced Settings: IPv6 source routing: checked
Advanced Settings: Delegate IPv6 prefixes: checked
Advanced Settings: IPv6 assignment length: disabled
Advanced Settings: IPv6 prefix filter: blank
Advanced Settings: IPv6 suffix: ::1
Advanced Settings: IPv6 preference: 0
Firewall Settings: Create/Assign firewall-zone: wan + wan6
DHCP Server: No DHCP Server configured for this interface.
Click the “Save” button.
Go to Network >> Wireless. Click the “Add” button for radio0.
Set up the new wireless network thusly:
Device Configuration: General Setup: Mode: AX
Device Configuration: General Setup: Channel: auto
Device Configuration: General Setup: Width: 20 MHz
Device Configuration: General Setup: Allow 802.11b rates: unchecked
Device Configuration: General Setup: Maximum transmit power: driver default
Device Configuration: General Setup: Country Code: your country
Device Configuration: Advanced Settings: Coverage cell density: Disabled
Device Configuration: Advanced Settings: Distance Optimization: auto
Device Configuration: Advanced Settings: Fragmentation Threshold: off
Device Configuration: Advanced Settings: RTS/CTS Threshold: off
Device Configuration: Advanced Settings: Force 40MHz mode: unchecked
Device Configuration: Advanced Settings: Beacon Interval: 300
Device Configuration: Advanced Settings: Rx LDPC: checked
Device Configuration: Advanced Settings: Tx LDPC: checked
Interface Configuration: General Setup: Mode: Client
Interface Configuration: General Setup: ESSID: The hotspot’s SSID
Interface Configuration: General Setup: BSSID: blank
Interface Configuration: General Setup: Network: {the interface you just set up}
For mine, it would be trm-wwan.
Interface Configuration: Wireless Security: WPA2-PSK/WPA3-SAE Mixed Mode (strong security)
Interface Configuration: Wireless Security: Key: The hotspot SSID’s keyphrase
Interface Configuration: Wireless Security: 802.11w Management Frame Protection: Optional
Interface Configuration: Wireless Security: 802.11w maximum timeout: 1000
Interface Configuration: Wireless Security: 802.11w retry timeout: 201
Interface Configuration: Wireless Security: Operating Channel Validation: Disabled
Interface Configuration: Advanced Settings: Multi To Unicast: unchecked
Interface Configuration: Advanced Settings: Isolate Bridge Port: unchecked
Interface Configuration: Advanced Settings: Interface name: blank
Interface Configuration: Advanced Settings: MAC address: driver default (undefined)
Interface Configuration: Advanced Settings: Short Preamble: checked
Interface Configuration: Advanced Settings: DTIM Interval: 2
Interface Configuration: Advanced Settings: Time interval for rekeying GTK: 600
Interface Configuration: Advanced Settings: Disable Inactivity Polling: unchecked
Interface Configuration: Advanced Settings: Station inactivity limit: 300
Interface Configuration: Advanced Settings: Maximum allowed Listen Interval: 65535
Interface Configuration: Advanced Settings: Disassociate On Low Acknowledgement: checked
Click ‘Save’, then click ‘Save & Apply’ at the bottom of the page.
Start up your cell phone’s hotspot.
Go to Network >> Wireless, and for the new wireless network you just created, if its button says “Enable”, click to enable the wireless network, then click the “Save & Apply” button.
Wait for the router to connect to the cellphone hotspot. You’ll see the bars in the signal strength meter for that network turn blue, and numbers denoting the signal strength will display.
In Services >> Terminal, enter:
uci show wireless | grep .device=
It will display something like this:
wireless.default_radio0.device=‘radio0’
wireless.default_radio1.device=‘radio1’
wireless.wifinet2.device=‘radio0’
That last entry should be the wireless network you set up to connect to the hotspot.
To be absolutely sure, in Services >> Terminal, enter:
uci show wireless.wifinet2
It will display something like this:
wireless.wifinet2=wifi-iface
wireless.wifinet2.device=‘radio0’
wireless.wifinet2.mode=‘sta’
wireless.wifinet2.ssid=‘{SSID OF YOUR HOTSPOT}’
wireless.wifinet2.encryption=‘sae-mixed’
wireless.wifinet2.key=‘{PASSPHRASE FOR THAT SSID}’
wireless.wifinet2.ocv=‘0’
wireless.wifinet2.disabled=‘1’
wireless.wifinet2.network=‘trm_wwan’
If that is your hotspot, you’ll then change the code below to:
INTERFACE=“wifinet2”
NET_INTF=“trm_wwan”
Go to System >> Startup >> Local Startup.
Edit the code below to reflect your TARGET_SSID, your INTERFACE, your NET_INTF, your RADIO, the maximum_sleep you want (used to reduce CPU utilization) and whether you want logging (logging=1) or not (logging=0).
To see the logs in real-time, in Services >> Terminal, you’d enter:
logread -f | grep hotspot_monitor
At System >> Startup >> Local Startup, paste the code below the first two comment lines, but before the last (exit 0) line and click the “Save” button.
HOTSPOT MONITOR
TARGET_SSID=“Teracube”
INTERFACE=“wifinet2”
NET_INTF=“trm_wwan”
RADIO=“radio0”
current_sleep=20
missed_checks=0
minimum_sleep=20
maximum_sleep=90
logging=1
logger -t hotspot_monitor “Hotspot Monitor script started monitoring for SSID: $TARGET_SSID”
while true; do
# Check if the interface config is currently enabled in wireless settings IS_ENABLED=$(uci get wireless.$INTERFACE.disabled 2>/dev/null) # Check if the network interface layer is actually bound and running trafficINTF_UP=$(ubus call network.interface.$NET_INTF status 2>/dev/null | jsonfilter -e ‘@.up’)
if [ “$IS_ENABLED” = “0” ]; then
# ------------------------------------------------------------- # IF CONNECTED: Trust UBUS network status. NEVER scan the airwaves! # ------------------------------------------------------------- if [ "$INTF_UP" = "true" ]; then HOTSPOT_FOUND=1 else HOTSPOT_FOUND=0 fielse
# ------------------------------------------------------------- # IF DISCONNECTED: Safe to scan because the client layer is disabled! # ------------------------------------------------------------- if iwinfo phy0-ap0 scan 2>/dev/null | grep -q "ESSID: .$TARGET_SSID."; then HOTSPOT_FOUND=1 else HOTSPOT_FOUND=0 fifi
# ------------------------------------------------------------- # STATE ENGINE EXECUTION # -------------------------------------------------------------if [ “$HOTSPOT_FOUND” -eq 1 ]; then
missed_checks=0 if [ "$IS_ENABLED" = "1" ] || [ -z "$IS_ENABLED" ]; then if [ "$logging" = "1" ]; then logger -t hotspot_monitor "Hotspot $TARGET_SSID Found! Binding network to $NET_INTF and enabling client interface $INTERFACE." fi uci set wireless.$INTERFACE.disabled='0' uci set wireless.$INTERFACE.network="$NET_INTF" uci commit wireless wifi reload $RADIO current_sleep=$minimum_sleep sleep 25 else if [ "$logging" = "1" ]; then logger -t hotspot_monitor "Hotspot stable. Scaling sleep timer. Sleeping for $current_sleep seconds." fi sleep "$current_sleep" current_sleep=$((current_sleep + 1)) if [ "$current_sleep" -gt "$maximum_sleep" ]; then current_sleep=$maximum_sleep fi fielse
missed_checks=$((missed_checks + 1)) if [ "$missed_checks" -gt 1000000 ]; then missed_checks=1000000 fi if [ "$missed_checks" -ge 2 ]; then if [ "$IS_ENABLED" = "0" ]; then if [ "$logging" = "1" ]; then logger -t hotspot_monitor "Hotspot dropped! Missed checks: $missed_checks. Disabling interface $INTERFACE to keep radio0 stable." fi uci set wireless.$INTERFACE.disabled='1' uci commit wireless wifi reload $RADIO current_sleep=$minimum_sleep sleep 20 else if [ "$logging" = "1" ]; then logger -t hotspot_monitor "Hotspot absent. Radio0 operational. Scaling sleep timer. Sleeping for $current_sleep seconds." fi sleep "$current_sleep" current_sleep=$((current_sleep + 1)) if [ "$current_sleep" -gt "$maximum_sleep" ]; then current_sleep=$maximum_sleep fi fi else sleep 20 fifi
done &
Then to start the script, either reboot the router, or issue the command:
sh /etc/rc.local
in Services >> Terminal.
Note that I’m using metrics… the cellphone hotspot has a metric of 100, whereas the main ISP has a metric of 1. So if both the main ISP and the cellphone hotspot are connected, data preferentially flows to/from the main ISP.