This example is based on a Hetzner machine with a single public facing IP, but should apply to any such scenario.
The public IP should be shared with the Hypervisor that is installed on a Bare Metal host, that has only one Ethernet IF. In the case of Proxmox, firewall rules need to be configured, to only allow certain incoming ports.
We also need NAT and Masquerading, to forward ports to a virtualized firewall running on the Proxmox server.
This concerns Proxmox 9.x+ since nftables support is still in Beta and was only added recently. The same concepts should be applicable to iptables, but the commands and files referenced will be different.
Install Proxmox as you normally would and connect to it through the public IP.
Currently, nft is still in beta, therefore you need to explicitly install and enable support for it in Proxmox. To do so, please also refer to https://pve.proxmox.com/pve-docs/chapter-pve-firewall.html#pve_firewall_nft.
After installing nftables proxmox-firewall ensure that you do not lock yourself out. Create rules that allow your IP to connect to Proxmox via SSH!
You also need to create Rules (Cluster, Node, etc. Scoping is described in the Proxmox docs) for any ports that you'd like to forward to your internal/virtualized router/firewall.
When everything works and all unrequired Ports are closed, proceed.
Install your preferred Firewall/Router as a VM on Proxmox and create a bridge Network between Proxmox and that VM. That will be your VM's WAN Network.
In nftables you have to create the following ruleset:
table ip nat {
chain prerouting {
type nat hook prerouting priority filter; policy accept;
# any ports that you want to nat to your firewall vm
udp dport 12345 dnat to 192.168.0.1:12345 # to <ip of your firewall on bridge IF>
iifname "<name of public ethernet IF>" tcp dport { 80, 443 } dnat to 192.168.0.1 # different kind of rule
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip daddr 192.168.0.1 masquerade
ip saddr 192.168.0.1/32 oif "<name of public ethernet IF>" masquerade # outgoing traffic is masqueraded to public eth IF
}
}
By default proxmox-firewall does not consider any nftables config files, so you need to edit the service file to include your nft config.
systemctl edit proxmox-firewall
[Service]
ExecStartPost=/usr/sbin/nft -f /etc/nftables.conf
Important: Remember to also allow any port that you forward in your proxmox firewall ruleset (via GUI).
Set your incoming WAN rules accordingly. The rest should now work