#! /bin/sh

### BEGIN INIT INFO
# Provides:		firewall
# Required-Start:	$network $syslog $named
# Required-Stop:	$network $syslog $named
# Default-Start:	2 3 4 5
# Default-Stop:		0 1 6
# Short-Description: Provide firewalling
# Description: Provide firewalling
### END INIT INFO

DELIMITER='-----------------------------------------------------------------------------------------------------------------'

N='/etc/init.d/firewall'
IPT='/sbin/iptables'

UNPRIVPORTS='1024:65535'


IF_FE='eth0'
NET_FE_IN='192.168.254.113-192.168.254.116:21,80,443/tcp'
NET_FE_OUT='192.168.254.1:53/udp \
	80.67.169.12:53/udp'

IF_BO_ALT='eth1'
NET_BO_ALT_IN='192.168.0.1:22,53,10050/tcp'
NET_BO_ALT_OUT=''

IF_BO_NEU='eth2'
NET_BO_NEU_IN='192.168.1.1:22,53,10050/tcp'
NET_BO_NEU_OUT=''

IF_LOG='eth3'
NET_LOG_IN='192.168.97.113:10050/tcp'
NET_LOG_OUT='192.168.97.250:514/udp'

IF_BO='eth4'
NET_BO_IN='192.168.96.128:22,80,443/tcp'
NET_BO_OUT='192.168.96.113:22/tcp \
	192.168.96.209:22,2049,4242/tcp'


# hostnames that have more than 1 IP address, enabling output on port 80/tcp:
#MANYIP_OUT='database.clamav.net ftp.de.debian.org download.bitdefender.com'
MANYIP_OUT=''


ICMP='on'

set -e

#####################################################################

rules_in () {
	# default: NEW
	STATEIN='NEW'

	if ! [ "x$1" = 'x' ]; then
		for i in $1; do
			a=${i%/*}
			ip=${a%%:*}
			port=${a#*:}
			proto=${i#*/}
			if [ 'x' = "x$(echo "$ip" | grep '-')" ]; then
				if ! [ 'x' = "x$(echo "$port" | grep ',')" ]; then
					$IPT -A INPUT -i $2 -p $proto -d $ip -m multiport --dports $port -m state --state $STATEIN -j ACCEPT
				else
					$IPT -A INPUT -i $2 -p $proto -d $ip --dport $port -m state --state $STATEIN -j ACCEPT
				fi
			else
				if ! [ 'x' = "x$(echo "$port" | grep ',')" ]; then
					$IPT -A INPUT -i $2 -p $proto -m iprange --dst-range $ip -m multiport --dports $port -m state --state $STATEIN -j ACCEPT
				else
					$IPT -A INPUT -i $2 -p $proto -m iprange --dst-range $ip --dport $port -m state --state $STATEIN -j ACCEPT
				fi
			fi
		done
	fi
}

#####################################################################

rules_out () {
	# default: NEW
	STATEOUT='NEW'

	if ! [ "x$1" = 'x' ]; then
		for i in $1; do
			a=${i%/*}
			ip=${a%%:*}
			port=${a#*:}
			proto=${i#*/}
			if [ 'x' = "x$(echo "$ip" | grep '-')" ]; then
				if ! [ 'x' = "x$(echo "$port" | grep ',')" ]; then
					$IPT -A OUTPUT -o $2 -p $proto -d $ip -m multiport --dports $port -m state --state $STATEOUT -j ACCEPT
				else
					$IPT -A OUTPUT -o $2 -p $proto -d $ip --dport $port -m state --state $STATEOUT -j ACCEPT
				fi
			else
				if ! [ 'x' = "x$(echo "$port" | grep ',')" ]; then
					$IPT -A OUTPUT -o $2 -p $proto -m iprange --dst-range $ip -m multiport --dports $port -m state --state $STATEOUT -j ACCEPT
				else
					$IPT -A OUTPUT -o $2 -p $proto -m iprange --dst-range $ip --dport $port -m state --state $STATEOUT -j ACCEPT
				fi
			fi
		done
	fi
}

#####################################################################

do_rules_in () {
	if ! [ 'x' = "x$1" ] && \
	! [ 'x' = "x$2" ]
	then
		rules_in "$1" "$2"
	fi
}

#####################################################################

do_rules_out () {
	if ! [ 'x' = "x$1" ] && \
	! [ 'x' = "x$2" ]
	then
		rules_out "$1" "$2"
	fi
}

#####################################################################

stop () {
	# disable forwarding
	echo 0 > /proc/sys/net/ipv4/ip_forward

	# clear rules
	$IPT -F
	$IPT -X
	$IPT -t nat -F
	$IPT -t nat -X

	# default policies
	$IPT -P INPUT ACCEPT
	$IPT -P FORWARD ACCEPT
	$IPT -P OUTPUT ACCEPT
	$IPT -t nat -P PREROUTING ACCEPT
	$IPT -t nat -P POSTROUTING ACCEPT
	$IPT -t nat -P OUTPUT ACCEPT
}

start () {
	echo -n 'activating firewall... '
	stop

	# completing the variable NET_BO_OUT with IP's that come from a resolved fqdn:
	if ! [ 'x' = "x$MANYIP_OUT" ]; then
		ratatac="$(for i in $(for j in $MANYIP_OUT; do dig +short $j; done); do echo $i; done | egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}')"
		NET_BO_OUT="$NET_BO_OUT $(for i in $ratatac; do echo "$i:80/tcp"; done)"
	fi

	# default policies
	$IPT -P INPUT DROP
	$IPT -P FORWARD DROP
	$IPT -P OUTPUT DROP

	# just in case... enable loopback iface
	$IPT -A INPUT	-i lo -j ACCEPT
	$IPT -A OUTPUT	-o lo -j ACCEPT

	################################################################
	#			INPUT
	if [ "$ICMP" = 'on' ]; then
		$IPT -A INPUT -p icmp ! -i $IF_FE -j ACCEPT
	fi

	$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

	do_rules_in "$NET_FE_IN" "$IF_FE"
	do_rules_in "$NET_BO_ALT_IN" "$IF_BO_ALT"
	do_rules_in "$NET_BO_NEU_IN" "$IF_BO_NEU"
	do_rules_in "$NET_LOG_IN" "$IF_LOG"
	do_rules_in "$NET_BO_IN" "$IF_BO"

	################################################################
	#			OUTPUT
	if [ "$ICMP" = 'on' ]; then
		$IPT -A OUTPUT -p icmp ! -o $IF_FE -j ACCEPT
	fi

	$IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

	do_rules_out "$NET_FE_OUT" "$IF_FE"
	do_rules_out "$NET_BO_ALT_OUT" "$IF_BO_ALT"
	do_rules_out "$NET_BO_NEU_OUT" "$IF_BO_NEU"
	do_rules_out "$NET_LOG_OUT" "$IF_LOG"
	do_rules_out "$NET_BO_OUT" "$IF_BO"

	echo 'firewall activated !'
}

restart () {
	stop
	start
}

status () {
	echo $DELIMITER
	$IPT -L -n -v
	echo $DELIMITER
	$IPT -t nat -L -n -v
	echo $DELIMITER
}

case "$1" in
  start)
	start
	;;
  restart)
	restart
	;;
  status)
	status
	;;
  stop)
	stop
	;;
  *)
	echo "Usage: $N {start|stop|restart|status}" >&2
	exit 1
	;;
esac

exit 0
