Hosting a VPN
Thu 15 August 2024In order to access some parts of my home network from abroad, I decided to host a VPN. I had a few options to begin with:
- rent someone else's computer (the cloud)
- use a computer of my own
- break into a friend's house and plant a computer on which I'd configured a VPN server
A lot of internet tutorials are focused on the first one, but as a cheap person who also likes using my own hardware, I wanted to go with #2: using my own network and computer. I already have hardware that can serve a VPN, and I already have a home network with internet access that I'm paying for, so the marginal cost is tiny. Less, even, than the $4/mo for a Digital Ocean droplet, which is the frontrunner for option #1.
I use pfSense for my router so the setup was actually pretty easy. I set up a certificate authority, configured the OpenVPN directly in pfSense, added the client config export package, distributed the certs and client configs, and then tested my settings to make sure it was working as expected.
First Step: Certificate Authority
- Go to System -> Certificates. In the Authorities tab, click Add
- Pick a descriptive name
- For Method, select "Create an internal Certificate Authority"
- Select a Key type-- there are reasons to pick RSA over ECDSA, and there are reasons to pick ECDSA over RSA. That is an exercise left to the reader. I will simply say I went with a 2048 bit RSA key despite its shortcomings
- sha256 digest is good
Next: OpenVPN Setup in pfSense
- Go to VPN -> OpenVPN. In the Servers tab, click add
- Pick a descriptive name
- For Server mode, pick Remote Access, SSL + User Auth. This will require a key on the computer in addition to the correct username and password for authentication
- set Local Database as the auth backend
- Device Mode should be tun - Layer 3. This refers to the OSI model layer, which will enable routing via IP address instead of hardware address
- Endpoint configuration is up to what you're using it for. I use IPv4 for $reasons, and the difference in TCP and UDP is reliability vs speed (broadly). This VPN I'm setting up is not for media streaming or anything, so I'm using TCP for the reliability
- For cryptographic settings:
- use a TLS key (this is the key mentioned earlier for more auth security)
- Auto-generate one for convenience, selecting your earlier-configured cert authority
- Set Server certificate to the same earlier-configured server
- DH parameter length and ECDH curve setting defaults are fine
- Encryption algorithms, since you're using a key pair, do not matter. But, I've selected CHACHA20-POLY1305 as the fallback just in case
- The rest of the defaults are also fine
- For tunnel settings:
- Enabling IPv4 tunnel on different subnet will let your devices talk to each other (my whole goal). So with, e.g., a 192.168.1.0/24 LAN subnet, a tunnel subnet of 192.168.2.0/24 will give you a separate tunnel for device communication that is not conflicting with the LAN
- Depending on your security needs, you can allow access to your network's LAN as well. I.e., when you connect to the OpenVPN can you see just other connected devices, or your router's whole LAN
- For my personal preferences, I also changed the Inactive ping setting because 5 minutes of inactivity was causing my SSH sessions to hang and die even after the VPN reconnected
- Other than that, the rest of the defaults are fine! You can save and activate the server
Up next: Client Config + Cert Export and Setup
Now that the server is active, you can export settings and test connecting clients. I wanted to make sure that
- clients had a tun address
- clients could see each other
- clients could not see the LAN
To export settings, you'll need to go to System -> Package Manager, go to the Available Packages tab, and install openvpn-client-export. Once I got the client files, I set each server up using OpenVPN and made sure that a client not connected to the LAN couldn't see the LAN--thus isolating things like my desktop and steam deck from the VPN machines. It's no VLAN, but it is virtually some kind of LAN.
Setting up Automatic Connection on Boot for Client Servers (wait what)
With the client config working, I set up the OpenVPN systemd service to autoconnect for my servers, which are clients to the VPN. To do that:
- Move the client .ovpn file to /etc/openvpn/ and change the file extension to .conf
- Edit
/etc/default/openvpnto haveAUTOSTART="all" - Make a password file with
sudo nano /etc/openvpn/vpn.txtand enter:
clientusername
passwordforthisconnection12345
Then, just enable openvpn daemon with sudo enable openvpn. Now the machine should be connected and should auto-connect without you entering a password every time it restarts.
Finishing Touches: Userland Config Changes for Usability
I've been using the VPN for a few days now by using sudo openvpn vpnconfigfile.ovpn then entering my sudo password, username, and cert password. It's been good because at first, my plan was to have the VPN up only when necessary and disconnect it otherwise, but in the interest of making it a more 'permanent' tool, I finally went through the process of setting it up in NetworkManager. For simplicity's sake, I didn't even use NMTUI, I just hit my super key and typed "network" to bring up the GUI frontend my distro (LMDE) provides for NetworkManager (It also does other things, yes, I know).
It was simple, though: Hit plus in the bottom left corner, import from file, select the *.ovpn file, add the username and password--or, in my case, tell it to prompt me for it every time it connects.
Blu Blog