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.
- PogoPlug V4
- Edimax EW-7811Un Wi-Fi adapter
- Ethernet connection
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.
- ArchLinux ARM
dnsmasq
openvpn
- TunnelBear VPN service
8192cu
network driver (custom built)hostapd-rtl871xdrv
(custom built)iptables
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.