I have a cable broadband connection at home – Virgin Media. It’s actually reliable, which is refreshing compared to the poor experience had with the same provider as a student living in Leicester.
It’s a problem when it is down as I work from home a lot and the rest of the family need it too.
Previously, I had used Internet Connection Sharing to provide internet via my macbook via the WAN port of my router. This worked, but it was fiddly and temperamental. The macbook provided the WAN interface with a DHCP address, so as far as my router was concerned it had a regular internet connection, albeit with an extra NAT layer.
I didn’t want to pay for a separate LTE dongle for a backup connection, which is possible with my provider. It also seems redundant as our iPhones have LTE.
What if it was as simple as connecting my iPhone to the router? The router would then:
Normally WAN failover is automated. As I don’t want my iPhone permanently connected, it makes sense for this to be semi-automatic as above.
My router/gateway is a supermicro server running NixOS, with nftables and dnsmasq. It’s what I’ve settled on after trying all sorts of platforms – I’ll blog about it soon.
The scripts here can be applied to any linux-based gateway so long as you have the right access and repositories available.
What’s relevant about my setup is I rename all my interfaces (and virtual interfaces for VLANs) using udev rules. This allows a predictable and meaningful name, (rather than en0s0fds0f7s0ad80s98ad0f
or whatever udev does nowadays….). It also makes the nftables firewall rules much easier to comprehend.
After some experimentation, I created a simple systemd service:
|
|
What is does is use lsusb
to poll for the iPhone. Once it sees the iPhone, it uses idevicepair
from libimobiledevice to attempt to pair. The first attempt will result in a prompt:
Once the user has “trusted” the gateway and entered the code, the pairing will succeed. This will create a new default route; the route will have a “metric” that’s too high – the traffic will still attempt to go over the default WAN at this point.
A new route is added manually, therefore – using the renamed device, wanfailover
which is the virtual ethernet adapter that the iPhone creates.
After this, the service waits for the iPhone to disconnect. As this removes the ethernet device, the associated route is removed by the kernel automatically. This is a useful side-effect of using a device name in the route – I think!
The service is configured with Restart=always
on a 10 second timer; this allows systemd to effectively be the outer loop here which simplifies the code and allows for some automatic error recovery.
You may have noticed a “HACK” – unfortunately the usbmuxd
service provided by libimobiledevice
seems to get stuck in a state where the second pairing attempt does not work.
The route is changed almost immediately, and devices appear to have a good internet connection throughout the house, albeit slower than the >1000Mbps primary WAN.
What is a little annoying, is existing SSH sessions freeze up and eventually time out. I’d like to look into a way of forcibly resetting existing TCP steams to avoid this, though realistically it is moot as during a real WAN-down situation the switch-over requires a human to notice and won’t be instant.
Foribly resetting the stream may allow streaming services to reconnect faster.
Interestingly, my SSH sessions that were running over wireguard (using dsnet!) seamlessly persisted. This is because wireguard is naturally stateless, operating over UDP.
I used fast.com to measure throughput; a good choice in my opinion because it uses the Netflix CDN – unlike the dedicated speedtest.net ISPs can’t artificially prioritise traffic without also prioritising Netflix traffic so it’s a better indicator.
I tested in the server cupboard, and also via a 5M USB extension cable in the loft; this provided more speed but something didn’t seem quite right still – check out the uplink speed – it may have increased due to height but I think it was impacted, at least in the first instance by my CCTV cameras.
I run a remote frigate instance for 4 cameras. That means around an 8 Mbps uplink load at any given time – enough to overwhelm the iPhone’s 4G LTE connection.
So, I added a few commands to disable the CCTV VLAN on WAN failover:
|
|
This probably worked:
This wasn’t in the loft, even. The downstream speed also increased – I wonder if I prevented some ACK starvation which would explain it; though this could just be network variance.
Semi-automatic iPhone based internet failover is a convenient an alternative for paying for a separate backup ADSL2 or LTE connection.
Thanks for reading! If you have comments or like this article, please post or upvote it on Hacker news, Twitter, Hackaday, Lobste.rs, Reddit and/or LinkedIn.
Please email me with any corrections or feedback.