From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <pve-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id DC8411FF165 for <inbox@lore.proxmox.com>; Thu, 24 Apr 2025 13:20:12 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E6AE45554; Thu, 24 Apr 2025 13:19:51 +0200 (CEST) From: Christoph Heiss <c.heiss@proxmox.com> To: pve-devel@lists.proxmox.com Date: Thu, 24 Apr 2025 13:19:22 +0200 Message-ID: <20250424111941.730528-3-c.heiss@proxmox.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250424111941.730528-1-c.heiss@proxmox.com> References: <20250424111941.730528-1-c.heiss@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.030 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 Subject: [pve-devel] [PATCH proxmox-firewall v2 2/13] firewall: add connmark rule with VMID to all guest chains X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/> List-Post: <mailto:pve-devel@lists.proxmox.com> List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Proxmox VE development discussion <pve-devel@lists.proxmox.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" <pve-devel-bounces@lists.proxmox.com> Adds a connmark attribute with the VMID inside to anything flowing in/out the guest, which are also carried over to all conntrack entries. This enables differentiating conntrack entries between VMs for live-migration. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> --- Changes v1 -> v2: * rebased on latest master proxmox-firewall/src/firewall.rs | 14 +++- .../integration_tests__firewall.snap | 84 +++++++++++++++++++ proxmox-nftables/src/expression.rs | 9 ++ proxmox-nftables/src/statement.rs | 10 ++- 4 files changed, 114 insertions(+), 3 deletions(-) diff --git a/proxmox-firewall/src/firewall.rs b/proxmox-firewall/src/firewall.rs index 086b96c..552c6d3 100644 --- a/proxmox-firewall/src/firewall.rs +++ b/proxmox-firewall/src/firewall.rs @@ -6,7 +6,9 @@ use anyhow::{bail, Error}; use proxmox_nftables::command::{Add, Commands, Delete, Flush}; use proxmox_nftables::expression::{Meta, Payload}; use proxmox_nftables::helper::NfVec; -use proxmox_nftables::statement::{AnonymousLimit, Log, LogLevel, Match, Set, SetOperation}; +use proxmox_nftables::statement::{ + AnonymousLimit, Log, LogLevel, Mangle, Match, Set, SetOperation, +}; use proxmox_nftables::types::{ AddElement, AddRule, ChainPart, MapValue, RateTimescale, SetName, TableFamily, TableName, TablePart, Verdict, @@ -944,7 +946,15 @@ impl Firewall { vmid: Some(vmid), }; - commands.reserve(config.rules().len()); + commands.reserve(config.rules().len() + 1); + + // Add a connmark to anything in/out the guest, to be able to later + // track/filter per guest, e.g. in the pve-conntrack-tool. + // Need to be first, such that it is always applied. + commands.push(Add::rule(AddRule::from_statement( + chain.clone(), + Mangle::ct_mark(vmid), + ))); for config_rule in config.rules() { for rule in NftRule::from_config_rule(config_rule, &env)? { diff --git a/proxmox-firewall/tests/snapshots/integration_tests__firewall.snap b/proxmox-firewall/tests/snapshots/integration_tests__firewall.snap index ad54ad0..e3db8ae 100644 --- a/proxmox-firewall/tests/snapshots/integration_tests__firewall.snap +++ b/proxmox-firewall/tests/snapshots/integration_tests__firewall.snap @@ -4489,6 +4489,27 @@ expression: "firewall.full_host_fw().expect(\"firewall can be generated\")" } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-100-in", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 100 + } + } + ] + } + } + }, { "add": { "rule": { @@ -4764,6 +4785,27 @@ expression: "firewall.full_host_fw().expect(\"firewall can be generated\")" } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-100-out", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 100 + } + } + ] + } + } + }, { "add": { "rule": { @@ -5150,6 +5192,27 @@ expression: "firewall.full_host_fw().expect(\"firewall can be generated\")" } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-101-in", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 101 + } + } + ] + } + } + }, { "add": { "rule": { @@ -5212,6 +5275,27 @@ expression: "firewall.full_host_fw().expect(\"firewall can be generated\")" } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-101-out", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 101 + } + } + ] + } + } + }, { "add": { "rule": { diff --git a/proxmox-nftables/src/expression.rs b/proxmox-nftables/src/expression.rs index e9ef94f..cbafe85 100644 --- a/proxmox-nftables/src/expression.rs +++ b/proxmox-nftables/src/expression.rs @@ -12,6 +12,8 @@ use proxmox_ve_config::firewall::types::port::{PortEntry, PortList}; use proxmox_ve_config::firewall::types::rule_match::{IcmpCode, IcmpType, Icmpv6Code, Icmpv6Type}; #[cfg(feature = "config-ext")] use proxmox_ve_config::firewall::types::Cidr; +#[cfg(feature = "config-ext")] +use proxmox_ve_config::guest::types::Vmid; #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] @@ -267,6 +269,13 @@ impl From<&BridgeName> for Expression { } } +#[cfg(feature = "config-ext")] +impl From<Vmid> for Expression { + fn from(value: Vmid) -> Self { + Expression::Number(value.raw_value().into()) + } +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Meta { key: String, diff --git a/proxmox-nftables/src/statement.rs b/proxmox-nftables/src/statement.rs index 5483368..3264e6c 100644 --- a/proxmox-nftables/src/statement.rs +++ b/proxmox-nftables/src/statement.rs @@ -10,6 +10,7 @@ use proxmox_ve_config::firewall::types::rule::Verdict as ConfigVerdict; #[cfg(feature = "config-ext")] use proxmox_ve_config::guest::types::Vmid; +use crate::expression::Ct; use crate::expression::Meta; use crate::helper::{NfVec, Null}; use crate::types::{RateTimescale, RateUnit, Verdict}; @@ -370,12 +371,19 @@ pub struct Mangle { } impl Mangle { - pub fn set_mark(value: impl Into<Expression>) -> Self { + pub fn meta_mark(value: impl Into<Expression>) -> Self { Self { key: Meta::new("mark").into(), value: value.into(), } } + + pub fn ct_mark(value: impl Into<Expression>) -> Self { + Self { + key: Ct::new("mark", None).into(), + value: value.into(), + } + } } #[derive(Clone, Copy, Debug, Deserialize, Serialize)] -- 2.49.0 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel