Skip to content

Commit 24c3e19

Browse files
author
Enver Cicak
committed
IPv6 support
1 parent a415ca5 commit 24c3e19

File tree

3 files changed

+143
-51
lines changed

3 files changed

+143
-51
lines changed

README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ extend:
114114
Using iptables.nat
115115
==================
116116

117-
You can use nat for interface.
117+
You can use nat for interface. This is supported for IPv4 alone. IPv6 deployments should not use NAT.
118118

119119
```yaml
120120
#Support nat
@@ -126,3 +126,30 @@ You can use nat for interface.
126126
'192.168.18.0/24':
127127
- 10.20.0.2
128128
```
129+
130+
IPv6 Support
131+
============
132+
133+
This formula supports IPv6 as long as it is activated with the option:
134+
135+
```
136+
firewall:
137+
ipv6: True
138+
```
139+
140+
Services and whitelists are supported under the sections `services_ipv6` and `whitelist_ipv6`, as below:
141+
142+
```
143+
services_ipv6:
144+
ssh:
145+
block_nomatch: False
146+
ips_allow:
147+
- 2a02:2028:773:d01:10a5:f34f:e7ff:f55b/64
148+
- 2a02:2028:773:d01:1814:28ef:e91b:70b8/64
149+
whitelist_ipv6:
150+
networks:
151+
ips_allow:
152+
- 2a02:2028:773:d01:1814:28ef:e91b:70b8/64
153+
```
154+
155+
These sections are only processed if the ipv6 support is activated.

iptables/init.sls

