X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FFirewall.pm;h=d22b15a506387bd7462ee8ae8ffa0f60f3ddf96e;hp=77cbaf46598ff7eff0842a0484ef90239e4a58b0;hb=HEAD;hpb=1f0303f82a7d661024a374ab2cf195835390b738 diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 77cbaf4..09544ba 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -1408,6 +1408,12 @@ our $host_option_properties = { default => 0, optional => 1 }, + nftables => { + description => "Enable nftables based firewall (tech preview)", + type => 'boolean', + default => 0, + optional => 1, + }, }; our $vm_option_properties = { @@ -2929,7 +2935,7 @@ sub parse_hostfw_option { my $loglevels = "emerg|alert|crit|err|warning|notice|info|debug|nolog"; - if ($line =~ m/^(enable|nosmurfs|tcpflags|ndp|log_nf_conntrack|nf_conntrack_allow_invalid|protection_synflood):\s*(0|1)\s*$/i) { + if ($line =~ m/^(enable|nosmurfs|tcpflags|ndp|log_nf_conntrack|nf_conntrack_allow_invalid|protection_synflood|nftables):\s*(0|1)\s*$/i) { $opt = lc($1); $value = int($2); } elsif ($line =~ m/^(log_level_in|log_level_out|tcp_flags_log_level|smurf_log_level):\s*(($loglevels)\s*)?$/i) { @@ -3360,7 +3366,7 @@ my $format_aliases = sub { my $raw = ''; $raw .= "[ALIASES]\n\n"; - foreach my $k (keys %$aliases) { + foreach my $k (sort keys %$aliases) { my $e = $aliases->{$k}; $raw .= "$e->{name} $e->{cidr}"; $raw .= " # " . encode('utf8', $e->{comment}) @@ -4673,12 +4679,51 @@ sub remove_pvefw_chains_ebtables { ebtables_restore_cmdlist(get_ebtables_cmdlist({})); } -sub init { - my $cluster_conf = load_clusterfw_conf(); - my $cluster_options = $cluster_conf->{options}; - my $enable = $cluster_options->{enable}; +sub is_nftables { + my ($cluster_conf, $host_conf) = @_; + + if (!-x "/usr/libexec/proxmox/proxmox-firewall") { + return 0; + } + + $cluster_conf = load_clusterfw_conf() if !defined($cluster_conf); + $host_conf = load_hostfw_conf($cluster_conf) if !defined($host_conf); + + return $host_conf->{options}->{nftables}; +} + +my sub update_force_nftables_disable_flag { + my ($cluster_firewall_enabled, $is_nftables) = @_; + + # This is checked in proxmox-firewall to avoid log-spam due to failing to parse the config + my $FORCE_NFT_DISABLE_FLAG_FILE = "/run/proxmox-nftables-firewall-force-disable"; + + if (!($cluster_firewall_enabled && $is_nftables)) { + if (! -e $FORCE_NFT_DISABLE_FLAG_FILE) { + open(my $_fh, '>', $FORCE_NFT_DISABLE_FLAG_FILE) + or warn "failed to create flag file '$FORCE_NFT_DISABLE_FLAG_FILE' – $!\n"; + } + } else { + unlink($FORCE_NFT_DISABLE_FLAG_FILE) + or $!{ENOENT} or warn "failed to unlink flag file '$FORCE_NFT_DISABLE_FLAG_FILE' - $!\n"; + } +} + +sub is_enabled_and_not_nftables { + my ($cluster_conf, $host_conf) = @_; + + $cluster_conf = load_clusterfw_conf() if !defined($cluster_conf); + $host_conf = load_hostfw_conf($cluster_conf) if !defined($host_conf); + + my $is_nftables = is_nftables($cluster_conf, $host_conf); - return if !$enable; + update_force_nftables_disable_flag($cluster_conf->{options}->{enable}, $is_nftables); + + return $cluster_conf->{options}->{enable} && !$is_nftables; +} + +sub init { + return if !is_enabled_and_not_nftables(); # load required modules here } @@ -4687,15 +4732,13 @@ sub update { my $code = sub { my $cluster_conf = load_clusterfw_conf(); - my $cluster_options = $cluster_conf->{options}; + my $hostfw_conf = load_hostfw_conf($cluster_conf); - if (!$cluster_options->{enable}) { + if (!is_enabled_and_not_nftables($cluster_conf, $hostfw_conf)) { PVE::Firewall::remove_pvefw_chains(); return; } - my $hostfw_conf = load_hostfw_conf($cluster_conf); - my ($ruleset, $ipset_ruleset, $rulesetv6, $ebtables_ruleset) = compile($cluster_conf, $hostfw_conf); apply_ruleset($ruleset, $hostfw_conf, $ipset_ruleset, $rulesetv6, $ebtables_ruleset);