From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 538601FF0AF for ; Fri, 06 Nov 2026 12:23:52 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 4A260216A1; Fri, 06 Nov 2026 12:23:34 +0100 (CET) From: Stefan Hanreich To: pve-devel@lists.proxmox.com Subject: [PATCH pve-firewall 1/2] fix #8268: firewall: keep bridge-nf-call sysctls set on upgrade Date: Fri, 6 Nov 2026 12:23:13 +0100 Message-ID: <20261106112315.151144-2-s.hanreich@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261106112315.151144-1-s.hanreich@proxmox.com> References: <20261106112315.151144-1-s.hanreich@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1793964208481 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.305 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust 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: TF26IOUHH3MMABOEYCZID5H7UR2WVLTZ X-Message-ID-Hash: TF26IOUHH3MMABOEYCZID5H7UR2WVLTZ X-MailFrom: s.hanreich@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 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Restarting systemd-sysctl, as done on some package upgrades, or loading br_netfilter re-applies the sysctl.d configuration. This resets bridge-nf-call-ip{,6}tables to the 0 from 10-pve.conf until the next update round enables them again. Bridged traffic bypasses conntrack in that window, so conntrack loses track of established connections and drops their packets as invalid afterwards. Write a drop-in to /run/sysctl.d while the iptables based firewall is active, so re-applying the configuration keeps the values. Only remove it once the firewall is disabled or switched to nftables, not on daemon shutdown, as the daemon itself may be restarted during the same upgrade. The nftables based proxmox-firewall does not need the drop-in. It filters bridged guest traffic in a bridge table, which has its own conntrack support, so it does not need br_netfilter. Remove the drop-in before handing over to proxmox-firewall, so a re-apply after the takeover cannot pick up its values. The new code uses PVE::File directly, which is available since libpve-common-perl 9.0.12, so raise the dependency accordingly. Fixes: https://bugzilla.proxmox.com/show_bug.cgi?id=8268 Signed-off-by: Stefan Hanreich --- debian/control | 4 ++-- src/PVE/Firewall.pm | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index 7fbbe33..d1d541a 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Build-Depends: debhelper-compat (= 13), libnetfilter-log-dev, libpve-access-control, libpve-cluster-perl, - libpve-common-perl (>= 7.3-2), + libpve-common-perl (>= 9.0.12), proxmox-firewall-data (>= 0.1), pve-cluster (>= 6.0-4), pve-doc-generator (>= 5.3-3), @@ -24,7 +24,7 @@ Depends: conntrack, iptables, libpve-access-control, libpve-cluster-perl, - libpve-common-perl (>= 9.0.2), + libpve-common-perl (>= 9.0.12), libpve-network-perl (>= 1.6.8~), libpve-rs-perl (>= 0.8.13), proxmox-firewall-data (>= 0.1), diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index dd5d92c..082e916 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -17,6 +17,7 @@ use Storable qw(dclone); use PVE::Cluster; use PVE::Corosync; use PVE::Exception qw(raise raise_param_exc); +use PVE::File; use PVE::INotify; use PVE::JSONSchema qw(register_standard_option get_standard_option); use PVE::Network; @@ -2110,8 +2111,34 @@ sub rules_audit_permissions { # core functions +my $bridge_sysctl_dropin_dir = "/run/sysctl.d"; +# must sort after 10-pve.conf, and must not reuse a name from another sysctl.d directory, which +# would mask that file +my $bridge_sysctl_dropin = "$bridge_sysctl_dropin_dir/90-pve-firewall-bridge.conf"; + +my sub write_bridge_sysctl_dropin { + return if PVE::File::file_exists($bridge_sysctl_dropin); + + eval { + File::Path::make_path($bridge_sysctl_dropin_dir); + PVE::File::file_set_contents( + $bridge_sysctl_dropin, + "net.bridge.bridge-nf-call-iptables = 1\nnet.bridge.bridge-nf-call-ip6tables = 1\n", + ); + }; + warn "failed to write '$bridge_sysctl_dropin' - $@" if $@; +} + +my sub remove_bridge_sysctl_dropin { + if (!unlink($bridge_sysctl_dropin)) { + warn "failed to unlink '$bridge_sysctl_dropin' - $!\n" if !$!{ENOENT}; + } +} + sub enable_bridge_firewall { + write_bridge_sysctl_dropin(); + PVE::ProcFSTools::write_proc_entry("/proc/sys/net/bridge/bridge-nf-call-iptables", "1"); PVE::ProcFSTools::write_proc_entry("/proc/sys/net/bridge/bridge-nf-call-ip6tables", "1"); @@ -5573,10 +5600,15 @@ my sub is_enabled_and_not_nftables { $host_conf = load_hostfw_conf($cluster_conf) if !defined($host_conf); my $is_nftables = get_nftables_option($cluster_conf, $host_conf); + my $enabled_and_not_nftables = $cluster_conf->{options}->{enable} && !$is_nftables; + + # remove the drop-in before handing over, as proxmox-firewall re-applies the bridge sysctls + # once it takes over + remove_bridge_sysctl_dropin() if !$enabled_and_not_nftables; update_force_nftables_disable_flag($cluster_conf->{options}->{enable}, $is_nftables); - return $cluster_conf->{options}->{enable} && !$is_nftables; + return $enabled_and_not_nftables; } sub init { -- 2.47.3