]> git.ipfire.org Git - network.git/blame - functions.iptables
ip: Remove log message when IP protocol could not be detected.
[network.git] / functions.iptables
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
22function iptables() {
23 local arg
24 local args
afb7d704
MT
25 local table="filter"
26 local src dst
27
28 # Default is both protocols.
29 local proto="6 4"
98146c00
MT
30
31 # Check if the directory where we put our rules in is set and
32 # exists.
33 assert isset IPTABLES_TMPDIR
34 assert [ -d "${IPTABLES_TMPDIR}" ]
35
98146c00
MT
36 # Parsing arguments
37 while [ $# -gt 0 ]; do
38 case "${1}" in
afb7d704
MT
39 # Select IPv4 protocol.
40 -4)
41 proto="4"
42 shift
43 ;;
44 # Select IPv6 protocol.
45 -6)
46 proto="6"
47 shift
48 ;;
98146c00
MT
49 -t)
50 table=${2}
51 shift 2
52 ;;
53 -A)
54 args="${args} -A ${2^^}"
55 shift 2
56 ;;
57 *)
58 args="${args} ${1}"
afb7d704
MT
59
60 # Save some values for further processing.
61 case "${1}" in
62 -s)
63 src="${2}"
64 ;;
65 -d)
66 dst="${2}"
67 ;;
68 esac
98146c00
MT
69 shift
70 ;;
71 esac
72 done
73
afb7d704
MT
74 # Check that the nat table is not used for IPv6.
75 if isoneof 6 ${proto}; then
76 assert [ "${table}" != "nat" ]
77 fi
78
79 # Detect the version of the IP protocol.
80 local src_proto
81 isset src && src_proto=$(ip_detect_protocol ${src})
82
83 local dst_proto
84 isset dst && dst_proto=$(ip_detect_protocol ${dst})
85
86 # Check that the source and destinations are not
87 # using different versions of the IP protocol.
88 if isset src_proto && isset dst_proto; then
89 assert [ "${src_proto}" = "${dst_proto}" ]
90 fi
91
92 local rulesfile
93 local p
94 for p in ${proto}; do
95 case "${p}" in
96 6)
97 listmatch ipv4 ${src_proto} ${dst_proto} \
98 && continue
99 ;;
100 4)
101 listmatch ipv6 ${src_proto} ${dst_proto} \
102 && continue
103 ;;
104 esac
105
106 rulesfile=$(iptables_rulesfile ipv${p} ${table})
107 print "${args:1:${#args}}" >> ${rulesfile}
108 done
109}
110
111# Calls the binary iptables command.
112function _iptables() {
113 local iptables_cmd=$(which iptables)
114 assert isset iptables_cmd
115
116 ${iptables_cmd} $@
117}
118
119function iptables_status() {
120 _iptables -L -n -v
121}
122
123# Returns which tables exist for the given protocol.
124function iptables_tables() {
125 local proto=${1}
126 local file
127
128 case "${proto}" in
129 ipv6)
130 file="/proc/net/ip6_tables_names"
131 ;;
132 ipv4)
133 file="/proc/net/ip_tables_names"
134 ;;
135 *)
136 return ${EXIT_ERROR}
137 ;;
138 esac
139
140 assert [ -r "${file}" ]
141
142 print "$(<${file})"
143 return ${EXIT_OK}
144}
145
146function iptables_rulesfile() {
147 local proto=${1}
148 proto=${proto/ipv/}
149
150 local chain=${2}
151 [ -z "${chain}" ] && chain="ruleset"
152
153 print "${IPTABLES_TMPDIR}/${chain}${proto}"
98146c00
MT
154}
155
156function iptables_init() {
157 local policy=${1}
afb7d704 158 assert isset policy
98146c00 159
afb7d704 160 # Create filter table and initialize chains.
98146c00 161 iptables "* filter"
afb7d704
MT
162 iptables_chain_create -t filter INPUT --policy=${policy}
163 iptables_chain_create -t filter OUTPUT --policy=${policy}
164 iptables_chain_create -t filter FORWARD --policy=${policy}
98146c00 165
afb7d704 166 # Create mangle table initialize chains.
98146c00 167 iptables -t mangle "* mangle"
afb7d704
MT
168 iptables_chain_create -t mangle PREROUTING --policy=ACCEPT
169 iptables_chain_create -t mangle INPUT --policy=ACCEPT
170 iptables_chain_create -t mangle OUTPUT --policy=ACCEPT
171 iptables_chain_create -t mangle FORWARD --policy=ACCEPT
172 iptables_chain_create -t mangle POSTROUTING --policy=ACCEPT
98146c00 173
afb7d704
MT
174 # Add NAT table for IPv4.
175 iptables -4 -t nat "* nat"
176 iptables_chain_create -4 -t nat PREROUTING --policy=ACCEPT
177 iptables_chain_create -4 -t nat OUTPUT --policy=ACCEPT
178 iptables_chain_create -4 -t nat POSTROUTING --policy=ACCEPT
98146c00
MT
179}
180
afb7d704
MT
181# Load the created ruleset into the kernel.
182function iptables_load() {
183 # If first argument is present and true, we
184 # run in test mode.
185 local test="${1}"
98146c00 186
afb7d704 187 local rulesfile
98146c00 188
afb7d704
MT
189 # First, commit all tables.
190 _iptables_commit
191
192 # Concat the table rulesets into one big file.
193 local proto
194 for proto in 6 4; do
195 rulesfile=$(iptables_rulesfile ipv${proto})
196
197 local table
198 local tablefile
199 for table in $(iptables_tables ipv${proto}); do
200 tablefile=$(iptables_rulesfile ipv${proto} ${table})
201 print "$(<${tablefile})"
202 done > ${rulesfile}
203 done
204
205 local error="false"
206 local ret
207
208 # First check if everything is correctly formatted.
209 for proto in 6 4; do
210 rulesfile=$(iptables_rulesfile ipv${proto})
211
212 _iptables_load ipv${proto} ${rulesfile} true
213 if [ $? -ne ${EXIT_OK} ]; then
214 log CRITICAL "Ruleset load check failed for IPv${proto}"
215 error="true"
216 fi
217 done
218
219 # Check if there has been an error in the load check.
220 if enabled error; then
221 iptables_dump CRITICAL
222
223 log CRITICAL "New firewall rules could not be loaded."
224 return ${EXIT_ERROR}
225 fi
226
227 # Dump the data, we are going to load.
228 iptables_dump
229
230 # If we are running in test mode, we are done here.
231 enabled test && return ${EXIT_OK}
232
233 # If we got until here, everything is fine to load the ruleset.
234 for proto in 6 4; do
235 rulesfile=$(iptables_rulesfile ipv${proto})
236
237 _iptables_load ipv${proto} ${rulesfile}
238 done
239 return ${EXIT_OK}
240}
241
242# Commit all tables.
243function _iptables_commit() {
98146c00
MT
244 iptables -t filter "COMMIT"
245 iptables -t mangle "COMMIT"
98146c00 246
afb7d704
MT
247 # Commit NAT chain for IPv4.
248 iptables -4 -t nat "COMMIT"
249}
250
251function _iptables_load() {
252 local proto=${1}
253 local file=${2}
254 local testmode=${3}
98146c00 255
afb7d704
MT
256 local command
257 case "${proto}" in
258 ipv6)
259 command="ip6tables-restore"
260 ;;
261 ipv4)
262 command="iptables-restore"
263 ;;
264 esac
265 assert isset command
266
267 if enabled testmode; then
268 command="${command} --test"
269 fi
270
271 local time_started=$(date -u "+%s")
272
273 cmd ${command} < ${file}
274 local ret=$?
275
276 case "${ret}" in
277 ${EXIT_OK})
278 local time_finished=$(date -u "+%s")
279 time_finished=$(( ${time_finished} - ${time_started} ))
280 log INFO \
281 "Successfully loaded new firewall ruleset for IPv${proto/ipv/} in ${time_finished}s!"
282 ;;
283 *)
284 if ! enabled testmode; then
285 log CRITICAL "Error loading firewall ruleset for IPv${proto/ipv/}!"
286 fi
287 ;;
288 esac
289
290 return ${ret}
291}
292
293function iptables_dump() {
294 local log_facility=${1-DEBUG}
295
296 # Here is nothing to do, if we are not running in
297 # debug mode.
298 enabled DEBUG || return ${EXIT_OK}
98146c00 299
afb7d704
MT
300 local rulesfile
301 local counter
98146c00 302 local line
98146c00 303
afb7d704
MT
304 local proto
305 for proto in 6 4; do
306 rulesfile=$(iptables_rulesfile ipv${proto})
307 [ -e "${rulesfile}" ] || continue
308
309 log ${log_facility} "Firewall ruleset for IPv${proto}:"
310
311 counter=1
312 while read line; do
313 line=$(print "%4d | %s" "${counter}" "${line}")
314 log ${log_facility} "${line}"
315
316 counter=$(( $counter + 1 ))
317 done < ${rulesfile}
318 done
98146c00
MT
319}
320
321function iptables_chain_create() {
afb7d704
MT
322 local chain
323 local table="filter"
324 local policy="-"
325 local proto
98146c00 326 local args
afb7d704
MT
327 while [ $# -gt 0 ]; do
328 case "${1}" in
329 -6|-4)
330 proto=${1}
331 ;;
332 -t)
333 table=${2}
334 shift
335 ;;
336 --policy=*)
337 policy=$(cli_get_val ${1})
338 ;;
339 *)
340 chain=${1}
341 ;;
342 esac
343 shift
344 done
345
346 assert isset chain
347 assert isset table
348 assert isoneof policy ACCEPT DROP "-"
98146c00 349
afb7d704 350 iptables ${proto} -t ${table} ":${chain} ${policy} [0:0]"
98146c00
MT
351}
352
353function iptables_LOG() {
354 local prefix=${1}
afb7d704 355 local ret
98146c00 356
afb7d704
MT
357 case "${FIREWALL_LOG_METHOD}" in
358 nflog)
359 ret="NFLOG --nflog-threshold ${FIREWALL_NFLOG_THRESHOLD}"
360 isset prefix && ret="${ret} --nflog-prefix \"$prefix\""
361 ;;
362 syslog)
363 ret="LOG"
364 isset prefix && ret="${ret} --log-prefix \"$prefix\""
365 ;;
366 esac
367
368 print "${ret}"
98146c00
MT
369}
370
371function iptables_protocol() {
372 local PROTO
373 PROTO=$1
374 for proto in tcp udp esp ah; do
375 if [ "$PROTO" = "$proto" ]; then
376 echo "-p $PROTO"
377 break
378 fi
379 done
380}
381
382IPTABLES_PORT=0
383IPTABLES_MULTIPORT=1
384IPTABLES_PORTRANGE=2
385
386function _iptables_port_range() {
387 grep -q ":" <<< $@
388}
389
390function _iptables_port_multiport() {
391 grep -q "," <<< $@
392}
393
394function _iptables_port() {
395 if _iptables_port_range "$@"; then
396 echo $IPTABLES_PORTRANGE
397 elif _iptables_port_multiport "$@"; then
398 echo $IPTABLES_MULTIPORT
399 else
400 echo $IPTABLES_PORT
401 fi
402}
403
404function iptables_source_port() {
405 [ -z "$@" ] && return
406 local type
407 type=$(_iptables_port $@)
408 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
409 echo "-m multiport --source-ports $@"
410 else
411 echo "--sport $@"
412 fi
413}
414
415function iptables_destination_port() {
416 [ -z "$@" ] && return
417 local type
418 type=$(_iptables_port $@)
419 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
420 echo "-m multiport --destination-ports $@"
421 else
422 echo "--dport $@"
423 fi
424}