Lines changed: 89 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,16 @@
55
{% from "iptables/map.jinja" import firewall with context %}
66
{% set install = firewall.install %}
77
{% set strict_mode = firewall.strict %}
8+
{% set ipv6 = firewall.get('ipv6', False) %}
89
{% set global_block_nomatch = firewall.block_nomatch %}
910
{% set packages = firewall.pkgs %}
11+
{% set ipv4 = 'IPv4' %}
12+
{% set ipv6 = 'IPv6' %}
13+
{% set protocols = [ipv4] %}
14+
{% if ipv6 %}
15+
{% do protocols.append(ipv6) %}
16+
{% endif %}
17+
{% set sufixes = {ipv4: '', ipv6: '_ipv6'} %}
1018
1119
{%- if firewall.enabled %}
1220
{%- if install %}
@@ -22,51 +30,65 @@
2230
{%- if strict_mode %}
2331
# If the firewall is set to strict mode, we'll need to allow some
2432
# that always need access to anything
25-
iptables_allow_localhost:
33+
{%- for protocol in protocols %}
34+
iptables_allow_localhost{{sufixes[protocol]}}:
2635
iptables.append:
2736
- table: filter
2837
- chain: INPUT
2938
- jump: ACCEPT
39+
{%- if protocol == ipv4 %}
3040
- source: 127.0.0.1
41+
{%- else %}
42+
- source: ::1
43+
- family: ipv6
44+
{%- endif %}
3145
- save: True
3246
3347
# Allow related/established sessions
34-
iptables_allow_established:
48+
iptables_allow_established{{sufixes[protocol]}}:
3549
iptables.append:
3650
- table: filter
3751
- chain: INPUT
3852
- jump: ACCEPT
3953
- match: conntrack
4054
- ctstate: 'RELATED,ESTABLISHED'
55+
{%- if protocol == ipv6 %}
56+
- family: ipv6
57+
{%- endif %}
4158
- save: True
4259
4360
# Set the policy to deny everything unless defined
44-
enable_reject_policy:
61+
enable_reject_policy{{sufixes[protocol]}}:
4562
iptables.set_policy:
4663
- table: filter
4764
- chain: INPUT
4865
- policy: DROP
66+
{%- if protocol == ipv6 %}
67+
- family: ipv6
68+
{%- endif %}
4969
- require:
50-
- iptables: iptables_allow_localhost
51-
- iptables: iptables_allow_established
70+
- iptables: iptables_allow_localhost{{sufixes[protocol]}}
71+
- iptables: iptables_allow_established{{sufixes[protocol]}}
72+
{%- endfor %}
5273
{%- endif %}
5374
5475
# Generate ipsets for all services that we have information about
55-
{%- for service_name, service_details in firewall.get('services', {}).items() %}
56-
{% set block_nomatch = service_details.get('block_nomatch', False) %}
57-
{% set interfaces = service_details.get('interfaces','') %}
58-
{% set protos = service_details.get('protos',['tcp']) %}
59-
{% if service_details.get('comment', False) %}
60-
{% set comment = '- comment: ' + service_details.get('comment') %}
61-
{% else %}
62-
{% set comment = '' %}
63-
{% endif %}
76+
{%- for protocol in protocols %}
77+
{%- for service_name, service_details in firewall.get('services' + sufixes[protocol], {}).items() %}
78+
{% set block_nomatch = service_details.get('block_nomatch', False) %}
79+
{% set interfaces = service_details.get('interfaces','') %}
80+
{% set protos = service_details.get('protos',['tcp']) %}
81+
{% if service_details.get('comment', False) %}
82+
{% set comment = '- comment: ' + service_details.get('comment') %}
83+
{% else %}
84+
{% set comment = '' %}
85+
{% endif %}
6486
65-
# Allow rules for ips/subnets
66-
{%- for ip in service_details.get('ips_allow', ['0.0.0.0/0']) %}
67-
{%- if interfaces == '' %}
68-
{%- for proto in protos %}
69-
iptables_{{service_name}}_allow_{{ip}}_{{proto}}:
87+
# Allow rules for ips/subnets
88+
{%- for ip in service_details.get('ips_allow', ['0.0.0.0/0']) %}
89+
{%- if interfaces == '' %}
90+
{%- for proto in protos %}
91+
iptables_{{service_name}}_allow_{{ip}}_{{proto}}{{sufixes[protocol]}}:
7092
iptables.insert:
7193
- position: 1
7294
- table: filter
@@ -75,13 +97,16 @@
7597
- source: {{ ip }}
7698
- dport: {{ service_name }}
7799
- proto: {{ proto }}
100+
{%- if protocol == ipv6 %}
101+
- family: ipv6
102+
{%- endif %}
78103
- save: True
79104
{{ comment }}
80-
{%- endfor %}
81-
{%- else %}
82-
{%- for interface in interfaces %}
83-
{%- for proto in protos %}
84-
iptables_{{service_name}}_allow_{{ip}}_{{proto}}_{{interface}}:
105+
{%- endfor %}
106+
{%- else %}
107+
{%- for interface in interfaces %}
108+
{%- for proto in protos %}
109+
iptables_{{service_name}}_allow_{{ip}}_{{proto}}_{{interface}}{{sufixes[protocol]}}:
85110
iptables.insert:
86111
- position: 1
87112
- table: filter
@@ -91,32 +116,38 @@
91116
- source: {{ ip }}
92117
- dport: {{ service_name }}
93118
- proto: {{ proto }}
119+
{%- if protocol == ipv6 %}
120+
- family: ipv6
121+
{%- endif %}
94122
- save: True
95123
{{ comment }}
124+
{%- endfor %}
96125
{%- endfor %}
97-
{%- endfor %}
98-
{%- endif %}
99-
{%- endfor %}
126+
{%- endif %}
127+
{%- endfor %}
100128
101-
{%- if not strict_mode and global_block_nomatch or block_nomatch %}
102-
# If strict mode is disabled we may want to block anything else
103-
{%- if interfaces == '' %}
104-
{%- for proto in protos %}
105-
iptables_{{service_name}}_deny_other_{{proto}}:
129+
{%- if not strict_mode and global_block_nomatch or block_nomatch %}
130+
# If strict mode is disabled we may want to block anything else
131+
{%- if interfaces == '' %}
132+
{%- for proto in protos %}
133+
iptables_{{service_name}}_deny_other_{{proto}}{{sufixes[protocol]}}:
106134
iptables.append:
107135
- position: last
108136
- table: filter
109137
- chain: INPUT
110138
- jump: REJECT
111139
- dport: {{ service_name }}
112140
- proto: {{ proto }}
141+
{%- if protocol == ipv6 %}
142+
- family: ipv6
143+
{%- endif %}
113144
- save: True
114145
{{ comment }}
115-
{%- endfor %}
116-
{%- else %}
117-
{%- for interface in interfaces %}
118-
{%- for proto in protos %}
119-
iptables_{{service_name}}_deny_other_{{proto}}_{{interface}}:
146+
{%- endfor %}
147+
{%- else %}
148+
{%- for interface in interfaces %}
149+
{%- for proto in protos %}
150+
iptables_{{service_name}}_deny_other_{{proto}}_{{interface}}{{sufixes[protocol]}}:
120151
iptables.append:
121152
- position: last
122153
- table: filter
@@ -125,14 +156,18 @@
125156
- i: {{ interface }}
126157
- dport: {{ service_name }}
127158
- proto: {{ proto }}
159+
{%- if protocol == ipv6 %}
160+
- family: ipv6
161+
{%- endif %}
128162
- save: True
129163
{{ comment }}
164+
{%- endfor %}
130165
{%- endfor %}
131-
{%- endfor %}
132-
{%- endif %}
166+
{%- endif %}
133167
134-
{%- endif %}
168+
{%- endif %}
135169
170+
{%- endfor %}
136171
{%- endfor %}
137172
138173
# Generate rules for NAT
@@ -153,15 +188,20 @@
153188
{%- endfor %}
154189
155190
# Generate rules for whitelisting IP classes
156-
{%- for service_name, service_details in firewall.get('whitelist', {}).items() %}
157-
{%- for ip in service_details.get('ips_allow', []) %}
158-
iptables_{{service_name}}_allow_{{ip}}:
159-
iptables.append:
160-
- table: filter
161-
- chain: INPUT
162-
- jump: ACCEPT
163-
- source: {{ ip }}
164-
- save: True
191+
{%- for protocol in protocols %}
192+
{%- for service_name, service_details in firewall.get('whitelist', {}).items() %}
193+
{%- for ip in service_details.get('ips_allow', []) %}
194+
iptables_{{service_name}}_allow_{{ip}}{{sufixes[protocol]}}:
195+
iptables.append:
196+
- table: filter
197+
- chain: INPUT
198+
- jump: ACCEPT
199+
- source: {{ ip }}
200+
{%- if protocol == ipv6 %}
201+
- family: ipv6
202+
{%- endif %}
203+
- save: True
204+
{%- endfor %}
165205
{%- endfor %}
166206
{%- endfor %}
167207

