Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gilangvperdana/4f80b83aadda3d813a9a60b2ecee300c to your computer and use it in GitHub Desktop.
Save gilangvperdana/4f80b83aadda3d813a9a60b2ecee300c to your computer and use it in GitHub Desktop.

How to secure a Proxmox exposed host

When you look for tutorials on how to install Proxmox, it always stops after the initial installation - which is quite dangerous, since it leaves a Proxmox host being exposed to the internet while listening to Ports 22 and 8006.

Heck, there is not even any SSH-hardening covered - your SSH is typically set to default values, which means: Password-authentication with the root account is perfectly possible. While you can mitigate some of these things by harding SSH or by installing fail2ban (which we will do anyhow), the host still exposes ports 22 and 8006.

For a secure system, these ports (and actually, apart from one single port ANY ports) have to be disabled. The only acceptable management access to the system should either happen via a Jumpserver or - if not available - via a direct VPN-connection.

In this gist, you find all the required steps to secure your Proxmox exposed host. This gist should work for any Proxmox host with - say - Hetzner, OVH or other vendors, it obviously also works on your internal systems (it is probably not a bad idea to have them secured a bit as well).

Prerequisites

  • Have a working Proxmox installation :-)

Install required components

apt install fail2ban sudo ufw

Add a dedicated user

useradd -m user

Then, set a strong password

passwd user

Add the user to the sudo group

usermod -aG sudo user

Log out off the SSH session

exit

Copy the SSH-key for this user to the machine (from your local machine):

ssh-copy-id user@<IP>

Re-Login to the machine, this time not as root

ssh user@<IP>

Secure SSH-access to the machine

On the machine, open the SSH-settings

sudo nano /etc/ssh/sshd_config 

Here, uncomment and set the following values

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Then, reload the SSH-Daemon

sudo systemctl restart sshd

Basic UFW configuration

Allow only SSH-connections to the machine

sudo ufw allow 22/tcp
sudo ufw enable

Configure a network bridge for OpenVPN

Open the network configuration

sudo nano /etc/network/interfaces

Here, you need to note down the name of the primary networking device (i.e. an ethernet connection with inet static and an external IP-address, or a vmbr-definition with an external IP-address):

Have a look at one of my network configurations:

auto lo
iface lo inet loopback

iface enp34s0 inet manual

auto vmbr0
iface vmbr0 inet static
	address xx.xx.xx.77/24
	gateway xx.xx.xx.1
	bridge-ports enp34s0
	bridge-stp off
	bridge-fd 0

The name I need to remember, is vmbr0.

Add a new bridge:

auto vmbr1
iface vmbr1 inet static
	address 10.1.1.254/24
	bridge-ports none
	bridge-stp off
	bridge-fd 0
	post-up iptables -t nat -A POSTROUTING -s '10.1.1.0/24' -o vmbr0 -j MASQUERADE
	post-down iptables -t nat -D POSTROUTING -s '10.1.1.0/24' -o vmbr0 -j MASQUERADE

Save the configuration, and reboot the machine (could also be done via ifup -a and / or sudo systemctl restart networking, but does not work all the time, so it is more secure to restart the machine)

sudo reboot

Install OpenVPN

Download a script to automate this:

wget https://git.io/vpn -O openvpn-install.sh

Make it executable

chmod +x openvpn-install.sh

Run it

sudo ./openvpn-install.sh

Obviously, you need to adjust the settings to your liking. :-)

Cat the generated .ovpn-file

cat <Path-to>/<Ovpn-File>.ovpn

and copy its contents to your local machine (I typically just do a copy, then create an empty file in my text-editor, paste the stuff in there, and then just save it as .ovpn-file).

Import it into your local OPVN-client.

Adjust the firewall for OpenVPN

On the machine, execute the following statements:

sudo ufw allow 1194/udp
sudo ufw reload

Now, exit from the machine, and connect from your local machine via VPN to the remote machine - which should work. Also, open a new SSH-connection from your local machine to the remote machine via the internal IP-address:

ssh user@10.1.1.254

This should also work and connect you with your machine.

Disable external SSH

On the remote machine, you can now disable SSH apart from your VPN-connection and allow it from the VPN-connection only

sudo ufw delete allow 22/tcp
sudo ufw allow from 10.8.0.0/24 to any port 22
sudo ufw allow from 10.8.0.0/24 to any port 8006
sudo ufw reload

Now, SSH and access to the Proxmox-GUI only work from your VPN connection.

Lastly, edit /etc/default/ufw and allow forwarding:

DEFAULT_FORWARD_POLICY="ACCEPT"

Restart the machine to make everything work.

Allow external traffic to a workload on Proxmox

Since we now have completely shut off external access from our Proxmox, we should allow some access to - say - web-workloads.

If you want to start such workload, make sure, its network stack is bound to vmbr1. We now need to create a NAT-Rule for UFW, so that every web-request to the machine - which in our example runs on the internal IP 10.1.1.100 - is forwarded to the VM or container.

Do that by editing /etc/ufw/before.rules and by inserting these lines before *filter:

### NAT ###
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-F

# Port Forwardings
-A PREROUTING -i vmbr0 -p tcp --dport 80 -j DNAT --to-destination 10.1.1.100
-A PREROUTING -i vmbr0 -p tcp --dport 443 -j DNAT --to-destination 10.1.1.100

# Forward traffic through eth0 - Change to match you out-interface
-A POSTROUTING -s 10.1.1.0/24 -o vmbr0 -j MASQUERADE

COMMIT
### EOF NAT ###

Please make sure, that you are forwarding from the correct network interface - should be the same as identified above (vmbr0 in my case).

Reload UFW

sudu ufw reload

Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment