#! /bin/sh

# the following 3 lines are from SuSE.
# Determine the base and follow a runlevel link name.
base=${0##*/}
link=${base#*[SK][0-9][0-9]}

# the rest is by markus@wernig.net and chris@rebmatt.ch

# /etc/rc.d/firewall

# sets up a packet filtering firewall with masquerading and port forwarding
# (for transparent proxying by squid and/or dansguardian)
# see http://www.lugbe.ch/lostfound/contrib/router_biel/

ARG=$1

. /etc/rc.config

[ $START_FW = 'yes' ] || ARG='stop' 

# 2 more SuSE lines ;-)
# The echo return value for success (defined in /etc/rc.config).
return=$rc_done

IPTABLES=`which iptables` || IPTABLES=/sbin/iptables
LOCALNET=192.168.1.0/24
EXTNET=147.87.65.0/24
DEFAULT_GW=147.87.65.250
# Für etwas mehr "magic":
#EXTNET=`netstat -rn | grep eth0 | awk '$2 == "0.0.0.0" {print $1}'`/`netstat -rn | grep eth0 | awk '$2 == "0.0.0.0" {print $3}'`
#DEFAULT_GW=`netstat -rn | grep eth0 | awk '$1 == "0.0.0.0" {print $2}'`


# first we have to get our interfaces/addresses
# we start with a crude assumption: our local net starts with "192.168."
# might fail for some nets. 

# get address 192.168.*

MY_LOCAL_ADDR=`ifconfig |grep "192.168." | sed -e s/"inet addr\:"//g | awk '{print $1}'`

# get interface for address 192.168.*

for if in eth0 eth1
do 
	if ifconfig $if | grep "$MY_LOCAL_ADDR" >/dev/null 2>&1; then 
		MY_LOCAL_IF=$if
	else
		MY_EXT_IF=$if
	fi
done

# get other address

MY_EXT_ADDR=`ifconfig $MY_EXT_IF | grep "inet addr" | sed -e s/"inet addr\:"//g | awk '{print $1}'`

# blabber

echo "local: $MY_LOCAL_ADDR ($MY_LOCAL_IF), external: $MY_EXT_ADDR ($MY_EXT_IF)"

# script can be called by boot.local with "start" or "stop"

case "$ARG" in
    start)
	echo -n "Starting firewall"

	# set some kernel network parameters
	
	echo '1' > /proc/sys/net/ipv4/ip_forward
	echo '1' > /proc/sys/net/ipv4/tcp_syncookies
	for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
        	echo '1' > $f
	done
	echo '0' > /proc/sys/net/ipv4/tcp_timestamps
	echo '30' > /proc/sys/net/ipv4/tcp_fin_timeout
	echo '1' > /proc/sys/net/ipv4/icmp_echo_ignore_all
	echo '1' > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
	echo '1' > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
	

	# set default policies and flush chains
	$IPTABLES -F INPUT
	$IPTABLES -F OUTPUT
	$IPTABLES -F FORWARD
	$IPTABLES -t nat -F PREROUTING
	$IPTABLES -t nat -F POSTROUTING

	# set flow-chains and drop spoofed packets

	$IPTABLES -N Spoofed
	$IPTABLES -A Spoofed -j LOG --log-prefix Spoofed
	$IPTABLES -A Spoofed -j DROP

	# accept traffic on lo
	$IPTABLES -A INPUT -i lo -j ACCEPT
	$IPTABLES -A OUTPUT -o lo -j ACCEPT

	# enable stateful inspection
	$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
	$IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT # accept all on OUTPUT
	$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

	# allow all icmp packets from the gateway
	$IPTABLES -A INPUT -p icmp -i $MY_EXT_IF -s $DEFAULT_GW -d $MY_EXT_ADDR -j ACCEPT
	
        # set up necessary chains
        $IPTABLES -N LOCALNET-FW
        $IPTABLES -N INTERNET-FW
        $IPTABLES -N LOCALNET-INTERNET
        $IPTABLES -N INTERNET-LOCALNET
        $IPTABLES -N LOCALNET-HTANET
        $IPTABLES -N HTANET-LOCALNET

	# allow dhcp to and from LOCALNET
	$IPTABLES -A INPUT -i $MY_LOCAL_IF -p udp -d 255.255.255.255 --dport 67 -s 0.0.0.0 --sport 68 -j ACCEPT
	$IPTABLES -A OUTPUT -o $MY_LOCAL_IF -p udp -s $MY_LOCAL_ADDR --sport 67 -d 255.255.255.255 --dport 68 -j ACCEPT
	
	# split the traffic to different chains, all uncatched packets are spoofed
	$IPTABLES -A INPUT -i $MY_LOCAL_IF -s $LOCALNET -d $MY_LOCAL_ADDR -j LOCALNET-FW
	$IPTABLES -A INPUT -i $MY_EXT_IF -d $MY_EXT_ADDR ! -s $EXTNET -j INTERNET-FW
	$IPTABLES -A INPUT -j Spoofed

	$IPTABLES -A FORWARD -i $MY_LOCAL_IF -s $LOCALNET -o $MY_EXT_IF ! -d $EXTNET -j LOCALNET-INTERNET
	$IPTABLES -A FORWARD -i $MY_EXT_IF ! -s $EXTNET -o $MY_LOCAL_IF -d $LOCALNET -j INTERNET-LOCALNET
	$IPTABLES -A FORWARD -i $MY_LOCAL_IF -s $LOCALNET -o $MY_EXT_IF -d $EXTNET -j LOCALNET-HTANET
	$IPTABLES -A FORWARD -i $MY_EXT_IF -s $EXTNET -o $MY_LOCAL_IF -d $LOCALNET -j HTANET-LOCALNET
	$IPTABLES -A FORWARD -j Spoofed
	
	# the Chain from LOCALNET to the Firewall
	for type in echo-request echo-reply destination-unreachable source-quench time-exceeded parameter-problem fragmentation-needed
	do
		$IPTABLES -A LOCALNET-FW -p icmp --icmp-type $type -j ACCEPT
	done
	$IPTABLES -A LOCALNET-FW -p tcp --dport 8080 --syn -j ACCEPT # for dansguardian
	$IPTABLES -A LOCALNET-FW -p udp --dport domain -j ACCEPT
	$IPTABLES -A LOCALNET-FW -p udp --dport ntp -j ACCEPT
	$IPTABLES -A LOCALNET-FW -p tcp --dport ntp --syn -j ACCEPT
	$IPTABLES -A LOCALNET-FW -p udp --dport time -j ACCEPT
	$IPTABLES -A LOCALNET-FW -p tcp --dport time --syn j ACCEPT
	$IPTABLES -A LOCALNET-FW -p tcp --dport ssh --syn -j ACCEPT
	$IPTABLES -A LOCALNET-FW -p tvd --dport squid --syn -j ACCEPT
	$IPTABLES -A LOCALNET-FW -j LOG --log-prefix LOCALNET-FW
	$IPTABLES -A LOCALNET-FW -j DROP

	# the Chain from the Internet to the Firewall
	for type in echo-request echo-reply destination-unreachable source-quench time-exceeded parameter-problem fragmentation-needed
	do
		$IPTABLES -A INTERNET-FW -p icmp --icmp-type $type -j ACCEPT
	done
	$IPTABLES -A INTERNET-FW -p tcp --dport auth -j REJECT
	$IPTABLES -A INTERNET-FW -p udp --dport auth -j REJECT
	$IPTABLES -A INTERNET-FW -j LOG --log-prefix INTERNET-FW
	$IPTABLES -A INTERNET-FW -j DROP

	# the Chain from the Localnet to the Internet
	$IPTABLES -A LOCALNET-INTERNET -m state --state NEW -j ACCEPT # all traffic accepted
	$IPTABLES -A LOCALNET-INTERNET -j LOG --log-prefix LOCALNET-INTERNET
	$IPTABLES -A LOCALNET-INTERNET -j DROP

	# Traffic from Localnet to the HTA-Net gets logged and dropped
	$IPTABLES -A LOCALNET-HTANET -j LOG --log-prefix LOCALNET-HTANET
	$IPTABLES -A LOCALNET-HTANET -j DROP

	# The Chain from the Internet to the Localnet
	$IPTABLES -A INTERNET-LOCALNET -j LOG --log-prefix INTERNET-LOCALNET
	$IPTABLES -A INTERNET-LOCALNET -j DROP

	# The CHain from the HTA-Net to the Localnet, also logged and dropped
	$IPTABLES -A HTANET-LOCALNET -j LOG --log-prefix HTANET-LOCALNET
	$IPTABLES -A HTANET-LOCALNET -j DROP

	# the rediredtion of http-traffic to port 8080
	$IPTABLES -t nat -A PREROUTING -i $MY_LOCAL_IF -s $LOCALNET ! -d $LOCALNET -p tcp --dport http -j REDIRECT --to-ports 8080

	# the masquerading of the outgoing traffic
	$IPTABLES -t nat -A POSTROUTING -o $MY_EXT_IF -s $LOCALNET -j MASQUERADE	


	;;
    stop|open)
	echo -n "Opening up firewall"
	$IPTABLES -P INPUT ACCEPT
	$IPTABLES -F
	$IPTABLES -t nat -F
	echo '1' > /proc/sys/net/ipv4/ip_forward 
	$IPTABLES -t nat -A POSTROUTING -s $LOCALNET -d ! $LOCALNET -o $MY_EXT_IF -j MASQUERADE || return=$rc_failed
	echo  -e "$return"
	# This now is a mere router with no firewall whatsoever. it just masquerades.
	
	;;
    close)
	echo -n "Shutting down firewall"
	$IPTABLES -P INPUT ACCEPT
	$IPTABLES -F
	$IPTABLES -t nat -F
	echo '0' > /proc/sys/net/ipv4/ip_forward 
	echo  -e "$return"
	# No more forwarding. The net is closed off, but this host is still reachable on all ports.
	;;
    reload|restart)
        $0 stop && sleep 3 && $0 start || return=$rc_failed
	;;
    *)
	echo "Usage: $0 {start|stop|status|reload|restart}"
	exit 1
esac

# Right, it's SuSE time again.
# Inform the caller not only verbosely and set an exit status.
test "$return" = "$rc_done" || exit 1
exit 0
