From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id E427F1FF183 for ; Wed, 16 Jul 2025 18:38:31 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 81EFB17DB3; Wed, 16 Jul 2025 18:39:19 +0200 (CEST) From: Stefan Hanreich To: pve-devel@lists.proxmox.com Date: Wed, 16 Jul 2025 18:39:06 +0200 Message-Id: <20250716163911.406995-5-s.hanreich@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250716163911.406995-1-s.hanreich@proxmox.com> References: <20250716163911.406995-1-s.hanreich@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.217 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 KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [PATCH proxmox-firewall v3 1/1] firewall: add altname support for firewall rules X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" This works by reading all the currently configured altnames and then replacing any occurences of altnames when creating the firewall rules. We handle it this way because nftables has no support for matching on the altnames of interfaces. Signed-off-by: Stefan Hanreich --- proxmox-firewall/src/config.rs | 29 +++++++++++++++++++++ proxmox-firewall/src/rule.rs | 6 ++++- proxmox-firewall/tests/integration_tests.rs | 7 +++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/proxmox-firewall/src/config.rs b/proxmox-firewall/src/config.rs index ec9849e..f07fb1e 100644 --- a/proxmox-firewall/src/config.rs +++ b/proxmox-firewall/src/config.rs @@ -13,6 +13,8 @@ use proxmox_ve_config::firewall::types::alias::{Alias, AliasName, AliasScope}; use proxmox_ve_config::guest::types::Vmid; use proxmox_ve_config::guest::{GuestEntry, GuestMap}; +use proxmox_ve_config::host::network::InterfaceMapping; +use proxmox_ve_config::host::network::IpLink; use proxmox_ve_config::host::types::BridgeName; use proxmox_nftables::command::{CommandOutput, Commands, List, ListOutput}; @@ -40,6 +42,7 @@ pub trait FirewallConfigLoader { &self, bridge_name: &BridgeName, ) -> Result>, Error>; + fn interface_mapping(&self) -> Result; } #[derive(Default)] @@ -221,6 +224,26 @@ impl FirewallConfigLoader for PveFirewallConfigLoader { Ok(None) } + + fn interface_mapping(&self) -> Result { + let output = std::process::Command::new("ip") + .arg("-details") + .arg("-json") + .arg("link") + .arg("show") + .stdout(std::process::Stdio::piped()) + .output() + .with_context(|| "could not obtain ip link output")?; + + if !output.status.success() { + bail!("ip link returned non-zero exit code") + } + + Ok(serde_json::from_slice::>(&output.stdout) + .with_context(|| "could not deserialize ip link output")? + .into_iter() + .collect()) + } } pub trait NftConfigLoader { @@ -255,6 +278,7 @@ pub struct FirewallConfig { nft_config: BTreeMap, sdn_config: Option, ipam_config: Option, + interface_mapping: InterfaceMapping, } impl FirewallConfig { @@ -380,6 +404,7 @@ impl FirewallConfig { sdn_config: Self::parse_sdn(firewall_loader)?, ipam_config: Self::parse_ipam(firewall_loader)?, nft_config: Self::parse_nft(nft_loader)?, + interface_mapping: firewall_loader.interface_mapping()?, }) } @@ -415,6 +440,10 @@ impl FirewallConfig { self.cluster().is_enabled() && self.host().nftables() } + pub fn interface_mapping(&self, iface_name: &str) -> Option<&str> { + self.interface_mapping.get(iface_name).map(|x| x.as_str()) + } + pub fn alias(&self, name: &AliasName, vmid: Option) -> Option<&Alias> { log::trace!("getting alias {name:?}"); diff --git a/proxmox-firewall/src/rule.rs b/proxmox-firewall/src/rule.rs index 14ee544..c4975a9 100644 --- a/proxmox-firewall/src/rule.rs +++ b/proxmox-firewall/src/rule.rs @@ -135,7 +135,11 @@ impl NftRuleEnv<'_> { rule_iface.to_string() } - None => rule_iface.to_string(), + None => self + .firewall_config + .interface_mapping(rule_iface) + .map(|iface_name| iface_name.to_string()) + .unwrap_or_else(|| rule_iface.to_string()), } } diff --git a/proxmox-firewall/tests/integration_tests.rs b/proxmox-firewall/tests/integration_tests.rs index 1c014ad..69f9cc2 100644 --- a/proxmox-firewall/tests/integration_tests.rs +++ b/proxmox-firewall/tests/integration_tests.rs @@ -1,4 +1,5 @@ use anyhow::{Context, Error}; +use proxmox_ve_config::host::network::InterfaceMapping; use std::collections::HashMap; use proxmox_firewall::config::{FirewallConfig, FirewallConfigLoader, NftConfigLoader}; @@ -91,6 +92,12 @@ impl FirewallConfigLoader for MockFirewallConfigLoader { ) -> Result>, Error> { Ok(None) } + + fn interface_mapping( + &self, + ) -> Result { + Ok(InterfaceMapping::from_iter(vec![])) + } } struct MockNftConfigLoader {} -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel