#!/bin/bash
# modified linux-iptables-script (c) 2009 under GPL
# modifications are HN-openvz-specific. as the firewall script at
# http://wiki.openvz.org/Setting_up_an_iptables_firewall
# wasn't working for me because I need to assign international IP-addresses to containers
# for internationalization I translated the german-comments from the original author to english
# and added a file-based configuration similat to the one in the mentioned wiki 
# not a lot of testing done, as of february 2009,
#
# original written by:
# ---------------------------------------------------------------------
# Linux-iptables-Firewallskript, Copyright (c) 2009 under the GPL
# Autogenerated by iptables Generator v1.22 (c) 2002-2009 by Harald Bertram 
# Please visit http://harry.homelinux.org for new versions of
# the iptables Generator (c).
# 
#
# If you have questions about the iptables Generator or about
# your Firewall-Skript feel free to take a look at out website or
# send me an E-Mail to webmaster@harry.homelinux.org.
# 
# My special thanks are going to Lutz Heinrich (trinitywork at hotmail dot com)
# who made lots of Beta-Testing and gave me lots of well qualified
# Feedback that made me able to improve the iptables Generator.
# --------------------------------------------------------------------

case "$1" in
  start)
  #
  # check for config-file and load
    CONFIG=/etc/fw/firewall.conf
	if [ ! -r $CONFIG ] ; then echo "Sorry, couldn't find or open $CONFIG" ; exit 2 ; else chmod 0500 $CONFIG ; fi
	echo "starting IP packet filtering"
    # load iptables module (in most cases already loaded)
    modprobe ip_tables
    # load connection tracking module
    modprobe ip_conntrack
    # ip_conntrack_irc only available at kernels >= 2.4.19
    modprobe ip_conntrack_irc
    modprobe ip_conntrack_ftp

    # flush tables
    iptables -F
    iptables -t nat -F
    iptables -t mangle -F
    iptables -X
    iptables -t nat -X
    iptables -t mangle -X

    # set default policies
    iptables -P INPUT DROP
    iptables -P OUTPUT DROP
    iptables -P FORWARD DROP

    # MY_REJECT chain
    iptables -N MY_REJECT

    # define MY_REJECT chain
    iptables -A MY_REJECT -p tcp -m limit --limit 7200/h -j LOG --log-prefix "REJECT TCP "
    iptables -A MY_REJECT -p tcp -j REJECT --reject-with tcp-reset
    iptables -A MY_REJECT -p udp -m limit --limit 7200/h -j LOG --log-prefix "REJECT UDP "
    iptables -A MY_REJECT -p udp -j REJECT --reject-with icmp-port-unreachable
    iptables -A MY_REJECT -p icmp -m limit --limit 7200/h -j LOG --log-prefix "DROP ICMP "
    iptables -A MY_REJECT -p icmp -j DROP
    iptables -A MY_REJECT -m limit --limit 7200/h -j LOG --log-prefix "REJECT OTHER "
    iptables -A MY_REJECT -j REJECT --reject-with icmp-proto-unreachable

    # MY_DROP chain
    iptables -N MY_DROP
    iptables -A MY_DROP -m limit --limit 7200/h -j LOG --log-prefix "PORTSCAN DROP "
    iptables -A MY_DROP -j DROP

    # log all invalid packets -(may be a lot!)
    iptables -A INPUT -m state --state INVALID -m limit --limit 7200/h -j LOG --log-prefix "INPUT INVALID "
    iptables -A OUTPUT -m state --state INVALID -m limit --limit 7200/h -j LOG --log-prefix "OUTPUT INVALID "
    iptables -A FORWARD -m state --state INVALID -m limit --limit 7200/h -j LOG --log-prefix "FORWARD INVALID "

    # DROP invalid packets
    iptables -A INPUT -m state --state INVALID -j DROP
    iptables -A OUTPUT -m state --state INVALID -j DROP
    iptables -A FORWARD -m state --state INVALID -j DROP

    # DROP stealth scans
    # don't set flags
    iptables -A INPUT -p tcp --tcp-flags ALL NONE -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags ALL NONE -j MY_DROP

    # set SYN and FIN
    iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags SYN,FIN SYN,FIN -j MY_DROP

    # set SYN and RST
    iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN,RST -j MY_DROP

    # set FIN and RST
    iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags FIN,RST FIN,RST -j MY_DROP

    # FIN without ACK
    iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags ACK,FIN FIN -j MY_DROP

    # PSH without ACK
    iptables -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags ACK,PSH PSH -j MY_DROP

    # URG without ACK
    iptables -A INPUT -p tcp --tcp-flags ACK,URG URG -j MY_DROP
    iptables -A FORWARD -p tcp --tcp-flags ACK,URG URG -j MY_DROP

    # allow loopback and virtual (openvz) connections 
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -o lo -j ACCEPT
	iptables -A FORWARD -i $NIC -o venet0 -j ACCEPT
	iptables -A FORWARD -o $NIC -i venet0 -j ACCEPT
	iptables -A FORWARD -i venet0 -o venet0 -j ACCEPT

    # set max. segment size (MSS) for forwarding according to PMTU
    iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

    # activate connection-tracking
    iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    iptables -A FORWARD -i ! $NIC -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
    iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

	# let us open some ports
	# but first include config file, cave! config is executed
	. $CONFIG

if [ -n "$OPEN_TCP_PORT" ] ; then
        for p in "$OPEN_TCP_PORT" ; do
                iptables -A INPUT -i $NIC -m state --state NEW -p tcp --dport $p -j ACCEPT
        done
fi
if [ -n "$OPEN_UDP_PORT" ] ; then
        for p in "$OPEN_TCP_PORT" ; do
                iptables -A INPUT -i $NIC -m state --state NEW -p udp --dport $p -j ACCEPT
        done
fi

#
# DMZ and BANNED
#
if [ -n "$DMZ_IP" ] ; then
        for i in "$DMZ_IP" ; do
                iptables -A INPUT -m state --state NEW --source $i -j ACCEPT
        done
fi
if [ - "$BANNED_IP" ] ; then
        for i in "$BANNED_IP" ; do
                iptables -A INPUT --source $i -j DROP
        done
fi

#
# special TCP and UDP ports open only to trusted IPs
# first lookup host entries merge with static IPs into $USE_IP
#
TRUSTED_HOST_IP="`for a in $TRUSTED_HOST; do nslookup $a | grep Address | awk '{print $2 }' | sed -n '2p'; done`"
USE_IP="`echo $TRUSTED_HOST_IP` `echo $TRUSTED_IP`"
if [ -n "$USE_IP" ] ; then
        if [ -n "$RESTRICTED_TCP_PORT" ] ; then
                for i in "$USE_IP" ; do
                for p in "$RESTRICTED_TCP_PORT" ; do
                        iptables -A INPUT -i $NIC -m state --state NEW -p tcp -s $i --dport &p -j ACCEPT
                done
                done
        fi
        if [ -n "$RESTRICTED_UDP_PORT" ] ; then
                for i in "$USE_IP"; do
                for p in "$RESTRICTED_UDP_PORT"; do
                        iptables -A INPUT -i $NIC -m state --state NEW -p udp -s $i --dport &p -j ACCEPT
                done
                done
        fi
fi

#
# open a specific udp and/or tcp port for one host/block only
#
n=${!open*}
for i in $n ; do
        k=${!i}
        MAC=`echo $k|awk '{ print $1 }'`
        IP=`echo $k|awk '{ print $2 }'`
        if [ `echo $k|awk '{ print $3 }'` ] ; then PORT=" --dport `echo $k|awk '{ print $3 }'`" ; else PORT="" ; fi
        if [ `echo $k|awk '{ print $4 }'` ] ; then PTC=" -p `echo $k|awk '{print $4 }'`" ; else PTC="" ; fi
        ARG1=`echo "$IP"|grep -E "(([0-9]{1,3}\.){2}[0-9])"`
        ARG2=`echo "$IP"|grep -E "((([0-9]{1,3}\.){2}[0-9])\/[0-9]{2})"`
        if [ -n "$ARG1" -o -n "$ARG2" ] ; then
                ifconfig -A INPUT -i $MAC -m state --state NEW $PTC -s $IP --dport $PORT -j ACCEPT
                else
                ifconfig -A INPUT -i $MAC -m state --state NEW $PTC -s `nslookup "$IP" | grep Address | awk '{print $2 }' | sed -n '2p'` --dport $PORT -j ACCEPT
                fi

