Skip to content

Commit 2bd43f6

Browse files
committed
First version of IPtables module
1 parent 619a101 commit 2bd43f6

File tree

6 files changed

+471
-0
lines changed

6 files changed

+471
-0
lines changed

modules/iptables/manifests/init.pp

+12
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,16 @@
7373
provider => 'ip6tables';
7474
}
7575
}
76+
77+
# Testing new iptables module
78+
class { 'iptables::ng':
79+
chains => {
80+
'INPUT' => 'DROP',
81+
'FORWARD' => upcase($forward_policy),
82+
'OUTPUT' => 'ACCEPT',
83+
},
84+
rules => $rules,
85+
log_fallthrough => str2bool($log_fallthrough),
86+
}
87+
7688
}

modules/iptables/manifests/ng.pp

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Copyright 2018 dhtech
2+
#
3+
# Use of this source code is governed by a BSD-style
4+
# license that can be found in the LICENSE file
5+
#
6+
# == Class: iptables
7+
#
8+
# Firewall hooks for the firewall lib.
9+
#
10+
# === Parameters
11+
#
12+
# [*rules*]
13+
# The host specific rules for this machine as calculated from ipplan.
14+
#
15+
# [*log_fallthrough*]
16+
# Log the packets that will be policy dropped in the INPUT chain.
17+
#
18+
# [*chains*]
19+
# A hash containing chains with their default policy. Defaults to
20+
# ```
21+
# {
22+
# 'INPUT' => 'DROP',
23+
# 'FORWARD' => 'DROP',
24+
# 'OUTPUT' => 'ACCEPT',
25+
# }
26+
# ```
27+
# [*ipv4file*]
28+
# The file to store the IPv4 rules in. Defaults to
29+
# `/etc/iptables/rules.v4.puppet`
30+
#
31+
# [*ipv6file*]
32+
# The file to store the IPv6 rules in. Defaults to
33+
# `/etc/iptables/rules.v6.puppet`
34+
35+
class iptables::ng (
36+
37+
Hash $rules,
38+
Boolean $log_fallthrough,
39+
Hash[String, Enum['ACCEPT', 'DROP', 'REJECT'], 1] $chains = {
40+
'INPUT' => 'DROP',
41+
'FORWARD' => 'DROP',
42+
'OUTPUT' => 'ACCEPT',
43+
},
44+
String $ipv4file = '/etc/iptables/rules.v4.puppet',
45+
String $ipv6file = '/etc/iptables/rules.v6.puppet',
46+
47+
) {
48+
49+
$chains_header = $chains.map |$chain,$policy| { sprintf(':%s %s [0:0]', $chain, $policy) }
50+
51+
$enforce_command = '/usr/local/sbin/enforce-iptables'
52+
file { 'enforce-command':
53+
path => $enforce_command,
54+
source => 'puppet:///scripts/iptables/enforce-iptables.sh',
55+
owner => 'root',
56+
group => 'root',
57+
mode => '0750',
58+
}
59+
60+
61+
# Header and trailer rules
62+
class { 'iptables::ng::header': }
63+
class { 'iptables::ng::trailer':
64+
log_input => $log_fallthrough,
65+
}
66+
67+
68+
# IPv4
69+
concat { $ipv4file:
70+
ensure => present,
71+
backup => true,
72+
warn => '# This file is managed by Puppet. Do not edit.',
73+
order => 'numeric',
74+
validate_cmd => '/usr/sbin/iptables-restore -t < %',
75+
ensure_newline => true,
76+
notify => Exec['enforce-puppet-iptables'],
77+
}
78+
79+
concat::fragment { '00-ipv4-header':
80+
target => $ipv4file,
81+
order => 0,
82+
content => ([
83+
'*filter'
84+
] + $chains_header).join("\n"),
85+
}
86+
87+
concat::fragment { '99-ipv4-trailer':
88+
target => $ipv4file,
89+
order => 9999,
90+
content => [
91+
'COMMIT'
92+
].join("\n"),
93+
}
94+
95+
exec { 'enforce-puppet-iptables':
96+
command => "/usr/bin/echo ${enforce_command} ipv4 '${ipv4file}'",
97+
refreshonly => true,
98+
require => File['enforce-command'],
99+
}
100+
101+
each($rules['v4']) |$rule| {
102+
$name = $rule['name']
103+
$proto = $rule['proto']
104+
105+
iptables::ng::rule { "v4 ${name} ${proto}":
106+
type => 'ipv4',
107+
chain => 'INPUT',
108+
action => 'ACCEPT',
109+
order => 500,
110+
source => $rule['src'],
111+
proto => $rule['proto'],
112+
dport => $rule['dports'],
113+
sport => $rule['sports'],
114+
}
115+
}
116+
117+
118+
# IPv6
119+
concat { $ipv6file:
120+
ensure => present,
121+
backup => true,
122+
warn => '# This file is managed by Puppet. Do not edit.',
123+
order => numeric,
124+
validate_cmd => '/usr/sbin/ip6tables-restore -t < %',
125+
ensure_newline => true,
126+
notify => Exec['enforce-puppet-ip6tables'],
127+
}
128+
129+
concat::fragment { '00-ipv6-header':
130+
target => $ipv6file,
131+
order => 0,
132+
content => ([
133+
'*filter'
134+
] + $chains_header).join("\n"),
135+
}
136+
137+
concat::fragment { '99-ipv6-trailer':
138+
target => $ipv6file,
139+
order => 9999,
140+
content => [
141+
'COMMIT',
142+
].join("\n"),
143+
}
144+
145+
exec { 'enforce-puppet-ip6tables':
146+
command => "/usr/bin/echo ${enforce_command} ipv6 '${ipv6file}'",
147+
refreshonly => true,
148+
require => File['enforce-command'],
149+
}
150+
151+
each($rules['v6']) |$rule| {
152+
$name = $rule['name']
153+
$proto = $rule['proto']
154+
155+
iptables::ng::rule { "v6 ${name} ${proto}":
156+
type => 'ipv6',
157+
chain => 'INPUT',
158+
action => 'ACCEPT',
159+
order => 500,
160+
source => $rule['src'],
161+
proto => $rule['proto'],
162+
dport => $rule['dports'],
163+
sport => $rule['sports'],
164+
}
165+
}
166+
167+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Copyright 2018 dhtech
2+
#
3+
# Use of this source code is governed by a BSD-style
4+
# license that can be found in the LICENSE file
5+
#
6+
# == Class: iptables::ng::rule
7+
#
8+
# Firewall rules for the firewall lib.
9+
#
10+
# === Parameters
11+
#
12+
# [*type*]
13+
# Version of the IP protocol for this rule. Must be `4` or `6`.
14+
#
15+
# [*rule*]
16+
# The rule that should be used. In a format that can be understood
17+
# by `iptables-restore` it will have `-A ${chain} ` prepended
18+
#
19+
# [*order*]
20+
# Allows you to change the order in which the rules are placed. Header rules
21+
# should have `order < 200`, trailer rules `order >= 800`. Defaults to `500`
22+
23+
define iptables::ng::advanced_rule (
24+
25+
Enum['ipv4', 'ipv6', 'both'] $type,
26+
String $rule,
27+
Integer $order = 500,
28+
29+
) {
30+
31+
include iptables::ng
32+
33+
34+
if $type in ['ipv4', 'both'] {
35+
36+
concat::fragment { "v4 ${name}":
37+
target => $::iptables::ng::ipv4file,
38+
order => $order,
39+
content => $rule,
40+
}
41+
42+
}
43+
44+
if $type in ['ipv6', 'both'] {
45+
46+
concat::fragment { "v6 ${name}":
47+
target => $::iptables::ng::ipv6file,
48+
order => $order,
49+
content => $rule,
50+
}
51+
52+
}
53+
54+
}
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copyright 2018 dhtech
2+
#
3+
# Use of this source code is governed by a BSD-style
4+
# license that can be found in the LICENSE file
5+
#
6+
# Initial iptables rules that always applies
7+
8+
class iptables::ng::header {
9+
10+
iptables::ng::advanced_rule { 'accept related established rules':
11+
type => 'both',
12+
order => 1,
13+
rule => [
14+
'-A INPUT -m state --state RELATED,ESTABLISHED',
15+
'-m comment --comment "accept related established rules"',
16+
'-j ACCEPT',
17+
].join(' '),
18+
}
19+
20+
iptables::ng::advanced_rule { 'accept all to lo interface':
21+
type => 'both',
22+
order => 10,
23+
rule => [
24+
'-A INPUT -i lo',
25+
'-m comment --comment "accept all to lo interface"',
26+
'-j ACCEPT',
27+
].join(' '),
28+
}
29+
30+
31+
# IPv4 ICMP
32+
iptables::ng::advanced_rule { 'v4 accept icmp, heavy rate limited':
33+
type => 'ipv4',
34+
order => 20,
35+
rule => [
36+
'-A INPUT -p icmp',
37+
'-m limit --limit 5/sec --limit-burst 20',
38+
'-m comment --comment "accept icmp, heavy rate limited"',
39+
'-j ACCEPT',
40+
].join(' '),
41+
}
42+
43+
iptables::ng::advanced_rule { 'v4 reject with icmp udp echo, heavy rate limited':
44+
type => 'ipv4',
45+
order => 21,
46+
rule => [
47+
'-A INPUT -p udp',
48+
'-m multiport --dports 33434:33523',
49+
'-m limit --limit 5/sec --limit-burst 20',
50+
'-m comment --comment "reject with icmp udp echo, heavy rate limited"',
51+
'-j REJECT --reject-with icmp-port-unreachable',
52+
].join(' '),
53+
}
54+
55+
iptables::ng::advanced_rule { 'v4 drop remaining icmp':
56+
type => 'ipv4',
57+
order => 29,
58+
rule => [
59+
'-A INPUT -p icmp',
60+
'-m comment --comment "drop remaining icmp"',
61+
'-j DROP',
62+
].join(' '),
63+
}
64+
65+
66+
# IPv6 ICMP
67+
iptables::ng::advanced_rule { 'v6 accept icmp, heavy rate limited':
68+
type => 'ipv6',
69+
order => 20,
70+
rule => [
71+
'-A INPUT -p ipv6-icmp',
72+
'-m limit --limit 5/sec --limit-burst 20',
73+
'-m comment --comment "accept icmp, heavy rate limited"',
74+
'-j ACCEPT',
75+
].join(' '),
76+
}
77+
78+
iptables::ng::advanced_rule { 'v6 reject with icmp udp echo, heavy rate limited':
79+
type => 'ipv6',
80+
order => 21,
81+
rule => [
82+
'-A INPUT -p udp',
83+
'-m multiport --dports 33434:33523',
84+
'-m limit --limit 5/sec --limit-burst 20',
85+
'-m comment --comment "reject with icmp udp echo, heavy rate limited"',
86+
'-j REJECT --reject-with icmp6-port-unreachable',
87+
].join(' '),
88+
}
89+
90+
iptables::ng::advanced_rule { 'v6 drop remaining icmp':
91+
type => 'ipv6',
92+
order => 29,
93+
rule => [
94+
'-A INPUT -p ipv6-icmp',
95+
'-m comment --comment "drop remaining icmp"',
96+
'-j DROP',
97+
].join(' '),
98+
}
99+
100+
}

0 commit comments

Comments
 (0)