Révision 0ba57c66
ID | 0ba57c66a35ed4e9b570d8a6315a33a1c4ba3181 |
Enfant | a534e044 |
initial release
README.md | ||
---|---|---|
1 |
# nftables puppet module |
|
2 |
|
|
3 |
This module manages an opinionated nftables configuration |
|
4 |
|
|
5 |
By default it sets up a firewall that drops every incoming |
|
6 |
and outgoing connection. |
|
7 |
|
|
8 |
It only allows outgoing dns,ntp and web traffic. |
|
9 |
|
|
10 |
The config file has a inet filter and a ip nat table setup. |
|
11 |
|
|
12 |
Additionally, the module comes with a basic infrastrcuture |
|
13 |
to hook into different places. |
|
14 |
|
|
15 |
## nftables config |
|
16 |
|
|
17 |
The main configuration file loaded by the nftables service |
|
18 |
will be `files/config/puppet.nft`, all other files created |
|
19 |
by that module go into `files/config/puppet` and will also |
|
20 |
be purged if not managed anymore. |
|
21 |
|
|
22 |
The main configuration file includes dedicated files for |
|
23 |
the filter and nat tables, as well as processes any |
|
24 |
`custom-*.nft` files before hand. |
|
25 |
|
|
26 |
The filter and NAT tables both have all the master chains |
|
27 |
(INPUT,OUTPUT,FORWARD) configured, to which you can hook |
|
28 |
in your own chains that can contain specific rules. |
|
29 |
|
|
30 |
All filter masterchains drop by default. |
|
31 |
By default we have a set of default_MASTERCHAIN chains |
|
32 |
configured to which you can easily add your custom rules. |
|
33 |
|
|
34 |
For specific needs you can add your own chain. |
|
35 |
|
|
36 |
There is a global chain, that defines the default behavior |
|
37 |
for all masterchains. |
|
38 |
|
|
39 |
INPUT and OUTPUT to the loopback device is allowed by default, |
|
40 |
though you could restrict it later. |
|
41 |
|
|
42 |
### nftables::config |
|
43 |
|
|
44 |
Manages a raw file in `/etc/nftables/puppet/${name}.nft` |
|
45 |
|
|
46 |
Use this for any custom table files. |
|
47 |
|
|
48 |
## nftables::chain_file |
|
49 |
|
|
50 |
Prepares a chain file as a `concat` file to which you will be |
|
51 |
able to add dedicated rules through `concat::fragments`. |
|
52 |
|
|
53 |
The name must follow the pattern `TABLE@chain_name`, e.g. |
|
54 |
`filter@my_chain`. This will a) prepare a snippet defining |
|
55 |
the chain, that will be included in the filter table. |
|
56 |
|
|
57 |
This define is more intended as a helper to setup chains |
|
58 |
that will be used for the different tables, through their |
|
59 |
own defines. See `nftables::filter::chain` as an example. |
|
60 |
|
|
61 |
## nftables::filter::chain |
|
62 |
|
|
63 |
This setups a chain for the filter table. You will be able |
|
64 |
to add rules to that chain by using `nftables::filter::chain::rule`. |
|
65 |
|
|
66 |
The name must follow the pattern: `MASTERCHAIN-new_chain_name`, which |
|
67 |
defines to which masterchain that custom chain should be hooked into. |
|
68 |
|
|
69 |
new_chain_name must be unique for all chains. |
|
70 |
|
|
71 |
There is automatically a `jump` instruction added to the masterchain, |
|
72 |
with the order preference. |
|
73 |
|
|
74 |
## nftables::filter::chain::rule |
|
75 |
|
|
76 |
A simple way to add rules to your custom chain. The name must be: |
|
77 |
`CHAIN_NAME-rulename`, where CHAIN_NAME refers to your chain and |
|
78 |
an arbitrary name for your rule. |
|
79 |
The rule will be a `concat::fragment` to the chain `concat`. |
|
80 |
|
|
81 |
You can define the order by using the `order` param. |
files/config/puppet-filter.nft | ||
---|---|---|
1 |
table inet filter { |
|
2 |
include "/etc/nftables/puppet/filter-chains-*.nft" |
|
3 |
|
|
4 |
# something we want for all |
|
5 |
chain global { |
|
6 |
ct state established,related accept |
|
7 |
ct state invalid drop |
|
8 |
|
|
9 |
ip protocol icmp limit rate 4/second accept |
|
10 |
ip6 nexthdr ipv6-icmp limit rate 4/second accept |
|
11 |
ip protocol igmp limit rate 4/second accept |
|
12 |
} |
|
13 |
|
|
14 |
chain INPUT { |
|
15 |
type filter hook input priority 0 |
|
16 |
policy drop |
|
17 |
|
|
18 |
jump global |
|
19 |
|
|
20 |
iifname lo accept |
|
21 |
|
|
22 |
include "/etc/nftables/puppet/filter-input-chains-*.nft" |
|
23 |
|
|
24 |
log prefix "[nftables] INPUT Rejected: " flags all counter reject with icmpx type port-unreachable |
|
25 |
} |
|
26 |
|
|
27 |
chain FORWARD { |
|
28 |
type filter hook forward priority 0 |
|
29 |
policy drop |
|
30 |
|
|
31 |
jump global |
|
32 |
|
|
33 |
include "/etc/nftables/puppet/filter-forward-chains-*.nft" |
|
34 |
|
|
35 |
log prefix "[nftables] FORWARD Rejected: " flags all counter reject with icmpx type port-unreachable |
|
36 |
} |
|
37 |
|
|
38 |
chain OUTPUT { |
|
39 |
type filter hook output priority 0 |
|
40 |
policy drop |
|
41 |
|
|
42 |
jump global |
|
43 |
|
|
44 |
oifname lo accept |
|
45 |
|
|
46 |
include "/etc/nftables/puppet/filter-output-chains-*.nft" |
|
47 |
|
|
48 |
log prefix "[nftables] OUTPUT Rejected: " flags all counter reject with icmpx type port-unreachable |
|
49 |
} |
|
50 |
} |
files/config/puppet-nat.nft | ||
---|---|---|
1 |
table nat { |
|
2 |
include "/etc/nftables/puppet/nat-chains-*.nft" |
|
3 |
|
|
4 |
chain PREROUTING { |
|
5 |
type nat hook prerouting priority 0 |
|
6 |
policy accept |
|
7 |
|
|
8 |
include "/etc/nftables/puppet/nat-chain-prerouting-*.nft" |
|
9 |
} |
|
10 |
chain INPUT { |
|
11 |
type nat hook input priority 100 |
|
12 |
policy accept |
|
13 |
|
|
14 |
include "/etc/nftables/puppet/nat-chain-input-*.nft" |
|
15 |
} |
|
16 |
chain OUTPUT { |
|
17 |
type nat hook output priority 0 |
|
18 |
policy accept |
|
19 |
|
|
20 |
include "/etc/nftables/puppet/nat-chain-output-*.nft" |
|
21 |
} |
|
22 |
|
|
23 |
chain POSTROUTING { |
|
24 |
type nat hook postrouting priority 100 |
|
25 |
policy accept |
|
26 |
|
|
27 |
include "/etc/nftables/puppet/nat-chain-postrouting-*.nft" |
|
28 |
} |
|
29 |
} |
files/config/puppet.nft | ||
---|---|---|
1 |
# drop any existing nftables ruleset |
|
2 |
flush ruleset |
|
3 |
|
|
4 |
include "/etc/nftables/puppet/custom-*.nft" |
|
5 |
|
|
6 |
include "/etc/nftables/puppet/filter.nft" |
|
7 |
|
|
8 |
include "/etc/nftables/puppet/nat.nft" |
|
9 |
|
manifests/chain_file.pp | ||
---|---|---|
1 |
# manage a chain file |
|
2 |
# chain must be: |
|
3 |
# TABLE@chain_name |
|
4 |
define nftables::chain_file( |
|
5 |
Pattern[/^[a-z0-9]+@[a-z0-9_]+$/] $chain = $title, |
|
6 |
){ |
|
7 |
$data = split($chain,'@') |
|
8 |
$concat_name = "nftables-chain-${data[0]}-${data[1]}" |
|
9 |
concat{ |
|
10 |
$concat_name: |
|
11 |
path => "/etc/nftables/puppet/${data[0]}-chains-${data[1]}.nft", |
|
12 |
owner => root, |
|
13 |
group => root, |
|
14 |
mode => '0644', |
|
15 |
ensure_newline => true, |
|
16 |
require => Package['nftables'], |
|
17 |
notify => Service['nftables'], |
|
18 |
} |
|
19 |
concat::fragment{ |
|
20 |
default: |
|
21 |
target => $concat_name; |
|
22 |
"${chain}-header": |
|
23 |
order => '00', |
|
24 |
content => "chain ${data[1]} {"; |
|
25 |
"${chain}-footer": |
|
26 |
order => '99', |
|
27 |
content => '}'; |
|
28 |
} |
|
29 |
} |
manifests/config.pp | ||
---|---|---|
1 |
# manage a config snippet |
|
2 |
define nftables::config( |
|
3 |
Optional[String] |
|
4 |
$content = undef, |
|
5 |
Optional[Variant[String,Array[String,1]]] |
|
6 |
$source = undef, |
|
7 |
){ |
|
8 |
Package['nftables'] -> file{ |
|
9 |
"/etc/nftables/puppet/${name}.nft": |
|
10 |
owner => root, |
|
11 |
group => root, |
|
12 |
mode => '0640', |
|
13 |
} ~> Service['nftables'] |
|
14 |
|
|
15 |
if $source { |
|
16 |
File["/etc/nftables/puppet/${name}.nft"]{ |
|
17 |
source => $source, |
|
18 |
} |
|
19 |
} else { |
|
20 |
File["/etc/nftables/puppet/${name}.nft"]{ |
|
21 |
content => $content, |
|
22 |
} |
|
23 |
} |
|
24 |
} |
manifests/filter/chain.pp | ||
---|---|---|
1 |
# register a filter chain |
|
2 |
# Name should match the following pattern: |
|
3 |
# |
|
4 |
# MASTERCHAIN-new_chain_name |
|
5 |
define nftables::filter::chain( |
|
6 |
Pattern[/^[a-z0-9]+\-[a-z0-9_]+$/] |
|
7 |
$chain_name = $title, |
|
8 |
Pattern[/^\d{2}$/] |
|
9 |
$order = '50', |
|
10 |
){ |
|
11 |
$data = split($chain_name,'-') |
|
12 |
nftables::config{ |
|
13 |
"filter-${data[0]}-chains-${order}-${data[1]}": |
|
14 |
content => "jump ${data[1]}", |
|
15 |
} |
|
16 |
nftables::chain_file{ |
|
17 |
"filter@${data[1]}":; |
|
18 |
} |
|
19 |
} |
manifests/filter/chain/rule.pp | ||
---|---|---|
1 |
# manage a filter chain rule |
|
2 |
# Name should be: |
|
3 |
# TABLE_NAME-rulename |
|
4 |
define nftables::filter::chain::rule( |
|
5 |
Enum['present','absent'] |
|
6 |
$ensure = 'present', |
|
7 |
Pattern[/^[a-z0-9_]+\-[0-9a-z]+$/] |
|
8 |
$rulename = $title, |
|
9 |
Pattern[/^\d\d$/] |
|
10 |
$order = '50', |
|
11 |
Optional[String] |
|
12 |
$content = undef, |
|
13 |
Optional[Variant[String,Array[String,1]]] |
|
14 |
$source = undef, |
|
15 |
){ |
|
16 |
if $ensure == 'present' { |
|
17 |
$data = split($rulename,'-') |
|
18 |
concat::fragment{ |
|
19 |
"nftables-filter-chain-rule-${rulename}": |
|
20 |
order => $order, |
|
21 |
target => "nftables-chain-filter-${data[0]}", |
|
22 |
} |
|
23 |
|
|
24 |
if $content { |
|
25 |
Concat::Fragment["nftables-filter-chain-rule-${rulename}"]{ |
|
26 |
content => " ${content}", |
|
27 |
} |
|
28 |
} else { |
|
29 |
Concat::Fragment["nftables-filter-chain-rule-${rulename}"]{ |
|
30 |
source => $source, |
|
31 |
} |
|
32 |
} |
|
33 |
} |
|
34 |
} |
manifests/init.pp | ||
---|---|---|
1 |
# manage nftables |
|
2 |
class nftables { |
|
3 |
package{'nftables': |
|
4 |
ensure => installed, |
|
5 |
} -> file_line{ |
|
6 |
'enable_nftables': |
|
7 |
line => 'include "/etc/nftables/puppet.nft"', |
|
8 |
path => '/etc/sysconfig/nftables.conf', |
|
9 |
notify => Service['nftables'], |
|
10 |
} -> file{ |
|
11 |
default: |
|
12 |
owner => 'root', |
|
13 |
group => 'root', |
|
14 |
mode => '0640'; |
|
15 |
'/etc/nftables/puppet.nft': |
|
16 |
source => 'puppet:///modules/nftables/config/puppet.nft'; |
|
17 |
'/etc/nftables/puppet': |
|
18 |
ensure => directory, |
|
19 |
purge => true, |
|
20 |
force => true, |
|
21 |
recurse => true; |
|
22 |
} ~> service{'nftables': |
|
23 |
ensure => running, |
|
24 |
enable => true, |
|
25 |
} |
|
26 |
|
|
27 |
nftables::config{ |
|
28 |
'filter': |
|
29 |
source => 'puppet:///modules/nftables/config/puppet-filter.nft'; |
|
30 |
'nat': |
|
31 |
source => 'puppet:///modules/nftables/config/puppet-nat.nft'; |
|
32 |
} |
|
33 |
|
|
34 |
nftables::filter::chain{ |
|
35 |
[ |
|
36 |
'forward-default_fwd', |
|
37 |
'output-default_out', |
|
38 |
'input-default_in', |
|
39 |
]:; |
|
40 |
} |
|
41 |
# basic outgoing rules |
|
42 |
nftables::filter::chain::rule{ |
|
43 |
'default_out-dnsudp': |
|
44 |
content => 'udp dport 53 accept'; |
|
45 |
'default_out-dnstcp': |
|
46 |
content => 'tcp dport 53 accept'; |
|
47 |
'default_out-web': |
|
48 |
content => 'tcp dport {80, 443} accept'; |
|
49 |
} |
|
50 |
} |
manifests/rules/out/chrony.pp | ||
---|---|---|
1 |
# manage out chrony |
|
2 |
class nftables::rules::out::chrony { |
|
3 |
nftables::filter::chain::rule{ |
|
4 |
'default_out-chrony': |
|
5 |
content => 'udp dport 123 accept', |
|
6 |
} |
|
7 |
} |
manifests/rules/out/smtp.pp | ||
---|---|---|
1 |
# manage out smtp |
|
2 |
class nftables::rules::out::smtp { |
|
3 |
nftables::filter::chain::rule{ |
|
4 |
'default_out-smtp': |
|
5 |
content => 'tcp dport 25 accept', |
|
6 |
} |
|
7 |
} |
manifests/rules/out/ssh.pp | ||
---|---|---|
1 |
# manage out ssh |
|
2 |
class nftables::rules::out::ssh { |
|
3 |
nftables::filter::chain::rule{ |
|
4 |
'default_out-ssh': |
|
5 |
content => 'tcp dport 22 accept', |
|
6 |
} |
|
7 |
} |
manifests/rules/out/ssh/remove.pp | ||
---|---|---|
1 |
# disable outgoing ssh |
|
2 |
class nftables::rules::out::ssh::remove inherits nftables::rules::out::ssh { |
|
3 |
Nftables::Filter::Chain::Rule['default_out-ssh']{ |
|
4 |
ensure => absent, |
|
5 |
} |
|
6 |
} |
manifests/rules/ssh.pp | ||
---|---|---|
1 |
# manage in ssh |
|
2 |
class nftables::rules::ssh( |
|
3 |
Array[Integer,1] |
|
4 |
$ports = [22], |
|
5 |
) { |
|
6 |
nftables::filter::chain::rule{ |
|
7 |
'default_in-ssh': |
|
8 |
content => "tcp dport {${join($ports,', ')}} accept", |
|
9 |
} |
|
10 |
} |
Formats disponibles : Unified diff