Firewall

From Nick's Wiki

Jump to: navigation, search

Contents


Nick's Linux-based Firewall Project

The Sandesnet network is protected by Linux iptables-based firewalls built with the ipmasq(1) utility. The ipmasq(1) utility is distributed with the Debian and Ubuntu GNU/Linux distributions and allows the modular building of firewalls.

The iptables firewall rules are set by the ipmasq utility by running a set of shell scripts stored in the /etc/ipmasq/rules directory. The scripts are files with names ending in .def or .rul and they are run by ipmasq in alphabetic order.

The Sandesnet firewalls are built with the help of scripts similar to the ones listed below.

Definitions and Functions

These scripts start with "A" and they initialize the environment and define the functions used by the subsequent scripts.

A00path.def

Included in the standard ipmasq package, sets the PATH environment variable.

# You should not edit this file.  Instead, create a file with the same
# name as this one, but with a .rul extension instead of .def.  The
# .rul file will override this one.
#
# However, any changes you make to this file will be preserved.

# sanitize the path
PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin

A00sanitycheck.def

Included in the ipmasq package, checks whether the kernel allows forwarding and masquerading.

# You should not edit this file.  Instead, create a file with the same
# name as this one, but with a .rul extension instead of .def.  The
# .rul file will override this one.
#
# However, any changes you make to this file will be preserved.

# check to see if kernel has masquerade built in
if [ ! -e /proc/net/ip_forward -a ! -e /proc/sys/net/ipv4/ip_forward ]; then
    echo "IP Forwarding has not been enabled in the kernel."
    exit 1
fi

if [ ! -e /proc/net/ip_masquerade -a ! -e /proc/net/ip_tables_names ]; then
    if ! /sbin/modprobe -q iptable_nat 2>/dev/null; then
        echo "IP Masquerade has not been enabled in the kernel."
        exit 1
    fi
fi

A01interfaces.rul

Define the network interfaces configured in the system. The following environment variables are defined:

  • EXTERNAL = A list of interfaces connected to the internet
  • INTERNAL = A list of interfaces connected to local area networks
  • INTMASQ = A list of internal interfaces that have to be masqueraded
  • LOCAL = A list of interfaces connected to other nodes in a cluster
  • REALSERV = A list of interfaces configured as real servers in a Linux Virtual Server configuration, needed for direct routing and tunnel modes only.
  • IMAP = IMAP/POP3 server IP address
  • HTTP = HTTP server IP address for the local networks
  • OPENVPN = OpenVPN tunnel IP address
  • SMTPAUTH = Authenticated SMTP server IP address
  • VIRTSERVIP = Linux Virtual Server IP address

The script generates a list of active network interfaces and IP addresses used in the subsequent scripts.

#: Define interfaces

# External interfaces
EXTERNAL=eth0
# Internal interfaces (local networks)
INTERNAL=eth1
# Internal interfaces that have to be masqueraded
INTMASQ=eth1
# Local interfaces (cluster nodes etc.)
LOCAL=eth2
# Real server interfaces (for load balancers)
REALSERV=
# Cluster IP addresses
IMAP=192.168.1.1
HTTP=192.168.1.2
OPENVPN=192.168.1.3
SMTPAUTH=192.168.1.4
# Virtual server IP addresses
VIRTSERVIP=75.127.235.10

