While my trip to the AWS re:Invent conference last month resulted in a giant pile of swag from the expo, by far the most interesting of it was from the communications company Twilio that gave me a SIM card for their Programmable Wireless service (as well as something else that will be the topic of at least one future post). Programmable Wireless is really cool: for $3 per SIM and $3 per month (in single unit quantity) I get a 2G/3G/4G SIM card with 20MB of monthly data. That’s not much data in the world of smartphones, but it’s more than enough for many IoT or embedded use cases. More importantly, the SIM is also tied to your Twilio account that provides customizable rate plans (data rates, quotas, and roaming configuration) and detailed bi-hourly breakdowns of upload and download transfer, as well as ReST APIs to manage everything and retrieve usage information and wonderful documentation.
Anyway, at re:Invent one of the Twilio folks was telling me about their new Programmable Wireless service and the low costs even for a single SIM, and it occurred to me that this would be the perfect solution for an out-of-band notification solution for my home automation and security system (blog posts in the “security” category). I’ve done quite a bit this year with automation and security for my house, as well as video surveillance. I’ve handled a lot of reasonable failure scenarios including power outage but, while my AT&T fiber connection has been remarkably reliable so far, loss of connectivity was the one major issue I didn’t have a working solution for. My needs in the case of a loss of connectivity are somewhat different from the normal day-to-day; it’s a rare enough condition that I’m not really concerned with getting massive collections of surveillance camera still images like usual, but just a simple alert when connectivity is lost or restored, or if the alarm is triggered when my primary Internet connection is offline. Within those constraints it seemed like Programmable Wireless would be perfect for my needs, especially at the $3 USD/month price tag for a one-off personal project.
A few weeks ago, before going out of state for a week, I purchased the Huawei E397u-53 unlocked USB 4G LTE modem on Twilio’s compatible hardware list from Amazon and started work on the project. At first I spun my wheels for quite a while trying to figure out a way to handle the insane routing that I wanted in Linux: route everything out the default gateway (my LAN, going to my router and out the AT&T Fiber uplink) when it’s working, but when the AT&T link is down, route only certain “special” traffic through the USB modem. After a bunch of thinking in circles and researching - and digging into all sorts of ugly stuff like policy-based routing - I resorted to posting a question on Twitter. Luckily a brilliant engineer who I used to work with pointed me in the right direction with Docker. After thinking through his suggestion for a comparatively short amount of time, I hit on the solution that I’m currently using.
My solution was to run a lightweight HTTP(S) proxy server (tinyproxy) inside a Docker container, with the container running in privileged mode and the PPP connection managed inside the container. Since it’s running in privileged mode, the Docker container has full access to the host devices including the USB modem. When the container starts it launches pppd which establishes the PPP link over the cellular modem, sets a new default route over the link, and then starts tinyproxy (adding some other routes to the LAN as needed). The container exposes port 8888 for tinyproxy, which allows HTTP(S) traffic to be routed over the cellular link just by using the container as a proxy. I handle the failover component at the application level, by attempting to send data over the default route a certain number of times and then falling back to the proxy if all attempts failed (example commit).
My solution to this is still very rough around the edges and shows all the unfortunate signs of being thrown together in a single rushed evening, but the jantman/twilio-ppp-proxy Docker image and corresponding GitHub repo are available for anyone who would like to use them; I hope to polish them up a bit in the near future. While my needs are somewhat specific, I hope this will be of assistance to anyone else who wants the ability to easily proxy certain traffic over a Twilio Programmable Wireless link while preserving their existing routing.
Most importantly, many many thanks to the folks at the Twilio booth at re:Invent (I really, really wish I remembered the name of the person I spoke to) for discussing their services with me and giving me the SIM card that got this project started!