ProxmoxGuide
Flat isometric illustration of a dark server rack marked with a padlock badge, standing inside a glowing square perimeter with four lit corner posts on a grid platform
security

Proxmox Firewall Not Working? host.fw & the Enable Chain

Why Proxmox VE firewall rules do nothing: the three enable switches, where host.fw lives, pve-firewall localnet, and defaults that avoid lockout.

By ProxmoxGuide Editorial · ·Updated · 14 min read

The Proxmox VE firewall is off until you set enable: 1 at datacenter level. Once on, it drops inbound traffic to every node except a built-in list: hosts in the management IPSet keep TCP 8006, the default admin port for the web GUI (https://<node-ip>:8006), plus SSH on 22 and the console ports 5900-5999 and 3128.

Under the hood it is three firewalls stacked on top of each other, and most “it isn’t working” reports are really “it isn’t switched on at the level I think it is.”

  • Three config levels: datacenter (/etc/pve/firewall/cluster.fw), node (/etc/pve/nodes/<nodename>/host.fw), and guest (/etc/pve/firewall/<VMID>.fw).
  • The datacenter switch gates everything. Until it is on, nothing filters, no matter what rules you wrote lower down.
  • Guests need two switches. The guest’s own firewall enable option and a per-NIC firewall checkbox on each virtual network device.
  • Open an SSH session before you enable it. Turning the firewall on blocks inbound traffic to every host by default.
  • Define the management IPSet first. It generates the access rules you would otherwise hand-write and forget.

Where host.fw lives: /etc/pve/nodes/<nodename>/host.fw

The node firewall config file is /etc/pve/nodes/<nodename>/host.fw, one file per node. Substitute the real node name for <nodename>: on a node called pve1 it is /etc/pve/nodes/pve1/host.fw. It lives on the cluster file system, so it replicates to every node automatically, and the datacenter (cluster.fw) and per-guest (<VMID>.fw) files sit beside it.

The three levels and how they nest

The pve-firewall service regenerates the underlying iptables rules whenever one of these files changes, so a rule you write is not live until that regeneration runs.

  • Datacenter — /etc/pve/firewall/cluster.fw. Cluster-wide options, rules applied to all nodes, plus the shared definitions everything else references: security groups, IPSets, and IP aliases.
  • Node — /etc/pve/nodes/<nodename>/host.fw. Host-specific rules and netfilter tuning. Rules at host level take precedence over datacenter rules for the host zone.
  • Guest — /etc/pve/firewall/<VMID>.fw. Per-VM and per-container rules, options, IPSets and aliases.

The defaults across those three files are deliberately asymmetric, and that asymmetry is the source of most confusion:

LevelKeyDefault
Datacenter (cluster.fw)enable0 (off)
Node (host.fw)enable1 (on)
Guest (<VMID>.fw)enable0 (off)

Read that table again, because it explains a very common support thread. The node firewall is already enabled by default. It is simply inert, because the datacenter switch above it is off. Someone writes a careful set of node rules, sees enable: 1 sitting in host.fw, and concludes the firewall is broken. It is not broken. It was never armed.

Why your rules appear to do nothing

There are four distinct ways to get silence out of the Proxmox firewall, and they need different fixes.

1. The datacenter firewall is off. The master switch. Set it in the GUI under Datacenter → Firewall → Options, or directly:

# /etc/pve/firewall/cluster.fw
[OPTIONS]
enable: 1

2. The guest firewall option is off. Each VM or container has its own enable flag, defaulting to 0. Cluster-level rules do not implicitly filter guest traffic.

3. The per-NIC firewall checkbox is off. This is the one that burns people. Every virtual network device carries its own firewall flag so you can filter net0 and leave net1 alone. That checkbox is required in addition to the guest’s general enable option. A VM with enable: 1 in its .fw file and an unchecked NIC is unfiltered on that interface. Check it in the VM’s Hardware tab on the network device, not in the Firewall tab where you have been staring.

4. You wrote FORWARD rules on the stock backend. The documentation is blunt here: any forward rules are ignored by the stock pve-firewall and have no effect. Same for anything defined at the SDN VNet level, which is forward-direction only by nature. Both need the newer nftables backend, discussed at the end.

When you want ground truth rather than guesswork, two commands settle it:

pve-firewall status

This reads and compiles every rule, so it surfaces configuration errors and tells you whether the firewall is actually running.

iptables-save

This shows the chains and rules genuinely loaded in the kernel. If your rule is not in that output, it was never applied, so check the enable flags before you start rewriting the rule itself. One caveat: iptables-save only reflects the classic backend. If you have switched a node to the nftables backend described at the end, its rules live in nftables and you want nft list ruleset instead.

Proxmox and iptables: what pve-firewall generates

The stock backend is iptables-based: pve-firewall compiles the .fw files into iptables rules on every node, plus ebtables rules while the datacenter ebtables option keeps its default of 1. Its chains carry a PVEFW- prefix and hang off the built-in ones (-A INPUT -j PVEFW-INPUT), with node rules in PVEFW-HOST-IN, as the dump in this Proxmox forum thread shows. To see only Proxmox’s rules, or what it would load without applying anything:

iptables-save | grep PVEFW
pve-firewall compile

Treat those chains as generated output and edit the .fw files instead. Guests on Linux bridges also get extra fwbrX firewall bridges under this backend, which is why ip link lists interfaces you never created.

Zones and directions

Proxmox groups traffic into three zones, and each zone supports a different set of directions. Mismatching them is failure mode four above.

  • Host — traffic to and from a node, or forwarded by it. Rules can be defined at datacenter or host level. Supports IN, OUT and FORWARD.
  • VM — traffic to and from a VM or container. Supports IN and OUT only. There is no forward concept here.
  • VNet — traffic passing through an SDN VNet, guest to guest or host to guest. FORWARD only, since all of it is transit traffic.

Rules are direction plus action (ACCEPT, DROP, REJECT), optionally via a macro. Prefix a line with | to disable it without deleting it, which is far better practice than commenting rules out and losing them.

[RULES]
IN SSH(ACCEPT) -i net0 -source 192.168.2.192
IN ACCEPT -p tcp -dport 443 -source +management
|IN SSH(ACCEPT) -i net0

Safe defaults: enabling without locking yourself out

Enabling the datacenter firewall blocks inbound traffic to all hosts by default, with a small set of built-in exceptions. Do this in the right order.

Step one: open an SSH session to a node and leave it open. Established connections are exempt from the default rules, so that session survives the change and gives you a way back in. This is the official advice and it is worth following literally.

Step two: create the management IPSet before flipping the switch. This standard IPSet applies to host firewalls only, and the addresses in it are permitted to do normal management work: the web GUI, VNC, SPICE and SSH. Defining it generates the access rules automatically, which is strictly better than hand-writing four allow rules and forgetting one.

# /etc/pve/firewall/cluster.fw
[IPSET management]
192.168.2.0/24 # admin LAN

The local cluster network is added to this set automatically so inter-node communication keeps working.

Step three: sanity-check the auto-detected local network. Proxmox defines a local_network alias by autodetection and builds the cluster-communication rules (corosync, API, SSH) around it. Confirm what it resolved to:

pve-firewall localnet

If you run a single node on a public network, autodetection can be far too generous. Override it explicitly:

[ALIASES]
local_network 1.2.3.4 # pin to the single host IP

Step four: enable, then verify from a second machine while the first SSH session is still open.

With input blocked, loopback and established connections keep working, and a small built-in set of ports stays reachable from your management hosts. Two matter for not locking yourself out: TCP 8006 (web GUI) and TCP 22 (SSH). The port-level exceptions are tabulated in the next section; the Ceph and Backup Server ranges that are not auto-permitted are tabulated with their purpose in every port Proxmox VE listens on. A correctly configured management IPSet is therefore nearly the whole job for a management-plane firewall; anything else on the host, such as a reverse proxy, a metrics exporter, or Proxmox Backup Server traffic, needs its own rule.

Proxmox default ports, and which stay open after enabling

TCP 8006 is the default admin port and one of the few the firewall keeps open for management hosts without a rule of yours. The table merges the port list and default rules from the admin guide’s firewall chapter (docs version 9.2.12, checked September 2026):

PortProtocolServiceOpen after enabling?
8006TCPWeb GUI and API over HTTPSYes, from management
22TCPSSH, also used for cluster actionsYes, from management
5900-5999TCPVNC web console (WebSocket)Yes, from management
3128TCPSPICE proxyYes, from management
60000-60050TCPLive migrationYes, from management
5405-5412UDPCorosync cluster trafficYes, within the cluster network
111UDPrpcbindNo built-in exception
25TCPsendmailNot applicable, outgoing only

“From management” means the source must be in that IPSet. The cluster network is added to it automatically, so node-to-node SSH and migration survive the switch-on; a laptop on another subnet does not.

Opening a port range, and building IPSets

-dport takes a port (0-65535), a service name from /etc/services, a colon range such as 5900:5999, or a comma-separated list of ports and ranges. -source and -dest take an IP, CIDR, alias, IPSet (+name), hyphenated address range or comma-separated list; the rule reference asks you not to mix IPv4 and IPv6 in one list.

[RULES]
IN ACCEPT -p tcp -dport 8000:8010 -source +management
IN ACCEPT -p tcp -dport 80,443,8443 -source 192.168.2.10-192.168.2.20

Your own IPSets use the same [IPSET name] block as management, with IPs, CIDR networks or aliases as entries (IPSet API schema). The third reserved name, ipfilter-net<N>, is a per-NIC set: outgoing guest traffic whose source IP is not in it is dropped.

Before reloading, ask the compiler which rule a packet would hit:

pve-firewall simulate --source 192.168.2.50 --dport 8006

simulate defaults to TCP from the outside zone to the host zone and checks rules only, not the kernel routing table (pve-firewall man page).

Guest rules are not host rules

The most important thing to internalise about guest firewalls: the host exceptions do not apply to them. Guests inherit the datacenter drop and reject behaviour, but not the accept exceptions that keep the GUI and SSH reachable on nodes. The management IPSet does nothing for a VM. The only exceptions a guest gets are the ones its own options produce, for DHCP, NDP, router advertisement and MAC/IP filtering, depending on how it is configured. Enable a guest firewall with a drop policy and no rules of your own, and that guest goes dark for everything else. Plan its ruleset before you enable it.

A few guest options are worth knowing rather than discovering:

  • macfilter is on by default and blocks a guest from spoofing MAC addresses.
  • ipfilter adds implicit ipfilter-net<id> sets per interface to prevent IP spoofing. For containers, configured addresses are added automatically.
  • ndp is on by default, at host level as well as guest level, so IPv6 neighbour discovery works. IPv6 is filtered transparently alongside IPv4, so you do not maintain a parallel ruleset.
  • radv is what lets a guest advertise itself as a router, and a guest cannot do that unless you set it. Sending router solicitations and receiving advertisements works without it.
  • dhcp needs enabling if the guest gets its address by DHCP and you have a restrictive policy.

For anything you run more than once, define a security group at datacenter level and reference it from each guest rather than duplicating rules; the webserver group in the next section shows the pattern. This scales well across a fleet of LXC containers and VMs.

There is also a standard blacklist IPSet at cluster level whose addresses are dropped by every host and guest firewall. Useful, but treat it as a scalpel for specific abusers, not a threat feed.

Common rules, ready to adapt

Most homelab and small-cluster firewalls are the same handful of rules at each level. Below are the ones worth having in front of you, written as config files because the GUI writes exactly the same thing. Change every address to yours before applying any of it.

Datacenter — /etc/pve/firewall/cluster.fw. The master switch, the shared definitions, and a default-deny inbound policy.

[OPTIONS]
enable: 1
policy_in: DROP
policy_out: ACCEPT

[ALIASES]
admin_lan 192.168.2.0/24
backup_host 192.168.2.40

[IPSET management]
192.168.2.0/24 # admin LAN, generates host management access rules

[group webserver]
IN ACCEPT -p tcp -dport 80
IN ACCEPT -p tcp -dport 443

[group db-internal]
IN ACCEPT -p tcp -dport 5432 -source dc/admin_lan

Security groups defined here are referenced by name from any guest, which is how you avoid maintaining the same two rules in forty .fw files.

Node — /etc/pve/nodes/<nodename>/host.fw. The management IPSet already covers the GUI, SSH, VNC, SPICE, and migration, so host rules are for the extra services you actually run on the hypervisor.

[OPTIONS]
enable: 1
log_level_in: info

[RULES]
IN ACCEPT -p tcp -dport 8007 -source +dc/management # Proxmox Backup Server GUI
IN ACCEPT -p tcp -dport 9100 -source dc/admin_lan   # metrics exporter
IN ACCEPT -p udp -dport 123 -source dc/admin_lan    # only if this node serves NTP to the LAN
|IN ACCEPT -p tcp -dport 3000 -source dc/admin_lan   # disabled, kept for later

Guest — /etc/pve/firewall/<VMID>.fw. None of the host exceptions apply here.

[OPTIONS]
enable: 1
policy_in: DROP
policy_out: ACCEPT
macfilter: 1
ipfilter: 1
dhcp: 1

[RULES]
GROUP webserver
IN SSH(ACCEPT) -source dc/admin_lan
IN ACCEPT -p tcp -dport 5432 -source 192.168.2.51 # only the app VM
IN ACCEPT -p icmp -log nolog

Three details in that block are worth spelling out. Cluster-level definitions are referenced from a guest with a dc/ prefix for aliases and +dc/ for IPSets, because a bare name resolves to the guest’s own definitions first. dhcp: 1 is required if the guest leases its address and you are running a drop policy, or it will boot with no network and look like a firewall bug. And GROUP webserver pulls in the security group verbatim, so editing that group at datacenter level changes every guest that references it at once.

The minimum viable homelab set. If you want the shortest path to a firewall that is on and not in your way: enable at datacenter with policy_in: DROP, define the management IPSet with your admin subnet, leave node rules empty, and enable guest firewalls only on the VMs that are actually exposed. That gets you a filtered management plane without forty rule files to maintain.

How to disable the Proxmox firewall

Each level has its own switch; turn off only the one you mean:

  1. Whole cluster: enable: 0 under [OPTIONS] in cluster.fw, or Datacenter → Firewall → Options. That is the install default: nothing filters.
  2. One node: enable: 0 in its host.fw. This covers host rules only; guests keep theirs.
  3. One guest: enable: 0 in <VMID>.fw, or untick one NIC’s firewall checkbox, which removes firewall=1 from its netN line.
  4. Locked out, at the console: pve-firewall stop, which the man page warns “actively removes all Proxmox VE related iptable rules rendering the host potentially unprotected”. The config is untouched, so fix it before the service starts again.

Logging, and what it will not tell you

Logging is off by default. Set a log level for incoming or outgoing traffic under Firewall → Options, per host or per guest, and read it in Firewall → Log. Two caveats save a lot of confusion:

  • The log level does not control how much traffic is logged. It sets a numeric LOGID prefix for filtering. Only some dropped or rejected packets are logged by the standard rules at all, so a quiet log is not proof that nothing was blocked.
  • Log lines are formatted VMID LOGID CHAIN TIMESTAMP POLICY: PACKET_DETAILS. For host firewall entries, VMID is 0.

For per-rule granularity, append -log <level> to an individual rule. That is independent of the zone’s configured level and is the right tool when you are chasing one specific drop.

The nftables backend

Proxmox offers proxmox-firewall, an nftables-based reimplementation that reads the same configuration files and format. It is not what runs by default: install the proxmox-firewall package, set nftables: 1 in the node’s host.fw, and restart every guest on the node to complete the switch, which makes it a maintenance-window job. It is what you need for FORWARD rules and SDN VNet rules, both of which the classic backend ignores. It is still labelled a tech preview and the documentation explicitly states it is not suited for production use, so treat forward-direction filtering as not yet available if the cluster matters.

If you do trial it on a lab node, know the behavioural differences going in: REJECT becomes a drop for guest traffic, and guest rules are evaluated even for connections that already hold conntrack entries.

Next steps

See also

FAQ

what is the default port for proxmox ve?

TCP 8006. The web GUI and API listen there over HTTPS, so after installation you browse to https://<node-ip>:8006 and log in as root in the PAM realm, as the installation chapter describes. SSH stays on 22, and the console uses 5900-5999, plus 3128 for SPICE.

how do i restrict access to the proxmox admin port?

Add your admin subnet to the management IPSet and enable the firewall, or use pveproxy’s own access list. In /etc/default/pveproxy, set ALLOW_FROM="192.168.2.0/24", DENY_FROM="all" and POLICY="allow", then run systemctl restart pveproxy.service spiceproxy.service. Addresses matching both lists are allowed and everything else is refused, per the pveproxy man page.

what does ndp do in the proxmox firewall?

It lets IPv6 Neighbor Discovery Protocol packets in and out. IPv6 replaced ARP with NDP, which works at the IP level using link-local addresses derived from each interface’s MAC. The ndp option defaults to on for both hosts and guests, so leave it enabled anywhere IPv6 runs, especially behind a DROP policy.

can i add my own iptables rules on a proxmox host?

Not inside the PVEFW- chains: pve-firewall owns them and rewrites them when the configuration changes, so hand-added rules there do not last. Express the rule in the .fw files wherever the syntax allows. The nftables backend is friendlier, managing only its proxmox-firewall and proxmox-firewall-guests tables and inviting you to add your own, though it remains a tech preview.

Sources

  1. Proxmox VE Firewall (Wiki)
  2. Proxmox VE Administration Guide: Firewall
  3. pve-firewall(8) manual page
  4. pveproxy(8) manual page
  5. Proxmox VE Administration Guide: Installation
  6. pve-firewall source: IPSet API (IPSet.pm)
  7. Proxmox Support Forum: PVE-Firewall doesn't have any effect

Related