# remove external interfaces that are also listed as internal or local
if [ -n "$EXTERNAL" ]; then
    for i in $EXTERNAL; do
        INTERNAL=$(echo $INTERNAL | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
        INTMASQ=$(echo $INTMASQ | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
        LOCAL=$(echo $LOCAL | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
        REALSERV=$(echo $REALSERV | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
    done
fi

# remove masqueraded interfaces that are also listed as internal
if [ -n "$INTMASQ" ]; then
    for i in $INTMASQ; do
        INTERNAL=$(echo $INTERNAL | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
    done
fi

# remove interfaces that don't have networks attached to them
for i in $EXTERNAL $INTERNAL $INTMASQ $LOCAL $REALSERV; do
        nm=$(nmofif $i)
        if [ -z "${nm}" ]; then
            EXTERNAL=$(echo $EXTERNAL | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
            INTERNAL=$(echo $INTERNAL | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
            INTMASQ=$(echo $INTMASQ | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
            LOCAL=$(echo $LOCAL | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
            REALSERV=$(echo $REALSERV | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
        fi
done

A01precompute.rul

Generates a list of IP addresses and netmasks for the active interfaces. The cached values are used by the subsequent scripts.

# display if -d
if [ "$SHOWRULES" = "yes" ]; then
    echo "#: Interfaces found:"
fi

# precompute ips and netmasks
for i in $EXTERNAL $LOCAL $INTERNAL $INTMASQ; do
        ii=$(echo $i | sed -e 's/\:/_/g' -e 's/\./__/g')
        ip=$(ipofif $i)
        nm=$(nmofif $i)
        peer=$(peerofif $i)
        bc=$(bcofif $i)
        eval "IPOFIF_$ii=$ip"
        eval "NMOFIF_$ii=$nm"
        eval "PEEROFIF_$ii=$peer"
        eval "BCOFIF_$ii=$bc"
        if [ "$SHOWRULES" = "yes" ]; then
            echo -e "#:   $i\t$ip/$nm"
        fi
done

A02masqmethod.rul

Sets command paths and parameters.

# export command paths
export IPTABLES=/sbin/iptables

# modify command paths to deal with --display, --no-act, and --verbose
if [ "$SHOWRULES" = "yes" ]; then
    if [ "$NOACT" = "yes" ]; then
        IPTABLES="echo $IPTABLES"
    else
        showanddo () {
            echo "$@"
            "$@"
        }

        IPTABLES="showanddo $IPTABLES"
    fi
else
    if [ "$NOACT" = "yes" ]; then
        IPTABLES=":"
    fi
fi

A02unkernelforward.def

Script distributed with the ipmasq package, turns off IP forwarding before modifying the iptables rules.

# You should not edit this file.  Instead, create a file with the same
# name as this one, but with a .rul extension instead of .def.  The
# .rul file will override this one.
#
# However, any changes you make to this file will be preserved.

#: Turn off forwarding for 2.1 kernels
if [ -e /proc/sys/net/ipv4/ip_forward ]; then
    if [ "$NOACT" != "yes" ]; then
        echo "0" > /proc/sys/net/ipv4/ip_forward
    fi

    if [ "$SHOWRULES" = "yes" ]; then
        echo "echo \"0\" > /proc/sys/net/ipv4/ip_forward"
    fi
fi

#: Disable automatic IP defragmentation
if [ -e /proc/sys/net/ipv4/ip_always_defrag ]; then
    if [ "$NOACT" != "yes" ]; then
        echo "0" > /proc/sys/net/ipv4/ip_always_defrag
    fi

    if [ "$SHOWRULES" = "yes" ]; then
        echo "echo \"0\" > /proc/sys/net/ipv4/ip_always_defrag"
    fi
fi

A03flush.rul

Flushes all chains, sets a default 'DROP' policy and enables the local interfaces.

#: Flush all, set default policy of deny and enable local interfaces.
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -F INPUT
$IPTABLES -A INPUT -j ACCEPT -i lo
if [ -n "$LOCAL" ]; then
    for i in $LOCAL; do
        $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*}
    done
fi
$IPTABLES -F OUTPUT
$IPTABLES -A OUTPUT -j ACCEPT -o lo
if [ -n "$LOCAL" ]; then
    for i in $LOCAL; do
        $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*}
    done
fi
$IPTABLES -F FORWARD
$IPTABLES -t mangle -P PREROUTING ACCEPT
$IPTABLES -t mangle -P OUTPUT ACCEPT
$IPTABLES -t mangle -F PREROUTING
$IPTABLES -t mangle -F OUTPUT
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t nat -F PREROUTING
$IPTABLES -t nat -F POSTROUTING
$IPTABLES -t nat -F OUTPUT

A04functions.def

This script is included in the ipmasq package and definesfunctions used in subsequent scripts.

# You should not edit this file.  Instead, create a file with the same
# name as this one, but with a .rul extension instead of .def.  The
# .rul file will override this one.
#
# However, any changes you make to this file will be preserved.

# define used functions
ipnm_cache () {
    privatei=$(echo $1 | sed -e 's/\:/_/g' -e 's/\./__/g')
    eval "IPOFIF=\$IPOFIF_$privatei"
    eval "NMOFIF=\$NMOFIF_$privatei"
    eval "PEEROFIF=\$PEEROFIF_$privatei"
    eval "BCOFIF=\$BCOFIF_$privatei"
    return
}

A10smtpfwd.rul

Generates a list of IP addresses and netmasks for the interfaces used to forward SMTP connections to the mail servers. The cached values are used by the subsequent scripts.

#: Define SMTP forwarding interfaces

# External interfaces
SMTPFWD="eth0 eth0:0"

# remove interfaces that don't have networks attached to them
for i in $SMTPFWD; do
        nm=$(nmofif $i)
        if [ -z "${nm}" ]; then
            SMTPFWD=$(echo $SMTPFWD | sed -e "s/\(  *\|^\)$i\(  *\|$\)/\1/")
        fi
done

# precompute ips and netmasks
for i in $SMTPFWD; do
        ii=$(echo $i | sed -e 's/\:/_/g' -e 's/\./__/g')
        ip=$(ipofif $i)
        nm=$(nmofif $i)
        peer=$(peerofif $i)
        bc=$(bcofif $i)
        eval "IPOFIF_$ii=$ip"
        eval "NMOFIF_$ii=$nm"
        eval "PEEROFIF_$ii=$peer"
        eval "BCOFIF_$ii=$bc"
        if [ "$SHOWRULES" = "yes" ]; then
            echo -e "#:   $i\t$ip/$nm"
        fi
done

Custom chains

C00abuse.rul

This script initializes the ABUSE and SBLDROP chains, which deny connections from abusive hosts. The SBLDROP chain is generated by downloading the Spamhaus "Do not route or peer (DROP)" list and converting it into iptables rules. The ABUSE chain is reserved for site-specific rules.

#: Initialize the ABUSE chain (networks that we don't want connections from)
$IPTABLES -F ABUSE
$IPTABLES -X ABUSE
$IPTABLES -N ABUSE

#: Initialize the SBLDROP chain (networks listed on http://www.spamhaus.org/drop)
$IPTABLES -F SBLDROP
$IPTABLES -X SBLDROP
$IPTABLES -N SBLDROP

#: Insert the chains into the INPUT and FORWARD rules
for i in $EXTERNAL; do
    $IPTABLES -A INPUT -j ABUSE -i $i
    $IPTABLES -A INPUT -j SBLDROP -i $i
    $IPTABLES -A FORWARD -j ABUSE -i $i
    $IPTABLES -A FORWARD -j SBLDROP -i $i
done

C00invalid.rul

Drop bogus TCP packets.

#: Drop bogus TCP packets
$IPTABLES -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "C00invalid-INPUT-"
$IPTABLES -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPTABLES -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "C00invalid-INPUT-"
$IPTABLES -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP

C01dns.rul

Initialize the BINDIN chain. The BINDIN chain allows secondary name servers to transfer zones from the master name server.

# Initialize the external DNS transfer chains
$IPTABLES -F BINDIN
$IPTABLES -X BINDIN
$IPTABLES -N BINDIN


Forwarding Chain Rules

F30internal.rul

This script sets up the FORWARD chain rules allowing packet forwarding between local area networks.

for j in $INTERNAL $INTMASQ; do
        test `echo $j | grep -v ':'` && $IPTABLES -A FORWARD -j ACCEPT -i $j -o $j
        ipnm_cache $j
        DESTIP=$IPOFIF
        DESTNM=$NMOFIF
        for i in $INTERNAL $INTMASQ; do
          if [ "$i" != "$j" ] || echo $i | grep -q "^br"; then
            # if $i and $j are different or start with "br"
            ipnm_cache $i
            if [ -n "$PEEROFIF" ]; then
                for ipnm in `/sbin/route -n | grep -v '^0\.' | grep " $j\$" | awk '{printf "%s/%s ", $1, $3}'`
                do
                    $IPTABLES -A FORWARD -j ACCEPT -s $PEEROFIF/$NMOFIF -d $ipnm
                done
                $IPTABLES -A FORWARD -j ACCEPT -d $PEEROFIF/$NMOFIF
            fi
            for ipnm in `/sbin/route -n | grep -v '^0\.' | grep " $i\$" | awk '{printf "%s/%s ", $1, $3}'`
            do
                for destipnm in `/sbin/route -n | grep -v '^0\.' | grep " $j\$" | awk '{printf "%s/%s ", $1, $3}'`
                do
                    $IPTABLES -A FORWARD -j ACCEPT -s $ipnm -d $destipnm
                done
            done
          fi
        done
done

Input Chain Rules

The following scripts set the INPUT chain rules.

I15spoof.rul

Prevent the spoofing of local interfaces.

#: Prevent spoofing of local and internal interfaces
$IPTABLES -A INPUT -j LOG -i ! lo -s 127.0.0.1/255.0.0.0 --log-prefix "I15spoof-INPUT "
$IPTABLES -A INPUT -j DROP -i ! lo -s 127.0.0.1/255.0.0.0
for i in $LOCAL; do
        ipnm_cache $i
        if [ "$NMOFIF" != "0.0.0.0" ]; then
            $IPTABLES -A INPUT -j LOG -i ! ${i%%:*} -s $IPOFIF --log-prefix "I15spoof-INPUT "
            $IPTABLES -A INPUT -j DROP -i ! ${i%%:*} -s $IPOFIF
        fi
done

I30intbcast.rul

Accept broadcast packets on the internal interfaces.

#: Accept dumb broadcast packets on internal interfaces
for i in $INTERNAL $INTMASQ; do
        ipnm_cache $i
        $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*} -d 255.255.255.255/32
done

I30internal.rul

Accept packets from internal networks on internal interfaces.

#: Accept packets from internal networks on internal interfaces
for i in $INTERNAL $INTMASQ; do
        if [ `/sbin/route -n | grep '^0\.' | grep " $i\$" | wc -l` -gt 0 ] ; then
            $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*}
        else
            ipnm_cache $i
            if [ -n "$PEEROFIF" ]; then
                $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*} -s $PEEROFIF/$NMOFIF
            else
                for ipnm in `/sbin/route -n | grep " $i\$" | awk '{printf "%s/%s ", $1, $3}'`
                do
                    $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*} -s $ipnm
                done
            fi
        fi
done

I32intmcast.rul

Accept multicast packets on the internal interfaces.

#: Accept multicast packets (adresses 224.0.0.0) from internal interfaces
for i in $INTERNAL $INTMASQ; do
        ipnm_cache $i
        $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*} -d 224.0.0.0/4 -p ! 6 #tcp
done

I70masq.rul

Prevent SYN floods and spoofing of internal hosts on external interfaces.

#: Disallow and log packets trying to come in over external interfaces
#: from hosts claiming to be internal
for j in $EXTERNAL; do
        # Prevent smurf attacks
        $IPTABLES -A INPUT -i ${j%%:*} -p tcp -m tcp --tcp-flags RST RST -m limit --limit 5/second --limit-burst 5 -j ACCEPT
        # Prevent SYN floods
        $IPTABLES -A INPUT -i ${j%%:*} -m state --state NEW -p tcp -m tcp --syn -m recent --name synflood --update --seconds 1 --hitcount 20 -j DROP
        $IPTABLES -A INPUT -i ${j%%:*} -m state --state NEW -p tcp -m tcp --syn -m recent --name synflood --set
        for i in $INTERNAL $INTMASQ; do
            ipnm_cache $i
            if [ "$NMOFIF" != "0.0.0.0" ]; then
                IPNMOFIF=`netmask $IPOFIF/$NMOFIF`
                $IPTABLES -A INPUT -j LOG -i ${j%%:*} -s $IPNMOFIF --log-prefix "I70masq-INPUT "
                $IPTABLES -A INPUT -j DROP -i ${j%%:*} -s $IPNMOFIF
                for ipnm in `/sbin/route -n | grep -v '^0\.' | grep " $i\$" | awk '{printf "%s/%s ", $1, $3}'`
                do
                    IPNM=`netmask $ipnm`
                    test $IPNM = $IPNMOFIF && continue
                    $IPTABLES -A INPUT -j LOG -i ${j%%:*} -s $IPNM --log-prefix "I70masq-INPUT "
                    $IPTABLES -A INPUT -j DROP -i ${j%%:*} -s $IPNM
                done
            fi
        done
done

I80external.rul

Accept incoming packets on external interfaces for established connections.

#: Accept incoming packets from external networks on external interfaces
for i in $EXTERNAL; do
        ipnm_cache $i
        $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*} -d $IPOFIF/32 -m state --state ESTABLISHED,RELATED
done

Masquerading Rules

M70masq.rul

Masquerade packets from internal connections and forward established connections over the external interfaces.

#: Masquerade packets from internal networks
for j in $EXTERNAL; do
    for i in $INTERNAL $INTMASQ; do
        ipnm_cache $i
        if [ -n "$PEEROFIF" ]; then
            $IPTABLES -t nat -A POSTROUTING -o ${j%%:*} -s $PEEROFIF/$NMOFIF -j MASQUERADE
            $IPTABLES -A FORWARD -i ${i%%:*} -o ${j%%:*} -s $PEEROFIF/$NMOFIF -j ACCEPT
        else
            IPNMOFIF=`netmask $IPOFIF/$NMOFIF`
            $IPTABLES -t nat -A POSTROUTING -o ${j%%:*} -s $IPNMOFIF -j MASQUERADE
            $IPTABLES -A FORWARD -i ${i%%:*} -o ${j%%:*} -s $IPNMOFIF -j ACCEPT
            for ipnm in `/sbin/route -n | grep -v '^0\.' | grep " $i\$" | awk '{printf "%s/%s ", $1, $3}'`
            do
                IPNM=`netmask $ipnm`
                test $IPNM = $IPNMOFIF && continue
                $IPTABLES -t nat -A POSTROUTING -o ${j%%:*} -s $IPNM -j MASQUERADE
                $IPTABLES -A FORWARD -i ${i%%:*} -o ${j%%:*} -s $IPNM -j ACCEPT
            done
        fi
    done
done
for j in $INTERNAL; do
    for i in $INTMASQ; do
        ipnm_cache $i
        if [ -n "$PEEROFIF" ]; then
            $IPTABLES -t nat -A POSTROUTING -o ${j%%:*} -s $PEEROFIF/$NMOFIF -j MASQUERADE
            $IPTABLES -A FORWARD -i ${i%%:*} -o ${j%%:*} -s $PEEROFIF/$NMOFIF -j ACCEPT
        else
            IPNMOFIF=`netmask $IPOFIF/$NMOFIF`
            $IPTABLES -t nat -A POSTROUTING -o ${j%%:*} -s $IPNMOFIF -j MASQUERADE
            $IPTABLES -A FORWARD -i ${i%%:*} -o ${j%%:*} -s $IPNMOFIF -j ACCEPT
            for ipnm in `/sbin/route -n | grep -v '^0\.' | grep " $i\$" | awk '{printf "%s/%s ", $1, $3}'`
            do
                IPNM=`netmask $ipnm`
                test $IPNM = $IPNMOFIF && continue
                $IPTABLES -t nat -A POSTROUTING -o ${j%%:*} -s $IPNM -j MASQUERADE
                $IPTABLES -A FORWARD -i ${i%%:*} -o ${j%%:*} -s $IPNM -j ACCEPT
            done
        fi
    done
done
#
# Continue forwarding for RELATED or ESTABLISHED packets
#
if [ -n "$EXTERNAL" -o -n "$INTMASQ" ] ; then
    $IPTABLES -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
fi

Output Chain Rules

The following scripts set the OUTPUT chain rules.

O30intbcast.rul

Allow broadcasting packets on the internal interfaces.

#: Allow dumb broadcast packets to leave on internal interfaces
for i in $INTERNAL $INTMASQ; do
    ipnm_cache $i
    $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*} -d 255.255.255.255/32
done

O30internal.rul

Allow packets to internal networks on internal interfaces.

#: Allow packets for internal hosts to be delivered using internal interfaces
for i in $INTERNAL $INTMASQ; do
        if [ `/sbin/route -n | grep '^0\.' | grep " $i\$" | wc -l` -gt 0 ] ; then
            $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*}
        else
            ipnm_cache $i
            if [ -n "$PEEROFIF" ]; then
                $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*} -d $PEEROFIF/$NMOFIF
            else
                for ipnm in `/sbin/route -n | grep " $i\$" | awk '{printf "%s/%s ", $1, $3}'`
                do
                    $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*} -d $ipnm
                done
            fi
        fi
done

O32intmcast.rul

Allow multicast packets on internal interfaces.

#: Allow multicast packets (adresses 224.0.0.0) to be delivered using
#: internal interfaces
for i in $INTERNAL $INTMASQ; do
        ipnm_cache $i
        $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*} -d 224.0.0.0/4 -p ! 6 #tcp
done

O70masq.rul

Prevent spoofing of internal IP addresses over external interfaces.

#: Deny and log packets attempting to leave over external interfaces claiming
#: to be for internal networks
for j in $EXTERNAL; do
        for NETWORK in 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16
        do
                $IPTABLES -A FORWARD -j LOG -o ${j%%:*} -d $NETWORK --log-prefix "O70masq-OUTPUT "
                $IPTABLES -A FORWARD -j DROP -o ${j%%:*} -d $NETWORK
                $IPTABLES -A OUTPUT -j LOG -o ${j%%:*} -d $NETWORK --log-prefix "O70masq-OUTPUT "
                $IPTABLES -A OUTPUT -j DROP -o ${j%%:*} -d $NETWORK
        done
done

O80external.rul

Allow packets for external networks over external interfaces.

#: Allow packets for external networks leave over external interfaces
for i in $EXTERNAL; do
        ipnm_cache $i
        $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*} -s $IPOFIF/32
        IPSECLIST=`ip addr | grep " secondary ${i%%:*}\$" | awk '{print $2}' | cut -f1 -d/`
        IPSECLIST2=`ip addr | grep " secondary ${i}:" | awk '{print $2}' | cut -f1 -d/`
        for IPADDR in $IPSECLIST $IPSECLIST2 $VIRTSERVIP ; do
                $IPTABLES -A OUTPUT -j ACCEPT -o ${i%%:*} -s $IPADDR/32
        done
