This patch adds code which creates a default set of chains.
No thing will be put into them which makes any sense, but
it's a start...
# List of parameters which are saved in the configuration file.
FIREWALL_CONFIG_PARAMS=""
+# Valid arguments in the rules file.
+FIREWALL_RULES_CONFIG_PARAMS="src dst proto action sport dport in out"
+
# Define the default logging method (nflog or syslog).
FIREWALL_LOG_METHOD="nflog"
FIREWALL_CONFIG_PARAMS="${FIREWALL_CONFIG_PARAMS} FIREWALL_LOG_METHOD"
# Enable clamping MSS for braindead ISPs which filter ICMP packets.
FIREWALL_CLAMP_PATH_MTU="false"
FIREWALL_CONFIG_PARAMS="${FIREWALL_CONFIG_PARAMS} FIREWALL_CLAMP_PATH_MTU"
+
+FIREWALL_SUPPORTED_PROTOCOLS="tcp udp icmp igmp esp ah gre"
+FIREWALL_PROTOCOLS_SUPPORTING_PORTS="tcp udp"
+
+# Firewall zone settings.
+FIREWALL_ZONE_SETTINGS="FRIEND_ZONES MASQUERADE4"
+
+# Default values.
+FIREWALL_ZONE_SETTINGS_MASQUERADE4="false"
firewall_tcp_clamp_mss
# Add policies for every zone.
- policy_add_localhost
+ firewall_localhost_create_chains
local zone
for zone in $(zones_get_all); do
- policy_add_zone ${zone}
+ # Create all needed chains for the zone.
+ firewall_zone_create_chains ${zone}
+
+ # After the chains that are always available have been
+ # created, we will add a custom policy to every single
+ # zone.
+
+ # XXX TODO
+ #policy_zone_add ${zone}
done
# Load the new ruleset.
iptables -A FORWARD -j CONNTRACK
}
-function firewall_import_rules() {
+function firewall_localhost_create_chains() {
+ 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
+}
+
+function firewall_zone_create_chains() {
local zone=${1}
+ 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 "${chain_prefix}_OUTPUT"
+ iptables -A OUTPUT -o ${zone} -j "${chain_prefix}_OUTPUT"
+
+ # Custom rules.
+ iptables_chain_create "${chain_prefix}_CUSTOM"
+
+ # Intrusion Prevention System.
+ iptables_chain_create "${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}
+
+ # Connect the chain with the FORWARD chain.
+ iptables -A FORWARD -i ${zone} -o ${other_zone} \
+ -j "${other_chain_prefix}"
+
+ # Handle custom rules.
+ iptables -A ${other_chain_prefix} -j "${chain_prefix}_CUSTOM"
+
+ # Link IPS.
+ iptables -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"
+
+ # Policy.
+ iptables_chain_create "${other_chain_prefix}_POLICY"
+ iptables -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}
+
+ ## 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"
+
+ # 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}
+
+ # 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"
+
+ # UPnP
+ iptables_chain_create -4 -t nat "${chain_prefix}_UPNP"
+ iptables -4 -t nat -A ${chain_prefix} -j "${chain_prefix}_UPNP"
+
+ return ${EXIT_OK}
+}
+
+function firewall_parse_rules() {
+ local file=${1}
+ assert isset file
shift
- local protocol="ipv6"
- local table="filter"
+ # End if no rule file exists.
+ [ -r "${file}" ] || return ${EXIT_OK}
- while [ $# -gt 0 ]; do
- case "${1}" in
- --table=*)
- table=$(cli_get_val ${1})
- ;;
- --protocol=*)
- protocol=$(cli_get_val ${1})
- ;;
- esac
+ local cmd
+
+ local ${FIREWALL_RULES_CONFIG_PARAMS}
+ local line
+ while read -r line; do
+ # Skip empty lines.
+ [ -n "${line}" ] || continue
+
+ # Skip commented lines.
+ [ "${line:0:1}" = "#" ] && continue
+
+ # Parse the rule.
+ _firewall_parse_rule_line ${line}
+ if [ $? -ne ${EXIT_OK} ]; then
+ log WARNING "Skipping invalid line: ${line}"
+ continue
+ fi
+
+ cmd="iptables $@"
+
+ # Source IP address/net.
+ if isset src; then
+ list_append cmd "-s ${src}"
+ fi
+
+ # Destination IP address/net.
+ if isset dst; then
+ list_append cmd "-d ${dst}"
+ fi
+
+ # Protocol.
+ if isset proto; then
+ list_append cmd "-p ${proto}"
+
+ if list_match ${proto} ${FIREWALL_PROTOCOLS_SUPPORTING_PORTS}; then
+ if isset sport; then
+ list_append cmd "--sport ${sport}"
+ fi
+
+ if isset dport; then
+ list_append cmd "--dport ${dport}"
+ fi
+ fi
+ fi
+
+ # Always append the action.
+ list_append cmd "-j ${action}"
+
+ # Execute command.
+ ${cmd}
+ done < ${file}
+}
+
+function _firewall_parse_rule_line() {
+ local arg
+
+ # Clear all values.
+ for arg in ${FIREWALL_RULES_CONFIG_PARAMS}; do
+ assign "${arg}" ""
done
- assert isoneof protocol ipv4 ipv6
- assert isoneof table $(iptables_table ${protocol})
+ local key val
+ while read -r arg; do
+ key=$(cli_get_key ${arg})
- # XXX TODO
+ if ! listmatch "${key}" ${FIREWALL_RULES_CONFIG_PARAMS}; then
+ log WARNING "Unrecognized argument: ${arg}"
+ return ${EXIT_ERROR}
+ fi
- local src dst proto
- while read src dst proto; do
- case "${chain}" in
- filter)
- ;;
- nat)
- ;;
- esac
- done < ${FIREWALL_CONFIG_RULES}
+ val=$(cli_get_val ${arg})
+ assign "${key}" "${val}"
+ done <<< "$(args $@)"
+
+ # action must always be set.
+ if ! isset action; then
+ log WARNING "'action' is not set: $@"
+ return ${EXIT_ERROR}
+ fi
+
+ for arg in src dst; do
+ isset ${arg} || continue
+
+ # Check for valid IP addresses.
+ if ! ip_is_valid ${!arg}; then
+ log WARNING "Invalid IP address for '${arg}=${!arg}': $@"
+ return ${EXIT_ERROR}
+ fi
+ done
+
+ if isset proto; then
+ # Make lowercase.
+ proto=${proto,,}
+
+ if ! list_match "${proto}" ${FIREWALL_SUPPORTED_PROTOCOLS}; then
+ log WARNING "Unsupported protocol type 'proto=${proto}': $@"
+ return ${EXIT_ERROR}
+ fi
+ fi
+
+ for arg in sport dport; do
+ isset ${arg} || continue
+
+ # Check if port is valid.
+ if ! isinteger ${arg}; then
+ log WARNING "Invalid port '${arg}=${!arg}': $@"
+ return ${EXIT_ERROR}
+ fi
+ done
+
+ return ${EXIT_OK}
}
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
-#
-
-FIREWALL_ZONE_SETTINGS="MASQUERADE POLICY"
function firewall_zone_create() {
local zone=${1}
[ -r "${file}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
}
-function firewall_zone_defaults() {
- local zone=${1}
- assert isset zone
-
- # Default policy.
- POLICY="DROP"
-
- # Don't masquerade by default (IPv4 only).
- MASQUERADE="false"
-}
-
function firewall_zone_read() {
local zone=${1}
assert isset zone
local file=$(firewall_zone_config ${zone})
assert isset file
- # Load default settings.
- firewall_zone_defaults ${zone}
-
config_read ${file} ${FIREWALL_ZONE_SETTINGS}
+
+ local arg default
+ for arg in ${FIREWALL_ZONE_SETTINGS}; do
+ isset ${arg} && continue
+
+ default="FIREWALL_ZONE_SETTINGS_${arg}"
+ assign "${arg}" "${!default}"
+ done
+
return ${EXIT_OK}
}
function firewall_zone_edit() {
local zone=${1}
+ assert isset zone
shift
assert firewall_zone_exists ${zone}
while [ $# -gt 0 ]; do
case "${1}" in
- --masquerade=*)
- MASQUERADE=$(cli_get_val ${1})
+ --masquerade4=*)
+ MASQUERADE4=$(cli_get_val ${1})
;;
--policy=*)
POLICY=$(cli_get_val ${1})
shift
done
+ # Sanetize saved value.
+ if enabled MASQUERADE4; then
+ MASQUERADE4="true"
+ else
+ MASQUERADE4="false"
+ fi
+
# Write updated settings.
firewall_zone_write ${zone}
)
+++ /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_add_zone() {
- local zone=${1}
- assert isset zone
-
- log DEBUG "Creating firewall policy for zone '${zone}'."
-
- local chain="ZONE_${zone}"
- chain=${chain^^}
-
- # Create filter chain.
- iptables_chain_create ${chain}
- iptables -A INPUT -i ${zone} -j ${chain}
- iptables -A FORWARD -i ${zone} -j ${chain}
- iptables -A FORWARD -o ${zone} -j ${chain}
- iptables -A OUTPUT -o ${zone} -j ${chain}
-
- # Leave some space for own rules right at the beginning
- # to make it possible to overwrite _everything_.
- iptables_chain_create ${chain}_CUSTOM
- iptables -A ${chain} -j ${chain}_CUSTOM
-
- # Intrusion Prevention System
- iptables_chain_create ${chain}_IPS
- iptables -A ${chain} -i ${zone} -j ${chain}_IPS
-
- # Rules for incoming packets.
- iptables_chain_create ${chain}_RULES_INC
- iptables -A ${chain} -i ${zone} -j ${chain}_RULES_INC
-
- # Rules for outgoing packets.
- iptables_chain_create ${chain}_RULES_OUT
- iptables -A ${chain} -o ${zone} -j ${chain}_RULES_OUT
-
- # Policy rules
- iptables_chain_create ${chain}_POLICY
- iptables -A ${chain} -j ${chain}_POLICY
-
- # Create mangle chain.
- iptables_chain_create -t mangle ${chain}
- iptables -t mangle -A PREROUTING -i ${zone} -j ${chain}
- iptables -t mangle -A POSTROUTING -o ${zone} -j ${chain}
-
- # Quality of Service
- iptables_chain_create -t mangle ${chain}_QOS_INC
- iptables -t mangle -A ${chain} -i ${zone} -j ${chain}_QOS_INC
- iptables_chain_create -t mangle ${chain}_QOS_OUT
- iptables -t mangle -A ${chain} -o ${zone} -j ${chain}_QOS_OUT
-
- # Create NAT chain.
- iptables_chain_create -4 -t nat ${chain}
- iptables -4 -t nat -A PREROUTING -i ${zone} -j ${chain}
- iptables -4 -t nat -A POSTROUTING -o ${zone} -j ${chain}
-
- # Network Address Translation
- iptables_chain_create -4 -t nat ${chain}_NAT
- iptables -4 -t nat -A ${chain} -i ${zone} -j ${chain}_NAT
-
- # Port forwarding
- iptables_chain_create -4 -t nat ${chain}_PORTFW
- iptables -4 -t nat -A ${chain} -i ${zone} -j ${chain}_PORTFW
-
- # UPNP
- iptables_chain_create -4 -t nat ${chain}_UPNP
- iptables -4 -t nat -A ${chain} -j ${chain}_UPNP
-
- # After the chains that are always available have been
- # created, we will add a custom policy to every single
- # zone.
-
- # Local zones are currently allowed to access everything.
- if zone_is_local ${zone}; then
- policy_allow_all ${zone} ${chain}
-
- # Uplink connections are not.
- else
- : # XXX TODO
- fi
-
- # Import all configured rules and those things.
- policy_import_all_rules ${zone} ${chain}
-}
-
-function policy_add_localhost() {
- log DEBUG "Creating firewall policy for localhost..."
-
- # Accept everything on lo
- iptables -A INPUT -i lo -j ACCEPT
- iptables -A OUTPUT -o lo -j ACCEPT
-}
-
-function policy_allow_all() {
- local zone=${1}
- assert isset zone
-
- local chain=${2}
- assert isset chain
-
- # Just accept everything.
- iptables -A ${chain}_POLICY -j ACCEPT
-}
-
-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
-
- # XXX TODO
-}