public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Lukas Sichert <l.sichert@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Lukas Sichert <l.sichert@proxmox.com>
Subject: [PATCH network 2/3] fix #5066: snat: push simplezone snat rules into separate iptables chain
Date: Fri,  5 Jun 2026 13:48:03 +0200	[thread overview]
Message-ID: <20260605114810.43030-3-l.sichert@proxmox.com> (raw)
In-Reply-To: <20260605114810.43030-1-l.sichert@proxmox.com>

When creating a Subnet with SNAT enabled and applying the changes, then
afterwards disabling SNAT and applying the changes, the rule still
persists in iptables. This is because ifreload -a only executes
(post/pre-)down hooks when an interface is removed from
/etc/network/interfaces, but the (post/pre-)up hooks are always
executed. As a result, the SNAT rule is not removed by 'ifreload -a' and
only a restart or 'ifdown' will remove it.

To be able to flush only the rules created by the Proxmox stack, add a
separate 'PROXMOX-SDN' chain to the iptables nat table, if a plugin
needs SNAT rules. Then add a jump from POSTROUTING to the new chain and
append all SNAT rules to the new chain. The new chain can then be
flushed separately.

Signed-off-by: Lukas Sichert <l.sichert@proxmox.com>
---
 src/PVE/Network/SDN/Zones/SimplePlugin.pm      | 18 +++++++++++++++---
 .../simple/ipv4snat/expected_sdn_interfaces    |  8 ++++++--
 .../simple/ipv6snat/expected_sdn_interfaces    |  8 ++++++--
 3 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/src/PVE/Network/SDN/Zones/SimplePlugin.pm b/src/PVE/Network/SDN/Zones/SimplePlugin.pm
index acc482c..0b7ddf4 100644
--- a/src/PVE/Network/SDN/Zones/SimplePlugin.pm
+++ b/src/PVE/Network/SDN/Zones/SimplePlugin.pm
@@ -127,12 +127,25 @@ sub generate_sdn_config {
         #add route for /32 pointtopoint
         push @iface_config, "up ip route add $cidr dev $vnetid" if $mask == 32 && $ipversion == 4;
         if ($subnet->{snat}) {
+            #find outgoing interface
+            my ($outip, $outiface) =
+                PVE::Network::SDN::Zones::Plugin::get_local_route_ip($checkrouteip);
+
+            push @iface_config, "post-up $iptables -t nat -N PROXMOX-SDN 2>/dev/null || true";
+            push @iface_config,
+                "post-up $iptables -t nat -C POSTROUTING -j PROXMOX-SDN 2>/dev/null || $iptables -t nat -A POSTROUTING -j PROXMOX-SDN";
+
+            push @iface_config, "post-down $iptables -t nat -N PROXMOX-SDN 2>/dev/null || true";
+            push @iface_config,
+                "post-down $iptables -t nat -D POSTROUTING -j PROXMOX-SDN 2>/dev/null || true";
             if ($outip && $outiface) {
                 #use snat, faster than masquerade
                 push @iface_config,
-                    "post-up $iptables -t nat -A POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+                    "post-up $iptables -t nat -A PROXMOX-SDN -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+
                 push @iface_config,
-                    "post-down $iptables -t nat -D POSTROUTING -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+                    "post-down $iptables -t nat -D PROXMOX-SDN -s '$cidr' -o $outiface -j SNAT --to-source $outip";
+
                 #add conntrack zone once on outgoing interface
                 push @iface_config,
                     "post-up $iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1";
@@ -180,4 +193,3 @@ sub get_mtu {
 }
 
 1;
-
diff --git a/src/test/zones/simple/ipv4snat/expected_sdn_interfaces b/src/test/zones/simple/ipv4snat/expected_sdn_interfaces
index 69d7986..34488eb 100644
--- a/src/test/zones/simple/ipv4snat/expected_sdn_interfaces
+++ b/src/test/zones/simple/ipv4snat/expected_sdn_interfaces
@@ -3,8 +3,12 @@
 auto myvnet
 iface myvnet
 	address 10.0.0.1/24
-	post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o vmbr0 -j SNAT --to-source 192.168.0.1
-	post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o vmbr0 -j SNAT --to-source 192.168.0.1
+	post-up iptables -t nat -N PROXMOX-SDN 2>/dev/null || true
+	post-up iptables -t nat -C POSTROUTING -j PROXMOX-SDN 2>/dev/null || iptables -t nat -A POSTROUTING -j PROXMOX-SDN
+	post-down iptables -t nat -N PROXMOX-SDN 2>/dev/null || true
+	post-down iptables -t nat -D POSTROUTING -j PROXMOX-SDN 2>/dev/null || true
+	post-up iptables -t nat -A PROXMOX-SDN -s '10.0.0.0/24' -o vmbr0 -j SNAT --to-source 192.168.0.1
+	post-down iptables -t nat -D PROXMOX-SDN -s '10.0.0.0/24' -o vmbr0 -j SNAT --to-source 192.168.0.1
 	post-up iptables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
 	post-down iptables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
 	bridge_ports none
diff --git a/src/test/zones/simple/ipv6snat/expected_sdn_interfaces b/src/test/zones/simple/ipv6snat/expected_sdn_interfaces
index f426774..73f735d 100644
--- a/src/test/zones/simple/ipv6snat/expected_sdn_interfaces
+++ b/src/test/zones/simple/ipv6snat/expected_sdn_interfaces
@@ -7,8 +7,12 @@ iface myvnet
 	post-down echo 0 > /proc/sys/net/ipv6/conf/vmbr0/force_forwarding
 	post-up echo 1 > /proc/sys/net/ipv6/conf/myvnet/force_forwarding
 	post-down echo 0 > /proc/sys/net/ipv6/conf/myvnet/force_forwarding
-	post-up ip6tables -t nat -A POSTROUTING -s '2a08:2142:302:3::/64' -o vmbr0 -j SNAT --to-source 2001:db8::2
-	post-down ip6tables -t nat -D POSTROUTING -s '2a08:2142:302:3::/64' -o vmbr0 -j SNAT --to-source 2001:db8::2
+	post-up ip6tables -t nat -N PROXMOX-SDN 2>/dev/null || true
+	post-up ip6tables -t nat -C POSTROUTING -j PROXMOX-SDN 2>/dev/null || ip6tables -t nat -A POSTROUTING -j PROXMOX-SDN
+	post-down ip6tables -t nat -N PROXMOX-SDN 2>/dev/null || true
+	post-down ip6tables -t nat -D POSTROUTING -j PROXMOX-SDN 2>/dev/null || true
+	post-up ip6tables -t nat -A PROXMOX-SDN -s '2a08:2142:302:3::/64' -o vmbr0 -j SNAT --to-source 2001:db8::2
+	post-down ip6tables -t nat -D PROXMOX-SDN -s '2a08:2142:302:3::/64' -o vmbr0 -j SNAT --to-source 2001:db8::2
 	post-up ip6tables -t raw -I PREROUTING -i fwbr+ -j CT --zone 1
 	post-down ip6tables -t raw -D PREROUTING -i fwbr+ -j CT --zone 1
 	bridge_ports none
-- 
2.47.3





  parent reply	other threads:[~2026-06-05 11:48 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-05 11:48 [RFC manager/network 0/3] fix #5066: make generated snat rules flushable Lukas Sichert
2026-06-05 11:48 ` [PATCH network 1/3] fix #5066: snat: push evpn snat rules into separate iptables chain Lukas Sichert
2026-06-05 11:48 ` Lukas Sichert [this message]
2026-06-05 11:48 ` [PATCH manager 3/3] fix #5066: reload networking: flush PROXMOX-SDN iptables chain at reload Lukas Sichert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260605114810.43030-3-l.sichert@proxmox.com \
    --to=l.sichert@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal