This creates a basic firewall for IPv4.
-mkdir -pv $(DESTDIR)$(systemdunitdir)
-mkdir -pv $(DESTDIR)$(tmpfilesdir)
+ install -m 755 -v firewall $(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
+
+function cli_start() {
+ firewall_start
+}
+
+function cli_stop() {
+ firewall_stop
+}
+
+# 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 $@
+ ;;
+
+ ""|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}
PORT_PATTERN="pN"
PORT_PATTERN_ACCESSPOINT="apN"
PORT_PATTERN_WIRELESS="wN"
+
+# This variable is used to point to a directory
+# in which the iptables ruleset will be generated.
+IPTABLES_TMPDIR=
+
+FIREWALL_LOG_FACILITY="syslog"
# At a later point of time, we need to find another solution how to
# react on those events.
#initctl emit ${event} $@
+
+ case "${event}" in
+ firewall-reload)
+ # Try to reload the firewall service.
+ __event_firewall_reload
+ ;;
+ esac
}
-function event_firewall_reload() {
- event_emit firewall-reload
+function __event_firewall_reload() {
+ local service="firewall"
+
+ # Reload the firewall service when it has
+ # been started earlier.
+ if service_is_running ${service}; then
+ service_restart ${service}
+ fi
}
function event_interface_up() {
--- /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/>. #
+# #
+###############################################################################
+
+# High-level function which will create a ruleset for the current firewall
+# configuration and load it into the kernel.
+function firewall_start() {
+ firewall_lock_acquire
+
+ # Initialize an empty iptables ruleset.
+ iptables_init DROP
+
+ # Add default chains.
+ firewall_tcp_state_flags
+ firewall_connection_tracking
+
+ # Add policies for every zone.
+ policy_add_localhost
+
+ local zone
+ for zone in $(zones_get_all); do
+ policy_add_zone ${zone}
+ done
+
+ # Commit the new ruleset.
+ iptables_commit
+
+ firewall_lock_release
+}
+
+function firewall_stop() {
+ firewall_lock_acquire
+
+ # Initialize an empty firewall ruleset
+ # with default policy ACCEPT.
+ iptables_init ACCEPT
+
+ # Commit it.
+ iptables_commit
+
+ firewall_lock_release
+}
+
+function firewall_lock_acquire() {
+ lock_acquire ${RUN_DIR}/.firewall_lock
+
+ # Make sure the lock is released after the firewall
+ # script has crashed or exited early.
+ trap firewall_lock_release EXIT TERM KILL
+
+ # Create a directory where we can put our
+ # temporary data in the most secure way as possible.
+ IPTABLES_TMPDIR=$(mktemp -d)
+}
+
+function firewall_lock_release() {
+ if isset IPTABLES_TMPDIR; then
+ # Remove all temporary data.
+ rm -rf ${IPTABLES_TMPDIR}
+
+ # Reset the tempdir variable.
+ IPTABLES_TMPDIR=
+ fi
+
+ # Reset the trap.
+ trap true EXIT TERM KILL
+
+ lock_release ${RUN_DIR}/.firewall_lock
+}
+
+function firewall_tcp_state_flags() {
+ 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
+}
+
+function firewall_connection_tracking() {
+ 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
+}
--- /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 iptables() {
+ local arg
+ local args
+ local table
+
+ # Check if the directory where we put our rules in is set and
+ # exists.
+ assert isset IPTABLES_TMPDIR
+ assert [ -d "${IPTABLES_TMPDIR}" ]
+
+ table=filter
+
+ # Parsing arguments
+ while [ $# -gt 0 ]; do
+ case "${1}" in
+ -t)
+ table=${2}
+ shift 2
+ ;;
+ -A)
+ args="${args} -A ${2^^}"
+ shift 2
+ ;;
+ *)
+ args="${args} ${1}"
+ shift
+ ;;
+ esac
+ done
+
+ echo "${args:1:${#args}}" >> ${IPTABLES_TMPDIR}/${table}
+}
+
+function iptables_init() {
+ local policy=${1}
+ assert isoneof policy ACCEPT DROP
+
+ iptables "* filter"
+ iptables_chain_create -t filter INPUT ${policy}
+ iptables_chain_create -t filter OUTPUT ${policy}
+ iptables_chain_create -t filter FORWARD ${policy}
+
+ iptables -t mangle "* mangle"
+ iptables_chain_create -t mangle PREROUTING ACCEPT
+ iptables_chain_create -t mangle INPUT ACCEPT
+ iptables_chain_create -t mangle OUTPUT ACCEPT
+ iptables_chain_create -t mangle FORWARD ACCEPT
+ iptables_chain_create -t mangle POSTROUTING ACCEPT
+
+ iptables -t nat "* nat"
+ iptables_chain_create -t nat PREROUTING ACCEPT
+ iptables_chain_create -t nat OUTPUT ACCEPT
+ iptables_chain_create -t nat POSTROUTING ACCEPT
+}
+
+function iptables_commit() {
+ local chain
+
+ # Check if the directory where we put our rules in is set and
+ # exists.
+ assert isset IPTABLES_TMPDIR
+ assert [ -d "${IPTABLES_TMPDIR}" ]
+
+ log INFO "Committing firewall configuration..."
+ iptables -t filter "COMMIT"
+ iptables -t mangle "COMMIT"
+ iptables -t nat "COMMIT"
+
+ local iptables_ruleset="${IPTABLES_TMPDIR}/commit"
+ : > ${iptables_ruleset}
+
+ # Concat the rules for every chain into one file.
+ local table
+ for table in filter mangle nat; do
+ cat ${IPTABLES_TMPDIR}/${table} \
+ >> ${iptables_ruleset} 2>/dev/null
+ done
+
+ log DEBUG "Dumping iptables ruleset"
+ local counter=1
+ local line
+ while read line; do
+ line=$(printf "%4d | %s\n" "${counter}" "${line}")
+ log DEBUG "${line}"
+
+ counter=$(( $counter + 1 ))
+ done < ${iptables_ruleset}
+
+ iptables-restore < ${iptables_ruleset}
+}
+
+function iptables_chain_create() {
+ local args
+ if [ "${1}" = "-t" ]; then
+ args="${1} ${2}"
+ shift 2
+ fi
+
+ iptables ${args} ":$1 ${2--} [0:0]"
+}
+
+function iptables_LOG() {
+ local prefix=${1}
+
+ if [ "${FIREWALL_LOG_FACILITY}" = "syslog" ]; then
+ echo -n "LOG"
+ [ -n "$prefix" ] && echo -n " --log-prefix \"$prefix\""
+ else
+ echo -n "NFLOG"
+ [ -n "$prefix" ] && echo -n " --nflog-prefix \"$prefix\""
+ echo -n " --nflog-threshold 30"
+ fi
+ echo
+}
+
+function iptables_protocol() {
+ local PROTO
+ PROTO=$1
+ for proto in tcp udp esp ah; do
+ if [ "$PROTO" = "$proto" ]; then
+ echo "-p $PROTO"
+ break
+ fi
+ done
+}
+
+IPTABLES_PORT=0
+IPTABLES_MULTIPORT=1
+IPTABLES_PORTRANGE=2
+
+function _iptables_port_range() {
+ grep -q ":" <<< $@
+}
+
+function _iptables_port_multiport() {
+ grep -q "," <<< $@
+}
+
+function _iptables_port() {
+ if _iptables_port_range "$@"; then
+ echo $IPTABLES_PORTRANGE
+ elif _iptables_port_multiport "$@"; then
+ echo $IPTABLES_MULTIPORT
+ else
+ echo $IPTABLES_PORT
+ fi
+}
+
+function iptables_source_port() {
+ [ -z "$@" ] && return
+ local type
+ type=$(_iptables_port $@)
+ if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
+ echo "-m multiport --source-ports $@"
+ else
+ echo "--sport $@"
+ fi
+}
+
+function iptables_destination_port() {
+ [ -z "$@" ] && return
+ local type
+ type=$(_iptables_port $@)
+ if [ "$type" = "$IPTABLES_MULTIPORT" ]; then
+ echo "-m multiport --destination-ports $@"
+ else
+ echo "--dport $@"
+ fi
+}
--- /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
+
+ # Port forwarding chain.
+ iptables_chain_create ${chain}_PORTFW
+ iptables -A ${chain} -i ${zone} -j ${chain}_PORTFW
+
+ # Outgoing firewall
+ iptables_chain_create ${chain}_OUTFW
+ iptables -A ${chain} -o ${zone} -j ${chain}_OUTFW
+
+ # 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 -t nat ${chain}
+ iptables -t nat -A PREROUTING -i ${zone} -j ${chain}
+ iptables -t nat -A POSTROUTING -o ${zone} -j ${chain}
+
+ # Network Address Translation
+ iptables_chain_create -t nat ${chain}_NAT
+ iptables -t nat -A ${chain} -i ${zone} -j ${chain}_NAT
+
+ # Portforwarding
+ iptables_chain_create -t nat ${chain}_PORTFW
+ iptables -t nat -A ${chain} -i ${zone} -j ${chain}_PORTFW
+
+ # UPNP
+ iptables_chain_create -t nat ${chain}_UPNP
+ iptables -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
+}
+
+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
+}
routing_db_from_ppp ${zone} ipv4
# Request firewall reload
- event_firewall_reload
+ event_emit firewall-reload
return ${EXIT_OK}
}
return ${ret}
}
-function uppercase() {
- local input
- read input
- echo "${input^^}"
-}
-
-function lowercase() {
- local input
- read input
- echo "${input,,}"
+function cmd_quiet() {
+ cmd $@ &>/dev/null
}
function seq() {
--- /dev/null
+[Unit]
+Description=Firewall Ruleset Manager
+Before=network.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/sbin/firewall start
+ExecStop=/usr/sbin/firewall stop
+
+[Install]
+WantedBy=multi-user.target