done

Service-oriented Rule Sets

The following rule sets open the firewall for specific services - DNS, SMTP, SMTPAUTH, HTTP, HTTPS, FTP, IMAP and POP3.

Rules starting with S02 allow connections on the specified ports to the IP address of the virtual server.

Rules starting with S05 allow connections on the specified ports to local host IP addresses.

S02dnslvs.rul

Accept UDP packets on port 53 (DNS) and pass TCP/53 packets through the BINDIN chain, allowing zone transfers to secondary name servers whose IP addresses have to be included in the BINDIN chain.

#: Accept DNS traffic to port 53
for i in $EXTERNAL ; do
    $IPTABLES -A INPUT -j ACCEPT -i ${i%%:*} -m udp -p udp -d $VIRTSERVIP/32 --dport 53
    $IPTABLES -A INPUT -j BINDIN -i ${i%%:*} -m tcp -p tcp -d $VIRTSERVIP/32 --dport 53
done

S02ftplvs.rul

Allow incoming FTP connections to the virtual server.

#: Allow connections on port 21 (ftp) to the virtual server
if [ -n "$EXTERNAL" -a -n "$VIRTSERVIP" ] ; then
   for i in $EXTERNAL ; do
      $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport 21
      $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 -m multiport --dports 61440:65534
   done
