Raspberry Pi 3 VPN: overseas multimedia streaming

Get a pi if you don't have one; I use CanaKit cause it comes with everything you need.

CanaKit


Flash Raspian to your SD Card, or use NOOBs to install and boot.


Login and become root; The default username is pi and password is raspberry

pi@pi:~$ sudo -i

Create a user to use, add the admin user to all the groups pi was in, most important is sudo

root@pi:~# useradd jimBob -G adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi,pi
root@pi:~# passwd jimBob

Delete the pi user so you don't get jacked

root@pi:~# userdel pi

Create an SSH Key Pair for your new user. This is easy to find on Google, make sure it works before doing the next step so you don't lock yourself out...


Configure SSH to allow accept PKI Auth to stop brute force SSH attacks.

root@pi:~# vi /etc/ssh/sshd_config
Set: PasswordAuthentication no
Set: PermitRootLogin no
:wq
root@pi:~# systemctl restart ssh

Set Static IP for eth0

root@pi:~# vi /etc/dhcpcd.conf
Add something like: 
interface eth0

static ip_address=192.168.1.254/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.10 192.168.1.1

I host my own DNS server on a different machine (1.10) and use my router as a backup cause resolution is faster

vi /etc/network/interfaces
Change to: iface eth0 inet manual

Update the system

root@pi:~# apt-get update
root@pi:~# apt-get dist-upgrade -y

Set the time and sync with NTP

root@pi:~# dpkg-reconfigure tzdata *navigate menu and choose correct timezone
root@pi:~# apt-get install ntpdate
root@pi:~# systemctl stop ntp
root@pi:~# ntpdate tick.usno.navy.mil
10 Aug 19:47:27 ntpdate[1831]: adjust time server 192.5.41.40 offset -0.001897 sec

root@pi:~# vi /etc/ntp.conf

#server 0.debian.pool.ntp.org iburst
#server 1.debian.pool.ntp.org iburst
#server 2.debian.pool.ntp.org iburst
#server 3.debian.pool.ntp.org iburst
server tick.usno.navy.mil
server tock.usno.navy.mil

root@pi:~# systemctl start ntp

Test with ntpq and pe

ntpq> pe
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*192.5.41.40     .PTP.            1 u   47   64  377  228.531    7.505  17.251
+192.5.41.41     .PTP.            1 u   50   64  377  240.868   17.914   7.601

Disable the GUI if you don't want that overhead; newer versions of Linux use systemd, not SYS-V init scripts anymore.

ln -sf /lib/systemd/system/multi-user.target
/etc/systemd/system/default.target

root@pi:~# ls -l /etc/systemd/system/default.target 
lrwxrwxrwx 1 root root 37 Aug 10 10:12 /etc/systemd/system/default.target ->
/lib/systemd/system/multi-user.target

root@pi:~# reboot

Install these two packages if not installed already

root@pi:~# dpkg --list | grep iptables
ii  iptables                              1.4.21-2
armhf        administration tools for packet filtering and NAT
ii  iptables-persistent                   1.0.3+deb8u1
all          boot-time loader for netfilter rules, iptables plugin

root@pi:~# apt-get install iptables
root@pi:~# apt-get install iptables-persistent

This will create a service called netfilter-persistent

root@pi:~# systemctl list-unit-files | grep netfilter
netfilter-persistent.service           enabled 

Enable the service if it's not already enabled.

root@pi:~# systemctl enable netfilter-persistent
Synchronizing state for netfilter-persistent.service with sysvinit using
update-rc.d...
Executing /usr/sbin/update-rc.d netfilter-persistent defaults
Executing /usr/sbin/update-rc.d netfilter-persistent enable

Start IPTables

root@pi:~# systemctl start netfilter-persistent

Tell Linux to be a router then make it permanent

root@pi:~# sysctl net.ipv4.ip_forward=1
root@pi:~# vi /etc/sysctl.conf and either uncomment or add:
    net.ipv4.ip_forward=1

Create firewall and NAT rules: I assume you are using the RFC1918 network 192.168.1.0/24 at home

I add in a rule to permit NTP to tick/tock.usno.navy.mil so you can keep accurate time and one to permit in SSH for management

root@pi:~# vi /etc/iptables/rules.v4

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o tun0 -s 192.168.1.0/24 -d 0/0 -j MASQUERADE
COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i eth0 -p udp -m udp -s 192.5.41.40 --dport 123 -j ACCEPT
-A INPUT -i eth0 -p udp -m udp -s 192.5.41.41 --dport 123 -j ACCEPT
-A INPUT -i eth0 -p icmp -j ACCEPT
-A INPUT -i tun0 -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth0 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j LOG --log-prefix "Default Input Drop: "
-A INPUT -j DROP
-A FORWARD -d 192.168.1.0/24 -o eth0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -s 192.168.1.0/24 -d 0/0 -j ACCEPT
-A FORWARD -j LOG --log-prefix "Default Forward Drop: "
-A FORWARD -j DROP
COMMIT

Figure out what kind of VPN provider you want to use; I chose ExpressVPN which uses openVPN which is open source

ExpressVPN provides a pre-built config for openVPN, and my iptables config assumes openVPN; tun0

You don't actually need a VPN provider; it's pretty simple to just setup a machine with a US IP and install openVPN

Don't use AWS or Azure as Netflix / Hulu / HBO / Showtime are smart enough to filter those CIDRs via a BGP prefix list

root@pi:~# apt-get install openvpn

Setup the config file in /etc/openvpn/client.conf

vi /etc/openvpn/client.conf

Add the config they gave you


I set my credentials in a seperate file, and make sure to change the permissions to non-world readable.

root@pi:~# vi /etc/openvpn/client.conf

Add

auth-user-pass /etc/openvpn/expressVPN
root@pi:/etc/openvpn# vi expressVPN

Add your credentials provided by your provider

root@pi:/etc/openvpn# chmod 640 expressVPN

root@pi:~# systemctl enable openvpn
Synchronizing state for openvpn.service with sysvinit using update-rc.d...
Executing /usr/sbin/update-rc.d openvpn defaults
insserv: warning: current start runlevel(s) (empty) of script `openvpn' overrides LSB defaults (2 3 4 5).
insserv: warning: current stop runlevel(s) (0 1 2 3 4 5 6) of script `openvpn' overrides LSB defaults (0 1 6).
Executing /usr/sbin/update-rc.d openvpn enable
root@pi:~# systemctl start openvpn@client
root@pi:~# 

root@pi:~# ps -ef | grep vpn
root      1089     1  1 20:35 ?        00:00:00 /usr/sbin/openvpn --daemon ovpn-client --status /run/openvpn/client.status 10 --cd /etc/openvpn --config /etc/openvpn/client.conf
root      1105  1022  0 20:36 pts/0    00:00:00 grep vpn
root@pi:~# 

Check if the VPN interface is up

root@pi:~# ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.122.13.206  P-t-P:10.122.13.205  Mask:255.255.255.255
          inet6 addr: fe80::f26c:2c3d:8bab:8871/64 Scope:Link
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:9 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:684 (684.0 B)  TX bytes:1020 (1020.0 B)

Install DNSMasq to make your pi funnel DNS queries to your VPN providers stateside DNS servers; to stop them from blocking you via Anycast tricks.

That way if you want to change back and forth, you don't have to change gateway and DNS settings on your media device.

root@pi:~# apt-get install dnsmasq
root@pi:~# vi /etc/dnsmasq.conf
Uncomment: no-resolv
Add: server=ip.ofyour.us.dns1
Add: server=ip.ofyour.us.dns2
Add: interface=eth0
:wq

root@pi:~# vi /etc/default/dnsmasq
Add: DNSMASQ_EXCEPT=lo
:wq

root@pi:~# reboot

Make sure this dnsmasq config works; If dnsmasq uses the two IP addresses of your providers US based DNS servers, and you can't reach those servers without the tunnel, openvVPN won't be able to resolve the VPN endpoint, and tun0 won't come up. Chicken and egg. After reboot, run ifconfig and make sure tun0 is up.

I've noticed that adding this to the dnsmasq.service file helps.

root@pi:~# vi /lib/systemd/system/dnsmasq.service

Add

After=network.target openvpn@.service

You can also just use something like:

8.8.8.8
8.8.4.4

Configure you media device to use the pi as the default gateway and the DNS.

Package Management Confusion

yum --whatprovides /path/to/file

on Debian based distro

dpkg -S /path/to/file

Reinstall config files on Debian

cd /tmp
mkdir deb
cd deb
apt-get update
apt-get download package
dpkg -i --force-confmiss *.deb

This should be possible with apt, but out of the 3-4 examples I tried from Google, none actually reinstalled the config file.