PogoPlug Wi-Fi VPN Access Point with ArchLinux

This project was a few weeks in the making. When I started there was a problem with some of the software not behaving. I leave the hardware driver voodoo to those that understand it. After an update this morning I was able to get all the parts working. So what exactly is a WiFi VPN access point?

It’s the combination of several pieces of hardware and software that when running on my Pogo provides me with:

  • A WiFi access point with WPA security.
  • A private wireless network.
  • VPN security for all wifi connections.

The end result is the Pogo acting as an Wi-Fi hotspot that any computer, tablet or phone can connect to. The wireless connection is tunneled through the ethernet connection using a VPN tunnel. The result is that any Wi-Fi connection to the Pogo automatically uses the VPN with no client configuration needed.

What follows are things I discovered from many sources. None of them were exactly what I needed for this project. Getting it all working together was a lot of work. Mostly because of the driver conflicts that came from using the Edimax EW-7811Un adapter.

Right now, this guide covers a situation that I haven’t seen anywhere else.

Needed Hardware

If you’ve been looked at my other Pogo guides, you should have almost everything. The Pogo needs to be connected to your cable/DSL modem with an ethernet cable and have internet access. This guide is built around the Edimax EW-7811Un USB Adapter. It is a low-priced and small adapter with driver support in Linux. I purchased mine for $8.99 in early March.

The problem is with the drivers for the 7811Un in the Linux kernel. They are buggy and don’t let the 7811Un work as a hotspot. The 7811Un will only work in client mode. This means the Pogo can connect to another hotspot normally. But without custom drivers, it won’t work as its own hotspot.

This was the reason for holding up this guide. The custom kernel driver for the 7811Un chip wouldn’t compile. The package was updated on March 11 and now works.

Needed Software

Quite a few software packages are needed. It’s all available within the ArchLinux build system.

The build system needs to be installed because we’re going to compile two packages. First, update your existing system.

$ sudo pacman -Syu

Then install the compiler tools and kernel headers. Using the headers from the regular kernel won’t work. It has to be the ones for the Kirkwood ARM platform. (Hint: the –needed flag will skip packages already installed.)

$ sudo pacman -S --needed base-devel linux-kirkwood-headers

OpenVPN & DNSMasq

Install these two packages, as they are the cornerstone of our project.

$ sudo pacman -S openvpn dnsmasq

If you plan on using TunnelBear as your VPN provider, read my guide. They package their drivers in a non-standard way. I’ve sorted it out and created a system service and helper program to make life easier.

Follow the directions in the README.md file, and make sure it works. If you’re using another VPN provider, get it working using their configuration files.

Network Driver

This is probably the most time-consuming part. This driver has to be built against the current installed kernel. The compiling takes time. With a slow computer like the Pogo, you might want to go get a sandwich.

The package is in the alarm repository. A standard ArchLinux ARM installation already has this configured. Start the installation and then read about why this step is needed.

$ sudo pacman -S dkms-8192cu

The original driver package was released by RealTek as GPL software. This is actually more than most companies do. It was eventually included in the mainline Linux kernel driver package. It was also a buggy turd of code. Lots of smart people have worked on it over the last couple of years. Now it’s in much better shape. But the fixes haven’t made it into the kernel yet. This is why we have to compile our own driver.

Wi-Fi Hotspot

The standard install of hostapd doesn’t work with the updated driver we just built. Luckily there’s an AUR package that applies the needed patches. Download the tarball, unpack it, and navigate into the new directory.

$ curl -O https://aur.archlinux.org/packages/ho/hostapd-rtl871xdrv/hostapd-rtl871xdrv.tar.gz
$ tar xf hostapd-rtl871xdrv.tar.gz 
$ cd hostapd-rtl871xdrv/ 

Edit the build file. The version as of March 15 is missing a conflict check. If your system happens to have hostapd already installed this will prevent an error.

$ nano PKGBUILD 

Add the following after the license line so it looks like this:

license=('custom')
provides=('hostapd')
conflicts=('hostapd')
makedepends=('git')

Finally make the package.

$ makepkg

Once it’s done (you might want to get another sandwich) it can be installed as a normal package. The -U flag is to tell pacman to use the file we just built, and not the one from its repositories.

$ sudo pacman -U hostapd-rtl871xdrv-2.2-2-arm.pkg.tar.xz 

We’ll deal with the configuration files once all the software is up and running.

IPTables

The default Linux packet filter will be enough for our needs. We only need to add three rules. First add some security for packets that might try and find their way into the VPN.

$ sudo iptables -A INPUT -i tun0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
$ sudo iptables -A INPUT -i tun0 -j DROP

This rule will connect the Wi-Fi network to the VPN.

$ sudo -t nat iptables -A POSTROUTING -o tun0 -j MASQUERADE

(Update 2015-04-21: add -t nat)

Right now, these rules are temporary and will be lost on a reboot. To have them active, they need to be reloaded. This is done by exporting these rules then having the iptables service load them at boot.

Export the rules. The sudo tee command writes the stdin as root, otherwise the redirect would fail for lack of permission.

$ sudo iptables-save | sudo tee /etc/iptables/iptables.rules

Have systemd launch iptables and load the saved rules at startup.

$ sudo systemctl enable iptables.service

If you’ve used iptables before you noticed that our NAT is being done of the tun0 interface. This way if the VPN is down no traffic will get out to the internet. OpenVPN creates the tun0 interface when it’s active. If it’s active, traffic can flow.

This is on purpose. Without the VPN, the Pogo would just be regular router. It’s also slower than my dedicated hardware cable modem/router/AP all-in-one. I don’t want to use it as a dedicated router. It’s only job is to funnel Wi-Fi to the VPN.

