#!/bin/bash
#

INTERFACE=$1
shift
IP=$1
shift

trap 'rm /tmp/firewall.$$' 0 1 2 3 4 5 6 7 8 15

ifconfig $INTERFACE >/tmp/firewall.$$ 2>&1

TEST_INTERFACE=` grep "error fetching interface information" /tmp/firewall.$$ `
if [ -z "$TEST_INTERFACE" ]
  then
# who am i ?
   myhost="`ifconfig $INTERFACE | grep 'inet addr:' | sed 's/.*inet addr:\([0-9\.]*\).*/\1/'`"
   mybrdcst="`ifconfig $INTERFACE | grep 'Bcast:' | sed 's/.*Bcast:\([0-9\.]*\).*/\1/'`"
else
  exit 1
fi

# some sanity checking

if [ "$1" = "start" ]
then
if [ "$IP" = "$myhost" ] 
  then
    logger -p daemon.info "firewall: $0 $INTERFACE $IP $1"
  else
    logger -i -p daemon.notice "firewall: error real ip $myhost $0 $INTERFACE $IP $1"
    exit 2
fi
else
    logger -p daemon.info "firewall: $0 $INTERFACE $IP $1"
fi

function start_firewall {
  # reset all
  ipchains -F
  ipchains -X

  # by default deny all incoming and forwarding traffic
  ipchains -P input DENY
  ipchains -P output DENY
  ipchains -P forward DENY

  # accept some outgoing traffic
  # (we need to specify outgoing traffic first, because in some rules,
  #  DNS lookups are needed and these are resolved externally ;-)

  # nothing destined for myself should go out
  ipchains -A output -d $myhost -l -j DENY

  # all outgoing traffic originating from me is valid
  ipchains -A output -s $myhost -j ACCEPT

  # loopback => OK
  ipchains -A output -i lo -j ACCEPT

  # vmware => OK
  ipchains -A output -i vmnet1 -j ACCEPT

  # Catch all other traffic and log it
  ipchains -A output -l -j DENY

  # accept/deny specific incoming traffic

  # somebody else is spoofing my IP-address => get lost
  ipchains -A input -s $myhost -l -j DENY

  # ICMP (ping, traceroute) => OK
  ipchains -A input -p icmp -d $myhost -j ACCEPT

  # Bootp (dhcp) => OK if coming from/going to designated bootp ports
  ipchains -A input -p udp -s 0/0 bootps -d $myhost bootpc -j ACCEPT
  ipchains -A input -p tcp -s 0/0 bootps -d $myhost bootpc -j ACCEPT

  # SSH ...
  # if established connection (ACK bit is set) => OK
  ipchains -A input -p tcp -s 0/0 ssh -d $myhost ! -y -j ACCEPT
  # if from DeptCW => OK
  ipchains -A input -p tcp -s 134.58.40.0/24 -d $myhost ssh -j ACCEPT
  ipchains -A input -p tcp -s 134.58.41.0/24 -d $myhost ssh -j ACCEPT
  ipchains -A input -p tcp -s 134.58.42.0/24 -d $myhost ssh -j ACCEPT
  ipchains -A input -p tcp -s 134.58.43.0/24 -d $myhost ssh -j ACCEPT
  ipchains -A input -p tcp -s 134.58.44.0/24 -d $myhost ssh -j ACCEPT
  ipchains -A input -p tcp -s 134.58.45.0/24 -d $myhost ssh -j ACCEPT
  ipchains -A input -p tcp -s 134.58.46.0/24 -d $myhost ssh -j ACCEPT

  # NTP => OK
  ipchains -A input -p udp -s 134.58.0.0/16 ntp -d $myhost -j ACCEPT

  # DNS ...
  # udp => OK
  # if from cs.kuleuven.ac.be and kulnet
  ipchains -A input -p udp -s 134.58.126.3/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 134.58.127.1/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 134.58.40.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 134.58.41.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 134.58.42.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 134.58.43.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 134.58.45.0/24 domain -d $myhost -j ACCEPT
  # from skynet.be
  ipchains -A input -p udp -s 195.238.2.21 domain -d $myhost -j ACCEPT
  ipchains -A input -p udp -s 195.238.2.22 domain -d $myhost -j ACCEPT
  # tcp => OK (if answer is large, tcp is used)
  ipchains -A input -p tcp -s 134.58.126.3/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 134.58.127.1/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 134.58.40.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 134.58.41.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 134.58.42.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 134.58.43.0/24 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 134.58.45.0/24 domain -d $myhost -j ACCEPT
  # from skynet.be
  ipchains -A input -p tcp -s 195.238.2.21 domain -d $myhost -j ACCEPT
  ipchains -A input -p tcp -s 195.238.2.22 domain -d $myhost -j ACCEPT

  # Identd => OK
  ipchains -A input -p tcp -s 0/0 -d $myhost auth -j ACCEPT

  # all other tcp connections only if established connection
  # (ACK bit is set)
  ipchains -A input -p tcp -d $myhost ! -y -j ACCEPT

# These are commented out because they are covered by the above ACK rule

  # Pop from/to server only if established connection (ACK bit is set)
#  ipchains -A input -p tcp -s mail.cs.kuleuven.ac.be pop-3 ! -y -j ACCEPT

  # Imap from/to server only if established connection (ACK bit is set)
#  ipchains -A input -p tcp -s mail.cs.kuleuven.ac.be imap2 ! -y -j ACCEPT
#  ipchains -A input -p tcp -s mail.cs.kuleuven.ac.be imap3 ! -y -j ACCEPT

  # Mail only if established connection (ACK bit is set)
#  ipchains -A input -p tcp -s 0/0 smtp -d $myhost ! -y -j ACCEPT

  # WWW only if established connection (ACK bit is set)
#  ipchains -A input -p tcp -s 0/0 www -d $myhost ! -y -j ACCEPT
#  ipchains -A input -p tcp -s 0/0 https -d $myhost ! -y -j ACCEPT

  # FTP only if established connection (ACK bit is set)
#  ipchains -A input -p tcp -s 0/0 ftp -d $myhost ! -y -j ACCEPT

  # Telnet only if established connection (ACK bit is set)
#  ipchains -A input -p tcp -s 0/0 telnet -d $myhost ! -y -j ACCEPT

  # RealAudio only on specified port
  ipchains -A input -p udp -s 0/0 -d $myhost 7070 -j ACCEPT

  # loopback => OK
  ipchains -A input -i lo -j ACCEPT

  # vmware => OK
  ipchains -A input -i vmnet1 -j ACCEPT

  # don't log anything sent to (global) broadcast
  ipchains -A input -d 255.255.255.255 -j -l DENY

  # don't log anything sent to broadcast and Windows ports
  # There are just too many stupid Windows machines looking for each other
  # Only log if they are not directed to (network) broadcast
  ipchains -A input -p udp -d $mybrdcst 137 -j -l DENY
  ipchains -A input -p udp -d $mybrdcst 138 -j -l DENY

  # Catch all other traffic and log it
  ipchains -A input -l -j -l DENY
}