pillar.example

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ firewall:
22
install: True
33
enabled: True
44
strict: True
5+
ipv6: True
56
services:
67
ssh:
78
block_nomatch: True
@@ -22,12 +23,36 @@ firewall:
2223
interfaces:
2324
- eth0
2425

26+
services_ipv6:
27+
ssh:
28+
block_nomatch: False
29+
ips_allow:
30+
- 2a02:2028:773:d01:10a5:f34f:e7ff:f55b/64
31+
- 2a02:2028:773:d01:1814:28ef:e91b:70b8/64
32+
http:
33+
block_nomatch: False
34+
protos:
35+
- udp
36+
- tcp
37+
snmp:
38+
block_nomatch: False
39+
protos:
40+
- udp
41+
- tcp
42+
interfaces:
43+
- eth0
44+
2545
whitelist:
2646
networks:
2747
ips_allow:
2848
- 10.0.0.0/8
2949

30-
#Suppport nat
50+
whitelist_ipv6:
51+
networks:
52+
ips_allow:
53+
- 2a02:2028:773:d01:1814:28ef:e91b:70b8/64
54+
55+
#Support nat (ipv4 only)
3156
# iptables -t nat -A POSTROUTING -o eth0 -s 192.168.18.0/24 -d 10.20.0.2 -j MASQUERADE
3257
# iptables -t nat -A POSTROUTING -o eth0 -s 192.168.18.0/24 -d 172.31.0.2 -j MASQUERADE
3358
nat:

0 commit comments

Comments
 (0)