Tuesday, 23 August 2016

Internet away from home

Nowadays on holidays we bring with us about 6 WiFi capable devices just for our little family. Make it a more extended group and we pass the 10 device mark easily. All these pieces of kit expect, or at least work better with, a connection to the internet. Fortunately, WiFi internet is available at most holiday parks, hotels and campsites in 2016. However, typically you get a password that allows a single device (or a few more) for a certain amount of Euros. Sharing this directly across this many devices is quite a hassle.

A few years ago, I bought a couple of TP-Link WR703N travelling routers on eBay. These come with a 2.4 GHz WiFi radio, an 10/100mbit Ethernet port and an USB2 port. Originally, I intended to repurpose them as network enabled things, but I could use them as travel router as well! For this, I put the latest and greatest Openwrt firmware on one, naturally with a few modifications. I also added an external pigtail antenna in place of the original internal one, as described here

The essentials of the external antenna hack. I later redid the soldering much neater than is shown here😉.

The Openwrt modifications are basically a default /etc/passwd file, an /etc/config/wireless file and a change of the failsafe control flow so that failsafe automatically triggers a firmware reset. In this way, when I press the little reset button, it restores the router to a state where I can connect to a known WiFi network and login with a known password. Normally the reset button in Openwrt triggers a default failsafe mode that only allows a login over Ethernet, but that is not really helping when I only have my phone with me.

As said, this router comes with a single radio, but it can do a combined access point and client mode. In this way, the router connects to the internet via WiFi client mode, and all WiFi devices connect to the router access point as clients. The router then uses NAT to forward the clients over WiFi to the internet.

Unfortunately, there is a problem with this scenario when the router tries to connect as a client but fails. For example because the WiFi network disappeared altogether, or is 300km away (not unlikely given the usage scenario for this device), or because of a simple typo. If this happens, then somewhere in the combined WiFi driver, kernel network layer, and Openwrt WiFi-controlling daemon stack things get stuck such that the access point interface of the WiFi radio never goes up. This is clearly a bug, because a simple ifconfig down wlanX ; ifconfig up wlanX for the access point part of the interface fixes things.
While I definitely would like to get to the bottom of this someday, for now I put the following script in crontab as a bandaid:
for W in $(ubus  call network.wireless status | jsonfilter -e '@.*.interfaces[@.config.mode="ap"].ifname'); do
  if [ x$(ubus call network.device status | jsonfilter -e "@['$W'].up") = "xtrue" ] && ! iw $W info | grep -q ssid ; then
    ifconfig $W down
    logger -p daemon.info -t $0 poked $W
    ifconfig $W up
exit 0
This script finds all wireless interfaces in access point ("ap") mode, filters the ones that are up according to Openwrt but not according to the kernel (no ssid), and gives them a gentle nudge. By running this script every 5 minutes the access point WiFi is restored in this case without the need to press the reset button.

The project was finished by adding a sticker with a QR code for the access point network, and a RFID tag with the same. In that way people can simply tap their phone on the router, or scan the QR to connect. And yes, I also added the WiFi name and password in human-readible format, as a less impressive option.

So far the router is doing well, but I found that some WiFi networks intentionally or by accident drop the connection after some time, even if I try to keep it going with a wget job in crontab. In these cases it helps a bit to have a second radio because that makes the access point less sensitive to trouble on the internet side. The exact reason for this dropping the connection is unfortunately too hard to diagnose with only my phone to make connections (holidays, remember).
Router in action. Here I use an additional USB wifi stick to try to fix/diagnose a problem with the local internet access.

No comments: