In this blogpost series I'm going to go over how I created a [site to site](https://computer.howstuffworks.com/vpn4.htm) [Virtual Private Network](https://en.m.wikipedia.org/wiki/Virtual_private_network) (abbreviated as VPN) for all of my personal devices. The best way to think about what this is doing is creating a _logical_ (or imaginary) network on top of the network infrastructure that really exists. This allows me to expose private services so that only people I trust can even know how to connect to them. For extra convenience and battery saving power, I'm going to use [WireGuard](https://www.wireguard.com) as the VPN protocol.
This series is going to be broken up into multiple posts about as follows:
- Base core network setup and naming (this post)
- Setting up DNS (including reverse DNS) and custom endpoints
- Setting up a custom TLS Certificate Authority
- Setting up iOS, macOS, Android and Linux clients
- Other future fun things (seamless tor2web routing, etc)
One of the most annoying parts of this exercise is going to be naming and numbering things, so let's get that out of the way as soon as possible.
### Naming your TLD
It's a good idea to create a custom top level domain that won't resolve on machines not inside your private network. This helps to prevent accidental information leakage by making it impossible for unauthorized third parties to resolve the name into a usable IP. If you don't want to do this for any particular reason, it is possible to set things up as subdomains of an existing domain. This may also be preferable depending on your philosophical beliefs about what is a "valid" or "real" domain name, which is beyond the scope of this article.
Names are known to be hard with computer science things. The annoying part about naming things are what I call name collisions, or when someone else uses a name you were using. This most famously happened with [.dev](https://ma.ttias.be/chrome-force-dev-domains-https-via-preloaded-hsts/), making many [tutorials referencing this old trick effectively useless](https://passingcuriosity.com/2013/dnsmasq-dev-osx/). As such, it is better to choose names that are very, very unlikely to ever be added as a valid global top level domain. Try picking names by these criteria:
- The names of deities (see the [Bionicle Effect](https://www.theguardian.com/world/2001/oct/31/andrewosborn) for an example)
- Curse words
- The last name of a famous person you like (that is alive for extra credit)
Numbering your site to site private networks is another common pain point, mainly because conflicts in these spaces can be hairy to resolve. It can help to make a list of the IP space of all of the common networks you visit so you can make sure your network range doesn't conflict with them:
Generally people will pick routes out of the lower /12 of `10.0.0.0/8`. This example will use the network range `10.55.0.0/16`. Because WireGuard requires us to create configuration for each device connecting to the network, let's draw out a map of the entire network as we intend to set it up:
Depending on free network space, it may be preferable to split the first /24 block up into two logical /25 blocks (10.55.0.0/25 and 10.55.0.128/25). This is all a matter of taste and has no functional impact on the network. I'd suggest using consistent conventions in your subnetting whenever possible.
WireGuard requires a UDP port to be exposed to the outside world to work. A commonly used port for this is 51820. Depending on your network configuration, you may have to [configure port forwarding](https://m.wikihow.com/Set-Up-Port-Forwarding-on-a-Router). I cannot help you with this step if it is the case, however.
#### Testing UDP Port Forwarding
In case you ever need to test the UDP port forwarding, run the following on the machine you want to test:
```console
$ nc -u -l -p 51820
```
And on another machine:
```console
$ echo "hello, world" | nc -u <externalIP> 51820
```
Run this command a few times in order to make sure the packets go through, as UDP is [not inherently reliable](https://en.wikipedia.org/wiki/User_Datagram_Protocol#Reliability_and_congestion_control_solutions). If you see at least one instance of "hello, world" on the machine you want to test, your port has been forwarded correctly. If not, contact whoever set up your network for help.
## Alpine Host Setup
Now that you have all of the hard parts chosen, provision a new server running [Alpine Linux](https://alpinelinux.org) and [upgrade it to edge](https://wiki.alpinelinux.org/wiki/Include:Upgrading_to_Edge), then [enable community](https://wiki.alpinelinux.org/wiki/Enable_Community_Repository) and testing. Your /etc/apk/repositories file should look something like this:
```
# /etc/apk/repositories
http://dl-3.alpinelinux.org/alpine/edge/main
http://dl-3.alpinelinux.org/alpine/edge/community
http://dl-3.alpinelinux.org/alpine/edge/testing
```
Upgrade all of the packages on the system and then reboot:
```console
# apk -U upgrade
# reboot
```
### Install WireGuard
To install WireGuard and all of the needed tools, run the following:
Save this and make sure only root can read any of these files:
```
# chown root:root /etc/wireguard/pele*
# chmod 600 /etc/wireguard/pele*
```
### Create client config for iOS device
On your iOS device, install the [WireGuard app](https://itunes.apple.com/us/app/wireguard/id1441195209?mt=8). Once it is installed, open it and do the following:
To add this client to the WireGuard server, add the following lines to the config file:
```
# /etc/wireguard/pele.conf
# <snip from earlier>
# la ta'orskami
[Peer]
PublicKey = <publickeyfromiOSdevice>
AllowedIPs = 10.55.1.1/32
```
Make sure the AllowedIPs range doesn't allow for routing loops. It should be a /32 for any "client" devices and larger rangers for any "server" devices.
### Manual Testing
To test this, enable the WireGuard interface on the server side:
```console
# wg-quick up pele
# ping 10.55.0.1
```
If the pinging works, then your interface has successfully been brought online! In order to test this from your iOS device, enable the VPN connection in the WireGuard app, look for the latest handshake timer and open [LibTerm](https://itunes.apple.com/us/app/libterm/id1380911705?mt=8). Run the following command:
```console
$ ping 10.55.0.1
```
If this fails or you don't see the connection handshake timer in the WireGuard app after enabling the connection, please be sure the UDP port is being properly forwarded. The version of netcat bundled into LibTerm is capable of running this test should you need to do that.
For convenience, we can add this to the [system networking configuration](https://bit.ly/2CP1M18) so it starts automatically on boot. Add the following to your /etc/network/interfaces file:
And then reboot to make sure the configuration changes take hold. You will need to add additional `post-up ip route` commands based on the AllowedIPs blocks for peers in your configuration; though this will be covered in detail when it is relevant.
#### Systemd Users
To automatically start a WireGuard configuration located at /etc/wireguard/pele.conf on boot using systemd, run the following:
```console
# systemctl enable wg-quick@pele
# systemctl start wg-quick@pele
```
### The Reboot Test
Reboot your box. After it comes back up, try and use the WireGuard tunnel. If it works, then you're all good.
Please give me feedback on my approach to this. I hope this is useful to you all in some way. Stay tuned for the future parts of this series as I build up the network infrastructure from scratch. Be well.