Setting up a Raspberry Pi 3 as a VPN Gateway.
I've got myself a Raspberry Pi 3 and want to use it as my home router and VPN gateway. At some point, I'll probably accidentally step on it or pour a flat white on it and then wonder how I set it up to do what it's supposed to do.
To avoid this, here are some notes and scripts to make it less painful when that happens. Don't confuse this with a tutorial. I'm writing this first and foremost for myself. However, if you have any suggestions, feel free to send PRs my way.
Goal
Have a WiFi access point that I can connect my phone and ChromeCast to and transparently get routed through an OpenVPN.
To set up the other side of this, I can whole-heartedly recommend the docker-openvpn suite which makes the server-side setup a breeze.
Status
It's working!
You get a WiFi hotspot that tunnels all requests through
tun0
which is backed by an OpenVPN connection. I'm not sure if this is stable enough for use and there's no good way from the outside to enable/disable VPNs.Preparing the SD Card
- Get Raspbian Jessie Lite. I used
2016-03-18
for this. Also, don't be a jerk, and use the Torrent option. - I use Lite because I don't even want to connect a monitor to the Pi and updating Xorg takes ages.
- Copy it onto an SD card. I'll leave it to you to figure out which device you're writing to, but keep in mind that this image is intended to partition the entire card, so don't specify a partition (i.e.
sdb
notsdb1
):dd bs=4M if=2016-03-18-raspbian-jessie.img of=/dev/sdb
- Follow this guide to get SSH enabled on first boot. TL;DR:
touch /media/$USER/boot/ssh
Initial setup
- Plug the Pi in and connect it to a DHCP-enabled router via ethernet.
- My old DD-WRT had the
.lan
domain, so I could directly connect toraspberrypi.lan
. Obviously, take care of conflicts if you have more than one.nmap
is your friend. ssh pi@raspberrypi.lan
, password israspberry
.- This could potentially be part of the ansible script, but I prefer pushing the SSH key over manually to minimize the chance of locking myself out.
ssh pi@raspberrypi.lan "mkdir -p ~/.ssh/"; scp ~/.ssh/id_rsa.pub pi@raspberrypi.lan:/home/pi/.ssh/authorized_keys
- Dont forget this one: Resize your partition or you're gonna have a bad time. Raspbian only leaves you with a few hundred megabytes left, so run
sudo raspi-config
and select option 1: "Expand Filesystem".
Ansible
Copy
playbook.yml.example
to playbook.yml
and make the necessary adjustments, notably add your premiumize.me credentials to it. Afterwards, you can run it like:ansible-playbook -i hosts playbook.yml
This assumes that the hostname in
hosts
can be resolved and you can log in password-less via the pi
user. It also expects the Pi to already have a working internet connection.Using the WiFi
Everything should automatically start up, but Linux boxes are painfully stateful so if the VPN or something else didn't come up, just reboot that thing.
Afterwards, you should be able to connect to the device via WiFi. The defaults are SSID "passy-pi" and password "raspberrypi". Afterwards, your connected device should be transparently routed through the VPN. Sorry, Netflix.
I now have a second ChromeCast that only connects to this AP and hence thinks it's in whatever country I tell it to. Neat.
Testing the Router manually
In case something is wrong with the WiFi and you just want to verify if the routing works, you can add a route manually.
On your target device, assuming it's IPv4:
# Figure out your current default route:
$ route -n | grep 0.0.0.0
# Delete the default GW
$ route del default gw
# Add the new route to the Pi
$ route add default gw
Updating parts of the config
Something I only found out about when working on this that I should have really known before is that you can selectively run ansible tasks by specifying tags.
If you, for instance, change your VPN settings but don't want to also run an
apt-get upgrade
you can use the openvpn
tag like so:ansible-playbook -i hosts playbook.yml --tags openvpn
Multiple tags can be comma-separated.
DNS Rerouting
Certain movie streaming services has gotten a lot more aggressive lately and not only block the usual suspects, but entire fucking IP ranges (both IPv4 and IPv6) for hosting providers like DigitalOcean, AWS and Linode. I wish they had done this a couple of weeks earlier so I could have avoided all the previous work.
But anyway, one so far unaddressed attack vector is using a custom DNS. This even comes with a bunch of benefits like better performance and no traffic limits. And all it takes is a couple of
iptables
rules to rewrite all DNS requests to those custom servers.
In order to prepare your Pi for the service, you need to change your
playbook.yml
ever so slightly. You can either leave the openvpn
part out entirely if you've never provisioned your device before or (damn you statefulness) make sure to set openvpn.autostart
to none
to avoid unnecessarily spinning up instances. Be aware that an empty string here means running daemons for all *.conf
files in /etc/openvpn/
.
Check out
playbook.yml.dnsexample
for an example. The interesting bits here are firewall.mode: "dns"
rather than "tunnel"
which is the default and the force_dns: "185.51.194.194"
which overrides all incoming DNS requests (or anything really talking to port 53) to the given IP address.
Afterwards, just replay the playbook and reboot the device.
If you've updated just the DNS redirect and want to skip the other tasks, the tag you want to use is
firewall
, i.e.ansible-playbook -i hosts playbook.yml --tags firewall
from
https://github.com/passy/raspbian-vpn-router
No comments:
Post a Comment