fi

S02httplvs.rul

Enable incoming HTTP and HTTPS connections to the virtual server.

#: Forward connections to tcp ports 80 and 443
if [ -n "$EXTERNAL" -a -n "$VIRTSERVIP" ] ; then
  for i in $EXTERNAL ; do
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport 80
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport 443
  done
fi

S02imaplvs.rul

Allow IMAP and POP3 connections to the virtual server.

#: Allow connections on port 110 and 143 (pop3 and imap) to the virtual server
if [ -n "$EXTERNAL" -a -n "$VIRTSERVIP" ] ; then
  for i in $EXTERNAL ; do
    for PORT in 110 143 993 995 ; do
      $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport $PORT
    done
  done
fi

S02openvpnlvs.rul

Allow OPENVPN connections to the virtual server.

#: Allow connections on port 1194 (openvpn) to the virtual server
if [ -n "$EXTERNAL" -a -n "$VIRTSERVIP" ] ; then
  for i in $EXTERNAL ; do
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport 1194
  done
fi

S02smtpauthlvs.rul

Allow SMTP-AUTH connections to the virtual server.

#: Allow connections on port 587 (smtp-auth) to the virtual server
if [ -n "$EXTERNAL" -a -n "$VIRTSERVIP" ] ; then
  for i in $EXTERNAL ; do
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport 587
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $VIRTSERVIP/32 --dport 25
  done
fi

S05icmp.rul

Allow PING on the external interfaces.

#: Enable ping
$IPTABLES -A INPUT -p icmp -m icmp --icmp-type echo-request -m limit --limit 4/second -j ACCEPT
$IPTABLES -A OUTPUT -j ACCEPT -p icmp --icmp-type echo-reply

S05smtpfwd.rul

Forward SMTP connections to the mail server.

if [ -n "$EXTERNAL" -a -n "$SMTPFWD" ] ; then
  for i in $SMTPFWD ; do
    ipnm_cache $i
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $IPOFIF/32 --dport 25
  done
fi

S05sshlimit.rul

Allow SSH connections on external interfaces and limit new connections to 10 / minute per IP address.

#: Limit new SSH connections to 10/minute
for i in $EXTERNAL ; do
    ipnm_cache $i
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $IPOFIF/32 --dport 22 \
      -m state --state ESTABLISHED,RELATED
    $IPTABLES -A INPUT -i ${i%%:*} -j DROP -m tcp -p tcp -d $IPOFIF/32 --dport 22 \
      -m state --state NEW -m recent --name tcp22 --update --seconds 60 --hitcount 20
    $IPTABLES -A INPUT -i ${i%%:*} -j LOG -m tcp -p tcp -d $IPOFIF/32 --dport 22 \
      -m state --state NEW -m recent --name tcp22 --update --seconds 60 --hitcount 10 --log-prefix "S05sshlimit-"
    $IPTABLES -A INPUT -i ${i%%:*} -j DROP -m tcp -p tcp -d $IPOFIF/32 --dport 22 \
      -m state --state NEW -m recent --name tcp22 --update --seconds 60 --hitcount 10
    $IPTABLES -A INPUT -i ${i%%:*} -j ACCEPT -m tcp -p tcp -d $IPOFIF/32 --dport 22 \
      -m state --state NEW -m recent --name tcp22 --set
done

Final Scripts

The following scripts set up the logging of rejected packets not caught by the rules and enable packet forwarding.

Z90kernelforward.def

Script included in the standard ipmasq package, enables IP packets forwarding after the firewall has been set up.

# You should not edit this file.  Instead, create a file with the same
# name as this one, but with a .rul extension instead of .def.  The
# .rul file will override this one.
#
# However, any changes you make to this file will be preserved.

#: Turn on forwarding for 2.1 kernels
if [ -e /proc/sys/net/ipv4/ip_forward ]; then
    if [ "$NOACT" != "yes" ]; then
        echo "1" > /proc/sys/net/ipv4/ip_forward
    fi

    if [ "$SHOWRULES" = "yes" ]; then
        echo "echo \"1\" > /proc/sys/net/ipv4/ip_forward"
    fi
fi

#: Enable automatic IP defragmentation
if [ -e /proc/sys/net/ipv4/ip_always_defrag ]; then
    if [ "$NOACT" != "yes" ]; then
        echo "1" > /proc/sys/net/ipv4/ip_always_defrag
    fi

    if [ "$SHOWRULES" = "yes" ]; then
        echo "echo \"1\" > /proc/sys/net/ipv4/ip_always_defrag"
    fi
fi

ZZZdenyandlog.rul

Log and deny packets not caught by other rules.

#: Deny and log anything that may have snuck past any of our other rules
$IPTABLES -A INPUT -j LOG -s 0.0.0.0/0 -d 0.0.0.0/0 --log-prefix "ZZZdenyandlog-INPUT "
$IPTABLES -A INPUT -j DROP -s 0.0.0.0/0 -d 0.0.0.0/0
$IPTABLES -A OUTPUT -j LOG -s 0.0.0.0/0 -d 0.0.0.0/0 --log-prefix "ZZZdenyandlog-OUTPUT "
$IPTABLES -A OUTPUT -j DROP -s 0.0.0.0/0 -d 0.0.0.0/0
$IPTABLES -A FORWARD -j LOG -s 0.0.0.0/0 -d 0.0.0.0/0 --log-prefix "ZZZdenyandlog-FORWARD "
$IPTABLES -A FORWARD -j DROP -s 0.0.0.0/0 -d 0.0.0.0/0
Personal tools