The Proxmox Problem: One Target, Many Casualties
Proxmox VE has become the hypervisor of choice for hosting providers, homelab enthusiasts, and small-to-mid-size infrastructure operators. Its combination of KVM virtualization, LXC containers, Ceph storage, and a clean web interface makes it an attractive alternative to VMware, especially after Broadcom's licensing changes sent the industry scrambling for alternatives.
But Proxmox introduces a DDoS problem that bare-metal servers do not have: a single point of failure for dozens or hundreds of workloads. When an attacker floods the public IP of a Proxmox node, every VM and container on that node becomes unreachable. The hypervisor's management interface becomes unresponsive. If the node is part of a Ceph cluster, storage replication stalls. If Corosync cluster communication is disrupted, the cluster can trigger fencing operations and shut down VMs it believes are running on a failed node.
A DDoS attack against one Proxmox node can cascade into a cluster-wide outage. This is not theoretical. Hosting providers running Proxmox clusters have seen a 5 Gbps flood against one node trigger Corosync timeouts that caused the entire cluster to lose quorum, taking down every VM across all nodes.
Proxmox-Specific Attack Surfaces
Port 8006: The Web Management Interface
Proxmox's web UI runs on port 8006 via the pveproxy service. By default, it listens on all interfaces, meaning it is accessible from the public internet on every Proxmox node. The web UI is a full single-page application that makes API calls to the pvedaemon backend. Every request to port 8006 requires TLS negotiation, session handling, and potentially authentication checks against PAM or Proxmox's user database.
An HTTP flood against port 8006 does not need to authenticate. Simply requesting the login page repeatedly forces the server to handle TLS handshakes and serve static assets. At scale, this saturates the pveproxy workers and prevents legitimate administrators from managing the node. If you cannot access the management interface during an attack, you cannot respond to the attack.
Ceph Ports (6789, 6800-7300)
Proxmox clusters using Ceph for distributed storage expose monitor ports (6789) and OSD ports (6800-7300). These services are designed for low-latency, high-throughput communication between cluster nodes. They are not designed to withstand external traffic floods. If Ceph monitor communication is disrupted, the storage cluster enters a degraded state. VMs with their disks on Ceph experience I/O freezes, which often looks like the VM itself has crashed.
Corosync Cluster Communication (Port 5405 UDP)
Corosync uses UDP multicast or unicast on port 5405 for cluster heartbeat and membership communication. This is the most critical and most fragile service on a Proxmox cluster. Corosync expects heartbeat packets at regular intervals, typically every 2 seconds with a timeout of 6 seconds. If a node misses heartbeats because the network is congested from a DDoS attack, the cluster declares that node dead. Depending on your HA configuration, fencing kicks in: VMs on the "dead" node are either restarted on surviving nodes or shut down entirely.
A UDP flood against a Proxmox node does not even need to target port 5405 specifically. Any volumetric flood that saturates the node's network interface prevents Corosync packets from being processed in time. The cluster sees a heartbeat timeout and takes fencing action, turning a single-node DDoS into a cluster-wide event.
SSH (Port 22) and SPICE/VNC Consoles
Proxmox uses SSH for inter-node operations like migration, and SPICE/VNC for console access. SSH connection floods can exhaust the OpenSSH daemon's connection slots, preventing node-to-node management. Console connections through the web UI depend on the pveproxy service, so if that is overwhelmed, console access is lost too.
Why pve-firewall Is Not DDoS Protection
Proxmox includes its own firewall system, pve-firewall, which provides a centralized way to manage iptables rules across the cluster via the web UI or API. It supports rules at the datacenter level, node level, and per-VM/container level. It is a competent host-based firewall for access control. It is not DDoS protection, for the same reasons that CSF on cPanel is not DDoS protection.
pve-firewall processes packets after they arrive at the host's network interface. Volumetric attacks saturate the uplink before pve-firewall evaluates any rules. The firewall also adds processing overhead per packet through iptables chains, which under extreme PPS loads (millions of packets per second) becomes a bottleneck itself. Ironically, having complex firewall rules active during a volumetric flood can make things worse because the kernel spends CPU cycles evaluating rules against packets it should be dropping as early as possible.
pve-firewall also has no concept of traffic rate analysis. It allows or denies based on source, destination, port, and protocol. It cannot detect that incoming SYN packets have jumped from 500/s to 500,000/s. It cannot identify that UDP traffic has spiked by 4000%. It does not track bandwidth or PPS trends over time. Without rate awareness, there is no attack detection.
Bridge Interface Monitoring Challenges
Proxmox uses Linux bridge interfaces (vmbr0, vmbr1, etc.) to connect VMs and containers to the network. Traffic flows through the bridge, which means the hypervisor's network stack processes every packet destined for every VM on that bridge. This creates a monitoring challenge: you need to distinguish between traffic destined for the hypervisor itself and traffic destined for individual VMs.
# See traffic flowing through the bridge # This shows ALL traffic, not just host traffic tcpdump -i vmbr0 -n -c 100 # Check per-interface traffic rates cat /proc/net/dev | grep -E 'vmbr|tap|veth' # See bridge members (each tap/veth is a VM or container NIC) brctl show vmbr0 # Monitor PPS per bridge in real time watch -n1 'cat /proc/net/dev | grep vmbr'
When a DDoS targets a VM's IP address, the attack traffic enters the physical NIC, traverses the bridge, and hits the VM's virtual NIC. But the hypervisor's network stack still processes every one of those packets through the bridge. A 2 Gbps flood targeting a single VM saturates the same physical NIC that all other VMs share. Bridge-level monitoring is essential to identify which destination IP (which VM) is being targeted, so mitigation can be applied surgically rather than taking the whole node offline.
Practical Hardening for Proxmox Environments
Isolate Management Traffic on a Private VLAN
The single most impactful change you can make is moving all management and cluster traffic off the public network. Proxmox management (port 8006), Corosync (port 5405), Ceph (ports 6789, 6800-7300), and SSH between nodes should all run on a private VLAN that is not routable from the internet.
# Example: Create a separate bridge for cluster traffic
# In /etc/network/interfaces
# Public bridge (customer VM traffic)
auto vmbr0
iface vmbr0 inet static
address 203.0.113.10/24
gateway 203.0.113.1
bridge-ports eno1
bridge-stp off
bridge-fd 0
# Private cluster bridge (management, Corosync, Ceph)
auto vmbr1
iface vmbr1 inet static
address 10.10.0.10/24
bridge-ports eno2
bridge-stp off
bridge-fd 0
# Then configure Corosync to use the private interface
# In /etc/pve/corosync.conf, set ring addresses to 10.10.0.x
With this configuration, a DDoS flood against the public IP (203.0.113.10) saturates vmbr0 but does not affect cluster communication on vmbr1. Corosync heartbeats continue uninterrupted on the private network, so the cluster does not falsely fence the node. Ceph replication continues. The management interface remains accessible via the private IP.
Restrict Port 8006 Access
If you must run the Proxmox web UI on a public-facing interface, restrict access using pve-firewall or direct iptables rules:
# Using iptables directly on the Proxmox host iptables -A INPUT -p tcp --dport 8006 -s 198.51.100.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 8006 -j DROP # Or through pve-firewall at the datacenter level # Datacenter > Firewall > Add Rule: # Direction: IN, Action: ACCEPT, Protocol: tcp # Dest. port: 8006, Source: 198.51.100.0/24 # Then add a DROP rule for port 8006 from any source
Kernel Hardening for High-PPS Environments
# /etc/sysctl.d/99-proxmox-ddos.conf # Increase connection tracking for many VMs net.netfilter.nf_conntrack_max = 1048576 # Increase SYN backlog net.ipv4.tcp_max_syn_backlog = 65536 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_synack_retries = 2 # Increase network processing budget net.core.netdev_budget = 600 net.core.netdev_budget_usecs = 8000 # Increase ring buffer sizes net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 # Enable reverse path filtering on all interfaces net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Apply # sysctl -p /etc/sysctl.d/99-proxmox-ddos.conf
Per-VM Traffic Isolation with TC
You can use Linux traffic control to limit the impact of a DDoS against one VM on other VMs sharing the same bridge. This does not stop the attack, but it prevents one VM's flood from consuming all available bandwidth:
# Rate limit a specific VM's virtual NIC (tap100i0 = VM ID 100, interface 0) tc qdisc add dev tap100i0 root tbf rate 500mbit burst 256kb latency 50ms # For ingress limiting (traffic coming INTO the VM), use an IFB device modprobe ifb ip link set ifb0 up tc qdisc add dev vmbr0 ingress tc filter add dev vmbr0 parent ffff: protocol ip u32 match ip dst 203.0.113.50/32 action mirred egress redirect dev ifb0 tc qdisc add dev ifb0 root tbf rate 500mbit burst 256kb latency 50ms
Traffic control limits the blast radius but does not reduce the packet processing load on the hypervisor. Even with TC in place, the kernel still processes every packet that hits the physical NIC. Rate limiting only prevents forwarding beyond the cap; it does not prevent arrival.
Per-Node Detection: What Actually Works
Effective DDoS protection for Proxmox requires detection at the hypervisor level, where you can see all traffic flowing through the bridges to every VM. A detection agent on each Proxmox node monitors the physical and bridge interfaces, tracking PPS, bandwidth, protocol distribution, and traffic patterns at per-second granularity.
Flowtriq deploys a lightweight agent on each Proxmox node that monitors bridge-level traffic across all VMs without requiring any configuration inside the VMs themselves. The agent identifies which destination IP is under attack, enabling surgical mitigation that takes a specific IP offline for scrubbing rather than null-routing the entire node. Because it runs on the hypervisor, one agent covers every VM and container on that node.
Why Detection Must Be on the Hypervisor, Not Inside VMs
You might consider running detection agents inside each VM instead. This approach has serious limitations. A VM under a volumetric DDoS attack may become unresponsive, so its detection agent cannot report the attack. The VM's view is limited to its own traffic; it cannot see whether the attack is spilling over and affecting other VMs on the same node. Running agents in every VM also means managing dozens or hundreds of agent installations instead of one per node.
Hypervisor-level detection sees everything. It sees the overall PPS hitting the physical NIC, the bandwidth distribution across bridges, the per-VM traffic breakdown, and the Corosync and Ceph traffic health. It can correlate a spike in traffic to vmbr0 with degraded Corosync timing on vmbr1, identifying a DDoS that is beginning to affect cluster stability before the cluster actually fails.
# Deploy the agent on each Proxmox node pip install ftagent ftagent init --server-id proxmox-node-01 --api-key your-key # The agent auto-detects bridge interfaces ftagent status # Output shows monitoring on vmbr0, vmbr1, etc. # Verify per-VM traffic visibility ftagent stats --per-destination # Shows traffic breakdown by destination IP (each VM)
Protecting Proxmox Clusters: A Layered Approach
For a multi-node Proxmox cluster, protection needs to work at every level of the architecture:
- Network isolation: Separate public VM traffic from private cluster traffic using dedicated VLANs and bridges. Corosync and Ceph should never share a network path with customer traffic.
- Per-node detection: Each Proxmox node runs a monitoring agent that tracks all traffic on all bridges. Detection must be per-second to catch floods before Corosync timeouts trigger fencing.
- Per-IP mitigation signaling: When an attack targets a specific VM IP, mitigation should null-route or scrub only that IP, not the entire node. This requires detection that identifies the target IP and mitigation infrastructure that supports per-IP actions.
- Upstream scrubbing capability: Volumetric attacks must be absorbed upstream. No amount of hypervisor-level hardening will help if the physical port is saturated.
- Fencing awareness: Your monitoring should track Corosync health and alert if heartbeat latency increases, which is an early warning sign that network congestion from an attack is approaching the fencing threshold.
The most common mistake with Proxmox DDoS protection is treating it like bare-metal protection. It is not. The shared-infrastructure nature of a hypervisor means that every VM is a potential entry point for an attack that affects all other VMs. Detection must be at the hypervisor level, mitigation must be per-IP, and cluster communication must be isolated from public traffic. Miss any of these three requirements and a single flood can take down your entire Proxmox infrastructure.
Back to Blog