From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id DA1021FF142 for ; Fri, 05 Jun 2026 13:48:59 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id F1AE5178F4; Fri, 5 Jun 2026 13:48:51 +0200 (CEST) From: Lukas Sichert To: pve-devel@lists.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 Message-ID: <20260605114810.43030-3-l.sichert@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260605114810.43030-1-l.sichert@proxmox.com> References: <20260605114810.43030-1-l.sichert@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1780660057483 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.296 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: 3BKUBOPXZM3WJC5HHXVIYHNJZRWUUO3P X-Message-ID-Hash: 3BKUBOPXZM3WJC5HHXVIYHNJZRWUUO3P X-MailFrom: l.sichert@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Lukas Sichert X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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