# setting up a private vpn portal using wireguard and wg-portal ## ubuntu 20.04 on raspberry pi 4 edition ## updated 2021-03-13 by sundog # overview the goal of this exercise is to set up a privately hosted vpn portal using [wireguard](https://wireguard.com) and [wg-portal](https://github.com/h44z/wg-portal). # initial test network configuration for the purposes of this exercise, I will be configuring a vpn portal that provides clients with an address in the 10.42.1.0/24 subnet that will carry traffic for any address in the 10.42.0.0/16 subnet. I am starting from a clean install of ubuntu 20.04 for the raspberry pi 4 that has been updated and had the sshd config updated to use key based auth. # setting up prerequisites ## install wireguard ``` sudo apt install -y wireguard ``` ## install wg-portal grab the latest release (currently 1.0.3) from github (ugh): ``` # be the root. live the root. sudo -i # make some space for wg-portal and go there mkdir /opt/wg-portal && cd $_ # grab the arm64 binary, sample env config, and systemd service file wget https://github.com/h44z/wg-portal/releases/download/v1.0.3/wg-portal-arm64 wget https://github.com/h44z/wg-portal/releases/download/v1.0.3/wg-portal.env wget https://github.com/h44z/wg-portal/releases/download/v1.0.3/wg-portal.service # make the executable executable chmod +x wg-portal-arm64 # change the service file to use arm64 instead of amd64 sed -i 's/wg-portal-amd64/wg-portal-arm64/g' wg-portal.service ``` edit `wg-portal.env` with your favorite editor. update `EXTERNAL_URL` to a url under your control - in my example, this will be `pvpn.reclaim.technology` which has already been configured to point at the public facing addresses mapped to eth0 on my pi. update `ADMIN_USER` to be your email address and `ADMIN_PASS` to be something more secure than 'supersecret' update `WEBSITE_TITLE` and `COMPANY_NAME` at your pleasure. save the changes. ## configure wireguard assuming you are still the root: ``` # go to the wireguard config directory cd /etc/wireguard # generate a new public/private key pair and save them in /etc/wireguard/privatekey and /etc/wireguard/publickey wg genkey | tee privatekey | wg pubkey > publickey ``` now create `/etc/wireguard/wg0.conf` with your favorite editor and the following contents: ``` [Interface] Address = 10.42.1.1/24 # if you're using a different subnet, edit this!! ListenPort = 51820 PrivateKey = PRIVKEY PreUp = PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PreDown = PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE ``` save it, then run ``` sed -i "s/PRIVKEY/$(cat /etc/wireguard/privatekey)" wg0.conf ``` that should take care of the initial setup of the config files. onwards to the interface! still as the root: ``` ip link add dev wg0 type wireguard ip address add dev wg0 10.42.1.1/24 # if you're using a different subnet, edit this!! ``` ## configure and start wg-portal still the root? excellent. ``` ln -s /opt/wg-portal/wg-portal.service /etc/systemd/system/wg-portal.service # get the systemd service ready systemctl daemon-reload systemctl enable wg-portal.service systemctl start wg-portal.service ``` at this point, I believe the service should be up and running if you head to `http://:8080` but I went ahead and installed [Caddy](https://caddyserver.com) to act as a reverse proxy, mostly because it's simple to configure and automatically configures itself via letsencrypt to provide a trusted ssl connection. let the root keep rolling: ``` apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | apt-key add - curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee -a /etc/apt/sources.list.d/caddy-stable.list apt update apt install -y caddy ``` edit `/etc/caddy/Caddyfile` to contain: ``` your.domain.name.here reverese_proxy localhost:8080 ``` save the file, and `systemctl restart caddy` you should now be able to access https://your.domain.name.here and see the wg-portal page, all nice and secured by a certificate. ## finish setting up wg-portal via the web app click on the login link and enter the email address and password you provided in `/opt/wg-portal/wg-portal.env` click on the "Open Wireguard Administration" button at the bottom of the page. click the gear icon on the right-hand side of the "Interface status for wg0" header Listen port should be 51820 Address should be 10.42.1.1/24 (or whatever subnet you are using) Public endpoint for clients should be your.domain.name.here:51820 Default allowed IPs should be 10.42.1.0/24 (or, if you are planning on mucking about in a slightly larger setup with collaborators, something like 10.42.0.0/16, which is what I'm using in my test bed) Post Up and Post Down should already be properly populated with the commands entered into /etc/wireguard/wg0.conf earlier. Hit save, You should get a "Changes applied successfully" toast at the top of the page. ## add clients click where it says "Wireguard Administrator" in the upper right and go back to Administration page. next to the "Current VPN Peers" header, click the "manually add a peer" button fill out the friendly name and the email address fields as you like. leave everything else as-is. click save. the peer you just saved should now be listed under "Current VPN Peers" to test the setup, I added an android phone as my first peer. after installing wireguard via the goog play store and opening the app, click the + floating button and select "scan from qr code" back in your web browser, click the small plus sign to the left of your newly created vpn peer to expand its details point your android phone's camera at that qr code give the connection a name (maybe "tube test" or what have you) flip the toggle switch next to your newly created connection now go back and refresh your wg-portal web page if everything is well, you should notice that the formerly grey-and-broken chain symbol is now green-and-unbroken. expanding the details with the plus sign should show you the IP address from which your android phone is connected and the traffic statistics for that peer. this is as far as I have currently gone with this exercise. ## next steps personally, I will be looking at adding a bind daemon on the raspberry pi 4 next to act as a DNS server for VPN clients and then adding that DNS server as the default DNS server for VPN clients to facilitate setting up VPN-only services with names that are friendlier than 10.42.x.y IP addresses. might set up a simple domain name registrar web app that tweaks that dns server's config after that also want to look at setting up this same type of configuration but starting from a [Yunohost](https://yunohost.org/en/install?q=%2Finstall_on_raspberry) base install, to allow for an LDAP store to integrate into the wg-portal configuration for user management and SSO as well as a set of easy to install and maintain self hosted web apps to provide to VPN clients. greets to all my fediversians whomst dig weird alternets - hit me up and let's peer and stuff @djsundog@toot-lab.reclaim.technology