How to Automate Captive Portal Login on Ubuntu Linux 17.04

A while ago, I wrote a post on automating captive portal login on Windows. While that script once worked for me (though I've since reinstalled windows and not set it up again), and the page is relatively popular on this site, I haven't heard a single person tell me it worked for them. There might have been something special about the version of OpenSSL I used, or some other kink in the system messing things up for others. In any case, I'm using Ubuntu mostly now, so I needed a working solution for that.

Prerequisites

  • Ubuntu, or some flavor of linux which is close enough.

  • sudo access, to install lynx and change configuration files.

  • sudo apt-get install lynx

Lynx is a text based browser. A text based browser can be more easily automated than a graphical browser, and the automation will also be more reliable.

That's it - let's get started!

Creating the Login Script

Lynx has a command-line argument to simulate keystrokes from a file. We can make this file in a few easy steps. First, open lynx with a log output file:
sudo lynx -cmd_log="/etc/network/if-up.d/cpauth-wifi", where wifi is something reminiscent of your access point name (in case you use this more than once, you'll be able to differentiate).

Next, log into the captive portal. Use as few keystrokes as possible, as each will be saved, and if you're less efficient, your login script will be less efficient. Feel free to cancel and start over if you make a mistake. As soon as you're successfully logged in, press q to quit and y to confirm. Now, we just need to clean that up a little and it will be ready.

sudo nano /etc/network/if-up.d/cpauth-wifi

logfile created by lynx
Example output from lynx log

Get rid of the comments at the top with ctrl+k for each. Next, make sure you recognize the first line as the first key you pressed. If not, delete until the first line is the first key you pressed. Similarly, go down to the end of the file and make sure it ends with key q and key y to exit the program when it's done (otherwise you'll hang the network startup scripts till it times out. Delete any lines after that which you don't recognize. Finally, save it and exit nano with ctrl+x followed by y and enter to confirm the save.

At this point, you should test the script - wait till your captive portal times out, or take the laptop to another access point's zone if the network is big enough for that. Then run sudo lynx -cmd_script="/etc/network/if-up.d/cpauth-wifi" and confirm that you're connected to the rest of the internet after it's run.

If that worked, congratulations! The script works, we just need another script to trigger it when the network connects to a new access point.

Before we do that, it's important to note that this file, depending on the exact captive portal you're dealing with, may contain a personal password, and in plain text. To secure it, run sudo chmod 400 /etc/network/if-up.d/cpauth-wifi. This will ensure the file is only accessible to be read by root (the owner, since you created the file with sudo earlier) and by nobody else. If you have other sudoers on your laptop, this won't be secure from them, though - just something to keep in mind.

Network Connection Script

Ubuntu automatically calls scripts placed in the /etc/network/if-up.d/ directory when you connect to a network, so that's a good place for our script. Open a new file in nano:
sudo nano /etc/network/if-up.d/cp-wifi (same thing you used instead of wifi earlier would be appropriate now, just make sure it starts with cp-)

Here's the template code for this file:

#!/bin/bash

# Set the name of an SSID with a captive portal:
SSID="examplewifi"

# Don't run on the loopback device
[ "$IFACE" != "lo" ] || exit 0

# Don't run on ethernet
# Check your ethernet interface name(s) - Run `iwconfig` and find options other than "lo" with "no wireless connections." listed. Copy this line for each if there are more than one, replacing "eth0" as appropriate.
# This following line is an attempt at a generic alternative for the next. If your wifi isn't on eth0, switch it as appropriate on line 13.
# [ ${#`iwconfig $IFACE | grep $IFACE | grep "no wireless extensions."`} = 0 ] || exit 0
[ "$IFACE" != "eth0" ] || exit 0

# Only run on matching SSID
ESSID=$(iwconfig $IFACE | grep ESSID | cut -d":" -f2 | sed 's/^[^"]*"\|"[^"]*$//g')
[ "$ESSID" = "$SSID" ] || { echo "Not running script. SSID: $ESSID Expected: $SSID" && exit 0; }

# Only run if can't connect to the internet:
[[ $(curl 
https://peromsik.com/scripts/nettest/connection.php) != "ok" ]] || { echo "Not running script; already logged in to $SSID wifi." && exit 0; }

echo "Running login script for \$SSID=$SSID"

# Run your script that logs into the captive portal here. I've done it with lynx:
exec lynx -cmd_script="/etc/network/if-up.d/cp-wifi" -cmd_log="/var/log/lynx.log"

All you have to do is rename the SSID on line 4, and make sure the cmd_script at the bottom is in the right place. The main line is the last which actually calls your script. The rest are just precautions to prevent from typing your password into a browser unless there actually is a captive portal - and the correct one, at that.

Save this file, then exit nano and give the file execution permission:

sudo chmod +x /etc/network/if-up.d/cp-wifi

Congratulations! If you've followed through thus far, your laptop can automatically log in to the wifi when you connect to it. However, if your computer idles for a while and then you wake it up, it might still be connected, but the wifi portal will be active again and you'll have to do it manually. Let's trigger this script when the computer wakes as well to avoid this problem.

Unsuspend and Wakeup Script

Scripts placed in /etc/pm/sleep.d are called whenever the computer is either put to sleep or woken up. We want to run our cp-wifi scripts whenever we wake the computer, just in case we heaven forbid encounter the captive portal again. After all, who wants to be captive?

sudo nano /etc/pm/sleep.d/20_captive-portal-auths

And paste in the following code:

case "${1}" in
resume|thaw)
find /etc/network/if-up.d/ -maxdepth 1 -type f -name 'cp-*' | sort | bash
;;
esac

This script will be called whenever the system is woken, and it will run your network if-up scripts which start with cp-.

Save it and again add execution permission:

sudo chmod +x /etc/pm/sleep.d/20_captive-portal-auths

And - Congratulations! You're down one captive portal, and you shouldn't have to see it again unless your password changes or you boot windows (although you can try to deal with that as well here). And if you ever encounter another captive portal, you'll know how to make it go away for good. Freedom!