#!/bin/bash

internal="eth0 vmnet1 vmnet8"
external="ppp0 ippp0 ippp1 ippp2"

p=/usr/sbin/iptables
sysctl=/sbin/sysctl

p1="$p -t filter"
p2="$p -t nat"
p3="$p -t mangle"

#fake=echo
tmp_policy=DROP		# subject to change to DROP

function debug {
    echo "$@"
    "$@"
}

function get_nameservers {
    local word addr rest
    while read word addr rest; do
	if [ "$word" = "nameserver" ]; then
	    echo $addr
	fi
    done </etc/resolv.conf
}

function get_builtin_chain {
    local p=$1; shift;
    local chain dummy policy word

    $p -L -n|grep '^Chain'|while IFS="$IFS()" read dummy chain word policy; do
	case "$word" in
	policy)			# builtin chain
	    echo $chain
	    ;;
	*)
	    ;;
	esac
    done
}

function get_custom_chain {
    local p=$1; shift;
    local chain dummy policy word

    $p -L -n|grep '^Chain'|while IFS="$IFS()" read dummy chain word policy; do
	case "$word" in
	policy)			# builtin chain
	    ;;
	*)
	    echo $chain
	    ;;
	esac
    done
}

function clear {
    local p=$1; shift;
    local chain

    for chain in $(get_builtin_chain $p); do
	$fake $p -P $chain $tmp_policy
	$fake $p -F $chain
    done

    $fake $p -F
    $fake $p -X
}

function clear_all {
    echo Turn off forwarding
    $fake $sysctl -w net.ipv4.ip_forward=0

    echo Clearing Filter Rules
    clear "$p1"

    echo Clearing NAT Rules
    clear "$p2"

    echo Clearing Mangle Rules
    clear "$p3"
}

function make_chains {
    echo Setup Rules
    $fake $p1 -A INPUT -j ACCEPT -i lo
    $fake $p1 -A OUTPUT -j ACCEPT -o lo

    $fake $p1 -N reject_func
    # prevent a lot of logfile lines caused by p2p networks and netbios
    $fake $p1 -A reject_func -j DROP -p tcp --destination-port 4661:4671
    $fake $p1 -A reject_func -j DROP -p udp --destination-port 4661:4671
    $fake $p1 -A reject_func -j DROP -p tcp --destination-port 1214
    $fake $p1 -A reject_func -j DROP -p udp --destination-port 1214
    $fake $p1 -A reject_func -j DROP -p tcp --destination-port 137:139
    $fake $p1 -A reject_func -j DROP -p udp --destination-port 137:139
    $fake $p1 -A reject_func \
          -j LOG --log-ip-options --log-tcp-options --log-prefix FW-reject:
    $fake $p1 -A reject_func -p tcp -j DROP
#    $fake $p1 -A reject_func \
#          -p tcp -j REJECT --reject-with icmp-port-unreachable
#    $fake $p1 -A reject_func -p tcp -j REJECT --reject-with tcp-reset
    $fake $p1 -A reject_func \
          -p udp -j REJECT --reject-with icmp-port-unreachable
    $fake $p1 -A reject_func -p icmp -j DROP
    $fake $p1 -A reject_func -j REJECT --reject-with icmp-proto-unreachable

    $fake $p1 -N input_ext
    $fake $p1 -N input_int
    $fake $p1 -N forward_ext
    $fake $p1 -N forward_int
    $fake $p1 -N output_ext
    $fake $p1 -N output_int

    $fake $p1 -A input_int -j ACCEPT
    $fake $p1 -A output_int -j ACCEPT
    $fake $p1 -A forward_int -j ACCEPT

    $fake $p1 -A input_ext -j ACCEPT -p icmp --icmp-type echo-request
    for i in echo-reply \
	     destination-unreachable \
	     time-exceeded \
	     parameter-problem \
	     timestamp-reply \
	     address-mask-reply; do
	$fake $p1 -A input_ext -j ACCEPT \
              -m state --state ESTABLISHED,RELATED -p icmp --icmp-type $i
    done

    $fake $p1 -A input_ext -j ACCEPT \
          -p udp --sport 53 --dport 1024:65535
#    for i in $(get_nameservers); do
#	$fake $p1 -A input_ext -j ACCEPT \
#              -m state --state NEW,ESTABLISHED \
#              -p udp -s $i --sport 53 --dport 1024:65535
#    done

    $fake $p1 -A input_ext -j ACCEPT -p tcp \
          -m state --state ESTABLISHED,RELATED
    $fake $p1 -A input_ext -j reject_func

    for i in echo-reply \
	     port-unreachable \
	     time-exceeded \
	     fragmentation-needed \
	     network-prohibited \
	     communication-prohibited \
	     host-prohibited; do
	$fake $p1 -A output_ext -j ACCEPT -p icmp --icmp-type $i
    done
    $fake $p1 -A output_ext -j DROP -p icmp --icmp-type destination-unreachable
    $fake $p1 -A output_ext -j ACCEPT

    $fake $p1 -A forward_ext -j ACCEPT
    $fake $p1 -A FORWARD -j TCPMSS --clamp-mss-to-pmtu \
          -p tcp --tcp-flags SYN,RST SYN
}

function setup {
    local i
    for i in $internal; do
	$fake $p1 -A INPUT -j input_int -i $i
	$fake $p1 -A OUTPUT -j output_int -o $i
	$fake $p1 -A FORWARD -j forward_int -i $i
    done
    for i in $external; do
	$fake $p1 -A INPUT -j input_ext -i $i
	$fake $p1 -A OUTPUT -j output_ext -o $i
	$fake $p1 -A FORWARD -j forward_ext -i $i
	$fake $p2 -A POSTROUTING -j MASQUERADE -o $i
    done

    for i in $(get_builtin_chain "$p1"); do
	$fake $p1 -P $i DROP
    done

    for i in $(get_builtin_chain "$p2"); do
	$fake $p2 -P $i ACCEPT
    done

    for i in $(get_builtin_chain "$p3"); do
	$fake $p3 -P $i ACCEPT
    done

    $fake $sysctl -w net.ipv4.ip_forward=1
}

clear_all
make_chains
setup