2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2012 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 ###############################################################################
28 # Default is both protocols.
31 # Check if the directory where we put our rules in is set and
33 assert isset IPTABLES_TMPDIR
34 assert
[ -d "${IPTABLES_TMPDIR}" ]
37 while [ $# -gt 0 ]; do
39 # Select IPv4 protocol.
44 # Select IPv6 protocol.
54 args
="${args} -A ${2^^}"
60 # Save some values for further processing.
74 # Check that the nat table is not used for IPv6.
75 if isoneof
6 ${proto}; then
76 assert
[ "${table}" != "nat" ]
79 # Detect the version of the IP protocol.
81 isset src
&& src_proto
=$
(ip_detect_protocol
${src})
84 isset dst
&& dst_proto
=$
(ip_detect_protocol
${dst})
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}" ]
97 listmatch ipv4
${src_proto} ${dst_proto} \
101 listmatch ipv6
${src_proto} ${dst_proto} \
106 rulesfile
=$
(iptables_rulesfile ipv
${p} ${table})
107 print
"${args:1:${#args}}" >> ${rulesfile}
111 # Calls the binary iptables command.
112 function _iptables() {
113 local iptables_cmd=$(which iptables)
114 assert isset iptables_cmd
119 function iptables_status() {
123 # Returns which tables exist for the given protocol.
124 function iptables_tables() {
130 print "filter mangle
"
133 print "filter mangle nat
"
143 function iptables_rulesfile() {
148 [ -z "${chain}" ] && chain="ruleset
"
150 print "${IPTABLES_TMPDIR}/${chain}${proto}"
153 function iptables_init() {
157 # Create filter table and initialize chains.
159 iptables_chain_create -t filter INPUT --policy=${policy}
160 iptables_chain_create -t filter OUTPUT --policy=${policy}
161 iptables_chain_create -t filter FORWARD --policy=${policy}
163 # Create mangle table initialize chains.
164 iptables -t mangle "* mangle
"
165 iptables_chain_create -t mangle PREROUTING --policy=ACCEPT
166 iptables_chain_create -t mangle INPUT --policy=ACCEPT
167 iptables_chain_create -t mangle OUTPUT --policy=ACCEPT
168 iptables_chain_create -t mangle FORWARD --policy=ACCEPT
169 iptables_chain_create -t mangle POSTROUTING --policy=ACCEPT
171 # Add NAT table for IPv4.
172 iptables -4 -t nat "* nat
"
173 iptables_chain_create -4 -t nat PREROUTING --policy=ACCEPT
174 iptables_chain_create -4 -t nat OUTPUT --policy=ACCEPT
175 iptables_chain_create -4 -t nat POSTROUTING --policy=ACCEPT
178 # Load the created ruleset into the kernel.
179 function iptables_load() {
180 # If first argument is present and true, we
186 # Concat the table rulesets into one big file.
189 rulesfile=$(iptables_rulesfile ipv${proto})
190 assert isset rulesfile
194 for table in $(iptables_tables ipv${proto}); do
195 tablefile=$(iptables_rulesfile ipv${proto} ${table})
199 # Add the COMMIT statement for every table.
200 if [ -s "${tablefile}" ]; then
205 assert [ -s "${rulesfile}" ]
211 # First check if everything is correctly formatted.
213 rulesfile=$(iptables_rulesfile ipv${proto})
215 _iptables_load ipv${proto} ${rulesfile} true
216 if [ $? -ne ${EXIT_OK} ]; then
217 log CRITICAL "Ruleset load check failed
for IPv
${proto}"
222 # Check if there has been an error in the load check.
223 if enabled error; then
224 iptables_dump CRITICAL
226 log CRITICAL "New firewall rules could not be loaded.
"
230 # Dump the data, we are going to load.
233 # If we are running in test mode, we are done here.
234 enabled test && return ${EXIT_OK}
236 # If we got until here, everything is fine to load the ruleset.
238 rulesfile=$(iptables_rulesfile ipv${proto})
240 _iptables_load ipv${proto} ${rulesfile}
245 function _iptables_load() {
253 command="ip6tables-restore
"
256 command="iptables-restore
"
261 if enabled testmode; then
262 command="${command} --test"
265 local time_started=$(date -u "+%s
")
267 cmd ${command} < ${file}
272 local time_finished=$(date -u "+%s
")
273 time_finished=$(( ${time_finished} - ${time_started} ))
275 "Successfully loaded new firewall ruleset
for IPv
${proto/ipv/} in ${time_finished}s
!"
278 if ! enabled testmode; then
279 log CRITICAL "Error loading firewall ruleset
for IPv
${proto/ipv/}!"
287 function iptables_dump() {
288 local log_facility=${1-DEBUG}
290 # Here is nothing to do, if we are not running in
292 enabled DEBUG || return ${EXIT_OK}
300 rulesfile=$(iptables_rulesfile ipv${proto})
301 [ -e "${rulesfile}" ] || continue
303 log ${log_facility} "Firewall ruleset
for IPv
${proto}:"
306 while read -r line; do
307 printf -v line "%4d |
%s
" "${counter}" "${line}"
308 log ${log_facility} "${line}"
310 counter=$(( $counter + 1 ))
315 function iptables_chain_create() {
321 while [ $# -gt 0 ]; do
331 policy=$(cli_get_val ${1})
342 assert isoneof policy ACCEPT DROP "-"
344 iptables ${proto} -t ${table} ":${chain} ${policy} [0:0]"
347 function iptables_LOG
() {
351 case "${FIREWALL_LOG_METHOD}" in
353 ret
="NFLOG --nflog-threshold ${FIREWALL_NFLOG_THRESHOLD}"
354 isset prefix
&& ret
="${ret} --nflog-prefix \"$prefix\""
358 isset prefix
&& ret
="${ret} --log-prefix \"$prefix\""
365 function iptables_protocol
() {
368 for proto
in tcp udp esp ah
; do
369 if [ "$PROTO" = "$proto" ]; then
380 function _iptables_port_range
() {
384 function _iptables_port_multiport
() {
388 function _iptables_port
() {
389 if _iptables_port_range
"$@"; then
390 echo $IPTABLES_PORTRANGE
391 elif _iptables_port_multiport
"$@"; then
392 echo $IPTABLES_MULTIPORT
398 function iptables_source_port
() {
399 [ -z "$@" ] && return
401 type=$
(_iptables_port $@
)
402 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
403 echo "-m multiport --source-ports $@"
409 function iptables_destination_port
() {
410 [ -z "$@" ] && return
412 type=$
(_iptables_port $@
)
413 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
414 echo "-m multiport --destination-ports $@"