Create your own private VPN with Headscale, Tailscale, and Oracle Cloud Free Tier
I've blogged about Oracle's free tier before and you might be wondering "What can I do with a free online compute instance?" How about setting up your own VPN! Instructions:
1. Follow my other guide to create an Oracle Cloud free tier account but use the "Canonical Ubuntu 22.04 Minimal aarch64" image and keep the default of size 1 core OCPU, 6 GB memory -- this will be for our Headscale server, which doesn't require many resources (we'll use the remainder of our free tier allotment for the Tailscale exit node)
2. Once the instance is running, set the static IP and add the following ports to the Oracle Cloud Ingress Rules:
3. Purchase a domain from your desired registrar. In this guide I'll use mydomain.com as the example.
4. In the domain registrar DNS settings, create an A record for a subdomain Host (in this example I'll use vpn.mydomain.com), and the Public IP address from Step 1 above for the value. Wait 1-24 hours for the setting to propagate: https://dnschecker.org/
5. On your own computer, create an ED25519 SSH key, which is shorter and slightly more performant compared to RSA while maintaining equivalent security: ssh-keygen -t ed25519
6. Now, SSH into the compute instance and switch to using the new key:
sudo su -
apt update
systemctl stop ssh
apt autopurge -y openssh-server openssh-client xz-utils fuse3
apt install -y dialog nano less tinysshd ca-certificates --reinstall
echo 'CONTENTS OF YOUR ED25519 SSH KEY IN STEP 3 ABOVE HERE' > ~/.ssh/authorized_keys
(systemctl is-enabled tinysshd.socket && systemctl restart tinysshd.socket) || (systemctl start tinysshd.socket && systemctl enable tinysshd.socket)
(systemctl is-enabled systemd-networkd && systemctl restart systemd-networkd) || (systemctl start systemd-networkd && systemctl enable systemd-networkd)
7. Test you can login via a new terminal on your local machine: ssh -i id_ed25519 root@YOUR.CLOUD.IP.ADDRESS
8. Set up automatic OS updates, apply any pending updates, then restart the compute instance:
apt install -y unattended-upgrades update-notifier-common
sed -i 's/^\/\/Unattended-Upgrade::Remove-Unused-Dependencies.*$/Unattended-Upgrade::Remove-Unused-Dependencies "true";/' /etc/apt/apt.conf.d/50unattended-upgrades
sed -i 's/^\/\/Unattended-Upgrade::Automatic-Reboot .*$/Unattended-Upgrade::Automatic-Reboot "true";/' /etc/apt/apt.conf.d/50unattended-upgrades
sed -i 's/^\/\/Unattended-Upgrade::Automatic-Reboot-WithUsers.*$/Unattended-Upgrade::Automatic-Reboot-WithUsers "true";/' /etc/apt/apt.conf.d/50unattended-upgrades
echo -e "APT::Periodic::Update-Package-Lists \"1\";\nAPT::Periodic::Unattended-Upgrade \"1\";\nAPT::Periodic::AutocleanInterval \"7\";" > /etc/apt/apt.conf.d/20auto-upgrades
apt upgrade -y && apt dist-upgrade -y && apt autopurge -y && apt clean
reboot
9. Login once again and remove any old accounts
userdel -r ubuntu
userdel -r opc
10. Now we can install Headscale. Note: I'll be using the latest beta version since it's a major rewrite of the functionality.
cd /tmp
curl -sLO https://github.com/juanfont/headscale/releases/download/v0.23.0-beta1/headscale_0.23.0-beta1_linux_arm64.deb
apt install ./headscale*.deb
echo '{"acls":[{"action":"accept","src":["*"],"dst":["*:*"]}]}' > /etc/headscale/acl.hujson
chmod 644 /etc/headscale/acl.hujson
apt install -y wireguard-tools
wg genkey > /etc/headscale/private.key
chmod 400 /etc/headscale/private.key
systemctl enable headscale
11. We next need to configure Headscale: nano /etc/headscale/config.yaml
- server_url: https://vpn.mydomain.com:443
- listen_addr: 0.0.0.0:443
- grpc_listen_addr: 0.0.0.0:50443
- allocation: random
- acme_email: "youremail@mydomain.com"
- tls_letsencrypt_hostname: "vpn.mydomain.com"
- policy > path: "/etc/headscale/acl.hujson"
- base_domain: vpn.mydomain.com
Since we'll be using Tailscale like a traditional VPN, we don't need to allow devices to communicate with each other so we'll set this
- magic_dns: false
You can also optionally change the DNS upstream servers:
- nameservers:
- - 1.1.1.2
- - 1.0.0.2
Save and close the config.yaml file.
12. Although we already allowed the necessary ports in Step 2 above, Ubuntu has its own firewall you need to allow access:
iptables -I INPUT 6 -m state --state NEW -p tcp --dport 80 -j ACCEPT
iptables -I INPUT 6 -m state --state NEW -p tcp --dport 443 -j ACCEPT
iptables -I INPUT 6 -m state --state NEW -p tcp --dport 50443 -j ACCEPT
iptables -I INPUT 6 -m state --state NEW -p udp --dport 41641 -j ACCEPT
iptables -I INPUT 6 -m state --state NEW -p udp --dport 3478 -j ACCEPT
netfilter-persistent save
13. Now we're ready to start Headscale:
systemctl start headscale
sleep 10
systemctl status headscale
14. It should say Headscale is "active (running)". You can also browse to https://vpn.mydomain.com/windows and see instructions. If not, please troubleshoot.
Note: Headscale does not have a native graphical user interface (GUI) - you interact with it solely via the command line interface (CLI). Some community-supported GUI options exist, but this guide will focus on the command line.
15. Create a user account for the VPN exit node we're about to create (change bold to your desired name): headscale users create mynet
16. Now that Headscale is running, let's create our Tailscale exit node! Follow Step 1 above again to create a new cloud compute instance with size 3 core OCPU, 18 GB memory
17. Follow Steps 6-9 above to update and harden the instance.
18. Follow Step 12 above to open the necessary OS ports.
19. Now we can install and configure the Tailscale exit node with Linux optimizations:
curl -fsSL https://tailscale.com/install.sh | sh
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.d/99-tailscale.conf
sysctl -p /etc/sysctl.d/99-tailscale.conf
printf '#!/bin/sh\n\nethtool -K %s rx-udp-gro-forwarding on rx-gro-list off \n' "$(ip route show 0/0 | cut -f5 -d" " | head -n1)" | tee /etc/networkd-dispatcher/routable.d/50-tailscale
chmod 755 /etc/networkd-dispatcher/routable.d/50-tailscale
/etc/networkd-dispatcher/routable.d/50-tailscale
tailscale up --advertise-exit-node --login-server=https://vpn.mydomain.com:443
20. It will provide a URL for you to open. Click on it and copy the command to authenticate the request. Paste the command into your Headscale server terminal (changing USERNAME to the user you created in Step 15 above). It should respond with Node yournode registered
21. Then enable the new exit node:
headscale routes enable -r 1
headscale routes enable -r 2
22. Whew! The Headscale server and Tailscale exit nodes are now all set up. Let's try it out! Install the Tailscale client on a device. In this example, I'll use Android.
23. After installing Tailscale from the Google Play Store, open it. Tap "Get Started". Tap "OK" at the VPN prompt. At the screen with the "Log in" button, quickly tap the gear icon in the top-right corner. (If you wait too long and it redirects you to a login page with various SSO options, tap the back button to go back to the prior screen).
24. On the Settings page, tap Accounts.
25. On the Accounts page, tap the three vertical button icon in the top-right corner and select Use an alternate server
26. Type https://vpn.mydomain.com and then tap "Add account"
27. Copy the resulting command shown to your Headscale server to authenticate.
28. Once you get the Node yournode registered message, go back to the mobile app. In the EXIT NODE dropdown, select the exit node you created above. It should now appear in blue at the top of the Tailscale app screen and you should now be connected! Browse to https://www.whatismyip.com/ to verify.
Enjoy.
Comments
Post a Comment
Keep it clean and professional...