]> git.ipfire.org Git - people/stevee/network.git/blame - functions.firewall
Change dns command to dns-server.
[people/stevee/network.git] / functions.firewall
CommitLineData
98146c00
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2012 IPFire Network Development Team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
21
22# High-level function which will create a ruleset for the current firewall
23# configuration and load it into the kernel.
24function firewall_start() {
afb7d704
MT
25 # Test mode.
26 local test="false"
27
28 while [ $# -gt 0 ]; do
29 case "${1}" in
30 --test)
31 test="true"
32 ;;
33 esac
34 shift
35 done
36
37 if enabled test; then
38 log INFO "Test mode enabled."
39 log INFO "The firewall ruleset will not be loaded."
40 fi
41
98146c00
MT
42 firewall_lock_acquire
43
44 # Initialize an empty iptables ruleset.
45 iptables_init DROP
46
47 # Add default chains.
48 firewall_tcp_state_flags
3b256a38 49 firewall_custom_chains
98146c00 50 firewall_connection_tracking
c2d2d2a9 51 firewall_tcp_clamp_mss
98146c00
MT
52
53 # Add policies for every zone.
a2c9dff5 54 firewall_localhost_create_chains
98146c00
MT
55
56 local zone
57 for zone in $(zones_get_all); do
a2c9dff5
MT
58 # Create all needed chains for the zone.
59 firewall_zone_create_chains ${zone}
60
61 # After the chains that are always available have been
62 # created, we will add a custom policy to every single
63 # zone.
64
478de6f9 65 policy_zone_add ${zone}
98146c00
MT
66 done
67
afb7d704
MT
68 # Load the new ruleset.
69 iptables_load ${test}
98146c00
MT
70
71 firewall_lock_release
72}
73
74function firewall_stop() {
75 firewall_lock_acquire
76
77 # Initialize an empty firewall ruleset
78 # with default policy ACCEPT.
79 iptables_init ACCEPT
80
afb7d704
MT
81 # Load it.
82 iptables_load
83
84 firewall_lock_release
85}
86
87function firewall_show() {
88 # Shows the ruleset that is currently loaded.
89 iptables_status
90
91 return ${EXIT_OK}
92}
93
94function firewall_panic() {
95 local admin_hosts="$@"
96
97 firewall_lock_acquire
98
99 # Drop all communications.
100 iptables_init DROP
101
102 # If an admin host is provided, some administrative
103 # things will be allowed from there.
104 local admin_host
105 for admin_host in ${admin_hosts}; do
106 iptables -A INPUT -s ${admin_host} -j ACCEPT
107 iptables -A OUTPUT -d ${admin_host} -j ACCEPT
108 done
109
110 # Load it.
111 iptables_load
98146c00
MT
112
113 firewall_lock_release
114}
115
116function firewall_lock_acquire() {
117 lock_acquire ${RUN_DIR}/.firewall_lock
118
119 # Make sure the lock is released after the firewall
120 # script has crashed or exited early.
121 trap firewall_lock_release EXIT TERM KILL
122
123 # Create a directory where we can put our
124 # temporary data in the most secure way as possible.
125 IPTABLES_TMPDIR=$(mktemp -d)
126}
127
128function firewall_lock_release() {
129 if isset IPTABLES_TMPDIR; then
130 # Remove all temporary data.
131 rm -rf ${IPTABLES_TMPDIR}
132
133 # Reset the tempdir variable.
134 IPTABLES_TMPDIR=
135 fi
136
137 # Reset the trap.
138 trap true EXIT TERM KILL
139
140 lock_release ${RUN_DIR}/.firewall_lock
141}
142
3b256a38
MT
143function firewall_custom_chains() {
144 log INFO "Creating CUSTOM* chains..."
145
146 # These chains are intened to be filled with
147 # rules by the user. They are processed at the very
148 # beginning so it is possible to overwrite everything.
149
150 iptables_chain_create CUSTOMINPUT
151 iptables -A INPUT -j CUSTOMINPUT
152
153 iptables_chain_create CUSTOMFORWARD
154 iptables -A FORWARD -j CUSTOMFORWARD
155
156 iptables_chain_create CUSTOMOUTPUT
157 iptables -A OUTPUT -j CUSTOMOUTPUT
158
159 iptables_chain_create -4 -t nat CUSTOMPREROUTING
160 iptables -4 -t nat -A PREROUTING -j CUSTOMPREROUTING
161
162 iptables_chain_create -4 -t nat CUSTOMPOSTROUTING
163 iptables -4 -t nat -A POSTROUTING -j CUSTOMPOSTROUTING
164
165 iptables_chain_create -4 -t nat CUSTOMOUTPUT
166 iptables -4 -t nat -A OUTPUT -j CUSTOMOUTPUT
167}
168
98146c00
MT
169function firewall_tcp_state_flags() {
170 log INFO "Creating TCP State Flags chain..."
171 iptables_chain_create BADTCP_LOG
172 iptables -A BADTCP_LOG -p tcp -j $(iptables_LOG "Illegal TCP state: ")
173 iptables -A BADTCP_LOG -j DROP
174
175 iptables_chain_create BADTCP
176 iptables -A BADTCP -p tcp --tcp-flags ALL NONE -j BADTCP_LOG
177 iptables -A BADTCP -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADTCP_LOG
178 iptables -A BADTCP -p tcp --tcp-flags SYN,RST SYN,RST -j BADTCP_LOG
179 iptables -A BADTCP -p tcp --tcp-flags FIN,RST FIN,RST -j BADTCP_LOG
180 iptables -A BADTCP -p tcp --tcp-flags ACK,FIN FIN -j BADTCP_LOG
181 iptables -A BADTCP -p tcp --tcp-flags ACK,PSH PSH -j BADTCP_LOG
182 iptables -A BADTCP -p tcp --tcp-flags ACK,URG URG -j BADTCP_LOG
183
184 iptables -A INPUT -p tcp -j BADTCP
185 iptables -A OUTPUT -p tcp -j BADTCP
186 iptables -A FORWARD -p tcp -j BADTCP
187}
188
c2d2d2a9 189function firewall_tcp_clamp_mss() {
fc323fc4
MT
190 # Do nothing if this has been disabled.
191 enabled FIREWALL_CLAMP_PATH_MTU || return ${EXIT_OK}
192
c2d2d2a9
MT
193 log DEBUG "Adding rules to clamp MSS to path MTU..."
194 iptables -t mangle -A FORWARD \
195 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
196}
197
98146c00
MT
198function firewall_connection_tracking() {
199 log INFO "Creating Connection Tracking chain..."
200 iptables_chain_create CONNTRACK
201 iptables -A CONNTRACK -m state --state ESTABLISHED,RELATED -j ACCEPT
202 iptables -A CONNTRACK -m state --state INVALID -j $(iptables_LOG "INVALID packet: ")
203 iptables -A CONNTRACK -m state --state INVALID -j DROP
204
205 iptables -A INPUT -j CONNTRACK
206 iptables -A OUTPUT -j CONNTRACK
207 iptables -A FORWARD -j CONNTRACK
208}
3647b19f 209
a2c9dff5
MT
210function firewall_localhost_create_chains() {
211 log DEBUG "Creating firewall chains for localhost..."
212
213 # Accept everything on lo
214 iptables -A INPUT -i lo -m state --state NEW -j ACCEPT
215 iptables -A OUTPUT -o lo -m state --state NEW -j ACCEPT
216}
217
218function firewall_zone_create_chains() {
3647b19f 219 local zone=${1}
a2c9dff5
MT
220 assert isset zone
221
222 log DEBUG "Creating firewall chains for zone '${zone}'."
223
224 local chain_prefix="ZONE_${zone^^}"
225
226 # Create filter chains.
227 iptables_chain_create "${chain_prefix}_INPUT"
228 iptables -A INPUT -i ${zone} -j "${chain_prefix}_INPUT"
229
230 iptables_chain_create "${chain_prefix}_OUTPUT"
231 iptables -A OUTPUT -o ${zone} -j "${chain_prefix}_OUTPUT"
232
233 # Custom rules.
234 iptables_chain_create "${chain_prefix}_CUSTOM"
235
236 # Intrusion Prevention System.
237 iptables_chain_create "${chain_prefix}_IPS"
238
239 # Create a chain for each other zone.
240 # This leaves us with n^2 chains. Duh.
241
242 local other_zone other_chain_prefix
243 for other_zone in $(zones_get_all); do
244 other_chain_prefix="${chain_prefix}_${other_zone^^}"
245 iptables_chain_create ${other_chain_prefix}
246
247 # Connect the chain with the FORWARD chain.
248 iptables -A FORWARD -i ${zone} -o ${other_zone} \
249 -j "${other_chain_prefix}"
250
251 # Handle custom rules.
252 iptables -A ${other_chain_prefix} -j "${chain_prefix}_CUSTOM"
253
254 # Link IPS.
255 iptables -A ${other_chain_prefix} -j "${chain_prefix}_IPS"
256
257 # Rules.
258 iptables_chain_create "${other_chain_prefix}_RULES"
259 iptables -A ${other_chain_prefix} -j "${other_chain_prefix}_RULES"
260
261 # Policy.
262 iptables_chain_create "${other_chain_prefix}_POLICY"
263 iptables -A ${other_chain_prefix} -j "${other_chain_prefix}_POLICY"
264 done
265
266 ## Create mangle chain.
267 #iptables_chain_create -t mangle ${chain_prefix}
268 #iptables -t mangle -A PREROUTING -i ${zone} -j ${chain_prefix}
269 #iptables -t mangle -A POSTROUTING -o ${zone} -j ${chain_prefix}
270
271 ## Quality of Service
272 #iptables_chain_create -t mangle "${chain_prefix}_QOS_INC"
273 #iptables -t mangle -A ${chain_prefix} -i ${zone} -j "${chain_prefix}_QOS_INC"
274 #iptables_chain_create -t mangle "${chain_prefix}_QOS_OUT"
275 #iptables -t mangle -A ${chain_prefix} -o ${zone} -j "${chain_prefix}_QOS_OUT"
276
277 # Create NAT chain.
278 iptables_chain_create -4 -t nat ${chain_prefix}
279 iptables -4 -t nat -A PREROUTING -i ${zone} -j ${chain_prefix}
280 iptables -4 -t nat -A POSTROUTING -o ${zone} -j ${chain_prefix}
281
282 # Network Address Translation
283 iptables_chain_create -4 -t nat "${chain_prefix}_DNAT"
284 iptables -4 -t nat -A PREROUTING -i ${zone} -j "${chain_prefix}_DNAT"
285 iptables_chain_create -4 -t nat "${chain_prefix}_SNAT"
286 iptables -4 -t nat -A POSTROUTING -o ${zone} -j "${chain_prefix}_SNAT"
287
288 # UPnP
289 iptables_chain_create -4 -t nat "${chain_prefix}_UPNP"
290 iptables -4 -t nat -A ${chain_prefix} -j "${chain_prefix}_UPNP"
291
292 return ${EXIT_OK}
293}
294
295function firewall_parse_rules() {
296 local file=${1}
297 assert isset file
3647b19f
MT
298 shift
299
a2c9dff5
MT
300 # End if no rule file exists.
301 [ -r "${file}" ] || return ${EXIT_OK}
3647b19f 302
a2c9dff5
MT
303 local cmd
304
305 local ${FIREWALL_RULES_CONFIG_PARAMS}
306 local line
307 while read -r line; do
308 # Skip empty lines.
309 [ -n "${line}" ] || continue
310
311 # Skip commented lines.
312 [ "${line:0:1}" = "#" ] && continue
313
314 # Parse the rule.
315 _firewall_parse_rule_line ${line}
316 if [ $? -ne ${EXIT_OK} ]; then
317 log WARNING "Skipping invalid line: ${line}"
318 continue
319 fi
320
321 cmd="iptables $@"
322
323 # Source IP address/net.
324 if isset src; then
325 list_append cmd "-s ${src}"
326 fi
327
328 # Destination IP address/net.
329 if isset dst; then
330 list_append cmd "-d ${dst}"
331 fi
332
333 # Protocol.
334 if isset proto; then
335 list_append cmd "-p ${proto}"
336
337 if list_match ${proto} ${FIREWALL_PROTOCOLS_SUPPORTING_PORTS}; then
338 if isset sport; then
339 list_append cmd "--sport ${sport}"
340 fi
341
342 if isset dport; then
343 list_append cmd "--dport ${dport}"
344 fi
345 fi
346 fi
347
348 # Always append the action.
349 list_append cmd "-j ${action}"
350
351 # Execute command.
352 ${cmd}
353 done < ${file}
354}
355
356function _firewall_parse_rule_line() {
357 local arg
358
359 # Clear all values.
360 for arg in ${FIREWALL_RULES_CONFIG_PARAMS}; do
361 assign "${arg}" ""
3647b19f
MT
362 done
363
a2c9dff5
MT
364 local key val
365 while read -r arg; do
366 key=$(cli_get_key ${arg})
3647b19f 367
a2c9dff5
MT
368 if ! listmatch "${key}" ${FIREWALL_RULES_CONFIG_PARAMS}; then
369 log WARNING "Unrecognized argument: ${arg}"
370 return ${EXIT_ERROR}
371 fi
3647b19f 372
a2c9dff5
MT
373 val=$(cli_get_val ${arg})
374 assign "${key}" "${val}"
375 done <<< "$(args $@)"
376
377 # action must always be set.
378 if ! isset action; then
379 log WARNING "'action' is not set: $@"
380 return ${EXIT_ERROR}
381 fi
382
383 for arg in src dst; do
384 isset ${arg} || continue
385
386 # Check for valid IP addresses.
387 if ! ip_is_valid ${!arg}; then
388 log WARNING "Invalid IP address for '${arg}=${!arg}': $@"
389 return ${EXIT_ERROR}
390 fi
391 done
392
393 if isset proto; then
394 # Make lowercase.
395 proto=${proto,,}
396
397 if ! list_match "${proto}" ${FIREWALL_SUPPORTED_PROTOCOLS}; then
398 log WARNING "Unsupported protocol type 'proto=${proto}': $@"
399 return ${EXIT_ERROR}
400 fi
401 fi
402
403 for arg in sport dport; do
404 isset ${arg} || continue
405
406 # Check if port is valid.
407 if ! isinteger ${arg}; then
408 log WARNING "Invalid port '${arg}=${!arg}': $@"
409 return ${EXIT_ERROR}
410 fi
411 done
412
413 return ${EXIT_OK}
3647b19f 414}