The Proxmox firewall is a layered iptables/nftables system with three levels: cluster (Datacenter), host (node), and VM/CT. Rules cascade from top to bottom — a packet allowed at the cluster level still has to pass node-level and CT-level rules to reach the service. Most homelab guides skip this entirely and leave Proxmox open to anything that can reach the LAN. This post covers a real, working rule set for a 4-node cluster.
The Proxmox firewall can lock you out of your own cluster if you enable it before adding allow rules. Follow this guide in order — add rules first, enable firewall second.
How the Proxmox firewall layers work
A packet traverses all three layers in sequence. If any layer drops it, the packet is discarded.
Task 1: Create IPSETs for your trusted subnets
IPSETs let you group IP ranges into named sets so your rules stay readable. You reference the set name in rules instead of repeating IP ranges.
In the Proxmox web UI: Datacenter → Firewall → IPSet → Create.
Create two sets:
Set 1: homelan
Add your home LAN CIDR (e.g. 192.168.1.0/24). This is the network your router, laptop, phone, and desktop are on.
Set 2: lablan
Add your cluster’s management network CIDR (e.g. 10.0.0.0/24). This is the subnet all four Proxmox nodes use.
Set 3: tailscale (optional)
Add your Tailscale subnet (typically 100.64.0.0/10) to allow Tailscale peer traffic.
Task 2: Configure Datacenter-level rules
In Datacenter → Firewall → Rules → Add:
| # | Direction | Action | Source | Proto | Ports | Comment |
|---|---|---|---|---|---|---|
| 1 | in | ACCEPT | +lablan |
any | any | Full lab LAN access |
| 2 | in | ACCEPT | +homelan |
tcp | 8006, 22 | Web UI + SSH from home |
| 3 | in | ACCEPT | +tailscale |
any | any | Tailscale peers |
| 4 | in | ACCEPT | — | any | — | Corosync (cluster comms) — only if using cluster firewall |
The + prefix references an IPSET. +lablan means “any IP in the lablan set.” This is how Proxmox firewall distinguishes sets from literal IPs.
Datacenter → Firewall → Options:
- Firewall: Yes
- Input policy: DROP
- Output policy: ACCEPT (leave this as-is — hosts need to initiate outbound connections)
Click Save. The firewall is now active with your rules.
Open a second browser tab to the Proxmox web UI before enabling. If you lose access after enabling, you can connect via physical console or IPMI to disable the firewall from the command line.
To disable from the command line if locked out:
pvesh set /cluster/firewall/options --enable 0
Task 3: Configure node-level rules
Node-level rules apply to traffic reaching the Proxmox hypervisor itself (not containers). You typically want slightly tighter rules here.
Select any node (e.g. pvelab01) → Firewall → Options.
Key options:
- SMURFS: Enable (blocks SMURF attacks)
- TCP flags filter: Enable (blocks malformed TCP)
- NDP: Enable if using IPv6; can disable for IPv4-only setups
- Log level for incoming:
nolog(you can set toinfofor debugging, but it floods the log)
Node-level rules inherit from the datacenter unless you override them. For most home clusters, no additional node-level rules are needed if the datacenter rules are correct.
Task 4: Configure container-level firewall rules (optional)
Container-level rules give per-workload isolation. Useful for public-facing services, sensitive data (password managers), or multi-tenant scenarios.
Select any container → Firewall → Options → Firewall: Yes.
Example rules for a web-facing service (e.g. Vaultwarden on CT 111):
| Direction | Action | Source | Proto | Ports | Comment |
|---|---|---|---|---|---|
| in | ACCEPT | +lablan |
tcp | 80 | Web UI from LAN |
| in | ACCEPT | +tailscale |
tcp | 80 | Web UI via Tailscale |
| in | DROP | any | any | any | Deny everything else |
With this ruleset, the container only accepts web traffic from your LAN or Tailscale — not from any other container or untrusted source.
Task 5: Verify the firewall is working
From a device on your home LAN:
# Proxmox web UI should be accessible
curl -k -I https://10.0.0.73:8006
# SSH should work
ssh root@10.0.0.70 "hostname"
From a device that should be blocked (e.g., a phone not on the LAN, or port scan from outside):
# This should time out if firewall is working
nmap -p 8006 10.0.0.73
# You can test from a different subnet within your own network
# e.g. from an IoT VLAN that is not in lablan or homelan
Dropped packets time out rather than returning a refusal — this is correct behavior. “Connection refused” would mean the port is reachable but nothing is listening.
Firewall log access
# Recent firewall events
journalctl -k --grep="PVEFW" | tail -40
# Live view
journalctl -k -f --grep="PVEFW"
Each dropped packet logs with the source IP, destination, port, and which rule caused the drop. This is the first place to look if traffic that should be allowed is being blocked.
Summary: the minimal safe rule set
For a homelab cluster accessible from one home network and Tailscale:
- Datacenter level: ACCEPT lablan (any), ACCEPT homelan (ports 8006, 22), ACCEPT tailscale (any) — input policy DROP
- Node level: inherit from datacenter, enable TCP flags filter + SMURFS
- CT level: optional per-service, especially for any service with outbound internet exposure
This blocks everything not on your trusted subnets while keeping full management access from anywhere you run Tailscale.
Related posts:
- Proxmox Security Hardening: SSH Keys, Fail2ban, and TOTP — complement the firewall with SSH hardening and 2FA
- Proxmox LXC Networking: Bridges, VLANs, and Static IPs — understand how container network interfaces interact with firewall zones
- Tailscale Subnet Router: Remote Access to Your Entire Homelab — the Tailscale subnet that your ACCEPT rule above allows
- Proxmox Cluster Setup: Quorum, Corosync, and Node Joining — the cluster whose Corosync ports this firewall protects