Proxmox VE — Built-in Firewall

FIREWALL

Proxmox's iptables-based firewall — three-tier configuration (Datacenter, host, VM/CT), security groups, rule syntax, and enabling per-interface.

proxmoxfirewalliptablessecuritynetwork-security

Overview

Proxmox VE ships with a built-in firewall that is fully integrated into the management GUI. It is implemented using iptables (and ebtables for VM-level Ethernet filtering) and is managed by the pve-firewall service, which translates Proxmox firewall rules into actual iptables rules and applies them in real time.

The firewall is disabled by default — no rules are active until you explicitly enable it. All rule changes take effect immediately after saving — no service restart is required.

The Three-Tier Architecture

Proxmox’s firewall has a three-layer hierarchy. Rules at higher levels cascade down to lower levels:

Datacenter (cluster-wide)
  └── Node / Host (per-node)
        └── VM / Container (per-workload)

Datacenter level — rules apply to the entire cluster. A rule created here affects all nodes and all VMs across every node. This is where you define cluster-wide policies such as “all VMs must allow inbound port 443” or “no node accepts SSH from outside the management subnet.”

Node (Host) level — rules apply to a specific Proxmox node and cascade to VMs running on that node. Useful for node-specific access policies that do not need to apply cluster-wide.

VM / Container level — rules apply to a single VM or container. These rules follow the VM as it migrates between nodes. A firewall rule applied to VM 101 will be enforced on whichever node VM 101 is running on.

Critical Warning: Enable Rules Before Enabling the Firewall

Do not enable the Datacenter firewall without first creating rules to allow:

The default incoming policy when the firewall is enabled is DROP. Enabling the firewall before creating allow rules will lock you out of the GUI. Recovery requires console access to the physical node.

Enabling the Firewall

The firewall must be enabled at each tier separately. Enabling it at the Datacenter level does not automatically enable it on nodes or VMs — each must be explicitly enabled.

Enabling at Datacenter level: Datacenter → Firewall → Options → Firewall: Yes

Enabling at Node level: Node → Firewall → Options → Firewall: Yes

Enabling at VM level: VM → Firewall → Options → Firewall: Yes

Additionally, firewall filtering on a VM only applies to the VM’s network interfaces that have Firewall enabled in the VM’s hardware configuration. Go to VM → Hardware → Network Device → Edit and ensure the Firewall checkbox is ticked for each interface you want to protect.

Rule Anatomy

Each firewall rule has these properties:

PropertyOptionsDescription
Directionin, outInbound (to the zone) or outbound (from the zone)
ActionACCEPT, REJECT, DROPWhat to do with matching traffic
Protocoltcp, udp, icmp, anyLayer 4 protocol
SourceIP, CIDR, IPSet, AliasWhere traffic comes from
DestinationIP, CIDR, IPSet, AliasWhere traffic is going
PortSingle port or rangeDestination port (e.g., 80, 1024:65535)
MacroPre-built service definitionAuto-fills protocol and port for common services
CommentFree textRule documentation

Action semantics:

DROP is preferred over REJECT for public-facing interfaces because it reveals less information about the host. REJECT is more useful in internal networks where you want fast failure rather than timeout delays.

Disabling Individual Rules

Prefix a rule with | (pipe character) in the configuration file to disable it without deleting it. In the GUI, toggle the Enable checkbox per rule. Disabled rules appear greyed out in the GUI and have a | prefix in the config file.

Built-in Macros

Macros are pre-defined rule templates for common services. Selecting a macro in the GUI automatically fills in the correct protocol and port number. You only need to specify direction, action, and optionally source/destination.

Common macros include:

MacroProtocolPort
SSHTCP22
HTTPTCP80
HTTPSTCP443
DNSUDP53
PingICMP
FTPTCP21
MySQLTCP3306
VNCTCP5900–5999
NTPUDP123

The FTP macro only works with passive mode FTP. Active mode FTP requires additional rules for the data channel, which is dynamically assigned.

Default Policies

Each firewall zone has independent default policies for inbound (INPUT) and outbound (OUTPUT/FORWARD) traffic. These apply when no specific rule matches.

The recommended starting configuration:

This is the classic default-deny inbound / default-allow outbound posture. Outbound traffic restrictions are less common but useful in high-security environments where VMs should not be able to reach arbitrary external addresses.

Security Groups

Security groups are reusable sets of firewall rules that can be applied to any firewall zone. Instead of recreating the same set of rules on every VM that runs a web server, you define the rules once in a security group and apply the group to each VM.

Creating a security group: Security groups are created at the Datacenter level (Datacenter → Firewall → Security Group → Create). Enter a name — for example, webserver.

Add rules to the group. A webserver group might contain:

IN ACCEPT -macro SSH
IN ACCEPT -macro HTTP
IN ACCEPT -macro HTTPS

Applying a security group to a zone: In any firewall rule dialog (Datacenter, node, or VM), you can select a security group as the action instead of ACCEPT/DROP. The group’s rules are inserted at that position in the rule chain.

Groups created at the Datacenter level are available in all zones. Groups created at the VM level are only available for that specific VM.

IP Sets

IP sets are named collections of IP addresses and subnets that can be referenced in firewall rules. Instead of writing a separate rule for each management workstation’s IP address, you define them in an IP set and reference the set name.

IP sets are created at Datacenter → Firewall → IPSet → Create. Name the set (e.g., management_hosts), then add individual IPs and CIDR subnets.

In rules, IP sets are referenced with a + prefix:

IN ACCEPT -p tcp -dest +management_hosts -dport 8006
IN ACCEPT -macro SSH -dest +management_hosts

IP sets created at the Datacenter level are available cluster-wide. IP sets created at the VM level are only available for that VM’s rules.

IP set naming: Use alphanumeric characters, hyphens, and underscores only. IP sets appear in the GUI’s source/destination dropdowns with a + prefix to distinguish them from single IPs.

Aliases

Aliases map a human-readable name to a single IP address or CIDR network. They are simpler than IP sets (one alias = one address) and are especially useful for IPv6 addresses (where typing 2001:db8::1 repeatedly is error-prone).

Create aliases at Datacenter → Firewall → Aliases. Examples:

ProxmoxNet 172.16.2.0/24
CephNet 192.168.20.0/24
BackupServer 192.168.10.200

Reference aliases directly by name in rule source/destination fields (without a + prefix — that prefix is specific to IP sets).

Datacenter-level aliases are usable in rules at all zones.

Configuration Files

All firewall configuration is stored in /etc/pve/firewall/ (inside pmxcfs, replicated to all cluster nodes):

FileZone
/etc/pve/firewall/cluster.fwDatacenter-level rules
/etc/pve/nodes/<name>/host.fwNode-level rules
/etc/pve/firewall/<vmid>.fwVM/Container-level rules

cluster.fw Structure

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

[ALIASES]
ProxmoxNet 172.16.2.0/24
CephNet 192.168.20.0/24

[IPSET proxmox_nodes]
172.16.2.1
172.16.2.2
172.16.2.3

[RULES]
IN ACCEPT -i vmbr0 -p tcp -dport 8006    # Proxmox GUI
IN ACCEPT -macro SSH -dest +proxmox_nodes # SSH to management IPs only
|IN ACCEPT -p icmp                         # ICMP (disabled — note the | prefix)

[group webserver]
IN ACCEPT -macro HTTPS
IN ACCEPT -macro HTTP
IN ACCEPT -macro SSH

Sections in the file are delimited by square-bracket headers. Rules are listed one per line in the [RULES] section. Security group definitions appear as [group <name>] sections.

Emergency Recovery from Lockout

If you lock yourself out of the GUI by enabling the firewall before creating allow rules, recover by:

  1. Access the node via physical console or IPMI/iDRAC
  2. Edit the cluster firewall config directly:
    nano /etc/pve/firewall/cluster.fw
  3. Change enable: 1 to enable: 0
  4. The pve-firewall service polls the config file and will disable the firewall within seconds — no service restart required

Stateful Connection Tracking

The Proxmox firewall uses stateful connection tracking via the Linux netfilter nf_conntrack module. This means:

Two important tunables for high-traffic nodes (accessible at Node → Firewall → Options):

nf_conntrack_max — maximum number of simultaneous tracked connections. Default is 65536. Web servers or DNS servers handling thousands of concurrent connections may need this increased:

sysctl -a | grep nf_conntrack_max      # Check current value
sysctl -a | grep nf_conntrack_count    # Check current live connection count

nf_conntrack_tcp_timeout_established — how long an idle established TCP connection stays in the tracking table. Default is 432000 seconds (5 days). Reduce this for environments with many short-lived connections to prevent table exhaustion.

VM-Specific Options

At the VM firewall level, several additional options are available:

OptionDefaultDescription
DHCPOffAllow DHCP traffic (UDP 67/68); enable if this VM is a DHCP server
MAC filterOnPrevent MAC address spoofing from the VM; drops frames with unexpected source MACs
Input policyDROPDefault action for inbound traffic not matching any rule
Output policyACCEPTDefault action for outbound traffic not matching any rule

The MAC filter is enabled by default and should remain enabled. It uses ebtables to enforce that VMs can only send traffic from their assigned MAC address. This prevents a compromised VM from impersonating another VM’s MAC address on the same bridge.

Firewall Service Management

The pve-firewall service manages the lifecycle of all iptables rules:

pve-firewall start      # Enable and load rules
pve-firewall stop       # Disable and flush all Proxmox firewall rules
pve-firewall restart    # Reload all rules
pve-firewall status     # Show running status: "Status: enabled/running"

A companion service, pvefw-logger, handles firewall traffic logging when logging is enabled on rules. It is based on the netfilter logging daemon (ulogd) and writes firewall log entries separately from system logs.

Limitations

The Proxmox built-in firewall is a solid stateful packet filter, but it has limits to understand:

For environments needing application-layer filtering, deploy a dedicated firewall VM (pfSense, OPNsense, or similar) and route VM traffic through it rather than relying solely on the Proxmox built-in firewall.