Révision fcb79d73
support a different table name for 'nat'
- Some applications (such as libvirt) still use iptables to inject firewall
rules
- iptables will refuse to update tables that were initially created with nft
- This commit allows defining the name of the 'nat' table in order to avoid
namespace conflicts
manifests/init.pp | ||
---|---|---|
43 | 43 |
# @param nat |
44 | 44 |
# Add default tables and chains to process NAT traffic. |
45 | 45 |
# |
46 |
# @param nat_table_name |
|
47 |
# The name of the 'nat' table. |
|
48 |
# |
|
46 | 49 |
# @param sets |
47 | 50 |
# Allows sourcing set definitions directly from Hiera. |
48 | 51 |
# |
... | ... | |
99 | 102 |
Hash $rules = {}, |
100 | 103 |
Hash $sets = {}, |
101 | 104 |
String $log_prefix = '[nftables] %<chain>s %<comment>s', |
105 |
String[1] $nat_table_name = 'nat', |
|
102 | 106 |
Variant[Boolean[false], String] $log_limit = '3/minute burst 5 packets', |
103 | 107 |
Variant[Boolean[false], Pattern[/icmp(v6|x)? type .+|tcp reset/]] $reject_with = 'icmpx type port-unreachable', |
104 | 108 |
Variant[Boolean[false], Enum['mask']] $firewalld_enable = 'mask', |
manifests/ip_nat.pp | ||
---|---|---|
1 | 1 |
# manage basic chains in table ip nat |
2 | 2 |
class nftables::ip_nat inherits nftables { |
3 | 3 |
nftables::config { |
4 |
'ip-nat':
|
|
4 |
"ip-${nftables::nat_table_name}":
|
|
5 | 5 |
prefix => ''; |
6 |
'ip6-nat':
|
|
6 |
"ip6-${nftables::nat_table_name}":
|
|
7 | 7 |
prefix => ''; |
8 | 8 |
} |
9 | 9 |
|
... | ... | |
12 | 12 |
'PREROUTING', |
13 | 13 |
'POSTROUTING', |
14 | 14 |
]: |
15 |
table => 'ip-nat';
|
|
15 |
table => "ip-${nftables::nat_table_name}";
|
|
16 | 16 |
} |
17 | 17 |
|
18 | 18 |
nftables::chain { |
... | ... | |
20 | 20 |
'PREROUTING6', |
21 | 21 |
'POSTROUTING6', |
22 | 22 |
]: |
23 |
table => 'ip6-nat';
|
|
23 |
table => "ip6-${nftables::nat_table_name}";
|
|
24 | 24 |
} |
25 | 25 |
|
26 | 26 |
# ip-nat-chain-PREROUTING |
27 | 27 |
nftables::rule { |
28 | 28 |
'PREROUTING-type': |
29 |
table => 'ip-nat',
|
|
29 |
table => "ip-${nftables::nat_table_name}",
|
|
30 | 30 |
order => '01', |
31 | 31 |
content => 'type nat hook prerouting priority -100'; |
32 | 32 |
'PREROUTING-policy': |
33 |
table => 'ip-nat',
|
|
33 |
table => "ip-${nftables::nat_table_name}",
|
|
34 | 34 |
order => '02', |
35 | 35 |
content => 'policy accept'; |
36 | 36 |
'PREROUTING6-type': |
37 |
table => 'ip6-nat',
|
|
37 |
table => "ip6-${nftables::nat_table_name}",
|
|
38 | 38 |
order => '01', |
39 | 39 |
content => 'type nat hook prerouting priority -100'; |
40 | 40 |
'PREROUTING6-policy': |
41 |
table => 'ip6-nat',
|
|
41 |
table => "ip6-${nftables::nat_table_name}",
|
|
42 | 42 |
order => '02', |
43 | 43 |
content => 'policy accept'; |
44 | 44 |
} |
... | ... | |
46 | 46 |
# ip-nat-chain-POSTROUTING |
47 | 47 |
nftables::rule { |
48 | 48 |
'POSTROUTING-type': |
49 |
table => 'ip-nat',
|
|
49 |
table => "ip-${nftables::nat_table_name}",
|
|
50 | 50 |
order => '01', |
51 | 51 |
content => 'type nat hook postrouting priority 100'; |
52 | 52 |
'POSTROUTING-policy': |
53 |
table => 'ip-nat',
|
|
53 |
table => "ip-${nftables::nat_table_name}",
|
|
54 | 54 |
order => '02', |
55 | 55 |
content => 'policy accept'; |
56 | 56 |
'POSTROUTING6-type': |
57 |
table => 'ip6-nat',
|
|
57 |
table => "ip6-${nftables::nat_table_name}",
|
|
58 | 58 |
order => '01', |
59 | 59 |
content => 'type nat hook postrouting priority 100'; |
60 | 60 |
'POSTROUTING6-policy': |
61 |
table => 'ip6-nat',
|
|
61 |
table => "ip6-${nftables::nat_table_name}",
|
|
62 | 62 |
order => '02', |
63 | 63 |
content => 'policy accept'; |
64 | 64 |
} |
manifests/rules/dnat4.pp | ||
---|---|---|
32 | 32 |
"${chain}-${rulename}": |
33 | 33 |
content => "${iifname}ip daddr ${daddr} ${proto} dport ${filter_port} accept"; |
34 | 34 |
"PREROUTING-${rulename}": |
35 |
table => 'ip-nat',
|
|
35 |
table => "ip-${nftables::nat_table_name}",
|
|
36 | 36 |
content => "${iifname}${proto} dport ${port} dnat to ${daddr}${nat_port}"; |
37 | 37 |
} |
38 | 38 |
} |
manifests/rules/docker_ce.pp | ||
---|---|---|
79 | 79 |
|
80 | 80 |
if $manage_docker_chains { |
81 | 81 |
nftables::chain { |
82 |
'DOCKER-nat':
|
|
83 |
table => 'ip-nat',
|
|
82 |
"DOCKER-${nftables::nat_table_name}":
|
|
83 |
table => "ip-${nftables::nat_table_name}",
|
|
84 | 84 |
chain => 'DOCKER'; |
85 | 85 |
} |
86 | 86 |
} |
87 | 87 |
|
88 | 88 |
if $manage_base_chains { |
89 | 89 |
nftables::chain { |
90 |
'OUTPUT-nat':
|
|
91 |
table => 'ip-nat',
|
|
90 |
"OUTPUT-${nftables::nat_table_name}":
|
|
91 |
table => "ip-${nftables::nat_table_name}",
|
|
92 | 92 |
chain => 'OUTPUT'; |
93 |
'INPUT-nat':
|
|
94 |
table => 'ip-nat',
|
|
93 |
"INPUT-${nftables::nat_table_name}":
|
|
94 |
table => "ip-${nftables::nat_table_name}",
|
|
95 | 95 |
chain => 'INPUT'; |
96 | 96 |
} |
97 | 97 |
} |
98 | 98 |
|
99 | 99 |
nftables::rule { |
100 | 100 |
'POSTROUTING-docker': |
101 |
table => 'ip-nat',
|
|
101 |
table => "ip-${nftables::nat_table_name}",
|
|
102 | 102 |
content => "oifname != \"${docker_interface}\" ip saddr ${docker_prefix} counter masquerade"; |
103 | 103 |
'PREROUTING-docker': |
104 |
table => 'ip-nat',
|
|
104 |
table => "ip-${nftables::nat_table_name}",
|
|
105 | 105 |
content => 'fib daddr type local counter jump DOCKER'; |
106 |
'OUTPUT-jump_docker@ip-nat':
|
|
106 |
"OUTPUT-jump_docker@ip-${nftables::nat_table_name}":
|
|
107 | 107 |
rulename => 'OUTPUT-jump_docker', |
108 |
table => 'ip-nat',
|
|
108 |
table => "ip-${nftables::nat_table_name}",
|
|
109 | 109 |
content => 'ip daddr != 127.0.0.0/8 fib daddr type local counter jump DOCKER'; |
110 | 110 |
'DOCKER-counter': |
111 |
table => 'ip-nat',
|
|
111 |
table => "ip-${nftables::nat_table_name}",
|
|
112 | 112 |
content => "iifname \"${docker_interface}\" counter return"; |
113 |
'INPUT-type@ip-nat':
|
|
113 |
"INPUT-type@ip-${nftables::nat_table_name}":
|
|
114 | 114 |
rulename => 'INPUT-type', |
115 |
table => 'ip-nat',
|
|
115 |
table => "ip-${nftables::nat_table_name}",
|
|
116 | 116 |
order => '01', |
117 | 117 |
content => 'type nat hook input priority 100'; |
118 |
'INPUT-policy@ip-nat':
|
|
118 |
"INPUT-policy@ip-${nftables::nat_table_name}":
|
|
119 | 119 |
rulename => 'INPUT-policy', |
120 |
table => 'ip-nat',
|
|
120 |
table => "ip-${nftables::nat_table_name}",
|
|
121 | 121 |
order => '02', |
122 | 122 |
content => 'policy accept'; |
123 | 123 |
} |
manifests/rules/masquerade.pp | ||
---|---|---|
42 | 42 |
nftables::rule { |
43 | 43 |
"${chain}-${rulename}": |
44 | 44 |
ensure => $ensure, |
45 |
table => 'ip-nat',
|
|
45 |
table => "ip-${nftables::nat_table_name}",
|
|
46 | 46 |
order => $order, |
47 | 47 |
content => "${oifname}${src}${dst}${protocol}${port}masquerade"; |
48 | 48 |
} |
manifests/rules/qemu.pp | ||
---|---|---|
93 | 93 |
if $masquerade { |
94 | 94 |
nftables::rule { |
95 | 95 |
'POSTROUTING-qemu_ignore_multicast': |
96 |
table => 'ip-nat',
|
|
96 |
table => "ip-${nftables::nat_table_name}",
|
|
97 | 97 |
content => "ip saddr ${network_v4} ip daddr 224.0.0.0/24 return"; |
98 | 98 |
'POSTROUTING-qemu_ignore_broadcast': |
99 |
table => 'ip-nat',
|
|
99 |
table => "ip-${nftables::nat_table_name}",
|
|
100 | 100 |
content => "ip saddr ${network_v4} ip daddr 255.255.255.255 return"; |
101 | 101 |
'POSTROUTING-qemu_masq_tcp': |
102 |
table => 'ip-nat',
|
|
102 |
table => "ip-${nftables::nat_table_name}",
|
|
103 | 103 |
content => "meta l4proto tcp ip saddr ${network_v4} ip daddr != ${network_v4} masquerade to :1024-65535"; |
104 | 104 |
'POSTROUTING-qemu_masq_udp': |
105 |
table => 'ip-nat',
|
|
105 |
table => "ip-${nftables::nat_table_name}",
|
|
106 | 106 |
content => "meta l4proto udp ip saddr ${network_v4} ip daddr != ${network_v4} masquerade to :1024-65535"; |
107 | 107 |
'POSTROUTING-qemu_masq_ip': |
108 |
table => 'ip-nat',
|
|
108 |
table => "ip-${nftables::nat_table_name}",
|
|
109 | 109 |
content => "ip saddr ${network_v4} ip daddr != ${network_v4} masquerade"; |
110 | 110 |
} |
111 | 111 |
} |
manifests/rules/snat4.pp | ||
---|---|---|
38 | 38 |
nftables::rule { |
39 | 39 |
"${chain}-${rulename}": |
40 | 40 |
ensure => $ensure, |
41 |
table => 'ip-nat',
|
|
41 |
table => "ip-${nftables::nat_table_name}",
|
|
42 | 42 |
order => $order, |
43 | 43 |
content => "${oifname}${src}${protocol}${port}snat ${snat}"; |
44 | 44 |
} |
spec/acceptance/default_spec.rb | ||
---|---|---|
111 | 111 |
it { is_expected.to be_enabled } |
112 | 112 |
end |
113 | 113 |
end |
114 |
context 'with custom nat_table_name' do |
|
115 |
it 'no rules validate okay' do |
|
116 |
pp = <<-EOS |
|
117 |
class{'nftables': |
|
118 |
firewalld_enable => false, |
|
119 |
nat => true, |
|
120 |
nat_table_name => 'mycustomtablename', |
|
121 |
} |
|
122 |
# nftables cannot be started in docker so replace service with a validation only. |
|
123 |
systemd::dropin_file{"zzz_docker_nft.conf": |
|
124 |
ensure => present, |
|
125 |
unit => "nftables.service", |
|
126 |
content => [ |
|
127 |
"[Service]", |
|
128 |
"ExecStart=", |
|
129 |
"ExecStart=/sbin/nft -c -I /etc/nftables/puppet -f /etc/sysconfig/nftables.conf", |
|
130 |
"ExecReload=", |
|
131 |
"ExecReload=/sbin/nft -c -I /etc/nftables/puppet -f /etc/sysconfig/nftables.conf", |
|
132 |
"", |
|
133 |
].join("\n"), |
|
134 |
notify => Service["nftables"], |
|
135 |
} |
|
136 |
EOS |
|
137 |
apply_manifest(pp, catch_failures: true) |
|
138 |
end |
|
139 |
describe service('nftables') do |
|
140 |
it { is_expected.to be_running } |
|
141 |
it { is_expected.to be_enabled } |
|
142 |
end |
|
143 |
end |
|
114 | 144 |
end |
spec/classes/ip_nat_spec.rb | ||
---|---|---|
237 | 237 |
} |
238 | 238 |
end |
239 | 239 |
|
240 |
context 'custom ip nat table name' do |
|
241 |
let(:params) do |
|
242 |
{ |
|
243 |
'nat_table_name' => 'mycustomtablename', |
|
244 |
} |
|
245 |
end |
|
246 |
|
|
247 |
it { is_expected.to compile } |
|
248 |
it { |
|
249 |
is_expected.to contain_concat('nftables-ip-mycustomtablename').with( |
|
250 |
path: '/etc/nftables/puppet-preflight/ip-mycustomtablename.nft', |
|
251 |
ensure: 'present', |
|
252 |
owner: 'root', |
|
253 |
group: 'root', |
|
254 |
mode: '0640', |
|
255 |
) |
|
256 |
} |
|
257 |
end |
|
258 |
|
|
240 | 259 |
context 'all nat tables disabled' do |
241 | 260 |
let(:params) do |
242 | 261 |
{ |
spec/classes/rules/docker_ce_spec.rb | ||
---|---|---|
6 | 6 |
on_supported_os.each do |os, os_facts| |
7 | 7 |
context "on #{os}" do |
8 | 8 |
let(:facts) { os_facts } |
9 |
let(:pre_condition) { 'include nftables' } |
|
9 | 10 |
|
10 | 11 |
context 'default options' do |
11 | 12 |
it { is_expected.to compile } |
spec/classes/rules/qemu_spec.rb | ||
---|---|---|
4 | 4 |
on_supported_os.each do |os, os_facts| |
5 | 5 |
context "on #{os}" do |
6 | 6 |
let(:facts) { os_facts } |
7 |
let(:pre_condition) { 'include nftables' } |
|
7 | 8 |
|
8 | 9 |
context 'default options' do |
9 | 10 |
it { is_expected.to compile } |
... | ... | |
77 | 78 |
end |
78 | 79 |
|
79 | 80 |
it { is_expected.to compile } |
80 |
it { is_expected.to have_resource_count(0) } |
|
81 |
it { is_expected.not_to contain_nftables__rule('default_in-qemu_udp_dns') } |
|
82 |
it { is_expected.not_to contain_nftables__rule('default_in-qemu_tcp_dns') } |
|
83 |
it { is_expected.not_to contain_nftables__rule('default_in-qemu_dhcpv4') } |
|
84 |
it { is_expected.not_to contain_nftables__rule('default_fwd-qemu_oip_v4') } |
|
85 |
it { is_expected.not_to contain_nftables__rule('default_fwd-qemu_iip_v4') } |
|
86 |
it { is_expected.not_to contain_nftables__rule('default_fwd-qemu_io_internal') } |
|
87 |
it { is_expected.not_to contain_nftables__rule('POSTROUTING-qemu_ignore_multicast') } |
|
88 |
it { is_expected.not_to contain_nftables__rule('POSTROUTING-qemu_ignore_broadcast') } |
|
89 |
it { is_expected.not_to contain_nftables__rule('POSTROUTING-qemu_masq_tcp') } |
|
90 |
it { is_expected.not_to contain_nftables__rule('POSTROUTING-qemu_masq_udp') } |
|
91 |
it { is_expected.not_to contain_nftables__rule('POSTROUTING-qemu_masq_ip') } |
|
81 | 92 |
end |
82 | 93 |
|
83 | 94 |
context 'ipv6 prefix' do |
spec/defines/rules/dnat4_spec.rb | ||
---|---|---|
2 | 2 |
|
3 | 3 |
describe 'nftables::rules::dnat4' do |
4 | 4 |
let(:title) { 'foobar' } |
5 |
let(:pre_condition) { 'include nftables' } |
|
5 | 6 |
|
6 | 7 |
on_supported_os.each do |os, facts| |
7 | 8 |
context "on #{os}" do |
spec/defines/rules/masquerade_spec.rb | ||
---|---|---|
2 | 2 |
|
3 | 3 |
describe 'nftables::rules::masquerade' do |
4 | 4 |
let(:title) { 'foobar' } |
5 |
let(:pre_condition) { 'include nftables' } |
|
5 | 6 |
|
6 | 7 |
on_supported_os.each do |os, facts| |
7 | 8 |
context "on #{os}" do |
spec/defines/rules/snat4_spec.rb | ||
---|---|---|
2 | 2 |
|
3 | 3 |
describe 'nftables::rules::snat4' do |
4 | 4 |
let(:title) { 'foobar' } |
5 |
let(:pre_condition) { 'include nftables' } |
|
5 | 6 |
|
6 | 7 |
on_supported_os.each do |os, facts| |
7 | 8 |
context "on #{os}" do |
templates/config/puppet.nft.epp | ||
---|---|---|
26 | 26 |
include "inet-filter.nft" |
27 | 27 |
<% } -%> |
28 | 28 |
<% if $nat { -%> |
29 |
include "ip-nat.nft"
|
|
30 |
include "ip6-nat.nft"
|
|
29 |
include "ip-<%= $nftables::nat_table_name %>.nft"
|
|
30 |
include "ip6-<%= $nftables::nat_table_name %>.nft"
|
|
31 | 31 |
<% } -%> |
Formats disponibles : Unified diff