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 assert isset rulesfile
109 print
"${args:1:${#args}}" >> ${rulesfile}
113 # Calls the binary iptables command.
114 function _iptables() {
115 local iptables_cmd=$(which iptables)
116 assert isset iptables_cmd
118 cmd ${iptables_cmd} $@
121 function iptables_status() {
125 # Returns which tables exist for the given protocol.
126 function iptables_tables() {
132 print "filter mangle
"
135 print "filter mangle nat
"
145 function iptables_rulesfile() {
150 [ -z "${chain}" ] && chain="ruleset
"
152 print "${IPTABLES_TMPDIR}/${chain}${proto}"
155 function iptables_init() {
159 # Create filter table and initialize chains.
161 iptables_chain_create -t filter INPUT --policy=${policy}
162 iptables_chain_create -t filter OUTPUT --policy=${policy}
163 iptables_chain_create -t filter FORWARD --policy=${policy}
165 # Create mangle table initialize chains.
166 iptables -t mangle "* mangle
"
167 iptables_chain_create -t mangle PREROUTING --policy=ACCEPT
168 iptables_chain_create -t mangle INPUT --policy=ACCEPT
169 iptables_chain_create -t mangle OUTPUT --policy=ACCEPT
170 iptables_chain_create -t mangle FORWARD --policy=ACCEPT
171 iptables_chain_create -t mangle POSTROUTING --policy=ACCEPT
173 # Add NAT table for IPv4.
174 iptables -4 -t nat "* nat
"
175 iptables_chain_create -4 -t nat PREROUTING --policy=ACCEPT
176 iptables_chain_create -4 -t nat OUTPUT --policy=ACCEPT
177 iptables_chain_create -4 -t nat POSTROUTING --policy=ACCEPT
180 # Load the created ruleset into the kernel.
181 function iptables_load() {
182 # If first argument is present and true, we
188 # Concat the table rulesets into one big file.
191 rulesfile=$(iptables_rulesfile ipv${proto})
192 assert isset rulesfile
196 for table in $(iptables_tables ipv${proto}); do
197 tablefile=$(iptables_rulesfile ipv${proto} ${table})
201 # Add the COMMIT statement for every table.
202 if [ -s "${tablefile}" ]; then
207 assert [ -s "${rulesfile}" ]
213 # First check if everything is correctly formatted.
215 rulesfile=$(iptables_rulesfile ipv${proto})
216 assert isset rulesfile
218 _iptables_load ipv${proto} ${rulesfile} true
219 if [ $? -ne ${EXIT_OK} ]; then
220 log CRITICAL "Ruleset load check failed
for IPv
${proto}"
225 # Check if there has been an error in the load check.
226 if enabled error; then
227 iptables_dump CRITICAL
229 log CRITICAL "New firewall rules could not be loaded.
"
233 # Dump the data, we are going to load.
236 # If we are running in test mode, we are done here.
237 enabled test && return ${EXIT_OK}
239 # If we got until here, everything is fine to load the ruleset.
241 rulesfile=$(iptables_rulesfile ipv${proto})
243 _iptables_load ipv${proto} ${rulesfile}
248 function _iptables_load() {
256 command="ip6tables-restore
"
259 command="iptables-restore
"
264 if enabled testmode; then
265 command="${command} --test"
268 local time_started=$(date -u "+%s
")
270 cmd ${command} < ${file}
275 local time_finished=$(date -u "+%s
")
276 time_finished=$(( ${time_finished} - ${time_started} ))
278 "Successfully loaded new firewall ruleset
for IPv
${proto/ipv/} in ${time_finished}s
!"
281 if ! enabled testmode; then
282 log CRITICAL "Error loading firewall ruleset
for IPv
${proto/ipv/}!"
290 function iptables_dump() {
291 local log_facility=${1-DEBUG}
293 # Here is nothing to do, if we are not running in
295 enabled DEBUG || return ${EXIT_OK}
303 rulesfile=$(iptables_rulesfile ipv${proto})
304 [ -e "${rulesfile}" ] || continue
306 log ${log_facility} "Firewall ruleset
for IPv
${proto}:"
309 while read -r line; do
310 printf -v line "%4d |
%s
" "${counter}" "${line}"
311 log ${log_facility} "${line}"
313 counter=$(( $counter + 1 ))
318 function iptables_chain_create() {
324 while [ $# -gt 0 ]; do
334 policy=$(cli_get_val ${1})
345 assert isoneof policy ACCEPT DROP "-"
347 iptables ${proto} -t ${table} ":${chain} ${policy} [0:0]"
350 function iptables_LOG
() {
354 case "${FIREWALL_LOG_METHOD}" in
356 ret
="NFLOG --nflog-threshold ${FIREWALL_NFLOG_THRESHOLD}"
357 isset prefix
&& ret
="${ret} --nflog-prefix \"$prefix\""
361 isset prefix
&& ret
="${ret} --log-prefix \"$prefix\""
368 function iptables_protocol
() {
371 for proto
in tcp udp esp ah
; do
372 if [ "$PROTO" = "$proto" ]; then
383 function _iptables_port_range
() {
387 function _iptables_port_multiport
() {
391 function _iptables_port
() {
392 if _iptables_port_range
"$@"; then
393 echo $IPTABLES_PORTRANGE
394 elif _iptables_port_multiport
"$@"; then
395 echo $IPTABLES_MULTIPORT
401 function iptables_source_port
() {
402 [ -z "$@" ] && return
404 type=$
(_iptables_port $@
)
405 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
406 echo "-m multiport --source-ports $@"
412 function iptables_destination_port
() {
413 [ -z "$@" ] && return
415 type=$
(_iptables_port $@
)
416 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
417 echo "-m multiport --destination-ports $@"