done


    # allow and answer to ICMP echo requests (ping)  
    iptables -A INPUT -m state --state NEW -p icmp --icmp-type echo-request -j ACCEPT

    # accept all traffic from local device
    iptables -A INPUT -m state --state NEW -i eth1 -j ACCEPT

    # default-Policies with REJECT
    iptables -A INPUT -j MY_REJECT
    iptables -A OUTPUT -j MY_REJECT
    iptables -A FORWARD -j MY_REJECT

    # forwarding/routing
    echo "activating IP-routing"
    echo 1 > /proc/sys/net/ipv4/ip_forward 2> /dev/null
	echo 1 > /proc/sys/net/ipv4/conf/default/forwarding 2> /dev/null
	
    # masquerading
    iptables -t nat -A POSTROUTING -o $NIC -j MASQUERADE

    # SYN-cookies
    echo 1 > /proc/sys/net/ipv4/tcp_syncookies 2> /dev/null

    # stop Source-Routing
    for i in /proc/sys/net/ipv4/conf/*; do echo 0 > $i/accept_source_route 2> /dev/null; done
	
    # stop Redirecting
    for i in /proc/sys/net/ipv4/conf/*; do echo 0 > $i/accept_redirects 2> /dev/null; done
	
    # reverse-Path-Filter
    for i in /proc/sys/net/ipv4/conf/*; do echo 1 > $i/rp_filter 2> /dev/null; done

    # log martians
    for i in /proc/sys/net/ipv4/conf/*; do echo 1 > $i/log_martians 2> /dev/null; done

    # deactivate BOOTP-relaying 
    for i in /proc/sys/net/ipv4/conf/*; do echo 0 > $i/bootp_relay 2> /dev/null; done

    # activate ARP-proxy for internet-device only
	echo 1 > /proc/sys/net/ipv4/conf/$NIC/proxy_arp 2> /dev/null
	echo 0 > /proc/sys/net/ipv4/conf/default/proxy_arp 2> /dev/null
    # ignore invalid ICMP-responses
    echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses 2> /dev/null

    # ignore ICMP echo-broadcasts
    echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 2> /dev/null

    # send max. 500/sec (5/Jiffie)
    echo 5 > /proc/sys/net/ipv4/icmp_ratelimit

    # allocation and timing of memory for de-/fragmentation
    echo 262144 > /proc/sys/net/ipv4/ipfrag_high_thresh
    echo 196608 > /proc/sys/net/ipv4/ipfrag_low_thresh
    echo 30 > /proc/sys/net/ipv4/ipfrag_time

    # TCP-FIN-timeout for protection of DoS-attacks
    echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout

    # only allow 3 responses to TCP-SYN
    echo 3 > /proc/sys/net/ipv4/tcp_retries1

    # only allow 15 retries of TCP-packets
    echo 15 > /proc/sys/net/ipv4/tcp_retries2


    ;;

  stop)
    echo "stopping IP packet filtering"
    # flush table
    iptables -F
    iptables -t nat -F
    iptables -t mangle -F
    iptables -X
    iptables -t nat -X
    iptables -t mangle -X
    echo "stopping IP routing"
    echo 0 > /proc/sys/net/ipv4/ip_forward

    # set default policies
    iptables -P INPUT ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -P FORWARD ACCEPT
    ;;

  status)
    echo "table: filter"
    iptables -L -vn
    echo "table: nat"
    iptables -t nat -L -vn
    echo "table: mangle"
    iptables -t mangle -L -vn
    ;;

  *)
    echo "incorrect syntax: $0"
    echo "try {start|stop|status} instead!"
    exit 1
    ;;

esac

