Struggling to expose Proxmox VMs publicly via WireGuard + VPS routed IPs (routing loop & connectivity issues)

Binayak01

New Member
Feb 4, 2026
3
0
1
Hello Proxmox community,

I’m facing a complex networking issue and would appreciate guidance from anyone experienced with routed public IPs + VPN + Proxmox.

Current Setup​


I have:

  • Local server: Dell PowerEdge running Proxmox (behind NAT / LAN)
  • Remote VPS (Cloudzy):
    • Main public IP: 144.172.116.81
    • Extra routed public IPs:
      • 144.172.107.119
      • 144.172.115.159

WireGuard tunnel between:

  • Cloudzy VPS WG IP: 10.50.0.1
  • Proxmox WG IP: 10.50.0.2

Proxmox bridges:

  • vmbr0 → main LAN
  • vmbr1 → internal VM network (10.10.10.0/24)

Goal:
Expose Proxmox VMs directly to the internet using the extra Cloudzy public IPs and allow SSH/access via those IPs (basically: VPS routes public IP → WireGuard → Proxmox → VM).


What I Tried​

  1. WireGuard tunnel works (Proxmox ↔ VPS reachable).
  2. Added routed IPs on Cloudzy pointing to WireGuard.
  3. Enabled IP forwarding on both sides.
  4. Added routes like:

On VPS:

ip route add 144.172.107.119 via 10.50.0.2
ip route add 144.172.115.159 via 10.50.0.2

On Proxmox:
net.ipv4.ip_forward=1

  1. Assigned private IPs to VMs (10.10.10.x) and attempted DNAT / 1:1 NAT.
  2. Also attempted bridging public IP directly to VM.

Problems​

  • Routing loops appear.
  • Sometimes Proxmox loses access over VPN.
  • VM can’t reach internet properly.
  • Public IP does not respond when assigned to VM.
  • After manipulating routes (especially 10.50.0.0/24), Proxmox VPN access drops.
  • Traffic seems to bounce between WG and vmbr bridges.
I’m clearly missing something fundamental in the routing design.

What I’m Trying to Achieve​


I want something similar to Hetzner/OVH routed IP behavior:

  • Cloud VPS acts as gateway
  • Extra public IPs forwarded to Proxmox
  • Each VM gets its own public IP
  • No port forwarding — real public IP per VM
  • SSH directly to VM via public IP

Questions​

  1. Should I be using 1:1 NAT or true routed IPs + bridge?
  2. Is Linux policy routing required here?
  3. Should VMs use Cloudzy gateway or Proxmox as gateway?
  4. What is the cleanest architecture for this setup?
  5. Has anyone successfully done:
    VPS → WireGuard → Proxmox → VM (public IP)?

Any example configs or diagrams would be hugely appreciated.


Thanks in advance — this has been looping me for days.


— Binayak
 
If I wanted to trick VPS provider I would look does he use ARP. In that case I would use L2 VPN (wireguard is only L3): Cloudzy VPS eth0 -> bridge with VPN -> VPN L2 -> Proxmox -> bridge with VPS -> VPS
 
I could give you my setup this evening after work, I have a similar setup: Server collocated in public datacenter -> Wireguard CT -> One Ip.
 
Sure It would be helpful for me and I would really appreciate it
So my setup:

Wireguard container:

/etc/wireguard/wg0.conf:
Code:
[Interface]
Address = 10.10.10.1/24
ListenPort = 51820

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; iptables -t nat -A PREROUTING -i %i -p tcp --dport 8006 -j DNAT --to-destination 192.168.100.1:8006

PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; iptables -t nat -D PREROUTING -i %i -p tcp --dport 8006 -j DNAT --to-destination 192.168.100.1:8006

PrivateKey = SNd...

[Peer]
PublicKey = QpI...
AllowedIPs = 10.10.10.200/32

[Peer]
PublicKey = 1q2...
AllowedIPs = 10.10.10.201/32

[Peer]
PublicKey = rsd...
AllowedIPs = 10.10.10.202/32

The wireguard container has keyctl=1 and nesting=1 options.

Pve network:

Code:
auto lo
iface lo inet loopback

iface eno2 inet manual

iface eno1 inet manual

iface enxbe3af2b6059f inet manual

auto vmbr0
iface vmbr0 inet static
        address PUBLIC_IP/24
        gateway GATEWAY
        bridge-ports eno2
        bridge-stp off
        bridge-fd 0

        #ENABLE FORWARDING
        post-up sysctl -w net.ipv4.ip_forward=1

        #LAN ROUTING
        post-up iptables -t nat -A POSTROUTING -s '192.168.100.0/24' -o vmbr0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '192.168.100.0/24' -o vmbr0 -j MASQUERADE

        #FORWARD WIREGUARD PORT
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p udp --dport 51820 -j DNAT --to-destination 192.168.100.2:51820
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p udp --dport 51820 -j DNAT --to-destination 192.168.100.2:51820

        #FORWARD PORT 3000
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.30:3000
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 3000 -j DNAT --to-destination 192.168.100.30:3000

        post-up iptables -I FORWARD 1 -p tcp -d 192.168.100.30 --dport 3000 -j ACCEPT
        post-down iptables -D FORWARD -p tcp -d 192.168.100.30 --dport 3000 -j ACCEPT

        #FORWARD HTTP & HTTPS PORT
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 80 -j DNAT --to-destination 192.168.100.10:80
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 80 -j DNAT --to-destination 192.168.100.10:80

        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 443 -j DNAT --to-destination 192.168.100.10:443
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 443 -j DNAT --to-destination 192.168.100.10:443

        post-up iptables -I FORWARD 1 -p tcp -d 192.168.100.10 --dport 80 -j ACCEPT
        post-down iptables -D FORWARD -p tcp -d 192.168.100.10 --dport 80 -j ACCEPT

        post-up iptables -I FORWARD 1 -p tcp -d 192.168.100.10 --dport 443 -j ACCEPT
        post-down iptables -D FORWARD -p tcp -d 192.168.100.10 --dport 443 -j ACCEPT

        #FORWARD PORT 18080
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 18080 -j DNAT --to-destination 192.168.100.30:18080
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 18080 -j DNAT --to-destination 192.168.100.30:18080

        post-up iptables -I FORWARD 1 -p tcp -d 192.168.100.30 --dport 18080 -j ACCEPT
        post-down iptables -D FORWARD -p tcp -d 192.168.100.30 --dport 18080 -j ACCEPT


        #FORWARD PORT 4242
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 4242 -j DNAT --to-destination 192.168.100.30:4242
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 4242 -j DNAT --to-destination 192.168.100.30:4242

        post-up iptables -I FORWARD 1 -p tcp -d 192.168.100.30 --dport 4242 -j ACCEPT
        post-down iptables -D FORWARD -p tcp -d 192.168.100.30 --dport 4242 -j ACCEPT

        #FORWARD PORT 9130
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 9130 -j DNAT --to-destination 192.168.100.50:9130
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 9130 -j DNAT --to-destination 192.168.100.50:9130

        post-up iptables -I FORWARD 1 -p tcp -d 192.168.100.50 --dport 9130 -j ACCEPT
        post-down iptables -D FORWARD -p tcp -d 192.168.100.50 --dport 9130 -j ACCEPT

        #VPN REPLIES
        post-up ip route add 10.10.10.0/24 via 192.168.100.2 dev vmbr1
        post-down ip route del 10.10.10.0/24 via 192.168.100.2 dev vmbr1

auto vmbr1
iface vmbr1 inet static
        address 192.168.100.1/24
        bridge-ports none
        bridge-stp off
        bridge-fd 0

source /etc/network/interfaces.d/*