Moving my Proxmox server to an untrusted, natted network
What happened? Well, I wanted to get my server to my brother’s house. There, it would sit comfortable in his LAN. But as this server provides me some valuable services with sensitive data, I wanted to protect it as much as I could. I wanted to set up encryption on it’s partitions, but that’s gonna be in another episode.
Now, in this document, I want to focus on network security. So what are my objectives?
- Connect this server to my lan by installing wireguard and setting up the VPN configuration;
- Put vmbr0 to get IP via dhcp;
- Put all VMs natted and forwarding the needed ports to wg0 (wireguard interface);
- Block all connections to eth0 and vmbr0 using iptables.
Installing Wireguard
If you (like me) does not have a license for proxmox, you need to enable the community repository to make this work. Edit /etc/apt/sources.list.d/pve-enterprise.list and comment out the following line:
deb https://enterprise.proxmox.com/debian/pve bullseye pve-enterprise
#should become:
#deb https://enterprise.proxmox.com/debian/pve bullseye pve-enterprise
Now, to enable community repository, uncomment the last line in /etc/apt/sources.list:
#deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription
#should become:
deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription
Then update the repositories and install wireguard:
apt update && apt install wireguard
After this, put your client configuration in /etc/wireguard/wg0.conf and enable/start the service:
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
Put vmbr0 to get IP via DHCP
Since I’m going to access my server via wireguard, I don’t need to worry about it’s IP in my brother’s network (neither should I bother him with this). So here I set vmbr0 to get its IP via DHCP. First, copy the old configuration so you can easily rollback if needed:
cp /etc/network/interfaces /etc/network/interfaces.bak
Now, delete the file and create a new one with the following contents:
auto lo
iface lo inet loopback
iface enp3s0 inet manual
#DHCP vmbr0
auto vmbr0
iface vmbr0 inet dhcp
bridge-ports enp3s0
bridge-stp off
bridge-fd 0
Make all VMs natted
Natting via Wireguard depends on how you have set up the interface in the client and on how you have set your server nat configuration. Check here to see a quick how-to. Since we are already with wireguard working, I will focus here on how to create a second bridge to isolate the VMs from the main lan.
Append these lines to /etc/network/interfaces:
auto vmbr1
iface vmbr1 inet static
address 192.168.1.1/24
bridge-ports none
bridge-stp off
bridge-fd 0
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up iptables -t nat -A POSTROUTING -s '192.168.1.0/24' -o wg0 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s '192.168.1.0/24' -o wg0 -j MASQUERADE
Make sure that your wireguard interface has got the right name in the iptables command. As mine was not wg0, it wasn’t working until I fixed the name.
Now on every VM you have, configure your IP to be in the same subnetwork as vmbr1. My Windows VM, for example, I have put the IP 192.168.1.2, netmask 255.255.255.0 and gateway to 192.168.1.1. As DNS I used my Wireguard server. Remember to set your NIC to use the vmbr1 bridge in your guest VM.
For example, in Windows you can set the IP using the following command:
netsh interface ipv4 set address name="INTERFACE_NAME" static 192.168.1.2 255.255.255.0 192.168.1.1
netsh interface ipv4 set dns name="INTERFACE_NAME" static 8.8.8.8
Block all connections on vmbr0
Just add this to vmbr0 interface configuration:
post-up iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
post-up iptables -A INPUT -i vmbr0 -j DROP
Expose VM port
For every vm that needs a port exposed, run this command for tcp connections:
iptables -t nat -A PREROUTING -d YOUR-WIREGUARD-IP/32 -p tcp -m tcp --dport HOST-PORT -j DNAT --to-destination YOUR-VM-IP:YOUR-VM-PORT
For udp, run this:
iptables -t nat -A PREROUTING -d YOUR-WIREGUARD-IP/32 -p tcp -m tcp --dport HOST-PORT -j DNAT --to-destination YOUR-VM-IP:YOUR-VM-PORT
iptables -t nat -A PREROUTING -p udp -i YOUR-WIREGUARD-INTERFACE -d YOUR-WIREGUARD-IP --dport HOST-PORT -j DNAT --to-destination YOUR-VM-IP:YOUR-VM-PORT
And we’re done!
References
TUTORIAL PVE 6.2 Private VM (NAT) network configuration setup