One bonus is the built-in self-diagnostic. If the Internet is unreachable, the VPN must be down. This way I won’t be fooled into thinking my traffic is over the VPN when it isn’t.

IP Forwarding

None of this will work if the kernel doesn’t know about it. We have to enable port forwarding. This can be done by setting the ip_forward flag to true.

$ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

But it will reset to 0 on reboot. We can fix that with a sysctl command.

$ echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ip-forward.conf

The 99 at the beginning of the file ensures that it will be loaded last, after the /proc tree is ready.

Reboot check

This is a good time to check that everything we’ve done so far is working. Go ahead and reboot.

$ sudo systemctl reboot

Once you’ve ssh’d back in, check a few things.

$ cat /proc/sys/net/ipv4/ip_forward

Should output 1.

$ sudo iptables-save

Should output the settings we saved earlier. Mine looks like this:

# Generated by iptables-save v1.4.21 on Sun Mar 15 20:37:43 2015
*filter
:INPUT ACCEPT [2304:285431]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1199:181244]
-A INPUT -i tun0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i tun0 -j DROP
COMMIT
# Completed on Sun Mar 15 20:37:43 2015
# Generated by iptables-save v1.4.21 on Sun Mar 15 20:37:43 2015
*nat
:PREROUTING ACCEPT [178:31347]
:INPUT ACCEPT [176:30691]
:OUTPUT ACCEPT [21:2489]
:POSTROUTING ACCEPT [21:2489]
-A POSTROUTING -o tun0 -j MASQUERADE
COMMIT
# Completed on Sun Mar 15 20:37:43 2015

Now, plug in the 7811Un Wi-Fi adapter. Check that it was recognized as a valid interface. It will be the one with the awkward name. It’s named enp0s1u2 on my system.

$ ifconfig -a -s
Iface      MTU    ...
enp0s1u2  1500    ...
eth0      1500    ...
lo       65536    ...

If you have a name starting with wl there’s a chance the new driver isn’t loaded.

After all this, we should have all the software ready to configure. Also, the hardware is installed and recognized.

Configuration

There’s several steps involved and they touch quite a few files, I’ll break this into sections to keep it organized.

Network Interfaces

First, we need to make sure our DNS is correct. If you followed the directions for the TunnelBear setup, the eth0.network file should be good to go. This will make sure we’re using the OpenDNS servers all of the time. It will also automatically update /etc/resolv.conf.

If not, edit /etc/systemd/network/eth0.network to look like this:

[Match]
Name=eth0

[Network]
DHCP=both
DNS=208.67.222.222
DNS=208.67.220.220

[DHCP]
UseDNS=false

We need to create a new file for our new interface. This does two things, it is assigned the network address 10.0.0.1 and then it is activated.

Create the file /etc/systemd/network/enp0s1u2.network and add the following contents.

[Match]
Name=enp0s1u2

[Network]
Address=10.0.0.1/24

Once these files are saved, restart the network.

$ sudo systemctl restart systemd-networkd

Check that all the interfaces are now up. (Notice we’re not using the -a flag this time.)

$ ifconfig

You should see the same results as before, lo, eth0, and enp0s1u2. Also, enp0s1u2 should have the inet 10.0.0.1 address.

DNSMasq configuration

This one is easy, our DHCP and DNS server will come from the same program. DNSMasq has sane defaults and doesn’t require much configuration. The file /etc/dnsmasq.conf should contain the following:

dhcp-authoritative
interface=enp0s1u2
dhcp-range=enp0s1u2,10.0.0.5,10.0.0.100,255.255.255.0,6h
dhcp-option=3,10.0.0.1

There are other options shown by other how-to articles, but this way doesn’t repeat settings. Mainly it’s using /etc/resolv.conf for the DNS servers. In our case that’s okay. We set up our name servers in the eth0.network file. If we want to change them in the future, it’s only one file that needs changing.

HostAPd configuration

Create the file /etc/hostapd/hostapd.conf with the following contents. If you have a preference, change the ssid and wpa_passphrase to your liking. This will create a functioning 802.11n access point with WPA security. The most important change from a normal config is the use of the rtl871xdrv driver instead of nl80211.

# Wireless Interface
# ==================
interface=enp0s1u2
#driver=nl80211
driver=rtl871xdrv

# Wireless Environment
# ==================
ssid=AP_Pogo
channel=3
country_code=US
hw_mode=g

# Wireless N settings
# ==================
wme_enabled=1
ieee80211n=1

# WPA Settings
# ==================
wpa=2
auth_algs=1
wpa_passphrase=testpogo
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Wireless Check

Finally! It’s time to test our new toys. Start up the hotspot, DNS server, and VPN.

$ sudo systemctl start dnsmasq
$ sudo systemctl start hostapd
$ sudo tunnelbear

If you’re using another VPN, start it the more traditional way.

$ sudo systemctl start openvpn@[conf]

Then from another computer or device, find the AP_Pogo access point and login with your passphrase.

If all has gone well, you should have a working connection. Check your external IP address using a site like www.whatismyip.com or freegeoip.net

Start at boot

To make everything start at boot enable the services with systemd.

$ sudo systemctl enable dnsmasq
$ sudo systemctl enable hostapd

Having the VPN running all the time is your choice. Remember it needs the config file name added to the service name.

$ sudo systemctl enable tunnelbear@UnitedStates

Conclusion

I hope this guide got everything working for you. If not, leave a comment and I’ll try and help. Comments close after 14 days. After that, you can find me on Twitter.