voxpupuli / puppet-nftables

Puppet Module to manage nftables firewall rules.
Apache License 2.0
12 stars 33 forks source link

Support Arrays of source/destination IP addresses for nftables::simplerule #223

Closed bastelfreak closed 1 month ago

bastelfreak commented 9 months ago

Hi, I'm currently switching from our ferm module to nftables. The ferm module has the big advantage that I can pass an array of IPv4 and IPv6 addresses as source and destination and it will create proper rules. That's not possible with nftables::simplerule and I think it would be a big advantage. I poked a bit around in the template but I'm not really sure about the best way to implement this. Maybe someone else has an idea. At least passing and array of Ipv4 or IPv6 addresses would help.

Example with ferm from our wireguard module:

https://github.com/voxpupuli/puppet-wireguard/blob/a69ae4a30b8afe4b86b3f84d5f0262553a453944/manifests/interface.pp#L127-L140

    $daddr = empty($destination_addresses) ? {
      true    => undef,
      default => $destination_addresses,
    }
    ferm::rule { "allow_wg_${interface}":
      action    => 'ACCEPT',
      chain     => 'INPUT',
      proto     => 'udp',
      dport     => $dport,
      interface => $input_interface,
      saddr     => $source_addresses,
      daddr     => $daddr,
      notify    => Service['systemd-networkd'],
    }

and now with nftables:

    $daddr = empty($destination_addresses) ? {
      true    => undef,
      default => $destination_addresses,
    }
    # ToDo: It would be nice if this would be a parameter
    if $endpoint =~  /:(\d+)$/ {
      $endpoint_port = Integer($1)
    } else {
      $endpoint_port = undef
    }
    $source_addresses.each |$index1, $saddr| {
      if $saddr =~ Stdlib::IP::Address::V4 {
        $daddr.each |$index2, $_daddr| {
          if $_daddr =~ Stdlib::IP::Address::V4 {
            nftables::simplerule { "allow_in_wg_${interface}-${index1}${index2}":
              action  => 'accept',
              comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}",
              dport   => $dport,
              sport   => $endpoint_port,
              proto   => 'udp',
              daddr   => $_daddr,
              saddr   => $saddr,
              iifname => $input_interface,
              notify  => Service['systemd-networkd'],
            }
          }
        }
      } else {
        $daddr.each |$index2, $_daddr| {
          if $_daddr =~ Stdlib::IP::Address::V6 {
            nftables::simplerule { "allow_in_wg_${interface}-${index1}${index2}":
              action  => 'accept',
              comment => "Allow traffic from interface ${input_interface} from IP ${saddr} for wireguard tunnel ${interface}",
              dport   => $dport,
              proto   => 'udp',
              daddr   => $_daddr,
              saddr   => $saddr,
              iifname => $input_interface,
              notify  => Service['systemd-networkd'],
            }
          }
        }
      }
    }
anarcat commented 7 months ago

we can have sets of IP addresses in nftables, no?

e.g. ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 } is legal. couldn't we just concatenate those?

bastelfreak commented 7 months ago

yes nftables supports sets. I just had no time to implement it to cast arrays into sets (and if someone else want's to do that, that would be awesome).