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.he...@proxmox.com> --- Depends on patch #1 being applied first to proxmox-ve-rs & a appropriate crate bump. proxmox-firewall/src/firewall.rs | 14 ++- .../integration_tests__firewall.snap | 85 ++++++++++++++++++- proxmox-nftables/src/expression.rs | 9 ++ proxmox-nftables/src/statement.rs | 10 ++- 4 files changed, 114 insertions(+), 4 deletions(-) diff --git a/proxmox-firewall/src/firewall.rs b/proxmox-firewall/src/firewall.rs index 88fb460..9f7df56 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, @@ -934,7 +936,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 9194fc6..aa29e6e 100644 --- a/proxmox-firewall/tests/snapshots/integration_tests__firewall.snap +++ b/proxmox-firewall/tests/snapshots/integration_tests__firewall.snap @@ -1,7 +1,6 @@ --- source: proxmox-firewall/tests/integration_tests.rs expression: "firewall.full_host_fw().expect(\"firewall can be generated\")" -snapshot_kind: text --- { "nftables": [ @@ -4373,6 +4372,27 @@ snapshot_kind: text } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-100-in", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 100 + } + } + ] + } + } + }, { "add": { "rule": { @@ -4648,6 +4668,27 @@ snapshot_kind: text } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-100-out", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 100 + } + } + ] + } + } + }, { "add": { "rule": { @@ -5034,6 +5075,27 @@ snapshot_kind: text } } }, + { + "add": { + "rule": { + "family": "bridge", + "table": "proxmox-firewall-guests", + "chain": "guest-101-in", + "expr": [ + { + "mangle": { + "key": { + "ct": { + "key": "mark" + } + }, + "value": 101 + } + } + ] + } + } + }, { "add": { "rule": { @@ -5096,6 +5158,27 @@ snapshot_kind: text } } }, + { + "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.48.1 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel