2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2012-2013 IPFire Network Development Team #
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. #
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. #
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/>. #
20 ###############################################################################
22 IPTABLES_TABLES
="filter mangle nat"
29 # Rules go to the filter table by default
39 while [ $# -gt 0 ]; do
41 # Filter to which table this rule should go.
46 assert isoneof table
${IPTABLES_TABLES}
49 list_append args
"${1}"
51 # Save some values for further processing.
67 # Check if given IP addresses or networks match the protocol version.
70 src_proto
="$(ip_detect_protocol ${src})"
72 assert
[ "${protocol}" = "${src_proto}" ]
77 dst_proto
="$(ip_detect_protocol ${dst})"
79 assert
[ "${protocol}" = "${dst_proto}" ]
82 # Check if the directory where we put our rules in is set and
84 assert isset IPTABLES_TMPDIR
85 local rulesfile
="${IPTABLES_TMPDIR}/${protocol}-${table}"
87 print
"${args}" >> "${rulesfile}"
88 assert_check_retval $?
91 function iptables_chain_create
() {
100 while [ $# -gt 0 ]; do
107 policy
="$(cli_get_val ${1})"
110 log WARNING
"Unrecognized argument: ${1}"
121 assert isoneof policy ACCEPT DROP
"-"
123 iptables
"${protocol}" -t "${table}" ":${chain} ${policy} [0:0]"
126 # Calls the binary iptables command.
127 function _iptables
() {
128 local protocol
="${1}"
129 assert isset protocol
133 case "${protocol}" in
142 cmd
="$(which ${cmd})"
148 function iptables_status
() {
149 local protocol
="${1}"
150 assert isset protocol
153 for table
in ${IPTABLES_TABLES}; do
154 print
"${protocol} - ${table}:"
155 _iptables
"${protocol}" -t "${table}" -L -n -v
162 function iptables_rulesfile
() {
167 [ -z "${chain}" ] && chain
="ruleset"
169 print
"${IPTABLES_TMPDIR}/${chain}${proto}"
172 function iptables_init
() {
173 local protocol
="${1}"
174 assert isset protocol
179 # Create filter table and initialize chains.
180 iptables
"${protocol}" "* filter"
181 iptables_chain_create
"${protocol}" -t filter INPUT
--policy="${policy}"
182 iptables_chain_create
"${protocol}" -t filter OUTPUT
--policy="${policy}"
183 iptables_chain_create
"${protocol}" -t filter FORWARD
--policy="${policy}"
185 # Create mangle table and initialize chains.
186 iptables
"${protocol}" -t mangle
"* mangle"
187 iptables_chain_create
"${protocol}" -t mangle PREROUTING
--policy="ACCEPT"
188 iptables_chain_create
"${protocol}" -t mangle INPUT
--policy="ACCEPT"
189 iptables_chain_create
"${protocol}" -t mangle OUTPUT
--policy="ACCEPT"
190 iptables_chain_create
"${protocol}" -t mangle FORWARD
--policy="ACCEPT"
191 iptables_chain_create
"${protocol}" -t mangle POSTROUTING
--policy="ACCEPT"
193 # Create NAT table and initialize chains.
194 iptables
"${protocol}" -t nat
"* nat"
195 iptables_chain_create
"${protocol}" -t nat PREROUTING
--policy="ACCEPT"
196 iptables_chain_create
"${protocol}" -t nat OUTPUT
--policy="ACCEPT"
197 iptables_chain_create
"${protocol}" -t nat POSTROUTING
--policy="ACCEPT"
200 # Load the created ruleset into the kernel.
201 function iptables_commit
() {
202 local protocol
="${1}"
203 assert isset protocol
206 local testmode
="false"
208 while [ $# -gt 0 ]; do
214 log WARNING
"Unrecognized argument: ${1}"
220 # Concat all rules into one big file.
221 local rulesfile
="${IPTABLES_TMPDIR}/ruleset"
222 _iptables_commit_cat_rulesfile
"${protocol}" "${rulesfile}"
224 # Run the following loop twice:
225 # 1st: Check if the ruleset can be loaded
226 # 2nd: If not in test mode, actually load the ruleset into the kernel
227 local load_cmd
="--test"
232 _iptables_commit_load_rulesfile
"${protocol}" "${rulesfile}" "${load_cmd}"
235 case "${i},${ret}" in
237 iptables_dump
"${protocol}" "${rulesfile}" --log-facility="DEBUG"
238 log DEBUG
"Ruleset load check succeeded (${protocol})"
241 # Loading rules has failed (test)
243 iptables_dump
"${protocol}" "${rulesfile}" --log-facility="CRITICAL"
244 log CRITICAL
"Ruleset load check failed (${protocol} - ${ret})"
249 log DEBUG
"Ruleset successfully loaded (${protocol})"
254 log CRITICAL
"Ruleset loading failed (${protocol})"
259 # Skip the second loop iteration, if we are running in test mode.
260 enabled testmode
&& break
268 function _iptables_commit_cat_rulesfile
() {
269 local protocol
="${1}"
270 assert isset protocol
272 local rulesfile
="${2}"
273 assert isset rulesfile
277 for table
in ${IPTABLES_TABLES}; do
278 file="${IPTABLES_TMPDIR}/${protocol}-${table}"
282 # Add the COMMIT statement for every table.
284 done > "${rulesfile}"
286 assert
[ -s "${rulesfile}" ]
289 function _iptables_commit_load_rulesfile
() {
290 local protocol
="${1}"
291 assert isset protocol
293 local rulesfile
="${2}"
294 assert isset rulesfile
297 local testmode
="false"
298 while [ $# -gt 0 ]; do
308 case "${protocol}" in
310 iptables_cmd
="ip6tables-restore"
313 iptables_cmd
="iptables-restore"
316 assert isset iptables_cmd
318 if enabled testmode
; then
319 list_append iptables_cmd
"--test"
322 # Save when importing the rules has started.
323 local time_started
="$(timestamp)"
325 cmd
"${iptables_cmd}" < "${rulesfile}"
330 local time_finished
="$(timestamp)"
331 time_finished
="$(( ${time_finished} - ${time_started} ))"
333 enabled testmode
&& return ${EXIT_OK}
335 log INFO
"Successfully loaded new firewall ruleset for ${protocol} in ${time_finished}s!"
338 if ! enabled testmode
; then
339 log CRITICAL
"Error loading firewall ruleset for ${protocol}!"
347 function iptables_dump
() {
348 local protocol
="${1}"
349 assert isset protocol
351 local rulesfile
="${2}"
352 assert isset rulesfile
355 local log_facility
="INFO"
357 while [ $# -gt 0 ]; do
360 log_facility
="$(cli_get_val ${1})"
363 log WARNING
"Unrecognized argument: ${1}"
369 # Say what we are going to do:
370 log
"${log_facility}" "Firewall ruleset for ${protocol}:"
374 while read -r line
; do
375 counter
="$(( ${counter} + 1 ))"
377 printf -v line
"%4d | %s" "${counter}" "${line}"
378 log
"${log_facility}" "${line}"
379 done < "${rulesfile}"
382 function iptables_LOG
() {
386 case "${FIREWALL_LOG_METHOD}" in
388 ret
="NFLOG --nflog-threshold ${FIREWALL_NFLOG_THRESHOLD}"
389 isset prefix
&& ret
="${ret} --nflog-prefix \"$prefix\""
393 isset prefix
&& ret
="${ret} --log-prefix \"$prefix\""
400 function iptables_protocol
() {
403 for proto
in tcp udp esp ah
; do
404 if [ "$PROTO" = "$proto" ]; then
415 function _iptables_port_range
() {
419 function _iptables_port_multiport
() {
423 function _iptables_port
() {
424 if _iptables_port_range
"$@"; then
425 echo $IPTABLES_PORTRANGE
426 elif _iptables_port_multiport
"$@"; then
427 echo $IPTABLES_MULTIPORT
433 function iptables_source_port
() {
434 [ -z "$@" ] && return
436 type=$
(_iptables_port $@
)
437 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
438 echo "-m multiport --source-ports $@"
444 function iptables_destination_port
() {
445 [ -z "$@" ] && return
447 type=$
(_iptables_port $@
)
448 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
449 echo "-m multiport --destination-ports $@"