Puppet Class: nftables

Summary

Configure nftables

Overview

Examples:

allow dns out and do not allow ntp out

class{ 'nftables':
  out_ntp => false,
  out_dns => true,
}

do not flush particular tables, fail2ban in this case

class{ 'nftables':
  noflush_tables => ['inet-f2b-table'],
}

Parameters:

  • out_all (Boolean) (defaults to: false)

    Allow all outbound connections. If ‘true` then all other out parameters `out_ntp`, `out_dns`, … will be assuemed false.

  • out_ntp (Boolean) (defaults to: true)

    Allow outbound to ntp servers.

  • out_http (Boolean) (defaults to: true)

    Allow outbound to http servers.

  • out_dns (Boolean) (defaults to: true)

    Allow outbound to dns servers.

  • out_https (Boolean) (defaults to: true)

    Allow outbound to https servers.

  • out_icmp (Boolean) (defaults to: true)

    Allow outbound ICMPv4/v6 traffic.

  • in_ssh (Boolean) (defaults to: true)

    Allow inbound to ssh servers.

  • in_icmp (Boolean) (defaults to: true)

    Allow inbound ICMPv4/v6 traffic.

  • inet_filter (Boolean) (defaults to: true)

    Add default tables, chains and rules to process traffic.

  • nat (Boolean) (defaults to: true)

    Add default tables and chains to process NAT traffic.

  • nat_table_name (String[1]) (defaults to: 'nat')

    The name of the ‘nat’ table.

  • purge_unmanaged_rules (Boolean) (defaults to: false)

    Prohibits in-memory rules that are not declared in Puppet code. Setting this to true activates a check that reloads nftables if the rules in memory have been modified without Puppet.

  • inmem_rules_hash_file (Stdlib::Unixpath) (defaults to: '/var/tmp/puppet-nft-memhash')

    The name of the file where the hash of the in-memory rules will be stored.

  • sets (Hash) (defaults to: {})

    Allows sourcing set definitions directly from Hiera.

  • log_prefix (String) (defaults to: '[nftables] %<chain>s %<comment>s')

    String that will be used as prefix when logging packets. It can contain two variables using standard sprintf() string-formatting:

    * chain: Will be replaced by the name of the chain.
    * comment: Allows chains to add extra comments.
    
  • log_discarded (Boolean) (defaults to: true)

    Allow to log discarded packets

  • log_limit (Variant[Boolean[false], String]) (defaults to: '3/minute burst 5 packets')

    String with the content of a limit statement to be applied to the rules that log discarded traffic. Set to false to disable rate limiting.

  • reject_with (Variant[Boolean[false], Pattern[/icmp(v6|x)? type .+|tcp reset/]]) (defaults to: 'icmpx type port-unreachable')

    How to discard packets not matching any rule. If ‘false`, the fate of the packet will be defined by the chain policy (normally drop), otherwise the packet will be rejected with the REJECT_WITH policy indicated by the value of this parameter.

  • in_out_conntrack (Boolean) (defaults to: true)

    Adds INPUT and OUTPUT rules to allow traffic that’s part of an established connection and also to drop invalid packets.

  • in_out_drop_invalid (Boolean) (defaults to: $in_out_conntrack)

    Drops invalid packets in INPUT and OUTPUT

  • fwd_conntrack (Boolean) (defaults to: false)

    Adds FORWARD rules to allow traffic that’s part of an established connection and also to drop invalid packets.

  • fwd_drop_invalid (Boolean) (defaults to: $fwd_conntrack)

    Drops invalid packets in FORWARD

  • firewalld_enable (Variant[Boolean[false], Enum['mask']]) (defaults to: 'mask')

    Configures how the firewalld systemd service unit is enabled. It might be useful to set this to false if you’re externaly removing firewalld from the system completely.

  • noflush_tables (Optional[Array[Pattern[/^(ip|ip6|inet|arp|bridge|netdev)-[-a-zA-Z0-9_]+$/],1]]) (defaults to: undef)

    If specified only other existings tables will be flushed. If left unset all tables will be flushed via a ‘flush ruleset`

  • rules (Hash) (defaults to: {})

    Specify hashes of ‘nftables::rule`s via hiera

  • configuration_path (Stdlib::Unixpath)

    The absolute path to the principal nftables configuration file. The default varies depending on the system, and is set in the module’s data.

  • nft_path (Stdlib::Unixpath)

    Path to the nft binary

  • echo (Stdlib::Unixpath)

    Path to the echo binary

  • default_config_mode (Stdlib::Filemode)

    The default file & dir mode for configuration files and directories. The default varies depending on the system, and is set in the module’s data.

  • clobber_default_config (Boolean) (defaults to: false)

    Should the existing OS provided rules in the ‘configuration_path` be removed? If they are not being removed this module will add all of its configuration to the end of the existing rules.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'manifests/init.pp', line 126

class nftables (
  Stdlib::Unixpath $echo,
  Stdlib::Unixpath $configuration_path,
  Stdlib::Unixpath $nft_path,
  Stdlib::Filemode $default_config_mode,
  Boolean $clobber_default_config = false,
  Boolean $in_ssh = true,
  Boolean $in_icmp = true,
  Boolean $out_ntp = true,
  Boolean $out_dns = true,
  Boolean $out_http = true,
  Boolean $out_https = true,
  Boolean $out_icmp = true,
  Boolean $out_all = false,
  Boolean $in_out_conntrack = true,
  Boolean $in_out_drop_invalid = $in_out_conntrack,
  Boolean $fwd_conntrack = false,
  Boolean $fwd_drop_invalid = $fwd_conntrack,
  Boolean $inet_filter = true,
  Boolean $nat = true,
  Boolean $purge_unmanaged_rules = false,
  Hash $rules = {},
  Hash $sets = {},
  String $log_prefix = '[nftables] %<chain>s %<comment>s',
  String[1] $nat_table_name = 'nat',
  Stdlib::Unixpath $inmem_rules_hash_file = '/var/tmp/puppet-nft-memhash',
  Boolean $log_discarded = true,
  Variant[Boolean[false], String] $log_limit = '3/minute burst 5 packets',
  Variant[Boolean[false], Pattern[/icmp(v6|x)? type .+|tcp reset/]] $reject_with = 'icmpx type port-unreachable',
  Variant[Boolean[false], Enum['mask']] $firewalld_enable = 'mask',
  Optional[Array[Pattern[/^(ip|ip6|inet|arp|bridge|netdev)-[-a-zA-Z0-9_]+$/],1]] $noflush_tables = undef,
) {
  package { 'nftables':
    ensure => installed,
  }

  if $clobber_default_config {
    file { $configuration_path:
      ensure  => file,
      owner   => 'root',
      group   => 'root',
      mode    => $default_config_mode,
      content => "#Puppet Managed\ninclude \"/etc/nftables/puppet.nft\"\n",
      require => Package['nftables'],
      before  => File['/etc/nftables'],
      notify  => Service['nftables'],
    }
  } else {
    file_line { 'enable_nftables':
      line    => 'include "/etc/nftables/puppet.nft"',
      path    => $configuration_path,
      require => Package['nftables'],
      before  => File['/etc/nftables'],
      notify  => Service['nftables'],
    }
  }

  file {
    default:
      owner => 'root',
      group => 'root',
      mode  => $default_config_mode;
    '/etc/nftables':
      ensure => directory,
      mode   => $default_config_mode;
    '/etc/nftables/puppet-preflight':
      ensure  => directory,
      mode    => $default_config_mode,
      purge   => true,
      force   => true,
      recurse => true;
    '/etc/nftables/puppet-preflight.nft':
      ensure  => file,
      content => epp('nftables/config/puppet.nft.epp', {
          'inet_filter' => $inet_filter,
          'nat'         => $nat,
          'noflush'     => $noflush_tables
        }
      );
  } ~> exec {
    'nft validate':
      refreshonly => true,
      command     => "${nft_path} -I /etc/nftables/puppet-preflight -c -f /etc/nftables/puppet-preflight.nft || ( ${echo} '#CONFIG BROKEN' >> /etc/nftables/puppet-preflight.nft && /bin/false)"; # lint:ignore:check_unsafe_interpolations
  } -> file {
    default:
      owner => 'root',
      group => 'root',
      mode  => $default_config_mode;
    '/etc/nftables/puppet.nft':
      ensure  => file,
      content => epp('nftables/config/puppet.nft.epp', {
          'inet_filter' => $inet_filter,
          'nat'         => $nat,
          'noflush'     => $noflush_tables
        }
      );
    '/etc/nftables/puppet':
      ensure  => directory,
      mode    => $default_config_mode,
      purge   => true,
      force   => true,
      recurse => true;
  } ~> service { 'nftables':
    ensure     => running,
    enable     => true,
    hasrestart => true,
    restart    => 'PATH=/usr/bin:/bin systemctl reload nftables',
  }

  if $purge_unmanaged_rules {
    # Reload nftables ruleset from disk if running state not match last service change hash, or is absent (-s required to ignore counters)
    exec { 'nftables_memory_state_check':
      command  => ['echo', 'reloading_nftables'],
      path     => $facts['path'],
      provider => shell,
      unless   => ["test -s ${inmem_rules_hash_file} -a \"$(nft -s list ruleset | sha1sum)\" = \"$(cat ${inmem_rules_hash_file})\""],
      notify   => Service['nftables'],
    }

    # Generate nftables hash upon changes to the nftables service 
    exec { 'nftables_generate_hash':
      command     => ["nft -s list ruleset | sha1sum > ${inmem_rules_hash_file}"],
      path        => $facts['path'],
      provider    => shell,
      subscribe   => Service['nftables'],
      refreshonly => true,
    }
  }

  systemd::dropin_file { 'puppet_nft.conf':
    ensure  => present,
    unit    => 'nftables.service',
    content => epp('nftables/systemd/puppet_nft.conf.epp', {
        'configuration_path' => $configuration_path,
        'nft_path'           => $nft_path,
    }),
    notify  => Service['nftables'],
  }

  # firewalld.enable can be mask or false depending upon if firewalld is installed or not
  # https://tickets.puppetlabs.com/browse/PUP-10814
  service { 'firewalld':
    ensure => stopped,
    enable => $firewalld_enable,
  }

  if $inet_filter {
    include nftables::inet_filter
  }

  if $nat {
    include nftables::ip_nat
  }

  # inject custom rules e.g. from hiera
  $rules.each |$n,$v| {
    nftables::rule {
      $n:
        * => $v,
    }
  }

  # inject custom sets e.g. from hiera
  $sets.each |$n,$v| {
    nftables::set {
      $n:
        * => $v,
    }
  }
}