INTERFACE="ippp+"
LOCAL="192.168.0.0/24"
IPTABLES="/usr/sbin/iptables"

CreateBucket()
{
    ${IPTABLES} -N destroy
    
    # These rules are only there for logging.
    ${IPTABLES} -A destroy -j LOG --log-level notice -m limit
    ${IPTABLES} -A destroy -j DROP
}

# Accept all TCP packets from the external interface to a list of internal
# ports.
InTCP()
{
    for i in $*
    do
        ${IPTABLES} -A INPUT  -j ACCEPT -i ${INTERFACE} -p tcp \
                --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p tcp \
                --sport $i -m state --state ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD  -j ACCEPT -i ${INTERFACE} -p tcp \
                --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p tcp \
                --sport $i -m state --state ESTABLISHED,RELATED
    done
}

OutTCP()
{
    for i in $*
    do
        ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p tcp \
                --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A INPUT  -j ACCEPT -i ${INTERFACE} -p tcp \
                --sport $i -m state --state ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p tcp \
                -s ${LOCAL} --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD  -j ACCEPT -i ${INTERFACE} -p tcp \
                --sport $i -d ${LOCAL} -m state --state ESTABLISHED,RELATED
    done
}

InUDP()
{
    for i in $*
    do
        ${IPTABLES} -A INPUT  -j ACCEPT -i ${INTERFACE} -p udp \
                --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p udp \
                --sport $i --dport 1024: -m state --state ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD  -j ACCEPT -i ${INTERFACE} -p udp \
                --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p udp \
                --sport $i -m state --state ESTABLISHED,RELATED
    done
}

OutUDP()
{
    for i in $*
    do
        ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p udp \
                --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A INPUT  -j ACCEPT -i ${INTERFACE} -p udp \
                --sport $i -m state --state ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD -j ACCEPT -o ${INTERFACE} -p udp \
                -s ${LOCAL} --sport 1024: --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A FORWARD  -j ACCEPT -i ${INTERFACE} -p udp \
                --sport $i -d ${LOCAL} -m state --state ESTABLISHED,RELATED
    done
}

OutEqualUDP()
{
    for i in $*
    do
        ${IPTABLES} -A OUTPUT -j ACCEPT -o ${INTERFACE} -p udp \
                --sport $i --dport $i -m state --state NEW,ESTABLISHED,RELATED
        ${IPTABLES} -A INPUT  -j ACCEPT -i ${INTERFACE} -p udp \
                --sport $i --dport $i -m state --state ESTABLISHED,RELATED
    done
}

OutFTP()
{
    InOutTCP ftp-data
    ${IPTABLES} -A INPUT  -j ACCEPT -i ${INTERFACE} -p tcp \
            --sport ftp-data -m state --state ESTABLISHED,RELATED
}

InOutTCP()
{
    InTCP $*
    OutTCP $*
}

InOutUDP()
{
    InUDP $*
    OutUDP $*
}

EgressFilter()
{
    # Dont't let private addresses in.
    ${IPTABLES} -N in_private
    ${IPTABLES} -F in_private
    ${IPTABLES} -A in_private  -j destroy   -s 127.0.0.0/8
    ${IPTABLES} -A in_private  -j destroy   -s 10.0.0.0/8
    ${IPTABLES} -A in_private  -j destroy   -s 172.16.0.0/12
    ${IPTABLES} -A in_private  -j destroy   -s 192.168.0.0/16
    ${IPTABLES} -A in_private  -j destroy   -s 224.0.0.0/4
    ${IPTABLES} -A in_private  -j destroy   -s 240.0.0.0/4
    # Additionally we could destroy everything that doesn't have
    # the IP of our interface as destination address. But this IP
    # is dynamic...

    # Dont't let private addresses escape.
    ${IPTABLES} -N out_private
    ${IPTABLES} -F out_private
    ${IPTABLES} -A out_private -j destroy   -d 127.0.0.0/8
    ${IPTABLES} -A out_private -j destroy   -d 10.0.0.0/8
    ${IPTABLES} -A out_private -j destroy   -d 172.16.0.0/12
    ${IPTABLES} -A out_private -j destroy   -d 192.168.0.0/16
    ${IPTABLES} -A out_private -j destroy   -d 224.0.0.0/4
    ${IPTABLES} -A out_private -j destroy   -d 240.0.0.0/4

    ${IPTABLES} -A INPUT       -j in_private  -i ${INTERFACE}
    ${IPTABLES} -A FORWARD     -j in_private  -i ${INTERFACE}
    ${IPTABLES} -A OUTPUT      -j out_private -o ${INTERFACE}
    ${IPTABLES} -A FORWARD     -j out_private -o ${INTERFACE}
}

AcceptLocal()
{
    ${IPTABLES} -A INPUT  -j ACCEPT -i \! ${INTERFACE}
    ${IPTABLES} -A OUTPUT -j ACCEPT -o \! ${INTERFACE}
    ${IPTABLES} -A FORWARD -j ACCEPT -i \! ${INTERFACE} \
            -o \! ${INTERFACE}
    ${IPTABLES} -A FORWARD -j destroy -i ${INTERFACE} \
            -o ${INTERFACE}
}

Start()
{
    Close
    CreateBucket
    EgressFilter
    AcceptLocal

    InOutTCP  22                 # ssh
    OutTCP    http 81 https 8080
    OutTCP    ftp smtp finger pop3 nntp
    OutTCP    871                # sup
    OutTCP    realplayer
    OutTCP    cvspserver
    OutTCP    6667               # IRC
    OutFTP

    OutEqualUDP ntp

    InOutUDP domain

    # Firewall ICMP. ICMP is useful so allow any by default.
    ${IPTABLES} -A INPUT   -j ACCEPT -p icmp
    ${IPTABLES} -A OUTPUT  -j ACCEPT -p icmp
    ${IPTABLES} -A FORWARD -j ACCEPT -p icmp

    ${IPTABLES} -A INPUT  -j destroy
    ${IPTABLES} -A OUTPUT -j destroy
}

Flush()
{
    ${IPTABLES} -P INPUT $1
    ${IPTABLES} -P OUTPUT $1
    ${IPTABLES} -P FORWARD $1
    ${IPTABLES} -F
    ${IPTABLES} -F INPUT
    ${IPTABLES} -F OUTPUT
    ${IPTABLES} -F FORWARD
    ${IPTABLES} -X destroy     > /dev/null 2>&1
    ${IPTABLES} -X in_private  > /dev/null 2>&1
    ${IPTABLES} -X out_private > /dev/null 2>&1
}

Stop()
{
    Flush ACCEPT
}

Close()
{
    Flush DROP
}

