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 file="/proc
/net
/ip6_tables_names
"
133 file="/proc
/net
/ip_tables_names
"
140 assert [ -r "${file}" ]
146 function iptables_rulesfile() {
151 [ -z "${chain}" ] && chain="ruleset
"
153 print "${IPTABLES_TMPDIR}/${chain}${proto}"
156 function iptables_init() {
160 # Create filter table and initialize chains.
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}
166 # Create mangle table initialize chains.
167 iptables -t mangle "* mangle
"
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
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
181 # Load the created ruleset into the kernel.
182 function iptables_load() {
183 # If first argument is present and true, we
189 # First, commit all tables.
192 # Concat the table rulesets into one big file.
195 rulesfile=$(iptables_rulesfile ipv${proto})
199 for table in $(iptables_tables ipv${proto}); do
200 tablefile=$(iptables_rulesfile ipv${proto} ${table})
201 print "$
(<${tablefile})"
208 # First check if everything is correctly formatted.
210 rulesfile=$(iptables_rulesfile ipv${proto})
212 _iptables_load ipv${proto} ${rulesfile} true
213 if [ $? -ne ${EXIT_OK} ]; then
214 log CRITICAL "Ruleset load check failed
for IPv
${proto}"
219 # Check if there has been an error in the load check.
220 if enabled error; then
221 iptables_dump CRITICAL
223 log CRITICAL "New firewall rules could not be loaded.
"
227 # Dump the data, we are going to load.
230 # If we are running in test mode, we are done here.
231 enabled test && return ${EXIT_OK}
233 # If we got until here, everything is fine to load the ruleset.
235 rulesfile=$(iptables_rulesfile ipv${proto})
237 _iptables_load ipv${proto} ${rulesfile}
243 function _iptables_commit() {
244 iptables -t filter "COMMIT
"
245 iptables -t mangle "COMMIT
"
247 # Commit NAT chain for IPv4.
248 iptables -4 -t nat "COMMIT
"
251 function _iptables_load() {
259 command="ip6tables-restore
"
262 command="iptables-restore
"
267 if enabled testmode; then
268 command="${command} --test"
271 local time_started=$(date -u "+%s
")
273 cmd ${command} < ${file}
278 local time_finished=$(date -u "+%s
")
279 time_finished=$(( ${time_finished} - ${time_started} ))
281 "Successfully loaded new firewall ruleset
for IPv
${proto/ipv/} in ${time_finished}s
!"
284 if ! enabled testmode; then
285 log CRITICAL "Error loading firewall ruleset
for IPv
${proto/ipv/}!"
293 function iptables_dump() {
294 local log_facility=${1-DEBUG}
296 # Here is nothing to do, if we are not running in
298 enabled DEBUG || return ${EXIT_OK}
306 rulesfile=$(iptables_rulesfile ipv${proto})
307 [ -e "${rulesfile}" ] || continue
309 log ${log_facility} "Firewall ruleset
for IPv
${proto}:"
313 line=$(print "%4d |
%s
" "${counter}" "${line}")
314 log ${log_facility} "${line}"
316 counter=$(( $counter + 1 ))
321 function iptables_chain_create() {
327 while [ $# -gt 0 ]; do
337 policy=$(cli_get_val ${1})
348 assert isoneof policy ACCEPT DROP "-"
350 iptables ${proto} -t ${table} ":${chain} ${policy} [0:0]"
353 function iptables_LOG
() {
357 case "${FIREWALL_LOG_METHOD}" in
359 ret
="NFLOG --nflog-threshold ${FIREWALL_NFLOG_THRESHOLD}"
360 isset prefix
&& ret
="${ret} --nflog-prefix \"$prefix\""
364 isset prefix
&& ret
="${ret} --log-prefix \"$prefix\""
371 function iptables_protocol
() {
374 for proto
in tcp udp esp ah
; do
375 if [ "$PROTO" = "$proto" ]; then
386 function _iptables_port_range
() {
390 function _iptables_port_multiport
() {
394 function _iptables_port
() {
395 if _iptables_port_range
"$@"; then
396 echo $IPTABLES_PORTRANGE
397 elif _iptables_port_multiport
"$@"; then
398 echo $IPTABLES_MULTIPORT
404 function iptables_source_port
() {
405 [ -z "$@" ] && return
407 type=$
(_iptables_port $@
)
408 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
409 echo "-m multiport --source-ports $@"
415 function iptables_destination_port
() {
416 [ -z "$@" ] && return
418 type=$
(_iptables_port $@
)
419 if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
420 echo "-m multiport --destination-ports $@"