Duplicate iptables entries after ifreload -a in NAT table with SDN, SNAT enabled

gbgb1337

Member
Oct 25, 2020
2
1
23
29
Software running:
pve-firewall: enabled/running (pending changes)
proxmox-firewall disabled
nftables disabled
ebtables disabled
pve 8.4.1

Problem:
Every time I run ifreload -a, the system adds duplicate SNAT rules in the nat table (POSTROUTING chain). After a few reloads, I end up with multiple identical entries like:

Code:
-A POSTROUTING -s 10.2.1.0/24 -o vmbr0 -j SNAT --to-source x.x.x.x
-A POSTROUTING -s 10.2.2.0/24 -o vmbr0 -j SNAT --to-source x.x.x.x
-A POSTROUTING -s 10.2.1.0/24 -o vmbr0 -j SNAT --to-source x.x.x.x
-A POSTROUTING -s 10.2.2.0/24 -o vmbr0 -j SNAT --to-source x.x.x.x

This seems to happen because the SDN-generated /etc/network/interfaces.d/* files include post-up iptables commands to add SNAT rules, but ifreload -a (via ifupdown2) doesn't execute post-down, so rules never get cleaned up and keep stacking up on every reload.

My questions:
  • Is there an official or recommended way to handle SNAT in SDN zones without causing duplication on interface reloads?
  • Could the SDN-generated post-up rules be made idempotent by using iptables -C checks?
  • Is there a plan to handle this more cleanly in Proxmox SDN?
Thanks in advance for any guidance!
 
  • Like
Reactions: dozono
yes, it's a known bug, snat rules management should be improve. (currently they are put as post-up in /etc/network/intefaces , so applied multiple times). It should need some kind of service to manage it. (maybe in new proxmox firewall for example)

you can add a ping in this opened issue:
https://bugzilla.proxmox.com/show_bug.cgi?id=5066
 
Last edited:
Have same problem... each change (apply) of SDN config causa duplication of POSTROUTING SNAT

I quicly made script which clean up this. Script finds duplicate SNAT rules and removes them, keeping only the first occurrence of each unique rule.

Code:
# iptables -t nat -L POSTROUTING -n --line-numbers | grep "SNAT" | tac
3    SNAT       all  --  172.20.0.0/28        0.0.0.0/0            to:65.x.x.x
2    SNAT       all  --  172.20.0.0/28        0.0.0.0/0            to:65.x.x.x
1    SNAT       all  --  172.20.0.0/28        0.0.0.0/0            to:65.x.x.x

# bash check.sh


# iptables -t nat -L POSTROUTING -n --line-numbers | grep "SNAT" | tac
1    SNAT       all  --  172.20.0.0/28        0.0.0.0/0            to:65.x.x.x


script check.sh
Bash:
#!/bin/bash

# Get SNAT rules with line numbers (reverse order)
rules=$(iptables -t nat -L POSTROUTING -n --line-numbers | grep "SNAT" | tac)

# Track seen rules
declare -A seen

# Process each rule
while read -r line; do
    if [ -n "$line" ]; then
        # Get rule signature (everything except line number)
        rule=$(echo "$line" | awk '{for(i=2;i<=NF;i++) printf "%s ", $i}')
        line_num=$(echo "$line" | awk '{print $1}')
        
        # If we've seen this rule before, delete it
        if [ -n "${seen[$rule]}" ]; then
            iptables -t nat -D POSTROUTING "$line_num"
        else
            seen["$rule"]=1
        fi
    fi
done <<< "$rules"


Othere option is to find config where your SNAT apply under interface... add there pre-up rule which will first remove SNAT and post-up will add it again (during reload) - ie.

before
Code:
auto vmbr0.203
iface vmbr0.203 inet static
        address 203.0.113.1/24
        post-up   iptables -t nat -A POSTROUTING -s 203.0.113.0/24 -o vmbr0 -j SNAT --to-source 65.x.x.x
        post-down iptables -t nat -D POSTROUTING -s 203.0.113.0/24 -o vmbr0 -j SNAT --to-source 65.x.x.x

with pre-up:
Code:
auto vmbr0.203
iface vmbr0.203 inet static
        address 203.0.113.1/24
        post-up   iptables -t nat -A POSTROUTING -s 203.0.113.0/24 -o vmbr0 -j SNAT --to-source 65.x.x.x
        pre-up    iptables -t nat -D POSTROUTING -s 203.0.113.0/24 -o vmbr0 -j SNAT --to-source 65.x.x.x
        post-down iptables -t nat -D POSTROUTING -s 203.0.113.0/24 -o vmbr0 -j SNAT --to-source 65.x.x.x