Proxmox networking setup in a Hetzner data center

By the time I moved to the cloud (in my case Hetzner) I wanted to replicate my home lab setup I had before. This would include my own IP-Range because I want to create and delete VMs on my Proxmox installation on a regular basis. Since a hosting provider would only supply one external IP address and I want to host multiple services on it, I want to setup a NAT.

What is NAT?

Typically you get only one IP-Address assigned by your provider even though you have multiple devices which need an IP-Address to browse the internet. Therefor your router implements NAT which stands for network address translation.

Typical Home Networking Setup using NAT

To implement NAT the router has to keep track which device requested content. Then the router itself requests the content from the world wide web. When the content arrives at your router it does a lookup where he has to route the data. If PC1 requests, it sends it’s request to the router because translates to an IP-Address outside it’s own network. The Router creates an entry in it’s NAT-Table and also changes the source address to it’s own (public) address. This has to be done because has to know where the request came from. Since the IP-Address of PC1 is not public, would not be able to send the response back. As soon as the response of the requested website arrives at the router, the package gets retransmitted to PC1.

Whats the goal?

This is also what I want to replicate with my proxmox setup in the cloud. I only have one public IP-Address but multiple VM which need unique IP-Addresses. It would be possible to request additional public IP-Addresses but this would not only cost more money, but also is a lot less dynamic. Every time I create a new VM I would have to request a new one from the provider. Inside my own sub network I can host a DHCP Server which would assign IP-Addresses automatically.


All the configuration is done inside /etc/network/interfaces. Here is an example configuration. (I had to upload it with the file ending “.txt”. If you opt to use this as a basis please remove the ending)

Let’s talk about each block separately.

source /etc/network/interfaces.d/*This is kind of an include statement for other interface configuration files. This folder however is in my case empty.
auto lo
iface lo inet loopback
iface lo inet6 loopback
These lines of code define an internal loopback interface which is used for inter-process networking. We define one for IPv4 and one for IPv6.
auto enp0s31f6
iface enp0s31f6 inet static

address <public_ip>
netmask <netmask>
up ip link set enp0s31f6 txqueuelen 10000
This is the actual definition of your hardware network interface. enp0s31f6 is my network interface name. Yours is very likely different. If you are wondering what yours is called, check your own interfaces file.
Also this entry is used to specify the external IP Address and additional network configurations. The gateway is typically pretty much the same as your public ip address. The netmask typically contains a lot of 255.
auto vmbr0
iface vmbr0 inet static
bridge-ports none
bridge-stp off
bridge-fd 0

up ip link set vmbr0 txqueuelen 10000
post-up echo 1 > /proc/sys/net/ipv4/ip_forward

post-up echo 1 > /proc/sys/net/ipv4/conf/vmbr0/proxy_arp
post-up iptables -t nat -A POSTROUTING -o enp0s31f6 -j MASQUERADE --source ''
post-down iptables -t nat -D POSTROUTING -o enp0s31f6 -j MASQUERADE --source ''
post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1one 1
vmbr0 is the interface we want to configure for our VMs. Therefor we need to add some rules how the traffic should be managed and which IP-Addresses are valid. Line three is where it gets interesting. The configured address tells the interface which IP-Address it is assigned. This is typically an IP-Address ending with “.1” because it’s the gateway for the hole network (you can also change this to your liking). post-up and post-down is used to execute commands at interface startup or shutdown. As soon as the interface starts we want to enable ip forwarding and proxy arp requests. This is done by writing a 1 into the corresponding file. Also we want to use IP-Tables to configure the forwarding. This happens in the last four lines. If you changed the naming of your upstream interface you also need to change it here. If you decide to use a different network this also has to be changed here.
post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 80 -j DNAT --destination <public_ip> --to-destination
post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 80 -j DNAT --destination <public_ip> --to-destination

post-up iptables -t nat -A PREROUTING -i enp0s31f6 -p tcp --dport 80 -j DNAT --destination <public_ip> --to-destination
post-down iptables -t nat -D PREROUTING -i enp0s31f6 -p tcp --dport 80 -j DNAT --destination <public_ip>
Last but not least I want to mention how port forwarding works with this setup. If you want to expose a port of a virtual machine you will have to create those four entries. The first two create a port forwarding of port 80 to the host with the IP-Address The second two are pretty much the same but enables a vm behind the NAT to reach the public IP Address.

As soon as your configuration file is done you should do a restart. There are other possibilities like the ifup command but I encountered some problems with my VMs. Every time you add a new VM please make sure you only use the vmbr0 interface. Also because there is no DHCP-Server included with this configuration you have to assign IP-Addresses manually. During the configuration you will also be asked to input the gateway and DNS-Server. The gateway is in case of the example If you don’t host your own DNS-Server inside this network, you can use the common DNS-Servers like or or

If you are interested in a setup with IPv6 please check out this article.

I hope you could follow the steps to adjust the example to your needs. Signing off.

WordPress Appliance - Powered by TurnKey Linux