Set up Remote Access to Our Proxmox Home Lab

In this module, we will look at using dynamic DNS, OpenVPN, and WireGuard to setup remote access to our Proxmox home lab
Set up Remote Access to Our Proxmox Home Lab
In: Proxmox, Computer Networking, Home Lab
ℹ️
This page is part of the larger series of converting an old laptop into a bare metal home lab server. Click here to be taken back to the project home page.

Previous Step

Adding HackMyVm Boxes to Our Proxmox Cyber Range
In this module, we will look at how to import VMs from HackMyVM into our Proxmox home lab





Overview of the Setup




Register for a Free Dynamic DNS Hostname

This step is necessary if you do not have a static IP address provided by your Internet service provider (ISP). I imagine most residential customers do not have static WAN IPs, but check with your ISP if you want to be sure.

The dynamic DNS hostname will be used to track your WAN IP anytime it changes. This will work, because a client will reach out to the dynamic DNS provider (No-IP in this case) and periodically inform the provider of the current WAN IP. If the WAN IP has changed since the last check-in, the DNS record will be updated.

Go to https://noip.com. Create an account if you do not already have one. Go to Dynamic DNS > No-IP Hostnames.

Click Create Hostname. Create the host using the following options. Change somename with a hostname that you would like to resolve back to your house's public IP address.





Setup the Dynamic DNS Client in pfSense

pfSense is going to act as an updater client for us. It will periodically login to the https://noip.com service for us and tell them what our home’s new public IP address is when it changes.

Log into your pfSense web portal: https://pfsense-ip-address. Go to Services > Dynamic DNS. Click Add.

  • Service Type: No-IP (Free)
  • Interface to monitor: WAN
  • Hostname: Use the hostname from Step 5 above
  • Username: https://noip.com username
  • Password: https://noip.com password
  • Description: Home public IP address





OpenVPN Container Alternative: pfSense Running OpenVPN

ℹ️
If you'd rather run your OpenVPN server in a Linux container, proceed to the next section below.
Running your OpenVPN server in pfSense does provide some added benefits, such as being able to modify firewall rules at the network level, keeping all of your firewall rules unified under one interface.

Using the Configuration Wizard

Log into pfSense and go to VPN > OpenVPN > Wizards. Then, choose Local User Access.

Create the CA



Create the Server Certificate

Now that the local Certificate Authority (CA) has been created, we can create a server certificate and sign it via the CA.



Configure the Server

ℹ️
When asked for the Server Host Name, enter your dynamic DNS hostname you created earlier
ℹ️
For my tunnel settings, I'm using the internal network of 10.102.102.0/24, but use whatever tunnel network you prefer. Be sure that there is no IP overlap with an existing subnet that would cause routing conflicts.
ℹ️
My production network has an internal domain of home.lab, so change yours accordingly. 10.102.102.1 would be the gateway of the VPN tunnel network in this case, and the IP have chosen to provide DNS resolution to VPN clients.
ℹ️
The tun-mtu and mssfix options are the sizes that I chose to fix packet loss in accordance with my experience. You may need different options. Also, the push "route $NET $MASK"; options are those which I'm OK with universally setting on all VPN clients, since it's only me connecting to the VPN.

If you'd prefer, you can do the push options on a client-by-client basis.



Create a VPN User Profile

  1. Go to System > User Manager
    1. Add a user, do not provide any groups
    2. Set a strong password
    3. Create a certificate for the user (sign the certificate using the CA you created when initially setting up the server)
  2. Export the client connection package
    1. Go to VPN > OpenVPN > Client Export
      1. If you don't see this option, you may need to install the pfSense package under System > Package Manager
      2. Choose your Remote Access Server
        1. Ensure the hostname resolution uses the dynamic DNS record
        2. The Inline Configurations option for most clients / Android should work fine in most cases
  3. Import the .ovpn file into your OpenVPN client on your device





Create an OpenVPN Debian 11 Container

  1. Create the unprivileged container
  2. Set it to start at boot. Set the startup order if desired.
  3. Note the MAC address and create a static DHCP reservation for the server
  4. Port forward the OpenVPN listen port to the internal IP

Resources

  • RAM: 512 MiB
  • Swap: 512 MiB
  • Cores: 1
  • Disk: 10 GB



Network

This is going to give the container an IP address on your home’s network

  • Start at boot: Yes
  • Start/Shutdown order: User preference
  • Unprivileged Container: Yes



Create the Container

Open a shell on the Proxmox node and run this command:

# Update container template repository
pveam update

Now, create an unprivileged Debian 11 container using the GUI. Once you've created the container, we'll need to make a few small changes. Open a shell on the Proxmox node and run this command:

# Get the container configuration information
pct config [container-id]

# Edit the configuration information
nano /etc/pve/lxc/[id-number].conf

Add these lines:

lxc.cgroup.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net dev/net none bind,create=dir

Press CTRL + X to exit. Save your changes.

pct start [id-number]



Open a Shell on Your OpenVPN Container

Run these commands

apt update
apt dist-upgrade
apt install openvpn git
git clone https://github.com/angristan/openvpn-install
cd openvpn-install
bash openvpn-install.sh

Answer the questions in the wizard. When the wizard asks you for IP address or hostname, provide the Dynamic DNS hostname you configured above.

⚠️
Answer the questions in the wizard. When the wizard asks you for IP address or hostname, provide the Dynamic DNS hostname you configured above.

This way it will always use your Dynamic DNS hostname to resolve your home’s public IP when connecting to the VPN server.

The client configuration will be in /root/client.ovpn. Just move client.ovpn to your phone or laptop. Install OpenVPN client app on your phone or laptop. Import the client.ovpn configuration and connect.

If you have additional subnets you would like to be able to route to from your VPN client, you can edit the /etc/openvpn/server.conf file and add multiple push "route" commands. This will tell the VPN server to inform the VPN client of any routes that should be sent through the VPN tunnel.

push "route 10.0.0.0 255.255.255.0"
push "route 10.10.10.0 255.255.255.0"

Example

If you do push additional routes to your VPN client(s), you'll need to make sure you update any firewall rules as necessary.





Create a Wireguard Debian 11 Container

  1. Create the unprivileged container
  2. Set it to start at boot. Set the startup order if desired.
  3. Note the MAC address and create a static DHCP reservation for the server
  4. Port forward the Wireguard listen port to the internal IP

Resources

  • RAM: 512 MiB
  • Swap: 512 MiB
  • Cores: 1
  • Disk: 10 GB



Network

This is going to give the container an IP address on your home’s network



  • Start at boot: Yes
  • Start/Shutdown order: User preference
  • Unprivileged Container: Yes



Open the Proxmox Shell

ℹ️
WireGuard kernel modules are built into Linux kernels 6.x and there is no need to install the backported wireguard-dkms package at this time
pveupgrade # Reboot if necessary
modprobe wireguard # Load the kernel module
# Add kernel modules to autoload at boot
echo "wireguard" >> /etc/modules-load.d/modules.conf 
💡
Since Linux Containers (LXC) don't have their own kernel and use the host kernel — that's what allows them to boot so quickly — the WireGuard LXC will leverage the wireguard kernel modules loaded on the PVE host



Open the Wireguard Container Shell

apt clean && apt update
apt install -y --no-install-recommends wireguard-tools iptables
nano /etc/sysctl.conf

Uncomment the IPv4 forwarding configuration

  • Before: #net.ipv4.ip_forward=1
  • After: net.ipv4.ip_forward=1

Uncomment IPv6 forwarding configuration

  • Before: #net.ipv6.conf.all.forwarding=1
  • After: net.ipv6.conf.all.forwarding=1

Press CTRL+X, then Y, and Enter to save your changes. Now, run these commands:

sysctl -p
cd /etc/wireguard
umask 077



Wireguard Server Setup

Wireguard uses public-key authentication to verify peers. Wireguard does not authenticate users, rather it authenticates devices to create a tunnel between the two.

Create a Server Public and Private Key Pair

wg genkey | tee server-private-key | wg pubkey > server-public-key

Edit the Server Interface Configuration File

nano /etc/wireguard/wg0.conf

The configuration data in the wg0.conf file should look something like this.
Replace the <placeholder-values> with their respective information.

NOTE: in the interface PostUp command, I specified ip link set wg0 mtu 1500, because this is the default MTU on my network. When the Wireguard default MTU of 1420 was being used, it was fragmenting the packets and causing EXTREME latency on my Windows client (for some reason, Android didn’t seem to mind the default of 1420).

That said, your MTU settings may be different, so you can try adjusting this if you have connectivity issues or poor performance.

[Interface]
PrivateKey = <server-PRIVATE-KEY file contents>
Address = 10.0.10.1/24
ListenPort = <port forward created above>
PostUp = ip link set wg0 mtu 1500 ; iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# Smartphone
[Peer]
PublicKey = <smartphone-PUBLIC-KEY file contents>
AllowedIPs = 10.0.10.2/32

# Laptop
[Peer]
PublicKey = <laptop-PUBLIC-KEY file contents>
AllowedIPs = 10.0.10.3/32 # Same as internal LAN

Press CTRL+X, then Y, and Enter to save your changes.



Edit the Client Interface Configuration File

This is just an example of client configuration. It’s the same for any device.

mkdir -p /etc/wireguard/clients/smartphone
cd /etc/wireguard/clients/smartphone
wg genkey | tee smartphone-private-key | wg pubkey > smartphone-public-key
nano smartphone.conf

The configuration file should look something like this.
Replace the <placeholder-values> with their respective information.

[Interface]
PrivateKey = <smartphone-PRIVATE-KEY file contents>
Address = 10.0.10.2/32 
DNS = # example: <home-router-ip>, 1.1.1.1, 1.0.0.1

[Peer]
PublicKey = <server-PUBLIC-KEY file contents>
Endpoint = dynamicdns.host.name:[port-forward]
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

The AllowedIPs configuration specifies subnets available to the client. 0.0.0.0/0 means all traffic is sent through the tunnel.

For smartphones, you can import the config by scanning a QR code.
Install terminal QR code generator. This will be used to scan a QR code to generate a configuration file on the client.

You can enter the configuration details manually, this is just for convenience

apt install qrencode
qrencode -t ansiutf8 < smartphone.conf

Note: For laptops you’ll have to export the config file to the device and import it using the Wireguard client



Wrapping Up Wireguard Server Configurations

chown -R root:root /etc/wireguard
chmod -R og-rwx /etc/wireguard
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0





Setup Port Forwarding in Home Router

Default Service Ports

Unless you configured them otherwise, these services are running on these ports:

  • OpenVPN: UDP 1994
  • Wireguard: UDP 51820

Configuring Port Forward in Home Router

This will vary from router to router. I am just demonstrating using my own router.

ℹ️
The OpenVPN port forward is going to depend on which way you configured it -- Linux Container or pfSense VM running OpenVPN.

If the Linux Container is running OpenVPN server, forward to the LXC internal IP address. If the pfSense VM is running OpenVPN server, forward to the pfSense WAN IP address.
  1. Login to home router. For me, this is https://172.16.1.1
  2. Go to Firewall > Port Forwarding
    • Specify a target IP address from the list
      • This is the internal host that will receive the external traffic
    • Specify a port (eg. UDP 1194)
      • Click Add
  3. Now, when an application goes to: your-dynamic-dns-name:port,the application will be forewarded to the internal service



Example

  1. OpenVPN client tries to connect to fakehost.ddns.net:UDP1194
  2. Your home router receives the connection
  3. It forwards the UDP traffic to the internal IP address of the OpenVPN container



Next Step

Troubleshooting Proxmox
In this module, we will look at various command line utilities to troubleshoot our Proxmox home lab
More from 0xBEN
Table of Contents
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to 0xBEN.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.