-mkdir -pv $(DESTDIR)$(tmpfilesdir)
-mkdir -pv $(DESTDIR)$(datadir)/firewall
- install -m 755 -v firewall $(DESTDIR)$(sbindir)
+ install -m 755 -v firewall6 $(DESTDIR)$(sbindir)
+ install -m 755 -v firewall4 $(DESTDIR)$(sbindir)
install -m 755 -v network $(DESTDIR)$(sbindir)
cp -rfv {hooks,header*,functions*} $(DESTDIR)$(libdir)/network/
--- /dev/null
+#!/bin/bash
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2012 IPFire Network Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+. /usr/lib/network/functions
+
+# Read firewall configuration.
+firewall_config_read "ipv4"
+
+firewall_cli "ipv4" "$@"
+
+exit ${EXIT_ERROR}
--- /dev/null
+#!/bin/bash
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2012 IPFire Network Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+. /usr/lib/network/functions
+
+# Read firewall configuration.
+firewall_config_read "ipv6"
+
+firewall_cli "ipv6" "$@"
+
+exit ${EXIT_ERROR}
for file in /usr/lib/network/functions.*; do
. ${file}
done
-
-# Reading in global configuration files
-config_read_globals
# #
###############################################################################
-. /usr/lib/network/functions
+function firewall_cli() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
-function cli_start() {
- firewall_start $@
-}
+ # Parse the command line
+ while [ $# -gt 0 ]; do
+ case "${1}" in
+ -d|--debug)
+ DEBUG=1
+ log DEBUG "Enabled debugging mode"
+ ;;
+ *)
+ action=${1}
+ ;;
+ esac
+ shift
+ [ -n "${action}" ] && break
+ done
-function cli_stop() {
- firewall_stop
-}
+ # Process the given action
+ case "${action}" in
+ start|restart|reload)
+ firewall_start "${protocol}" "$@"
+ ;;
+
+ stop)
+ firewall_stop "${protocol}" "$@"
+ ;;
+
+ show)
+ firewall_show "${protocol}" "$@"
+ ;;
+
+ panic)
+ firewall_cli_panic "${protocol}" "$@"
+ ;;
+
+ config)
+ firewall_cli_config "${protocol}" $@
+ ;;
+
+ zone)
+ firewall_cli_zone $@
+ ;;
+
+ ""|help|--help|-h)
+ cli_usage root
+ exit ${EXIT_OK}
+ ;;
+
+ *)
+ error "Invalid command given: ${action}"
+ cli_usage usage
+ exit ${EXIT_CONF_ERROR}
+ ;;
+ esac
-function cli_show() {
- firewall_show $@
+ exit ${EXIT_OK}
}
-function cli_panic() {
+function firewall_cli_panic() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
if cli_help_requested $@; then
cli_show_man firewall-panic
exit ${EXIT_OK}
firewall_panic ${admin_hosts}
}
-function cli_config() {
+function firewall_cli_config() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
if cli_help_requested $@; then
cli_usage root-config
exit ${EXIT_OK}
fi
if [ -n "${1}" ]; then
- config_set $@
- firewall_config_write
+ config_set "$@"
+ firewall_config_write "${protocol}"
else
- firewall_config_print
+ firewall_config_print "${protocol}"
fi
}
-function cli_zone() {
+function firewall_cli_zone() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
if cli_help_requested $@; then
cli_show_man firewall-zone
exit ${EXIT_OK}
# Process the given action.
case "${action}" in
edit)
- cli_zone_edit ${zone} $@
+ firewall_cli_zone_edit ${zone} $@
;;
status|"")
- cli_zone_status ${zone} $@
+ firewall_cli_zone_status ${zone} $@
;;
# Print the raw configuration settings.
}
# Show firewall zone conifguration.
-function cli_zone_status() {
+function firewall_cli_zone_status() {
local zone=${1}
assert isset zone
}
# Edit firewall zone configuration.
-function cli_zone_edit() {
- firewall_zone_edit $@
+function firewall_cli_zone_edit() {
+ firewall_zone_edit "$@"
exit ${EXIT_OK}
}
-
-# Parse the command line
-while [ $# -gt 0 ]; do
- case "${1}" in
- -d|--debug)
- DEBUG=1
- log DEBUG "Enabled debugging mode"
- ;;
- *)
- action=${1}
- ;;
- esac
- shift
- [ -n "${action}" ] && break
-done
-
-# Process the given action
-case "${action}" in
- start|restart|reload)
- cli_start $@
- ;;
-
- stop)
- cli_stop $@
- ;;
-
- show)
- cli_show $@
- ;;
-
- panic)
- cli_panic $@
- ;;
-
- config)
- cli_config $@
- ;;
-
- zone)
- cli_zone $@
- ;;
-
- ""|help|--help|-h)
- cli_usage root
- exit ${EXIT_OK}
- ;;
-
- *)
- error "Invalid command given: ${action}"
- cli_usage usage
- exit ${EXIT_CONF_ERROR}
- ;;
-esac
-
-exit ${EXIT_OK}
# #
###############################################################################
-# Load all global configuration files.
-function config_read_globals() {
- network_config_read
- firewall_config_read
-}
-
function config_read() {
local file=${1}
assert isset file
config_print ${NETWORK_CONFIG_FILE_PARAMS}
}
+function firewall_config_file() {
+ local protocol="${1}"
+ assert isset protocol
+
+ local file
+ case "${protocol}" in
+ ipv6)
+ file="${FIREWALL6_CONFIG_FILE}"
+ ;;
+ ipv4)
+ file="${FIREWALL4_CONFIG_FILE}"
+ ;;
+ esac
+ assert isset file
+
+ print "${file}"
+ return ${EXIT_OK}
+}
+
+function firewall_config_env() {
+ local protocol="${1}"
+ assert isset protocol
+
+ case "${protocol}" in
+ ipv6)
+ file="${FIREWALL6_CONFIG_FILE}"
+ params="${FIREWALL6_CONFIG_PARAMS}"
+ ;;
+ ipv4)
+ file="${FIREWALL4_CONFIG_FILE}"
+ params="${FIREWALL4_CONFIG_PARAMS}"
+ ;;
+ esac
+ assert isset file
+ assert isset params
+}
+
function firewall_config_read() {
- config_read ${FIREWALL_CONFIG_FILE} ${FIREWALL_CONFIG_PARAMS}
+ local file params
+ firewall_config_env "$@"
+
+ config_read "${file}" "${params}"
}
function firewall_config_write() {
- config_write ${FIREWALL_CONFIG_FILE} \
- ${FIREWALL_CONFIG_PARAMS}
+ local file params
+ firewall_config_env "$@"
+
+ config_write "${file}" "${params}"
}
function firewall_config_print() {
- config_print ${FIREWALL_CONFIG_PARAMS}
+ local file params
+ firewall_config_env "$@"
+
+ config_print "${params}"
}
FIREWALL_CONFIG_DIR="/etc/firewall"
FIREWALL_ZONES_DIR="${FIREWALL_CONFIG_DIR}/zones"
-FIREWALL_CONFIG_FILE="${FIREWALL_CONFIG_DIR}/config"
+FIREWALL4_CONFIG_FILE="${FIREWALL_CONFIG_DIR}/config4"
+FIREWALL6_CONFIG_FILE="${FIREWALL_CONFIG_DIR}/config6"
FIREWALL_CONFIG_RULES="${FIREWALL_CONFIG_DIR}/rules"
FIREWALL_MACROS_DIRS="${FIREWALL_CONFIG_DIR}/macros"
FIREWALL_CLAMP_PATH_MTU="false"
FIREWALL_CONFIG_PARAMS="${FIREWALL_CONFIG_PARAMS} FIREWALL_CLAMP_PATH_MTU"
+FIREWALL4_CONFIG_PARAMS="${FIREWALL_CONFIG_PARAMS}"
+FIREWALL6_CONFIG_PARAMS="${FIREWALL_CONFIG_PARAMS}"
+
FIREWALL_SUPPORTED_PROTOCOLS="tcp udp icmp igmp esp ah gre"
FIREWALL_PROTOCOLS_SUPPORTING_PORTS="tcp udp"
# High-level function which will create a ruleset for the current firewall
# configuration and load it into the kernel.
function firewall_start() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
# Test mode.
local test="false"
firewall_lock_acquire
# Initialize an empty iptables ruleset.
- iptables_init DROP
+ iptables_init "${protocol}" "DROP"
# Add default chains.
- firewall_tcp_state_flags
- firewall_custom_chains
- firewall_connection_tracking
- firewall_tcp_clamp_mss
+ firewall_tcp_state_flags "${protocol}"
+ firewall_custom_chains "${protocol}"
+ firewall_connection_tracking "${protocol}"
+ firewall_tcp_clamp_mss "${protocol}"
# Add policies for every zone.
- firewall_localhost_create_chains
+ firewall_localhost_create_chains "${protocol}"
local zone
for zone in $(zones_get_all); do
# Create all needed chains for the zone.
- firewall_zone_create_chains ${zone}
+ firewall_zone_create_chains "${protocol}" "${zone}"
# After the chains that are always available have been
# created, we will add a custom policy to every single
# zone.
- policy_zone_add ${zone}
+ policy_zone_add "${protocol}" "${zone}"
done
# Load the new ruleset.
- iptables_load ${test}
+ local args
+ if enabled testmode; then
+ list_append args "--test"
+ fi
+ iptables_commit "${protocol}" ${args}
firewall_lock_release
}
function firewall_stop() {
+ local protocol="${1}"
+ assert isset protocol
+
firewall_lock_acquire
# Initialize an empty firewall ruleset
# with default policy ACCEPT.
- iptables_init ACCEPT
+ iptables_init "${protocol}" ACCEPT
# Load it.
- iptables_load
+ ipables_load "${protocol}"
firewall_lock_release
}
function firewall_show() {
+ local protocol="${1}"
+ assert isset protocol
+
# Shows the ruleset that is currently loaded.
- iptables_status
+ iptables_status "${protocol}"
return ${EXIT_OK}
}
function firewall_panic() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
local admin_hosts="$@"
- firewall_lock_acquire
+ firewall_lock_acquire "${protocol}"
# Drop all communications.
- iptables_init DROP
+ iptables_init "${protocol}" DROP
# If an admin host is provided, some administrative
# things will be allowed from there.
local admin_host
for admin_host in ${admin_hosts}; do
- iptables -A INPUT -s ${admin_host} -j ACCEPT
- iptables -A OUTPUT -d ${admin_host} -j ACCEPT
+ iptables "${protocol}" -A INPUT -s "${admin_host}" -j ACCEPT
+ iptables "${protocol}" -A OUTPUT -d "${admin_host}" -j ACCEPT
done
# Load it.
- iptables_load
+ iptables_commit "${protocol}"
firewall_lock_release
}
}
function firewall_custom_chains() {
+ local protocol="${1}"
+ assert isset protocol
+
log INFO "Creating CUSTOM* chains..."
# These chains are intened to be filled with
# rules by the user. They are processed at the very
# beginning so it is possible to overwrite everything.
- iptables_chain_create CUSTOMINPUT
- iptables -A INPUT -j CUSTOMINPUT
+ iptables_chain_create "${protocol}" CUSTOMINPUT
+ iptables "${protocol}" -A INPUT -j CUSTOMINPUT
- iptables_chain_create CUSTOMFORWARD
- iptables -A FORWARD -j CUSTOMFORWARD
+ iptables_chain_create "${protocol}" CUSTOMFORWARD
+ iptables "${protocol}" -A FORWARD -j CUSTOMFORWARD
- iptables_chain_create CUSTOMOUTPUT
- iptables -A OUTPUT -j CUSTOMOUTPUT
+ iptables_chain_create "${protocol}" CUSTOMOUTPUT
+ iptables "${protocol}" -A OUTPUT -j CUSTOMOUTPUT
- iptables_chain_create -4 -t nat CUSTOMPREROUTING
- iptables -4 -t nat -A PREROUTING -j CUSTOMPREROUTING
+ iptables_chain_create "${protocol}" -t nat CUSTOMPREROUTING
+ iptables "${protocol}" -t nat -A PREROUTING -j CUSTOMPREROUTING
- iptables_chain_create -4 -t nat CUSTOMPOSTROUTING
- iptables -4 -t nat -A POSTROUTING -j CUSTOMPOSTROUTING
+ iptables_chain_create "${protocol}" -t nat CUSTOMPOSTROUTING
+ iptables "${protocol}" -t nat -A POSTROUTING -j CUSTOMPOSTROUTING
- iptables_chain_create -4 -t nat CUSTOMOUTPUT
- iptables -4 -t nat -A OUTPUT -j CUSTOMOUTPUT
+ iptables_chain_create "${protocol}" -t nat CUSTOMOUTPUT
+ iptables "${protocol}" -t nat -A OUTPUT -j CUSTOMOUTPUT
}
function firewall_tcp_state_flags() {
+ local protocol="${1}"
+ assert isset protocol
+
log INFO "Creating TCP State Flags chain..."
- iptables_chain_create BADTCP_LOG
- iptables -A BADTCP_LOG -p tcp -j $(iptables_LOG "Illegal TCP state: ")
- iptables -A BADTCP_LOG -j DROP
-
- iptables_chain_create BADTCP
- iptables -A BADTCP -p tcp --tcp-flags ALL NONE -j BADTCP_LOG
- iptables -A BADTCP -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADTCP_LOG
- iptables -A BADTCP -p tcp --tcp-flags SYN,RST SYN,RST -j BADTCP_LOG
- iptables -A BADTCP -p tcp --tcp-flags FIN,RST FIN,RST -j BADTCP_LOG
- iptables -A BADTCP -p tcp --tcp-flags ACK,FIN FIN -j BADTCP_LOG
- iptables -A BADTCP -p tcp --tcp-flags ACK,PSH PSH -j BADTCP_LOG
- iptables -A BADTCP -p tcp --tcp-flags ACK,URG URG -j BADTCP_LOG
-
- iptables -A INPUT -p tcp -j BADTCP
- iptables -A OUTPUT -p tcp -j BADTCP
- iptables -A FORWARD -p tcp -j BADTCP
+
+ iptables_chain_create "${protocol}" BADTCP_LOG
+ iptables "${protocol}" -A BADTCP_LOG -p tcp -j "$(iptables_LOG "Illegal TCP state: ")"
+ iptables "${protocol}" -A BADTCP_LOG -j DROP
+
+ iptables_chain_create "${protocol}" BADTCP
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags ALL NONE -j BADTCP_LOG
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADTCP_LOG
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags SYN,RST SYN,RST -j BADTCP_LOG
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags FIN,RST FIN,RST -j BADTCP_LOG
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags ACK,FIN FIN -j BADTCP_LOG
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags ACK,PSH PSH -j BADTCP_LOG
+ iptables "${protocol}" -A BADTCP -p tcp --tcp-flags ACK,URG URG -j BADTCP_LOG
+
+ iptables "${protocol}" -A INPUT -p tcp -j BADTCP
+ iptables "${protocol}" -A OUTPUT -p tcp -j BADTCP
+ iptables "${protocol}" -A FORWARD -p tcp -j BADTCP
}
function firewall_tcp_clamp_mss() {
# Do nothing if this has been disabled.
enabled FIREWALL_CLAMP_PATH_MTU || return ${EXIT_OK}
+ local protocol="${1}"
+ assert isset protocol
+
log DEBUG "Adding rules to clamp MSS to path MTU..."
- iptables -t mangle -A FORWARD \
+
+ iptables "${protocol}" -t mangle -A FORWARD \
-p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
}
function firewall_connection_tracking() {
+ local protocol="${1}"
+ assert isset protocol
+
log INFO "Creating Connection Tracking chain..."
- iptables_chain_create CONNTRACK
- iptables -A CONNTRACK -m state --state ESTABLISHED,RELATED -j ACCEPT
- iptables -A CONNTRACK -m state --state INVALID -j $(iptables_LOG "INVALID packet: ")
- iptables -A CONNTRACK -m state --state INVALID -j DROP
-
- iptables -A INPUT -j CONNTRACK
- iptables -A OUTPUT -j CONNTRACK
- iptables -A FORWARD -j CONNTRACK
+
+ iptables_chain_create "${protocol}" CONNTRACK
+ iptables "${protocol}" -A CONNTRACK -m state --state ESTABLISHED,RELATED -j ACCEPT
+ iptables "${protocol}" -A CONNTRACK -m state --state INVALID -j "$(iptables_LOG "INVALID packet: ")"
+ iptables "${protocol}" -A CONNTRACK -m state --state INVALID -j DROP
+
+ iptables "${protocol}" -A INPUT -j CONNTRACK
+ iptables "${protocol}" -A OUTPUT -j CONNTRACK
+ iptables "${protocol}" -A FORWARD -j CONNTRACK
}
function firewall_localhost_create_chains() {
+ local protocol="${1}"
+ assert isset protocol
+
log DEBUG "Creating firewall chains for localhost..."
# Accept everything on lo
- iptables -A INPUT -i lo -m state --state NEW -j ACCEPT
- iptables -A OUTPUT -o lo -m state --state NEW -j ACCEPT
+ iptables "${protocol}" -A INPUT -i lo -m state --state NEW -j ACCEPT
+ iptables "${protocol}" -A OUTPUT -o lo -m state --state NEW -j ACCEPT
}
function firewall_zone_create_chains() {
- local zone=${1}
+ local protocol="${1}"
+ assert isset protocol
+
+ local zone="${2}"
assert isset zone
log DEBUG "Creating firewall chains for zone '${zone}'."
local chain_prefix="ZONE_${zone^^}"
# Create filter chains.
- iptables_chain_create "${chain_prefix}_INPUT"
- iptables -A INPUT -i ${zone} -j "${chain_prefix}_INPUT"
+ iptables_chain_create "${protocol}" "${chain_prefix}_INPUT"
+ iptables "${protocol}" -A INPUT -i ${zone} -j "${chain_prefix}_INPUT"
- iptables_chain_create "${chain_prefix}_OUTPUT"
- iptables -A OUTPUT -o ${zone} -j "${chain_prefix}_OUTPUT"
+ iptables_chain_create "${protocol}" "${chain_prefix}_OUTPUT"
+ iptables "${protocol}" -A OUTPUT -o ${zone} -j "${chain_prefix}_OUTPUT"
# Custom rules.
- iptables_chain_create "${chain_prefix}_CUSTOM"
+ iptables_chain_create "${protocol}" "${chain_prefix}_CUSTOM"
# Intrusion Prevention System.
- iptables_chain_create "${chain_prefix}_IPS"
+ iptables_chain_create "${protocol}" "${chain_prefix}_IPS"
# Create a chain for each other zone.
# This leaves us with n^2 chains. Duh.
local other_zone other_chain_prefix
for other_zone in $(zones_get_all); do
other_chain_prefix="${chain_prefix}_${other_zone^^}"
- iptables_chain_create ${other_chain_prefix}
+ iptables_chain_create "${protocol}" "${other_chain_prefix}"
# Connect the chain with the FORWARD chain.
- iptables -A FORWARD -i ${zone} -o ${other_zone} \
+ iptables "${protocol}" -A FORWARD -i "${zone}" -o "${other_zone}" \
-j "${other_chain_prefix}"
# Handle custom rules.
- iptables -A ${other_chain_prefix} -j "${chain_prefix}_CUSTOM"
+ iptables "${protocol}" -A "${other_chain_prefix}" -j "${chain_prefix}_CUSTOM"
# Link IPS.
- iptables -A ${other_chain_prefix} -j "${chain_prefix}_IPS"
+ iptables "${protocol}" -A "${other_chain_prefix}" -j "${chain_prefix}_IPS"
# Rules.
- iptables_chain_create "${other_chain_prefix}_RULES"
- iptables -A ${other_chain_prefix} -j "${other_chain_prefix}_RULES"
+ iptables_chain_create "${protocol}" "${other_chain_prefix}_RULES"
+ iptables "${protocol}" -A "${other_chain_prefix}" -j "${other_chain_prefix}_RULES"
# Policy.
- iptables_chain_create "${other_chain_prefix}_POLICY"
- iptables -A ${other_chain_prefix} -j "${other_chain_prefix}_POLICY"
+ iptables_chain_create "${protocol}" "${other_chain_prefix}_POLICY"
+ iptables "${protocol}" -A "${other_chain_prefix}" -j "${other_chain_prefix}_POLICY"
done
## Create mangle chain.
- #iptables_chain_create -t mangle ${chain_prefix}
- #iptables -t mangle -A PREROUTING -i ${zone} -j ${chain_prefix}
- #iptables -t mangle -A POSTROUTING -o ${zone} -j ${chain_prefix}
+ #iptables_chain_create "${protocol}" -t mangle "${chain_prefix}"
+ #iptables "${protocol}" -t mangle -A PREROUTING -i "${zone}" -j "${chain_prefix}"
+ #iptables "${protocol}" -t mangle -A POSTROUTING -o "${zone}" -j "${chain_prefix}"
## Quality of Service
- #iptables_chain_create -t mangle "${chain_prefix}_QOS_INC"
- #iptables -t mangle -A ${chain_prefix} -i ${zone} -j "${chain_prefix}_QOS_INC"
- #iptables_chain_create -t mangle "${chain_prefix}_QOS_OUT"
- #iptables -t mangle -A ${chain_prefix} -o ${zone} -j "${chain_prefix}_QOS_OUT"
+ #iptables_chain_create "${protocol}" -t mangle "${chain_prefix}_QOS_INC"
+ #iptables "${protocol}" -t mangle -A "${chain_prefix}" -i "${zone}" -j "${chain_prefix}_QOS_INC"
+ #iptables_chain_create "${protocol}" -t mangle "${chain_prefix}_QOS_OUT"
+ #iptables "${protocol}" -t mangle -A "${chain_prefix}" -o "${zone}" -j "${chain_prefix}_QOS_OUT"
# Create NAT chain.
- iptables_chain_create -4 -t nat ${chain_prefix}
- iptables -4 -t nat -A PREROUTING -i ${zone} -j ${chain_prefix}
- iptables -4 -t nat -A POSTROUTING -o ${zone} -j ${chain_prefix}
+ iptables_chain_create "${protocol}" -t nat "${chain_prefix}"
+ iptables "${protocol}" -t nat -A PREROUTING -i "${zone}" -j "${chain_prefix}"
+ iptables "${protocol}" -t nat -A POSTROUTING -o "${zone}" -j "${chain_prefix}"
# Network Address Translation
- iptables_chain_create -4 -t nat "${chain_prefix}_DNAT"
- iptables -4 -t nat -A PREROUTING -i ${zone} -j "${chain_prefix}_DNAT"
- iptables_chain_create -4 -t nat "${chain_prefix}_SNAT"
- iptables -4 -t nat -A POSTROUTING -o ${zone} -j "${chain_prefix}_SNAT"
+ iptables_chain_create "${protocol}" -t nat "${chain_prefix}_DNAT"
+ iptables "${protocol}" -t nat -A PREROUTING -i "${zone}" -j "${chain_prefix}_DNAT"
+ iptables_chain_create "${protocol}" -t nat "${chain_prefix}_SNAT"
+ iptables "${protocol}" -t nat -A POSTROUTING -o "${zone}" -j "${chain_prefix}_SNAT"
# UPnP
- iptables_chain_create -4 -t nat "${chain_prefix}_UPNP"
- iptables -4 -t nat -A ${chain_prefix} -j "${chain_prefix}_UPNP"
+ iptables_chain_create "${protocol}" -t nat "${chain_prefix}_UPNP"
+ iptables "${protocol}" -t nat -A "${chain_prefix}" -j "${chain_prefix}_UPNP"
return ${EXIT_OK}
}
--- /dev/null
+#!/bin/bash
+###############################################################################
+# #
+# IPFire.org - A linux based firewall #
+# Copyright (C) 2012 IPFire Network Development Team #
+# #
+# This program is free software: you can redistribute it and/or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation, either version 3 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+function policy_zone_add() {
+ local zone=${1}
+ assert isset zone
+
+ local ${FIREWALL_ZONE_SETTINGS}
+ firewall_zone_read ${zone}
+
+ # Apply masquerading.
+ if enabled MASQUERADE4; then
+ policy_zone_masquerade4 ${zone}
+ fi
+
+ # Allow/deny cross-zone communication.
+ local other_zone
+ for other_zone in $(zones_get_all); do
+ if list_match "${other_zone}" ${FRIEND_ZONES}; then
+ policy_zone_allow_all ${zone} ${other_zone}
+ else
+ policy_zone_deny_all ${zone} ${other_zone}
+ fi
+ done
+}
+
+function policy_zone_masquerade4() {
+ local zone=${1}
+ assert isset zone
+
+ local chain="ZONE_${zone^^}_SNAT"
+
+ iptables -4 -t nat -A "${chain}" -o ${zone} \
+ -j MASQUERADE --random
+}
+
+function policy_zone_allow_all() {
+ local zone=${1}
+ assert isset zone
+
+ local other_zone=${2}
+ assert isset other_zone
+
+ local chain="ZONE_${zone^^}_${other_zone^^}_POLICY"
+
+ # Just accept all new connections.
+ iptables -A "${chain}" -m state --state NEW -j ACCEPT
+}
+
+function policy_zone_deny_all() {
+ local zone=${1}
+ assert isset zone
+
+ local other_zone=${2}
+ assert isset other_zone
+
+ local chain="ZONE_${zone^^}_${other_zone^^}_POLICY"
+
+ # Just accept all new connections.
+ iptables -A "${chain}" -j DROP
+}
+
+function policy_drop_all() {
+ # Nothing to do here, because that is the
+ # default policy of the INPUT/OUTPUT/FORWARD chain.
+ :
+}
+
+function policy_import_all_rules() {
+ # This will populate all chains with the rules
+ # for the given zone.
+
+ local zone=${1}
+ assert isset zone
+
+ local chain=${2}
+ assert isset chain
+
+ local zone_dir=$(firewall_zone_dir ${zone})
+ assert isset zone_dir
+
+ local rulesfile="${zone_dir}/rules"
+
+ #firewall_parse_rules "${rulesfile}" \
+ # -A ${chain}_RULES_INC
+}
+
+function policy_load() {
+ local zone_from=${1}
+ assert isset zone_from
+
+ local zone_to=${2}
+ assert isset zone_to
+
+ local chain=${3}
+ assert isset chain
+
+ # Allow routes that have the same incoming and outgoing interface.
+ if [ "${zone_from}" = "${zone_to}" ]; then
+ iptables -A ${chain} -j ACCEPT
+ return ${EXIT_OK}
+ fi
+
+ # Grant all local zones accessing everything (GREEN).
+ if zone_is_local ${zone_from}; then
+ iptables -A ${chain} -j ACCEPT
+ return ${EXIT_OK}
+ fi
+}
###############################################################################
# #
# IPFire.org - A linux based firewall #
-# Copyright (C) 2012 IPFire Network Development Team #
+# Copyright (C) 2012-2013 IPFire Network Development Team #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# #
###############################################################################
+IPTABLES_TABLES="filter mangle nat"
+
function iptables() {
- local arg
- local args
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
+ # Rules go to the filter table by default
local table="filter"
- local src dst
- # Default is both protocols.
- local proto="6 4"
+ # Argument list
+ local args
- # Check if the directory where we put our rules in is set and
- # exists.
- assert isset IPTABLES_TMPDIR
- assert [ -d "${IPTABLES_TMPDIR}" ]
+ # Cached arguments
+ local src dst
# Parsing arguments
while [ $# -gt 0 ]; do
case "${1}" in
- # Select IPv4 protocol.
- -4)
- proto="4"
- shift
- ;;
- # Select IPv6 protocol.
- -6)
- proto="6"
- shift
- ;;
+ # Filter to which table this rule should go.
-t)
- table=${2}
- shift 2
- ;;
- -A)
- args="${args} -A ${2^^}"
+ table="${2}"
shift 2
+
+ assert isoneof table ${IPTABLES_TABLES}
;;
*)
- args="${args} ${1}"
+ list_append args "${1}"
# Save some values for further processing.
case "${1}" in
esac
done
- # Check that the nat table is not used for IPv6.
- if isoneof 6 ${proto}; then
- assert [ "${table}" != "nat" ]
- fi
+ assert isset action
- # Detect the version of the IP protocol.
+ # Check if given IP addresses or networks match the protocol version.
local src_proto
- isset src && src_proto=$(ip_detect_protocol ${src})
+ if isset src; then
+ src_proto="$(ip_detect_protocol ${src})"
+
+ assert [ "${protocol}" = "${src_proto}" ]
+ fi
local dst_proto
- isset dst && dst_proto=$(ip_detect_protocol ${dst})
+ if isset dst; then
+ dst_proto="$(ip_detect_protocol ${dst})"
- # Check that the source and destinations are not
- # using different versions of the IP protocol.
- if isset src_proto && isset dst_proto; then
- assert [ "${src_proto}" = "${dst_proto}" ]
+ assert [ "${protocol}" = "${dst_proto}" ]
fi
- local rulesfile
- local p
- for p in ${proto}; do
- case "${p}" in
- 6)
- listmatch ipv4 ${src_proto} ${dst_proto} \
- && continue
+ # Check if the directory where we put our rules in is set and
+ # exists.
+ assert isset IPTABLES_TMPDIR
+ local rulesfile="${IPTABLES_TMPDIR}/${protocol}-${table}"
+
+ print "${args}" >> "${rulesfile}"
+ assert_check_retval $?
+}
+
+function iptables_chain_create() {
+ local protocol="${1}"
+ assert isset protocol
+ shift
+
+ local chain
+ local table="filter"
+ local policy="-"
+
+ while [ $# -gt 0 ]; do
+ case "${1}" in
+ -t)
+ table="${2}"
+ shift
;;
- 4)
- listmatch ipv6 ${src_proto} ${dst_proto} \
- && continue
+ --policy=*)
+ policy="$(cli_get_val ${1})"
+ ;;
+ -*)
+ log WARNING "Unrecognized argument: ${1}"
+ ;;
+ *)
+ chain=${1}
;;
esac
+ shift
+ done
- rulesfile=$(iptables_rulesfile ipv${p} ${table})
- assert isset rulesfile
+ assert isset chain
+ assert isset table
+ assert isoneof policy ACCEPT DROP "-"
- print "${args:1:${#args}}" >> ${rulesfile}
- done
+ iptables "${protocol}" -t "${table}" ":${chain} ${policy} [0:0]"
}
# Calls the binary iptables command.
function _iptables() {
- local iptables_cmd=$(which iptables)
- assert isset iptables_cmd
-
- cmd ${iptables_cmd} $@
-}
-
-function iptables_status() {
- _iptables -L -n -v
-}
-
-# Returns which tables exist for the given protocol.
-function iptables_tables() {
- local proto=${1}
- assert isset proto
+ local protocol="${1}"
+ assert isset protocol
+ shift
- case "${proto}" in
+ local cmd
+ case "${protocol}" in
ipv6)
- print "filter mangle"
+ cmd="ip6tables"
;;
ipv4)
- print "filter mangle nat"
- ;;
- *)
- return ${EXIT_ERROR}
+ cmd="iptables"
;;
esac
+ assert isset cmd
+ cmd="$(which ${cmd})"
+
+ cmd "${cmd}" "$@"
+ return $?
+}
+
+function iptables_status() {
+ local protocol="${1}"
+ assert isset protocol
+
+ local table
+ for table in ${IPTABLES_TABLES}; do
+ print "${protocol} - ${table}:"
+ _iptables "${protocol}" -t "${table}" -L -n -v
+ print
+ done
return ${EXIT_OK}
}
}
function iptables_init() {
- local policy=${1}
+ local protocol="${1}"
+ assert isset protocol
+
+ local policy="${2}"
assert isset policy
# Create filter table and initialize chains.
- iptables "* filter"
- iptables_chain_create -t filter INPUT --policy=${policy}
- iptables_chain_create -t filter OUTPUT --policy=${policy}
- iptables_chain_create -t filter FORWARD --policy=${policy}
-
- # Create mangle table initialize chains.
- iptables -t mangle "* mangle"
- iptables_chain_create -t mangle PREROUTING --policy=ACCEPT
- iptables_chain_create -t mangle INPUT --policy=ACCEPT
- iptables_chain_create -t mangle OUTPUT --policy=ACCEPT
- iptables_chain_create -t mangle FORWARD --policy=ACCEPT
- iptables_chain_create -t mangle POSTROUTING --policy=ACCEPT
-
- # Add NAT table for IPv4.
- iptables -4 -t nat "* nat"
- iptables_chain_create -4 -t nat PREROUTING --policy=ACCEPT
- iptables_chain_create -4 -t nat OUTPUT --policy=ACCEPT
- iptables_chain_create -4 -t nat POSTROUTING --policy=ACCEPT
+ iptables "${protocol}" "* filter"
+ iptables_chain_create "${protocol}" -t filter INPUT --policy="${policy}"
+ iptables_chain_create "${protocol}" -t filter OUTPUT --policy="${policy}"
+ iptables_chain_create "${protocol}" -t filter FORWARD --policy="${policy}"
+
+ # Create mangle table and initialize chains.
+ iptables "${protocol}" -t mangle "* mangle"
+ iptables_chain_create "${protocol}" -t mangle PREROUTING --policy="ACCEPT"
+ iptables_chain_create "${protocol}" -t mangle INPUT --policy="ACCEPT"
+ iptables_chain_create "${protocol}" -t mangle OUTPUT --policy="ACCEPT"
+ iptables_chain_create "${protocol}" -t mangle FORWARD --policy="ACCEPT"
+ iptables_chain_create "${protocol}" -t mangle POSTROUTING --policy="ACCEPT"
+
+ # Create NAT table and initialize chains.
+ iptables "${protocol}" -t nat "* nat"
+ iptables_chain_create "${protocol}" -t nat PREROUTING --policy="ACCEPT"
+ iptables_chain_create "${protocol}" -t nat OUTPUT --policy="ACCEPT"
+ iptables_chain_create "${protocol}" -t nat POSTROUTING --policy="ACCEPT"
}
# Load the created ruleset into the kernel.
-function iptables_load() {
- # If first argument is present and true, we
- # run in test mode.
- local test="${1}"
-
- local rulesfile
+function iptables_commit () {
+ local protocol="${1}"
+ assert isset protocol
+ shift
- # Concat the table rulesets into one big file.
- local proto
- for proto in 6 4; do
- rulesfile=$(iptables_rulesfile ipv${proto})
- assert isset rulesfile
+ local testmode="false"
- local table
- local tablefile
- for table in $(iptables_tables ipv${proto}); do
- tablefile=$(iptables_rulesfile ipv${proto} ${table})
+ while [ $# -gt 0 ]; do
+ case "${1}" in
+ --test)
+ testmode="true"
+ ;;
+ *)
+ log WARNING "Unrecognized argument: ${1}"
+ ;;
+ esac
+ shift
+ done
- fread ${tablefile}
+ # Concat all rules into one big file.
+ local rulesfile="${IPTABLES_TMPDIR}/ruleset"
+ _iptables_commit_cat_rulesfile "${protocol}" "${rulesfile}"
+
+ # Run the following loop twice:
+ # 1st: Check if the ruleset can be loaded
+ # 2nd: If not in test mode, actually load the ruleset into the kernel
+ local load_cmd="--test"
+ local ret=0
+
+ local i
+ for i in 0 1; do
+ _iptables_commit_load_rulesfile "${protocol}" "${rulesfile}" "${load_cmd}"
+ ret=$?
+
+ case "${i},${ret}" in
+ 0,${EXIT_OK})
+ iptables_dump "${protocol}" "${rulesfile}" --log-facility="DEBUG"
+ log DEBUG "Ruleset load check succeeded (${protocol})"
+ ;;
- # Add the COMMIT statement for every table.
- if [ -s "${tablefile}" ]; then
- print "COMMIT"
- fi
- done > ${rulesfile}
+ # Loading rules has failed (test)
+ 0,*)
+ iptables_dump "${protocol}" "${rulesfile}" --log-facility="CRITICAL"
+ log CRITICAL "Ruleset load check failed (${protocol} - ${ret})"
+ return ${ret}
+ ;;
- assert [ -s "${rulesfile}" ]
- done
+ 1,${EXIT_OK})
+ log DEBUG "Ruleset successfully loaded (${protocol})"
+ return ${EXIT_OK}
+ ;;
- local error="false"
- local ret
+ 1,*)
+ log CRITICAL "Ruleset loading failed (${protocol})"
+ return ${ret}
+ ;;
+ esac
- # First check if everything is correctly formatted.
- for proto in 6 4; do
- rulesfile=$(iptables_rulesfile ipv${proto})
- assert isset rulesfile
+ # Skip the second loop iteration, if we are running in test mode.
+ enabled testmode && break
- _iptables_load ipv${proto} ${rulesfile} true
- if [ $? -ne ${EXIT_OK} ]; then
- log CRITICAL "Ruleset load check failed for IPv${proto}"
- error="true"
- fi
+ load_cmd=""
done
- # Check if there has been an error in the load check.
- if enabled error; then
- iptables_dump CRITICAL
+ return ${EXIT_OK}
+}
- log CRITICAL "New firewall rules could not be loaded."
- return ${EXIT_ERROR}
- fi
+function _iptables_commit_cat_rulesfile() {
+ local protocol="${1}"
+ assert isset protocol
- # Dump the data, we are going to load.
- iptables_dump
+ local rulesfile="${2}"
+ assert isset rulesfile
- # If we are running in test mode, we are done here.
- enabled test && return ${EXIT_OK}
+ local table
+ local file
+ for table in ${IPTABLES_TABLES}; do
+ file="${IPTABLES_TMPDIR}/${protocol}-${table}"
- # If we got until here, everything is fine to load the ruleset.
- for proto in 6 4; do
- rulesfile=$(iptables_rulesfile ipv${proto})
+ fread "${file}"
- _iptables_load ipv${proto} ${rulesfile}
- done
- return ${EXIT_OK}
+ # Add the COMMIT statement for every table.
+ print "COMMIT"
+ done > "${rulesfile}"
+
+ assert [ -s "${rulesfile}" ]
}
-function _iptables_load() {
- local proto=${1}
- local file=${2}
- local testmode=${3}
+function _iptables_commit_load_rulesfile() {
+ local protocol="${1}"
+ assert isset protocol
+
+ local rulesfile="${2}"
+ assert isset rulesfile
+ shift 2
+
+ local testmode="false"
+ while [ $# -gt 0 ]; do
+ case "${1}" in
+ --test)
+ testmode="true"
+ ;;
+ esac
+ shift
+ done
- local command
- case "${proto}" in
+ local iptables_cmd
+ case "${protocol}" in
ipv6)
- command="ip6tables-restore"
+ iptables_cmd="ip6tables-restore"
;;
ipv4)
- command="iptables-restore"
+ iptables_cmd="iptables-restore"
;;
esac
- assert isset command
+ assert isset iptables_cmd
if enabled testmode; then
- command="${command} --test"
+ list_append iptables_cmd "--test"
fi
- local time_started=$(date -u "+%s")
+ # Save when importing the rules has started.
+ local time_started="$(timestamp)"
- cmd ${command} < ${file}
+ cmd "${iptables_cmd}" < "${rulesfile}"
local ret=$?
case "${ret}" in
${EXIT_OK})
- local time_finished=$(date -u "+%s")
- time_finished=$(( ${time_finished} - ${time_started} ))
- log INFO \
- "Successfully loaded new firewall ruleset for IPv${proto/ipv/} in ${time_finished}s!"
+ local time_finished="$(timestamp)"
+ time_finished="$(( ${time_finished} - ${time_started} ))"
+
+ enabled testmode && return ${EXIT_OK}
+
+ log INFO "Successfully loaded new firewall ruleset for ${protocol} in ${time_finished}s!"
;;
*)
if ! enabled testmode; then
- log CRITICAL "Error loading firewall ruleset for IPv${proto/ipv/}!"
+ log CRITICAL "Error loading firewall ruleset for ${protocol}!"
fi
;;
esac
}
function iptables_dump() {
- local log_facility=${1-DEBUG}
+ local protocol="${1}"
+ assert isset protocol
- # Here is nothing to do, if we are not running in
- # debug mode.
- enabled DEBUG || return ${EXIT_OK}
+ local rulesfile="${2}"
+ assert isset rulesfile
+ shift 2
- local rulesfile
- local counter
- local line
+ local log_facility="INFO"
- local proto
- for proto in 6 4; do
- rulesfile=$(iptables_rulesfile ipv${proto})
- [ -e "${rulesfile}" ] || continue
-
- log ${log_facility} "Firewall ruleset for IPv${proto}:"
-
- counter=1
- while read -r line; do
- printf -v line "%4d | %s" "${counter}" "${line}"
- log ${log_facility} "${line}"
-
- counter=$(( $counter + 1 ))
- done < ${rulesfile}
- done
-}
-
-function iptables_chain_create() {
- local chain
- local table="filter"
- local policy="-"
- local proto
- local args
while [ $# -gt 0 ]; do
case "${1}" in
- -6|-4)
- proto=${1}
- ;;
- -t)
- table=${2}
- shift
- ;;
- --policy=*)
- policy=$(cli_get_val ${1})
+ --log-facility=*)
+ log_facility="$(cli_get_val ${1})"
;;
*)
- chain=${1}
+ log WARNING "Unrecognized argument: ${1}"
;;
esac
shift
done
- assert isset chain
- assert isset table
- assert isoneof policy ACCEPT DROP "-"
+ # Say what we are going to do:
+ log "${log_facility}" "Firewall ruleset for ${protocol}:"
+
+ local counter="0"
+ local line
+ while read -r line; do
+ counter="$(( ${counter} + 1 ))"
- iptables ${proto} -t ${table} ":${chain} ${policy} [0:0]"
+ printf -v line "%4d | %s" "${counter}" "${line}"
+ log "${log_facility}" "${line}"
+ done < "${rulesfile}"
}
function iptables_LOG() {
print "\"%s\"" "$@"
}
+function strip() {
+ local value="$@"
+
+ # remove leading whitespace characters
+ value="${value#"${value%%[![:space:]]*}"}"
+
+ # remove trailing whitespace characters
+ value="${value%"${value##*[![:space:]]}"}"
+
+ print "${value}"
+}
+
# Print a pretty error message
function error() {
echo -e " ${CLR_RED_B}ERROR${CLR_RESET} : $@" >&2
type -P $@
}
+# Prints the number of seconds since epoch.
+function timestamp() {
+ date -u "+%s"
+}
+
function beautify_time() {
local value=${1}
. /usr/lib/network/functions
+# Read network configuration.
+network_config_read
+
function cli_config() {
if cli_help_requested $@; then
cli_show_man network-config