public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Hanreich <s.hanreich@proxmox.com>
To: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
Cc: pve-devel@lists.proxmox.com
Subject: Re: [PATCH proxmox-firewall v2 10/12] firewall: dump config to local directory after apply
Date: Thu, 15 Oct 2026 14:44:27 +0200	[thread overview]
Message-ID: <179206826792.200327.730453550222014690.b4-review@b4> (raw)
In-Reply-To: <20261001122625.348730-11-a.bied-charreton@proxmox.com>

It feels as though it might make sense to move the cache handling into
its own struct instead of using a HashMap here that gets passed
around?

> The firewall configuration files are stored on pmxcfs, which is only
> available when pve-cluster is up. To be able to restore firewall rules
> before the network comes up and close the boot-time window in which the
> PVE host is unprotected, dump the required configuration files to a
> local directory after every apply.
> 
> The last dumped version is cached for each file, the daemon only
> actually writes to disk if there has been a change since the last write
> or the dump file does not exist.
> 
> Ownership of the dumps is keyed on the nftables option in the host
> config. When the firewall is disabled, the dumps are only removed if
> nftables is enabled - otherwise that responsibility is on pve-firewall.
> 
> The dumps are also removed when the daemon is stopped, to prevent a
> ruleset restored at boot from living forever if no daemon starts
> afterwards.
> 
> Signed-off-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
> Reviewed-by: Thomas Ellmenreich <t.ellmenreich@proxmox.com>
> Tested-by: Thomas Ellmenreich <t.ellmenreich@proxmox.com>
>
> diff --git a/debian/dirs b/debian/dirs
> new file mode 100644
> index 0000000..34355af
> --- /dev/null
> +++ b/debian/dirs
> @@ -0,0 +1 @@
> +/var/lib/pve/firewall
> diff --git a/proxmox-firewall/Cargo.toml b/proxmox-firewall/Cargo.toml
> index fa7fd34..77ca285 100644
> --- a/proxmox-firewall/Cargo.toml
> +++ b/proxmox-firewall/Cargo.toml
> @@ -22,9 +22,9 @@ proxmox-log.workspace = true
>  proxmox-network-types.workspace = true
>  proxmox-network-api = { workspace = true, features = [ "impl" ] }
>  proxmox-nftables = { workspace = true, features = [ "config-ext" ] }
> +proxmox-sys.workspace = true
>  proxmox-systemd.workspace = true
>  proxmox-ve-config.workspace = true
>  
>  [dev-dependencies]
>  insta = { workspace = true, features = [ "json" ] }
> -proxmox-sys.workspace = true
> diff --git a/proxmox-firewall/src/bin/proxmox-firewall.rs b/proxmox-firewall/src/bin/proxmox-firewall.rs
> index 27fd67d..1ac7c6c 100644
> --- a/proxmox-firewall/src/bin/proxmox-firewall.rs
> +++ b/proxmox-firewall/src/bin/proxmox-firewall.rs
> @@ -1,3 +1,6 @@
> +use std::collections::HashMap;
> +use std::os::unix::fs::PermissionsExt;
> +use std::path::Path;
>  use std::sync::Arc;
>  use std::sync::atomic::{AtomicBool, Ordering};
>  use std::time::{Duration, Instant};
> @@ -5,11 +8,14 @@ use std::time::{Duration, Instant};
>  use anyhow::{Context, Error, bail, format_err};
>  use pico_args::Arguments;
>  
> -use proxmox_firewall::config::{FirewallConfig, PveFirewallConfigLoader, PveNftConfigLoader};
> +use proxmox_firewall::config::{
> +    DUMP_DIR, FirewallConfig, PveFirewallConfigLoader, PveNftConfigLoader,
> +};
>  use proxmox_firewall::firewall::Firewall;
>  use proxmox_log as log;
>  use proxmox_log::{LevelFilter, Logger};
>  use proxmox_nftables::{NftClient, client::NftError};
> +use proxmox_sys::fs;
>  use proxmox_systemd::systemctl;
>  use proxmox_ve_config::firewall::host::Config as HostConfig;
>  
> @@ -42,14 +48,58 @@ fn remove_firewall() -> Result<(), std::io::Error> {
>      Ok(())
>  }
>  
> +fn dump_config(cfg: &FirewallConfig, cache: &mut HashMap<&str, Vec<u8>>) {
> +    let dump_dir = Path::new(DUMP_DIR);
> +    if !dump_dir.exists()
> +        && let Err(e) = fs::create_path(dump_dir, None, None)
> +    {
> +        log::error!("could not create {DUMP_DIR}: {e} - config will not be dumped");
> +        return;
> +    }
> +
> +    if let Err(e) = std::fs::set_permissions(dump_dir, std::fs::Permissions::from_mode(0o700)) {
> +        log::warn!("could not set permissions on {DUMP_DIR}: {e}");
> +    }

Would make sense to set the permissions on creation here as well
instead of doing it every update cycle.

> +
> +    for (bytes, name) in [
> +        (cfg.cluster_raw(), "cluster.fw"),
> +        (cfg.host_raw(), "host.fw"),
> +        (cfg.sdn_raw(), "sdn.json"),
> +    ] {
> +        let out = dump_dir.join(name);
> +        match bytes {
> +            Some(b) if !out.exists() || b != cache.get(name).map(Vec::as_slice).unwrap_or(&[]) => {
> +                match fs::replace_file(&out, b, fs::CreateOptions::new(), true) {
> +                    Err(e) => log::error!("could not dump {name} to {out:?}: {e}"),
> +                    Ok(()) => {
> +                        log::info!("successfully dumped {out:?}");
> +                        cache.insert(name, b.to_vec());
> +                    }
> +                }
> +            }
> +            Some(_) => log::debug!("no changes to {name} since last dump to {out:?}"),
> +            None => {
> +                log::debug!("nothing to dump for {name}");
> +                cache.remove(name);
> +                _ = std::fs::remove_file(&out);

at least log the error here if unsuccessful?

> +            }
> +        }
> +    }
> +}
> +
>  fn create_firewall_instance() -> Result<Firewall, Error> {
>      let config = FirewallConfig::new(&PveFirewallConfigLoader::new(), &PveNftConfigLoader::new())?;
>      Ok(Firewall::new(config))
>  }
>  
> -fn handle_firewall() -> Result<(), Error> {
> -    let firewall = create_firewall_instance()?;
> +fn delete_dumps(cache: &mut HashMap<&str, Vec<u8>>) {
> +    cache.clear();
> +    for f in ["cluster.fw", "host.fw", "sdn.json"] {
> +        _ = std::fs::remove_file(Path::new(DUMP_DIR).join(f));

same w.r.t. logging errors here as well...

-- 
Stefan Hanreich <s.hanreich@proxmox.com>




  reply	other threads:[~2026-10-15 12:44 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01 12:26 [RFC firewall/manager/proxmox{,-firewall} v2 00/12] fix #5759: keep firewall rules up across boot and shutdown Arthur Bied-Charreton
2026-10-01 12:26 ` [PATCH pve-manager v2 01/12] network interface pinning: write new firewall config to local dir Arthur Bied-Charreton
2026-10-01 12:26 ` [PATCH pve-firewall v2 02/12] firewall: config: sort OPTIONS when serializing Arthur Bied-Charreton
2026-10-15 12:45   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH pve-firewall v2 03/12] firewall: dump configs locally after applying Arthur Bied-Charreton
2026-10-15 12:45   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH pve-firewall v2 04/12] fix #5759: firewall: do not remove chains when host is shutting down Arthur Bied-Charreton
2026-10-15 12:45   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH pve-firewall v2 05/12] firewall: add restore command Arthur Bied-Charreton
2026-10-15 12:45   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH pve-firewall v2 06/12] fix #5759: firewall: restore from dumped config before network-pre Arthur Bied-Charreton
2026-10-15 12:45   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH proxmox v2 07/12] systemd: systemctl: add is-system-running helper Arthur Bied-Charreton
2026-10-01 12:26 ` [PATCH proxmox-firewall v2 08/12] firewall: fix clippy warnings Arthur Bied-Charreton
2026-10-15 12:44   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH proxmox-firewall v2 09/12] fix #5759: firewall: do not clear rules on system shutdown Arthur Bied-Charreton
2026-10-01 12:26 ` [PATCH proxmox-firewall v2 10/12] firewall: dump config to local directory after apply Arthur Bied-Charreton
2026-10-15 12:44   ` Stefan Hanreich [this message]
2026-10-01 12:26 ` [PATCH proxmox-firewall v2 11/12] firewall: add restore command Arthur Bied-Charreton
2026-10-15 12:44   ` Stefan Hanreich
2026-10-01 12:26 ` [PATCH proxmox-firewall v2 12/12] fix #5759: firewall: restore from dumped config before network-pre Arthur Bied-Charreton
2026-10-15 12:45 ` [RFC firewall/manager/proxmox{,-firewall} v2 00/12] fix #5759: keep firewall rules up across boot and shutdown Stefan Hanreich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=179206826792.200327.730453550222014690.b4-review@b4 \
    --to=s.hanreich@proxmox.com \
    --cc=a.bied-charreton@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal