Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
CHEF
cookbooks
sys
Commits
edb14d34
Commit
edb14d34
authored
May 05, 2022
by
m.pausch
Browse files
syntax, typos, bugs, style
parent
9674e8c8
Changes
4
Hide whitespace changes
Inline
Side-by-side
libraries/sys_helpers_nftables.rb
View file @
edb14d34
#
# Cookbook
Name
:: sys
# Cookbook:: sys
# Library:: Helpers::Nftables
#
# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
# Copyright
::
2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# Authors:
# Matthias Pausch (m.pausch@gsi.de)
...
...
@@ -28,14 +28,6 @@ module Sys
require
'ipaddr'
include
Chef
::
Mixin
::
ShellOut
def
dport
(
new_resource
)
new_resource
.
dest_port
||
new_resource
.
port
end
def
sport
(
new_resource
)
new_resource
.
source_port
end
def
valid_ips?
(
ips
)
Array
(
ips
).
inject
(
false
)
do
|
a
,
ip
|
a
||
!!
IPAddr
.
new
(
ip
)
...
...
@@ -55,16 +47,16 @@ module Sys
end
end
def
port_to_s
(
p
)
if
p
.
is_a?
(
String
)
p
elsif
p
&&
p
.
is_a?
(
Integer
)
p
.
to_s
elsif
p
&&
p
.
is_a?
(
Array
)
p_strings
=
p
.
map
{
|
o
|
port_to_s
(
o
)
}
"{
#{
p_strings
.
sort
.
join
(
','
)
}
}"
elsif
p
&&
p
.
is_a?
(
Range
)
"
#{
p
.
first
}
-
#{
p
.
last
}
"
def
port_to_s
(
p
ort
)
if
p
ort
.
is_a?
(
String
)
p
ort
elsif
p
ort
&&
p
ort
.
is_a?
(
Integer
)
p
ort
.
to_s
elsif
p
ort
&&
p
ort
.
is_a?
(
Array
)
p
ort
_strings
=
p
ort
.
map
{
|
o
|
port_to_s
(
o
)
}
"{
#{
p
ort
_strings
.
sort
.
join
(
','
)
}
}"
elsif
p
ort
&&
p
ort
.
is_a?
(
Range
)
"
#{
p
ort
.
first
}
-
#{
p
ort
.
last
}
"
end
end
...
...
@@ -73,33 +65,29 @@ module Sys
sorted_values
=
rules
.
values
.
sort
.
uniq
sorted_values
.
each
do
|
sorted_value
|
contents
<<
"# position
#{
sorted_value
}
"
contents
<<
rules
.
select
{
|
_
,
v
|
v
==
sorted_value
}.
keys
.
join
(
"
\n
"
)
contents
<<
rules
.
select
{
|
_
,
v
|
v
==
sorted_value
}.
keys
.
join
(
"
\n
"
)
end
"
#{
contents
.
join
(
"
\n
"
)
}
\n
"
end
unless
defined?
CHAIN
CHAIN
=
{
in:
'input'
,
out:
'output'
,
pre:
'prerouting'
,
post:
'postrouting'
,
forward:
'forward'
,
}.
freeze
end
unless
defined?
TARGET
TARGET
=
{
accept:
'accept'
,
allow:
'accept'
,
deny:
'drop'
,
drop:
'drop'
,
log:
'log prefix "nftables:" group 0'
,
masquerade:
'masquerade'
,
redirect:
'redirect'
,
reject:
'reject'
,
}.
freeze
end
CHAIN
||=
{
in:
'input'
,
out:
'output'
,
pre:
'prerouting'
,
post:
'postrouting'
,
forward:
'forward'
,
}.
freeze
TARGET
||=
{
accept:
'accept'
,
allow:
'accept'
,
deny:
'drop'
,
drop:
'drop'
,
log:
'log prefix "nftables:" group 0'
,
masquerade:
'masquerade'
,
redirect:
'redirect'
,
reject:
'reject'
,
}.
freeze
def
build_nftables_rule
(
rule_resource
)
return
rule_resource
.
raw
.
strip
if
rule_resource
.
raw
...
...
@@ -118,7 +106,7 @@ module Sys
nftables_rule
<<
CHAIN
.
fetch
(
rule_resource
.
direction
.
to_sym
)
nftables_rule
<<
' '
nftables_rule
<<
"iif
#{
rule_resource
.
interface
}
"
if
rule_resource
.
interface
nftables_rule
<<
"oif
#{
rule_resource
.
outerface
}
"
if
rule_resource
.
dest_in
terface
nftables_rule
<<
"oif
#{
rule_resource
.
outerface
}
"
if
rule_resource
.
ou
terface
if
rule_resource
.
source
source_set
=
build_set_of_ips
(
rule_resource
.
source
)
...
...
@@ -136,12 +124,12 @@ module Sys
when
:'ipv6-icmp'
,
:icmpv6
nftables_rule
<<
'icmpv6 type { echo-request, nd-router-solicit, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } '
when
:tcp
,
:udp
nftables_rule
<<
"
#{
rule_resource
.
protocol
}
sport
#{
port_to_s
(
rule_resource
.
sport
)
}
"
if
sport
(
rule_resource
)
nftables_rule
<<
"
#{
rule_resource
.
protocol
}
dport
#{
port_to_s
(
rule_resource
.
dport
)
}
"
if
dport
(
rule_resource
)
nftables_rule
<<
"
#{
rule_resource
.
protocol
}
sport
#{
port_to_s
(
rule_resource
.
sport
)
}
"
if
rule_resource
.
sport
nftables_rule
<<
"
#{
rule_resource
.
protocol
}
dport
#{
port_to_s
(
rule_resource
.
dport
)
}
"
if
rule_resource
.
dport
when
:esp
,
:ah
nftables_rule
<<
"
#{
ip_family
}
#{
ip_family
==
:ip6
?
'nexthdr'
:
'protocol'
}
#{
rule_resource
.
protocol
}
"
# nothing to do default :ipv6, :none
# nothing to do default :ipv6, :none
end
nftables_rule
<<
"ct state
#{
Array
(
rule_resource
.
stateful
).
join
(
','
).
downcase
}
"
if
rule_resource
.
stateful
...
...
@@ -152,39 +140,29 @@ module Sys
nftables_rule
end
def
log_nftables
shell_out!
(
'nft -n list ruleset'
)
rescue
Mixlib
::
ShellOut
::
ShellCommandFailed
Chef
::
Log
.
info
(
'log_nftables failed!'
)
rescue
Mixlib
::
ShellOut
::
CommandTimeout
Chef
::
Log
.
info
(
'log_nftables timed out!'
)
end
def
default_ruleset
(
new_resource
)
rules
=
{
'add table inet filter'
=>
1
,
"add chain inet filter
INPUT
{ type filter hook input priority 0 ; policy
#{
new_resource
.
input_policy
}
; }"
=>
2
,
"add chain inet filter
OUTPUT
{ type filter hook output priority 0 ; policy
#{
new_resource
.
output_policy
}
; }"
=>
2
,
"add chain inet filter
FOWARD
{ type filter hook forward priority 0 ; policy
#{
new_resource
.
forward_policy
}
; }"
=>
2
,
"add chain inet filter
input
{ type filter hook input priority 0 ; policy
#{
new_resource
.
input_policy
}
; }"
=>
2
,
"add chain inet filter
output
{ type filter hook output priority 0 ; policy
#{
new_resource
.
output_policy
}
; }"
=>
2
,
"add chain inet filter
forward
{ type filter hook forward priority 0 ; policy
#{
new_resource
.
forward_policy
}
; }"
=>
2
,
}
if
new_resource
.
table_ip_nat
rules
[
'add table ip nat'
]
=
1
rules
[
'add chain ip nat
POSTROUTING
{ type nat hook postrouting priority 100 ;}'
]
=
2
rules
[
'add chain ip nat
PREROUTING
{ type nat hook prerouting priority -100 ;}'
]
=
2
rules
[
'add chain ip nat
postrouting
{ type nat hook postrouting priority 100 ;}'
]
=
2
rules
[
'add chain ip nat
prerouting
{ type nat hook prerouting priority -100 ;}'
]
=
2
end
if
new_resource
.
table_ip6_nat
rules
[
'add table ip6 nat'
]
=
1
rules
[
'add chain ip6 nat
POSTROUTING
{ type nat hook postrouting priority 100 ;}'
]
=
2
rules
[
'add chain ip6 nat
PREROUTING
{ type nat hook prerouting priority -100 ;}'
]
=
2
rules
[
'add chain ip6 nat
postrouting
{ type nat hook postrouting priority 100 ;}'
]
=
2
rules
[
'add chain ip6 nat
prerouting
{ type nat hook prerouting priority -100 ;}'
]
=
2
end
rules
end
def
ensure_default_rules_exist
(
current_node
,
new_resource
)
def
ensure_default_rules_exist
(
new_resource
)
input
=
new_resource
.
rules
||
{}
input
.
merge!
(
default_ruleset
(
current_node
).
to_h
)
new_resource
.
rules
(
input
)
input
.
merge!
(
default_ruleset
(
new_resource
))
end
end
end
...
...
resources/nftables.rb
View file @
edb14d34
#
# Cookbook
Name
:: sys
# Cookbook:: sys
# Resource:: nftables
#
# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
# Copyright
::
2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# Authors:
# Matthias Pausch (m.pausch@gsi.de)
...
...
@@ -25,7 +25,6 @@
if
Gem
::
Requirement
.
new
(
'>= 12.15'
).
satisfied_by?
(
Gem
::
Version
.
new
(
Chef
::
VERSION
))
action_class
do
include
Sys
::
Helpers
::
Nftables
def
lookup_or_create_service
(
name
)
...
...
@@ -51,30 +50,29 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
end
end
#unified_mode true
provides
:nftables
,
os:
'linux'
,
platform:
%w(debian)
# unified_mode true
property
:rules
,
Hash
property
:input_policy
,
String
,
equal_to:
%w(drop accept)
,
default:
'accept'
String
,
equal_to:
%w(drop accept)
,
default:
'accept'
property
:output_policy
,
String
,
equal_to:
%w(drop accept)
,
default:
'accept'
String
,
equal_to:
%w(drop accept)
,
default:
'accept'
property
:forward_policy
,
String
,
equal_to:
%w(drop accept)
,
default:
'accept'
String
,
equal_to:
%w(drop accept)
,
default:
'accept'
property
:table_ip_nat
,
[
true
,
false
],
default:
false
[
true
,
false
],
default:
false
property
:table_ip6_nat
,
[
true
,
false
],
default:
false
[
true
,
false
],
default:
false
def
whyrun_supported?
false
...
...
@@ -91,14 +89,17 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
edit_resource
(
'sys_nftables'
,
new_resource
.
name
)
do
action
:nothing
delayed_action
:rebuild
forward_policy
new_resource
.
forward_policy
output_policy
new_resource
.
output_policy
input_policy
new_resource
.
input_policy
table_ip_nat
new_resource
.
table_ip_nat
table_ip6_nat
new_resource
.
table_ip6_nat
end
end
end
action
:rebuild
do
ensure_default_rules_exist
(
node
,
new_resource
)
# prints all the nftables rules
log_nftables
ensure_default_rules_exist
(
new_resource
)
# this takes the commands in each hash entry and builds a rule file
nftables_file
=
lookup_or_create_rulesfile
(
'/etc/nftables.conf'
)
...
...
resources/nftables_rule.rb
View file @
edb14d34
#
# Cookbook
Name
:: sys
# Cookbook:: sys
# Resource:: nftables_rule
#
# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
# Copyright
::
2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# Authors:
# Matthias Pausch (m.pausch@gsi.de)
...
...
@@ -35,6 +35,7 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
end
provides
:nftables_rule
# unified_mode true
default_action
:create
property
:nftables_name
,
...
...
@@ -43,15 +44,15 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
property
:command
,
Symbol
,
default: :allow
,
equal_to:
%i
[
equal_to:
%i
(
accept allow deny drop log masquerade redirect reject
]
)
property
:protocol
,
[
Integer
,
Symbol
],
default: :tcp
,
callbacks:
{
'must be valid IP protocol specification'
=>
lambda
(
p
)
do
%i
[
udp tcp icmp icmpv6 ipv6-icmp esp ah ipv6 none
]
.
include?
(
p
)
||
(
0
..
142
).
include?
(
p
)
lambda
do
|
p
|
%i
(
udp tcp icmp icmpv6 ipv6-icmp esp ah ipv6 none
)
.
include?
(
p
)
||
(
0
..
142
).
include?
(
p
)
end
}
property
:direction
,
Symbol
,
...
...
@@ -70,11 +71,11 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
property
:source
,
[
String
,
Array
],
callbacks:
{
'must be a valid ip address'
=>
lambda
(
ips
)
do
'must be a valid ip address'
=>
lambda
do
|
ips
|
Array
(
ips
).
inject
(
false
)
do
|
a
,
ip
|
a
||
!!
IPAddr
.
new
(
ip
)
end
end
end
,
}
property
:sport
,
[
Integer
,
String
,
Array
,
Range
]
...
...
@@ -85,11 +86,11 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
property
:destination
,
[
String
,
Array
],
callbacks:
{
'must be a valid ip address'
=>
lambda
(
ips
)
do
'must be a valid ip address'
=>
lambda
do
|
ips
|
Array
(
ips
).
inject
(
false
)
do
|
a
,
ip
|
a
||
!!
IPAddr
.
new
(
ip
)
end
end
end
,
}
property
:outerface
,
String
...
...
@@ -124,7 +125,7 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
edit_resource!
(
'sys_nftables'
,
new_resource
.
nftables_name
)
do
|
fw_rule
|
r
=
rules
.
dup
||
{}
r
.
merge!
({
fwr
=>
fw_rule
.
position
fwr
=>
fw_rule
.
position
,
})
rules
(
r
)
delayed_action
:rebuild
...
...
test/fixtures/cookbooks/nftables-test/recipes/default.rb
View file @
edb14d34
return
unless
Gem
::
Requirement
.
new
(
'>= 12.15'
).
satisfied_by?
(
Gem
::
Version
.
new
(
Chef
::
VERSION
))
firewall
'default'
do
nftables
'default'
do
table_ip_nat
true
table_ip6_nat
true
input_policy
'drop'
end
firewall
_rule
'allow loopback'
do
nftables
_rule
'allow loopback'
do
interface
'lo'
protocol
:none
command
:allow
only_if
{
node
[
'sys'
][
'firewall'
][
'allow_loopback'
]
}
end
firewall
_rule
'allow icmp'
do
nftables
_rule
'allow icmp'
do
protocol
:icmp
command
:allow
only_if
{
node
[
'sys'
][
'firewall'
][
'allow_icmp'
]
}
end
firewall_rule
'allow world to ssh'
do
port
22
only_if
{
node
[
'sys'
][
'firewall'
][
'allow_ssh'
]
}
end
# allow established connections
firewall
_rule
'established'
do
nftables
_rule
'established'
do
position
40
stateful
[
:related
,
:established
]
protocol
:none
# explicitly don't specify protocol
command
:allow
only_if
{
node
[
'sys'
][
'firewall'
][
'allow_established'
]
}
end
firewall_rule
'ssh22'
do
port
22
command
:allow
nftables_rule
'ssh22'
do
dport
22
end
firewall
_rule
'port array'
do
port
[
2222
,
2200
]
nftables
_rule
'port array'
do
d
port
[
2222
,
2200
]
command
:allow
end
firewall
_rule
'range'
do
port
1000
..
1100
nftables
_rule
'range'
do
d
port
1000
..
1100
command
:allow
end
firewall
_rule
'range-udp'
do
port
60000
..
61000
nftables
_rule
'range-udp'
do
d
port
60000
..
61000
protocol
:udp
end
firewall
_rule
'ping6'
do
nftables
_rule
'ping6'
do
protocol
:icmpv6
end
# other rules
firewall
_rule
'temp1'
do
port
1234
nftables
_rule
'temp1'
do
d
port
1234
command
:deny
end
firewall
_rule
'temp2'
do
port
1235
nftables
_rule
'temp2'
do
d
port
1235
command
:reject
end
firewall
_rule
'addremove'
do
port
1236
nftables
_rule
'addremove'
do
d
port
1236
command
:allow
end
firewall
_rule
'addremove2'
do
port
1236
nftables
_rule
'addremove2'
do
d
port
1236
command
:deny
end
firewall
_rule
'protocolnum'
do
nftables
_rule
'protocolnum'
do
protocol
112
command
:allow
end
firewall
_rule
'prepend'
do
port
7788
nftables
_rule
'prepend'
do
d
port
7788
position
5
end
firewall
_rule
"block single ip"
do
nftables
_rule
"block single ip"
do
source
'192.168.99.99'
position
49
command
:reject
end
firewall
_rule
'block ip-range'
do
nftables
_rule
'block ip-range'
do
source
[
'192.168.99.99'
,
'192.168.100.100'
]
command
:drop
end
firewall
_rule
"block single destination ip"
do
nftables
_rule
"block single destination ip"
do
destination
'192.168.99.99'
position
49
command
:reject
end
firewall
_rule
'block destination ip-range'
do
nftables
_rule
'block destination ip-range'
do
destination
[
'192.168.99.99'
,
'192.168.100.100'
]
command
:drop
end
firewall
_rule
'ipv6-source'
do
port
80
nftables
_rule
'ipv6-source'
do
d
port
80
family
:ip6
source
'2001:db8::ff00:42:8329'
command
:allow
end
firewall
_rule
'array'
do
port
[
1234
,
5000
..
5100
,
'5678'
]
nftables
_rule
'array'
do
d
port
[
1234
,
5000
..
5100
,
'5678'
]
command
:allow
end
firewall
_rule
'RPC Port Range In'
do
port
5000
..
5100
nftables
_rule
'RPC Port Range In'
do
d
port
5000
..
5100
protocol
:tcp
command
:allow
direction
:in
end
firewall
_rule
'HTTP HTTPS'
do
port
[
80
,
443
]
nftables
_rule
'HTTP HTTPS'
do
d
port
[
80
,
443
]
protocol
:tcp
direction
:out
command
:allow
end
firewall
_rule
'port2433'
do
nftables
_rule
'port2433'
do
description
'This should not be included'
include_comment
false
source
'127.0.0.0/8'
port
2433
d
port
2433
direction
:in
command
:allow
end
firewall
_rule
'esp'
do
nftables
_rule
'esp'
do
protocol
:esp
command
:allow
end
firewall
_rule
'ah'
do
nftables
_rule
'ah'
do
protocol
:ah
command
:allow
end
firewall
_rule
'esp-ipv6'
do
nftables
_rule
'esp-ipv6'
do
source
'::'
family
:ip6
protocol
:esp
command
:allow
end
firewall
_rule
'ah-ipv6'
do
nftables
_rule
'ah-ipv6'
do
source
'::'
family
:ip6
protocol
:ah
command
:allow
end
firewall
_rule
'redirect'
do
nftables
_rule
'redirect'
do
direction
:pre
port
5555
d
port
5555
redirect_port
6666
command
:redirect
end
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment