Proxmox Default rule Dynamic or static?

ExoNos

New Member
May 6, 2024
9
2
3
Hi,

I am wondering if Proxmox default rules are dynamically generated or statically defined, and if so where are they statically defined?

I noticed at the top of my pve-host IN chain I had a Accept All from everywhere entry

So i deleted it cause it made no sense to have it at the top and i figured it was proberly a dynamically generated default, but that user configured host.fw rules would take precedence anyway and proxmox would just dynamically generate it again seeing as no /etc/iptables/ folder existed and i could find no other configuration on the system with those rules hardcoded...

well like most things it quickily cascaded... i accidently ran the command twice and so deleted the entry below it as well:

2 DROP 0 -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID

I then discovered that i could no longer access ssh or the gui

so i rebooted figuring it would just be restored...

it wasnt

  • My chain now looks like
iptables -L PVEFW-HOST-IN -n --line-numbers
Chain PVEFW-HOST-IN (1 references)
num target prot opt source destination
1 PVEFW-smurfs 0 -- 0.0.0.0/0 0.0.0.0/0 ctstate INVALID,NEW
2 RETURN 2 -- 0.0.0.0/0 0.0.0.0/0
3 RETURN 6 -- 192.168.1.0/24 0.0.0.0/0 tcp dpt:33265
4 RETURN 6 -- 192.168.1.0/24 192.168.1.90 tcp dpt:8006
5 RETURN 6 -- 0.0.0.0/0 0.0.0.0/0 match-set PVEFW-0-management-v4 src tcp dpt:8006
6 RETURN 6 -- 0.0.0.0/0 0.0.0.0/0 match-set PVEFW-0-management-v4 src tcp dpts:5900:5999
7 RETURN 6 -- 0.0.0.0/0 0.0.0.0/0 match-set PVEFW-0-management-v4 src tcp dpt:3128
8 RETURN 6 -- 0.0.0.0/0 0.0.0.0/0 match-set PVEFW-0-management-v4 src tcp dpt:22
9 RETURN 6 -- 0.0.0.0/0 0.0.0.0/0 match-set PVEFW-0-management-v4 src tcp dpts:60000:60050
10 PVEFW-Drop 0 -- 0.0.0.0/0 0.0.0.0/0
11 DROP 0 -- 0.0.0.0/0 0.0.0.0/0
12 0 -- 0.0.0.0/0 0.0.0.0/0 /* PVESIG:NVFPLbg2z/Vp8tNI4BAHLEIt6cc */


These:

3 RETURN 6 -- 192.168.1.0/24 0.0.0.0/0 tcp dpt:33265
4 RETURN 6 -- 192.168.1.0/24 192.168.1.90 tcp dpt:8006

are the only rules i have actually defined myself.

I have considered adding the rules to my host.fw to restore functionality but that seems untidy and i hate having rules on my iptables that apparently are stored nowhere yet neither are they generated anywhere...

Can anyone shed any light on this?
 
Last edited:
Ok, They are back so they are dynamically generated... just not when expected ie after a 'pve-firewall restart' an/or a 'service pve-firewall restart' and not even always after a reboot.... definately some weird vodoo with that and definately makes analysing behaviour difficult.
 
Well I feel a bit beaten by proxmox i was unable to get reliable ssh and gui access to proxmox with out adding my ip to the management set while having my policies set to drop... oh well i wrote this now entirely useless script which seems to prevent me from having to reboot everytime i want to check a rule change`s effectiveness... still some weiardness though.

Code:
#!/bin/bash

set -e

IPTABLES=/sbin/iptables

echo "=== Proxmox Restart and Firewall Reload with Interface Auto-Selection ==="

# --- List interfaces excluding loopback and without IPv4 addresses ---
interfaces=()
addresses=()

while IFS= read -r iface; do
  ip_addr=$(ip -4 addr show dev "$iface" | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | head -n1)
  if [ -n "$ip_addr" ]; then
    interfaces+=("$iface")
    addresses+=("$ip_addr")
  fi
done < <(ip -o link show | awk -F': ' '{print $2}' | grep -v lo)

if [ ${#interfaces[@]} -eq 0 ]; then
  echo "No network interfaces with IPv4 addresses found!"
  exit 1
elif [ ${#interfaces[@]} -eq 1 ]; then
  NET_IFACE="${interfaces[0]}"
  IP_ADDR="${addresses[0]}"
  echo "------------------------------------------------------------------------"
  echo "Only one interface found with IP."
  echo "Automatically selecting interface: $NET_IFACE with IP: $IP_ADDR"
  echo "------------------------------------------------------------------------"
else
  echo "Available network interfaces with IPv4 addresses:"
  for i in "${!interfaces[@]}"; do
    echo "$((i+1))) ${interfaces[$i]} - ${addresses[$i]}"
  done

  # --- Prompt user to select interface ---
  while true; do
    read -rp "Select the interface number to use: " iface_num
    if [[ "$iface_num" =~ ^[0-9]+$ ]] && (( iface_num >= 1 && iface_num <= ${#interfaces[@]} )); then
      NET_IFACE="${interfaces[$((iface_num-1))]}"
      IP_ADDR="${addresses[$((iface_num-1))]}"
      break
    else
      echo "Invalid selection. Please enter a number between 1 and ${#interfaces[@]}."
    fi
  done
fi

echo "Selected interface: $NET_IFACE"
echo "IP address: $IP_ADDR"
echo "------------------------------------------------------------------------"
echo "WARNING: Restarting networking may cause temporary loss of connectivity."
echo "If you are connected remotely (e.g., via SSH), you may be disconnected."
echo "Proceed only if you have physical or out-of-band access."
echo "------------------------------------------------------------------------"

# --- Stop services in reverse dependency order ---
echo "Stopping pveproxy..."
systemctl stop pveproxy

echo "Stopping pvedaemon..."
systemctl stop pvedaemon

echo "Stopping pve-firewall..."
systemctl stop pve-firewall

echo "Stopping pve-cluster..."
systemctl stop pve-cluster

# --- Flush iptables before restarting firewall ---
echo "Flushing all iptables rules and deleting user chains..."
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
$IPTABLES -t raw -F
$IPTABLES -X

echo "Waiting 3 seconds for network cleanup..."
sleep 3

# --- Restart networking ---
echo "Restarting networking service (this may disrupt network connectivity)..."
systemctl restart networking

sleep 5

# --- Flush ARP cache ---
echo "Flushing ARP cache..."
ip -s -s neigh flush all

# --- Send gratuitous ARP (3 packets) ---
echo "Sending 3 gratuitous ARP packets on interface $NET_IFACE for IP $IP_ADDR..."
if ! command -v arping >/dev/null 2>&1; then
    echo "arping command not found! Please install it with: apt install arping"
    exit 1
fi

arping -U -c 3 -I "$NET_IFACE" "$IP_ADDR"
sleep 2

# --- Flush RRD cache to prevent RRDC update errors ---
echo "Stopping rrdcached service to flush RRD cache..."
systemctl stop rrdcached

echo "Flushing all RRD cache data..."
rrdcached -P FLUSHALL

echo "Starting rrdcached service..."
systemctl start rrdcached

# --- Start critical services in dependency order with pauses ---
echo "Starting pve-cluster..."
systemctl start pve-cluster
sleep 2

echo "Starting pve-firewall..."
systemctl start pve-firewall
sleep 2

# --- Verify firewall rules against .fw files ---
echo "-----------------------------------------------------------------------------"
echo "Firewall service restarted. Comparing .fw files with active iptables rules..."
echo "-----------------------------------------------------------------------------"

$IPTABLES-save > /tmp/iptables_rules

find /etc/pve -path /etc/pve/nodes/*/firewall -o -path /etc/pve/firewall -type d -print0 |
  while IFS= read -r -d $'\0' dir; do
    find "$dir" -name "*.fw" -print0 |
     while IFS= read -r -d $'\0' fwfile; do
        echo "Checking file: $fwfile"
        grep -q -f "$fwfile" /tmp/iptables_rules
        if [ $? -eq 0 ]; then
          echo "All rules in $fwfile are present in iptables."
          echo "---------------------------------------------"  
        else
          echo "WARNING: Some rules in $fwfile are missing from iptables!"
        fi
      done
  done

rm /tmp/iptables_rules

echo "Starting pvedaemon..."
systemctl start pvedaemon
sleep 2

echo "Starting pveproxy..."
systemctl start pveproxy
sleep 2

echo "-----------------------------------------------------------------------"
echo "=== All services restarted and firewall rules verified successfully ==="
echo "-----------------------------------------------------------------------"

echo "================================================ Service status summary ================================================"
echo "------------------------------------------------------------------------------------------------------------------------"
services=(   
  pve-cluster 
  pve-firewall
  pvedaemon
  pveproxy 
)
    
for svc in "${services[@]}"; do
  echo "================================================ Status of $svc: ================================================"
  # Display the full status output
  service "$svc" status
  echo "---------------------------------------------------------------------------------------------------------------------"
done

echo "================================================ End of status summary ================================================"
 
Last edited: