#!/bin/sh
#
# Firewall-Script fr Gymnasium Mnsingen
#
# Andreas Dangel
# 2002-07-08
# 2002-07-25: udp/4665,tcp/4661 (eDonkey) reject!
# 2002-08-29: samba optimations
# 2002-09-03: ip-Argument fr internet entfernt,
#             es wird darauf vertraut, dass auf ppp+ nur
#             Packete ankommen, die fr den Comp. bestimmt sind
# 2002-09-13: Status-Feststellung verndert
# 2002-10-14: Status ber /var/run/firewall
# 2002-11-09: Erlaube telnet von server nach 192.168.0.254 (drucker)
# 2002-11-10: reject udp/137 von auen!
#             reject tcp/4662 (eDonkey)!
#             reject tcp+udp/1214 (Kazaa)!
# 2002-11-14: reject all incoming (nach log)!
# 2002-11-16: erlaube dhcp-broadcast-pakete besser...
# 2002-11-22: erlaube jetdirect/9100 nach drucker
# 2002-11-25: erlaube printer/515 (lpd) nach drucker
# 2002-12-12: verbiete http/80 vom internet (siehe error_log -> angriffe!!)
# 2003-01-09: dhcp-regeln erweitern (broadcast, 67->68, ...)
# 2003-07-03: bei log, modul limit verwenden; kein REJECT mehr nach log in INPUT
# 2003-08-18: SuSE-spezielles entfernt
# 2003-08-19: state ESTABLISHED bei INPUT, viele Regeln entfernt
# 2003-08-20: Anpassung wegen neuem proxy-manager
# 2003-12-01: neue Broadcast-Regel fr smb (netz->broadcast, UDP 138)
# 2003-12-29: dasselbe udp 138 broadcast
# 2004-02-16: transparent proxy: PREROUTING...
# 2004-03-08: erlaube swat intern (samba web adminitration tool), tcp/901
# 2004-03-25: reject tcp/445 (samba) -> um timeouts zu verhindern, wenn
#                z.B. mit knoppix auf samba zugegriffen wird
# 2004-07-07: webmin port 10000 freischalten
#
# /etc/init.d/firewall -> /usr/local/sbin/firewall
#
# /etc/rc[2345].d/S10firewall -> ../init.d/firewall
#


# Tool iptables vorhanden?
iptables=/sbin/iptables
test -x $iptables || exit 5
# ip_tables-Modul laden
modprobe ip_tables || exit 5


##############################################################
# FUNKTIONEN
##############################################################
function firewall_config() {
    # 1. Interfaces
    # extern -> Internet
    ext_int="ppp+"  ## nicht eth1, das wird quasi nicht verwendet...
    # intern -> Intranet
    int_int="eth0"
    # loopback
    lo_int="lo"

    # 2. IP-Adressen
    # server externe adresse
    server_ext="0/0"  # ist egal, s.o.: auf ppp+ kommen nur pakete an,
                      # die fr den comp. bestimmt sind
    # server interne adresse
    server_int="192.168.0.1"
    # intranet adress-bereich
    lan="192.168.0.0/24"

    # 3. Ports
    # alle privilegierten ports
    priv_ports="0:1023"
    # alle unprivilegierten ports
    unpriv_ports="1024:65535"
}

function firewall_init() {
    # Alle regeln und chains lschen
    $iptables -F
    $iptables -t nat -F
    $iptables -X

    # default policy
    $iptables -P INPUT DROP
    $iptables -P FORWARD DROP
    $iptables -P OUTPUT ACCEPT

    # loopback interface aktivieren
    $iptables -A INPUT -i $lo_int -j ACCEPT

    # Schutz vor SYN Flooding
    for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
        echo "1" > $f
    done

    # IP Forwarding deaktivieren
    echo "0" > /proc/sys/net/ipv4/ip_forward

    # chains
    $iptables -N intranet
    $iptables -N internet


    # spezielle regeln:

    # spezielles dhcp-broadcast-paket
    $iptables -A INPUT -i $int_int -d 255.255.255.255 -p udp --dport 67 -j ACCEPT


    # spezielles smb-broadcast-paket...ntig??
    $iptables -A INPUT -i $int_int -d 192.168.0.255 -p udp --sport 138 --dport 138 -j ACCEPT
    $iptables -A INPUT -i $int_int -d 192.168.0.255 -p udp --sport 137 --dport 137 -j ACCEPT
    $iptables -A INPUT -i $int_int -d 192.168.0.255 -p udp --dport 138 -j ACCEPT
    $iptables -A INPUT -i $int_int -d 255.255.255.255 -p udp --dport 138 --sport 138 -j ACCEPT

    # allgemeine regeln mit userdefined chains
    $iptables -A INPUT -i $int_int -s $lan -d $server_int -j intranet
    $iptables -A INPUT -i $ext_int -j internet

    # erlaube ankommende Pakete von bestehenden Verbindungen
    $iptables -A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
    $iptables -A INPUT -p udp -m state --state ESTABLISHED -j ACCEPT

    # logging:
    $iptables -A INPUT -j LOG --log-prefix "firewall: " -m limit
}

function firewall_intranet () {
    #leere chain intranet
    $iptables -F intranet

    # icmp pakete in
    # see /usr/include/netinet/ip_icmp.h
    $iptables -A intranet -p icmp --icmp-type  0 -j ACCEPT
    $iptables -A intranet -p icmp --icmp-type  3 -j ACCEPT
    $iptables -A intranet -p icmp --icmp-type  4 -j ACCEPT
    $iptables -A intranet -p icmp --icmp-type  8 -j ACCEPT
    $iptables -A intranet -p icmp --icmp-type 12 -j ACCEPT
    # erlaube ssh (tcp,1222) in
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 1222 -j ACCEPT
    # erlaube smtp (tcp,25) in
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 25 -j ACCEPT
    # erlaube domain (udp,53) in
    $iptables -A intranet -p udp --sport $unpriv_ports --dport 53 -j ACCEPT
    # erlaube dhcp (udp,67/68) in
    $iptables -A intranet -p udp --sport $unpriv_ports --dport 67 -j ACCEPT
    $iptables -A intranet -p udp --sport 68 --dport 67 -j ACCEPT
    # erlaube httpd (tcp,80) in
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 80 -j ACCEPT
    # erlaube pop3 (tcp,110) in
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 110 -j ACCEPT
    # erlaube smb (tcp/udp,137:139) in
    $iptables -A intranet -p udp --sport 137 --dport 137 -j ACCEPT
    $iptables -A intranet -p udp --sport 138 --dport 138 -j ACCEPT
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 139 -j ACCEPT
    # erlaube swat (tcp/901) in
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 901 -j ACCEPT
    # reject smb (tcp/445) in
    $iptables -A intranet -p tcp --dport 445 -j REJECT
    # webmin (tcp/10000) in
    $iptables -A intranet -p tcp --dport 10000 -j ACCEPT


    ### proxy - internet-freigabe
    $iptables -A intranet -p tcp --sport $unpriv_ports --dport 3128 -j ACCEPT
    # proxy-manager aufrufen
    /usr/local/sbin/proxy-manager -d
    # transparent proxy (nur fr http)
    $iptables -t nat -A PREROUTING -i eth0 -p tcp -d ! $server_int --dport 80 -j REDIRECT --to-port 3128
}

function firewall_internet () {
    # leere chain internet
    $iptables -F internet

    # richtige adresse? -- prfung entfllt (s.o.), da nur pakete ankommen,
    #                      die auch fr dem comp. bestimmt sind.
    #$iptables -A internet -d ! $server_ext -j RETURN

    ### provided services! in
    # icmp pakete in
    $iptables -A internet -p icmp -d $server_ext --icmp-type  0 -j ACCEPT
    $iptables -A internet -p icmp -d $server_ext --icmp-type  3 -j ACCEPT
    $iptables -A internet -p icmp -d $server_ext --icmp-type  4 -j ACCEPT
    $iptables -A internet -p icmp -d $server_ext --icmp-type  8 -j ACCEPT
    $iptables -A internet -p icmp -d $server_ext --icmp-type 12 -j ACCEPT
    # erlaube ssh (tcp,1222) in
    $iptables -A internet -p tcp -d $server_ext --dport 1222 --sport $unpriv_ports -j ACCEPT
    # erlaube http (tcp,80) in
    #$iptables -A internet -p tcp -d $server_ext --dport 80 --sport $unpriv_ports -j ACCEPT
}

function firewall_stop () {
    # proxy-manager beenden
    /usr/local/sbin/proxy-manager -k

    # alle chains leeren
    $iptables -F
    $iptables -t nat -F
    # alle userdefined chains lschen
    $iptables -X
    # default policies
    $iptables -P INPUT ACCEPT
    $iptables -P OUTPUT ACCEPT
    $iptables -P FORWARD ACCEPT
}
##############################################################
runfile=/var/run/firewall



case "$1" in
    start)
        if [ -e $runfile ]; then
            echo "Firewall already running..."
            echo "see: $runfile"
            exit 1;
        fi

        echo "Starting firewall..."
        firewall_config
        echo "config: ext_int: $ext_int"
        echo "        int_int: $int_int"
        echo "        server_ext: $server_ext"
        echo "        server_int: $server_int"
        firewall_init
        firewall_intranet
        firewall_internet
        touch $runfile
        echo "...done"
        ;;
    stop)
        if [ ! -e $runfile ]; then
            echo "Firewall is not running..."
            exit 1;
        fi

        echo -n "Stopping firewall..."
        firewall_stop
        rm $runfile
        echo "done"
        ;;
    restart)
        $0 stop
        $0 start
        ;;
    status)
        /usr/local/sbin/proxy-manager -t
        echo -n "Checking for firewall..."
        if [ -e $runfile ]; then
          echo "running"
        else
          echo "not running!"
        fi

        ;;
    *)
        echo "Usage: $0 {start|stop|status|restart}"
        exit 1
        ;;
esac

exit 0

