]> git.proxmox.com Git - pve-firewall.git/blobdiff - src/PVE/Firewall.pm
bump version to 5.0.7
[pve-firewall.git] / src / PVE / Firewall.pm
index 81a879886ab4e66cff7a1305de162758a754dc44..09544ba71c090ed0d8f609b8115d7d116daf252e 100644 (file)
@@ -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) {
@@ -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);