function stop_firewall {
  # reset all
  ipchains -F
  ipchains -X

  # by default accept all incoming and forwarding traffic
  ipchains -P input ACCEPT
  ipchains -P output ACCEPT
  ipchains -P forward ACCEPT
}

function print_rules {
  ipchains -L -n
}

function print_accounting {
  ipchains -L -nv
}

function reset_accounting {
  ipchains -Z
}

function log_accounting {
  ipchains -L -Z -nvx
}

# main routine

# how long does testing last
WAIT=60

case "$1" in
start)
        start_firewall
        ;;
stop)
        stop_firewall
        ;;
test)
        start_firewall
        echo "**** THE FIREWALL WILL BE DISABLED AGAIN IN $WAIT SECONDS ****"
        ( sleep $WAIT; $0 stop ) &
        ;;
rules)
        print_rules
        ;;
status)
        print_accounting
        ;;
reset)
        reset_accounting
        ;;
log)
        log_accounting
        ;;
*)
        echo
        echo "Usage: $0 {start|stop|test|rules|status|reset|log}"
        echo
        echo "  start:   Enable the firewall"
        echo "  stop:    Disable the firewall"
        echo "  test:    Test the firewall : it will automatically be disabled"
        echo "           after $WAIT seconds"
        echo "  rules:   Print the firewall rules"
        echo "  status:  Print the accounting information"
        echo "  reset:   Reset the accounting counters"
        echo "  log:     Print and then reset the accounting information"
        echo "           Is to be called from crontab"
        echo
        exit 1
        ;;
esac

