#!/bin/bash #picofirewall.conf

#
# picoFIREWALL
# Do not change this line!  Version: -V2.9- 28Apr2004 / uk
#
# picofirewall.conf
#
# - This file contains HTML-commands to be viewed through a browser!
#
# - picoFIREWALL is - as the name implies - a small firewall. It is based on
#   information I have received from various sources; see file REFERENCES.
# - More information is given in the file README.
# - The installation of picoFIREWALL is explained in the file INSTALL.
# - Configuration of picoFIREWALL is done below, between the lines with '====='
#
#==============================================================================
## START of your personal configuration...
#
#>>> Please note: after any changes made in this file you have to enter  <<<
#>>>              ' picofirewall start '                                 <<<
#
# Interface to the Internet: eth0, ppp0 ... or whatever it is:
#
IFACE="eth0"

#
# Would you like that all machines can send a ping to your machine?
# Select "yes" or "no" on the following line. You may still exclude certain
# machines from pinging to you in the files noise_log.cfg or noise_nolog.cfg :
#
ALLOW_PING="no"

#
# Is the machine we are running on, a web- or a mail-server?
# Add the hostnames of those machines into the variables WEBSERVERS (and
# SECWEBSERVERS for secure webservers [https]), and MAILSERVERS below.
# If you have to maintain several machines, you may like this; add the host
# names of your web- and mail-servers here:
#
WEBSERVERS="zak seismo50 yogibear"
SECWEBSERVERS=""
MAILSERVERS="zak yogibear"

#
# Is this machine a DHCP server? Add the hostnames of those machines into the
# variable DHCPSERVERS below; if this script is for just one machine, add one.
#
DHCPSERVERS=""

#
# Many annoying packets, which are dropped anyway, are now only minimally
# logged. However, there are more than 65'000 ports... and we usually just want
# to be informed, but not have our log-file filled. Therefore, the default is
# now to log all dropped packets only partially (1 per hour). If you want more
# entries in the log-file, set the variable below to "no".
#
LIMIT_DROP_LOGGING="yes"

#
# If you really trust the TRUSTED hosts defined in /etc/picofirewall.trusted,
# then you may also want to limit the logging from packets of these machines.
# If you want more entries in the log-file, set the variable below to "no".
#
LIMIT_ACCEPT_LOGGING="yes"

#
## ...END of your personal configuration.
#==============================================================================
#
# check, whether we are on a Debian system:
if test -x /usr/bin/apt-get ; then
   debian="true"
   LOGLEVEL="warn"
else
   debian="false"
   LOGLEVEL="warning"
fi

#
# Check, whether we are a webserver, a secure webserver, a mailserver, or
# a dhcp server:
#
webserver="no"
secwebserver="no"
mailserver="no"
dhcpserver="no"
for ws in $WEBSERVERS ; do
   if test `hostname` = "$ws" ; then
      webserver="yes"
   fi
done
for sws in $SECWEBSERVERS ; do
   if test `hostname` = "$sws" ; then
      secwebserver="yes"
   fi
done
for ms in $MAILSERVERS ; do
   if test `hostname` = "$ms" ; then
      mailserver="yes"
   fi
done
for dhs in $DHCPSERVERS ; do
   if test `hostname` = "$dhs" ; then
      dhcpserver="yes"
   fi
done

#
# Here we define the limited logging for DROPped and ACCEPTed packets, as well
# as the logging of packets from noisy machines:
#
if test "$LIMIT_DROP_LOGGING" = "yes" ; then
   limD="-m limit --limit 1/hour --limit-burst 1"
else
   limD="-m limit --limit 1/minute --limit-burst 1"
fi
#
if test "$LIMIT_ACCEPT_LOGGING" = "yes" ; then
   limA="-m limit --limit 1/day --limit-burst 1"
else
   limA="-m limit --limit 1/hour --limit-burst 1"
fi
#
limN="-m limit --limit 1/day --limit-burst 1"
#

#
# Load appropriate modules of the kernel:
#
modprobe ip_tables
modprobe ip_conntrack
modprobe ip_conntrack_ftp

#
# In case we rerun this script: flush all chains, delete every non-builtin
# chain, and zero the packet and byte counters in all chains.
#
iptables -F
iptables -X
iptables -Z

#
# Set up a default DROP policy for the built-in chains.
# 'filter' is the default table. It contains the built-in chains INPUT,
# FORWARD, and OUTPUT.
# If we modify and re-run the script mid-session then (because we have a default
# DROP policy), what happens is that there is a small time period when packets
# are denied until the new rules are back in place. There is no period, however
# small, when packets we don't want are allowed.
#
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP
#
# find out IP address for this interface:
#
IPADDR=`ifconfig $IFACE | grep "inet addr" |cut -d':' -f 2 |cut -d' ' -f 1`

#
# find out Broadcast address for this interface:
#
BROADCAST=`ifconfig $IFACE | grep Bcast |cut -d':' -f 3 |cut -d' ' -f 1`

#
# find out the Domain Name Servers (DNS) used on this machine:
#
#NAMESERVER=`grep ^nameserver /etc/resolv.conf | tr '  ' ' ' | cut -d" " -f 2`
# Currently, this is not used... we allow incoming tcp/udp packets from port 53

#
# Definitions of some IPs...
#
LOOPBACK="127.0.0.0/8"
CLASS_A="10.0.0.0/8"
CLASS_B="172.16.0.0/12"
CLASS_C="192.168.0.0/16"
##uk##CLASS_D_MULTICAST="224.0.0.0/4"
# uk # see e.g. http://koeln.ccc.de/~drt/multicast.txt
# uk # see e.g. http://www.faqs.org/rfcs/rfc3171.html
#uk???#CLASS_D_MULTICAST="224.0.0/24"
CLASS_D_MULTICAST="224.0.0.1"

#
#
# Attention: DHCP server answers messages on the IP address 224.0.0.12
# (but only on a subnet)
#
# If you do not need multicast, uncomment the following line:
# (Do *not* do it if you are running VMware)
#
# iptables -t mangle -I PREROUTING -j DROP -d 224.0.0.0/8

#
CLASS_E_RESERVED_NET="240.0.0.0/5"
# not used#P_PORTS="0:1023"
UP_PORTS="1024:65535"
TR_SRC_PORTS="32769:65535"
TR_DEST_PORTS="33434:33523"

#
#------------------------------------------------------------------------------
## Kernel flags
# To dynamically change kernel parameters and variables on the fly you need
# CONFIG_SYSCTL defined in your kernel. I would advise the following:

# Disable response to ping.
# We are *not* doing this by default anymore; this is now handled in the
# ICMP section below in order to be more flexible.
#
###/bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
# We do the following in case someone has used an older version of picoFirewall:
/bin/echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_all

#
# Disable response to broadcasts.
# You don't want yourself becoming a Smurf amplifier.
#
/bin/echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

#
# Don't accept source routed packets. Attackers can use source routing to
# generate traffic pretending to be from inside your network, but which is
# routed back along the path from which it came, namely outside, so attackers
# can compromise your network. Source routing is rarely used for legitimate
# purposes.
#
/bin/echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route

#
# Disable ICMP redirect acceptance. ICMP redirects can be used to alter your
# routing tables, possibly to a bad end.
#
for interface in /proc/sys/net/ipv4/conf/*/accept_redirects; do
   /bin/echo "0" > ${interface}
done

#
# Enable bad error message protection.
#
/bin/echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

#
# Turn on reverse path filtering. This helps make sure that packets use
# legitimate source addresses, by automatically rejecting incoming packets
# if the routing table entry for their source address doesn't match the network
# interface they're arriving on. This has security advantages because it
# prevents so-called IP spoofing, however it can pose problems if you use
# asymmetric routing (packets from you to a host take a different path than
# packets from that host to you) or if you operate a non-routing host which has
# several IP addresses on different interfaces. (Note - If you turn on IP
# forwarding, you will also get this).
#
for interface in /proc/sys/net/ipv4/conf/*/rp_filter; do
   /bin/echo "1" > ${interface}
done

#
# Log spoofed packets, source routed packets, redirect packets.
#
/bin/echo "1" > /proc/sys/net/ipv4/conf/all/log_martians

#
# Make sure that IP forwarding is turned off. We only want this for a
# multi-homed host.
#
/bin/echo "0" > /proc/sys/net/ipv4/ip_forward

#
# Note: With connection tracking, all fragments are reassembled before being
# passed to the packet-filtering code so there is no ip_always_defrag switch
# as there was in the 2.2 kernel.

#------------------------------------------------------------------------------
# RULES
#
# Define the logging parameters/text (to be referenced in the commands below):
#
LOGP="--log-level $LOGLEVEL --log-tcp-options --log-ip-options --log-prefix P-Fw"

#
#------------------------------------------------------------------------------
## LOOPBACK
# Allow unlimited traffic on the loopback interface:
#
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

#
#------------------------------------------------------------------------------
## VMWARE
# Allow unlimited traffic for the VMware interface vmnet8:
#
iptables -A INPUT  -i vmnet8 -j ACCEPT
iptables -A OUTPUT -o vmnet8 -j ACCEPT

#
#------------------------------------------------------------------------------
## ESTABLISHED & RELATED CONNECTIONS
# Accept (no log) packets to ESTABLISHED or RELATED connections. Things worked
# mostly fine without this, but listening radio or watching TV with RealPlayer
# did not work without this. Instead of only allowing it for port 554, we
# allow such packets generally.
#
iptables -A INPUT -i $IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT

#
#------------------------------------------------------------------------------
## WEB- AND MAIL-SERVER:
# Allow tcp inbound for the corresponging ports, if we are a web-/mail-server:
#
if test "$webserver" = "yes" ; then
   iptables -A INPUT  -i $IFACE -p tcp --dport 80 \
            -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
fi

if test "$secwebserver" = "yes" ; then
   iptables -A INPUT  -i $IFACE -p tcp --dport 443 \
            -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
fi

if test "$mailserver" = "yes" ; then
   iptables -A INPUT  -i $IFACE -p tcp --dport 25 \
            -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
fi

#
#------------------------------------------------------------------------------
## NOISY HOSTS/PORTS - NOT LOGGED
if test -r /etc/picofirewall/noise_nolog.cfg ; then
   NOISENOLOG=`cat /etc/picofirewall/noise_nolog.cfg | grep -v ^# | cut -d# -f 1`
else
   NOISENOLOG=""
fi
#
for noise in $NOISENOLOG ; do
   ips=""
   pro=""
   por=""
   ip=`echo $noise | cut -d, -f 1`
   pr=`echo $noise | cut -d, -s -f 2`
   po=`echo $noise | cut -d, -s -f 3`
   if test ! -z "$ip" ; then ips="-s $ip" ; fi
   if test ! -z "$pr" ; then pro="-p $pr" ; fi
   if test ! -z "$po" ; then
      if test "$pr" = "icmp" ; then
         por="--icmp-type $po"
      else
         por="--dport $po"
      fi
   fi

   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state NEW,ESTABLISHED,RELATED,INVALID -j DROP
done

#
#------------------------------------------------------------------------------
## NOISY HOSTS/PORTS - LOGGED
if test -r /etc/picofirewall/noise_log.cfg ; then
   NOISELOG=`cat /etc/picofirewall/noise_log.cfg | grep -v ^# | cut -d# -f 1`
else
   NOISELOG=""
fi
#
for noise in $NOISELOG ; do
   ips=""
   pro=""
   por=""
   ip=`echo $noise | cut -d, -f 1`
   pr=`echo $noise | cut -d, -s -f 2`
   po=`echo $noise | cut -d, -s -f 3`
   if test ! -z "$ip" ; then ips="-s $ip" ; fi
   if test ! -z "$pr" ; then pro="-p $pr" ; fi
   if test ! -z "$po" ; then
      if test "$pr" = "icmp" ; then
         por="--icmp-type $po"
      else
         por="--dport $po"
      fi
   fi

   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state NEW \
            $limN -j LOG ${LOGP}"-DROP-noise_log-in: "
   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state NEW -j DROP

   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state ESTABLISHED,RELATED -j DROP
done

#
#------------------------------------------------------------------------------
## OPEN HOSTS/PORTS - NOT LOGGED
if test -r /etc/picofirewall/open_nolog.cfg ; then
   OPENNOLOG=`cat /etc/picofirewall/open_nolog.cfg | grep -v ^# | cut -d# -f 1`
else
   OPENNOLOG=""
fi
#
for open in $OPENNOLOG ; do
   ips=""
   pro=""
   por=""
   ip=`echo $open | cut -d, -f 1`
   pr=`echo $open | cut -d, -s -f 2`
   po=`echo $open | cut -d, -s -f 3`
   if test ! -z "$ip" ; then ips="-s $ip" ; fi
   if test ! -z "$pr" ; then pro="-p $pr" ; fi
   if test ! -z "$po" ; then
      if test "$pr" = "icmp" ; then
         por="--icmp-type $po"
      else
         por="--dport $po"
      fi
   fi

   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
done

#
#------------------------------------------------------------------------------
## OPEN HOSTS/PORTS - LOGGED
if test -r /etc/picofirewall/open_log.cfg ; then
   OPENLOG=`cat /etc/picofirewall/open_log.cfg | grep -v ^# | cut -d# -f 1`
else
   OPENLOG=""
fi
#
for open in $OPENLOG ; do
   ips=""
   pro=""
   por=""
   ip=`echo $open | cut -d, -f 1`
   pr=`echo $open | cut -d, -s -f 2`
   po=`echo $open | cut -d, -s -f 3`
   if test ! -z "$ip" ; then ips="-s $ip" ; fi
   if test ! -z "$pr" ; then pro="-p $pr" ; fi
   if test ! -z "$po" ; then
      if test "$pr" = "icmp" ; then
         por="--icmp-type $po"
      else
         por="--dport $po"
      fi
   fi

   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state NEW \
            $limA -j LOG ${LOGP}"-ACCEPT-open_log-in: "
   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state NEW -j ACCEPT

   iptables -A INPUT -i $IFACE $ips $pro $por \
            -m state --state ESTABLISHED,RELATED -j ACCEPT
done

#
#------------------------------------------------------------------------------
## SYN-FLOODING PROTECTION
# This rule maximises the rate of incoming connections. In order to do this we
# divert tcp packets with the SYN bit set off to a user-defined chain. Up to
# limit-burst connections can arrive in 1/limit seconds ..... in this case 4
# connections in one second. After this, one of the burst is regained every
# second and connections are allowed again. The default limit is 3/hour. The
# default limit burst is 5.
#
# We start a new chain 'syn-flood' and do some tests there; then we have the
# possibility to pass the OK packets back to the ruleset by the command 
# '-j RETURN' and drop the others.
#
# However, first we treat the case of web and mail servers: here we allow more
# SYN packets per time interval: 60/sec & limit-burst 60 --> (1/60)*60=1sec
# and hence the time burst-limit is recharged after one second.
#
if test "$webserver" = "yes" ; then
###   iptables -N syn-flood-web
###   iptables -A INPUT -i $IFACE -p tcp --dport 80 --syn -j syn-flood-web
   iptables -A INPUT -i $IFACE -p tcp --dport 80 --syn -j ACCEPT
###   iptables -A syn-flood-web -m limit --limit 1000/s --limit-burst 1000 -j RETURN
# The following is a testing version only....!!!!!
###   iptables -A syn-flood-web -m limit --limit 4/hour --limit-burst 11 \
###            -j LOG ${LOGP}"-DROP-SYN_floodWEB-IN: "
###   iptables -A syn-flood-web -j DROP
fi
#
if test "$mailserver" = "yes" ; then
   iptables -A INPUT -i $IFACE -p tcp --dport 25 --syn -j ACCEPT
fi
#
# Now treat syn-floods to all other ports:
#
iptables -N syn-flood
iptables -A INPUT -i $IFACE -p tcp --syn -j syn-flood
iptables -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN
#
## If *lots* of packets are arriving, logging should definitely be limited;
## burst-limit=11 --> detected by picofirescan, if maxpackspermin=10
## limit=4/hour --> 15min*11=165min --> after this time burst-limit is recharged
#
iptables -A syn-flood -m limit --limit 4/hour --limit-burst 11 \
         -j LOG ${LOGP}"-DROP-SYN_flood-IN: "
iptables -A syn-flood -j DROP


#
#------------------------------------------------------------------------------
## Make sure NEW tcp connections are SYN packets
#
iptables -A INPUT -i $IFACE -p tcp ! --syn -m state --state NEW \
         $limD -j LOG ${LOGP}"-DROP-NEWnoSYN-IN: "
iptables -A INPUT -i $IFACE -p tcp ! --syn -m state --state NEW -j DROP

#
#------------------------------------------------------------------------------
## DHCP
# Allow dhcp replies from servers
# The following is not necessary, since we already accept ESTABLISHED & RELATED
# connections!
#
###iptables -A INPUT -i $IFACE -p udp --sport 67 -d 255.255.255.255 --dport 68 \
###         -m state --state ESTABLISHED \
###         $limA -j LOG ${LOGP}"-ACCEPT-DHCP_reply-IN: "
###iptables -A INPUT -i $IFACE -p udp --sport 67 -d 255.255.255.255 --dport 68 \
###         -m state --state ESTABLISHED \
###         -j ACCEPT

#
# DHCP-SERVER
#
if test "$dhcpserver" = "yes" ; then
   iptables -A INPUT -i $IFACE -p udp --sport 68 --dport 67 \
            -m state --state NEW \
            $limA -j LOG ${LOGP}"-ACCEPT-DHCP_request-IN: "
   iptables -A INPUT -i $IFACE -p udp --sport 68 --dport 67 \
            -m state --state NEW,ESTABLISHED -j ACCEPT
fi

#
#------------------------------------------------------------------------------
## SPOOFING
# Most of this anti-spoofing stuff is theoretically not really necessary with
# the flags we have set in the kernel above ........... but you never know there
# isn't a bug somewhere in your IP stack.
#
# Refuse spoofed packets pretending to be from your IP address.
#
iptables -A INPUT -i $IFACE -s $IPADDR \
         $limD -j LOG ${LOGP}"-DROP-is_from_me-IN: "
iptables -A INPUT -i $IFACE -s $IPADDR -j DROP

#
# Refuse packets claiming to be from a Class A private network.
#
iptables -A INPUT -i $IFACE -s $CLASS_A $limD -j LOG ${LOGP}"-DROP-class_a-IN: "
iptables -A INPUT -i $IFACE -s $CLASS_A -j DROP

#
# Refuse packets claiming to be from a Class B private network.
#
iptables -A INPUT -i $IFACE -s $CLASS_B $limD -j LOG ${LOGP}"-DROP-class_b-IN: "
iptables -A INPUT -i $IFACE -s $CLASS_B -j DROP

#
# Refuse packets claiming to be from a Class C private network.
#
iptables -A INPUT -i $IFACE -s $CLASS_C $limD -j LOG ${LOGP}"-DROP-class_c-IN: "
iptables -A INPUT -i $IFACE -s $CLASS_C -j DROP

#
# Refuse Class D multicast addresses. Multicast is illegal as a source address.
# Do not log them...
#
iptables -A INPUT -i $IFACE -s $CLASS_D_MULTICAST \
         $limD -j LOG ${LOGP}"-DROP-multicast-IN: "
iptables -A INPUT -i $IFACE -s $CLASS_D_MULTICAST -j DROP

#
# Refuse Class E reserved IP addresses.
#
iptables -A INPUT -i $IFACE -s $CLASS_E_RESERVED_NET \
         $limD -j LOG ${LOGP}"-DROP-reserved_class-IN: "
iptables -A INPUT -i $IFACE -s $CLASS_E_RESERVED_NET -j DROP

#
# Refuse packets claiming to be to the loopback interface.
# Refusing packets claiming to be to the loopback interface protects against
# source quench, whereby a machine can be told to slow itself down by an icmp
# source

#
# quench to the loopback.
#
iptables -A INPUT  -i $IFACE -d $LOOPBACK \
         $limD -j LOG ${LOGP}"-DROP-to_loopback-IN: "
iptables -A INPUT  -i $IFACE -d $LOOPBACK -j DROP

#
# Refuse broadcast address packets.
#
iptables -A INPUT -i $IFACE -d $BROADCAST \
         $limD -j LOG ${LOGP}"-DROP-BROADCASTaddr-IN: "
iptables -A INPUT -i $IFACE -d $BROADCAST -j DROP

#
#------------------------------------------------------------------------------
## ICMP
#
# First we handle 'pings' seperately:
# If pings are allowed generally, we allow them here:
#
if test "ALLOW_PING" = "yes" ; then
   iptables -A INPUT  -i $IFACE -p icmp --icmp-type 8  -s 0/0 -d $IPADDR -j ACCEPT
fi

#
# We prefilter icmp by pulling it off to user-defined chains so that we can
# restrict which types are allowed from the beginning rather than leaving it to
# the connection tracking.
# For instance, we don't want redirects whatever happens.
# In case you hadn't realised, ICMP scares me ....(the words of snp...)
# My words:
# We start new chains 'icmp-in' and 'icmp-out' and do some tests there; then we
# have the possibility to pass the OK packets back to the ruleset by the
# command '-j RETURN' and drop the others.
#
#  0: echo reply (pong)
#  3: destination-unreachable (port-unreachable, fragmentation-needed etc).
#  4: source quench
#  5: redirect
#  8: echo request (ping)
#  9: router advertisement
# 10: router solicitation
# 11: time-exceeded
# 12: parameter-problem
# 13: timestamp request
# 14: timestamp reply
# 15: information request
# 16: information reply
# 17: address mask request
# 18: address mask reply
#
#
iptables -N icmp-in
iptables -N icmp-out

iptables -A INPUT  -i $IFACE -p icmp -j icmp-in
iptables -A OUTPUT -o $IFACE -p icmp -j icmp-out

#
# Accept 0,3,4,11,12,14,16,18 in.
#
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 0  -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 3  -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 4  -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 11 -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 12 -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 14 -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 16 -s 0/0 -d $IPADDR -j RETURN
iptables -A icmp-in -i $IFACE -p icmp --icmp-type 18 -s 0/0 -d $IPADDR -j RETURN

#
# Allow 4,8,12,13,15,17 out.
#
iptables -A icmp-out -o $IFACE -p icmp --icmp-type 4  -s $IPADDR -d 0/0 -j RETURN
iptables -A icmp-out -o $IFACE -p icmp --icmp-type 8  -s $IPADDR -d 0/0 -j RETURN
iptables -A icmp-out -o $IFACE -p icmp --icmp-type 12 -s $IPADDR -d 0/0 -j RETURN
iptables -A icmp-out -o $IFACE -p icmp --icmp-type 13 -s $IPADDR -d 0/0 -j RETURN
iptables -A icmp-out -o $IFACE -p icmp --icmp-type 15 -s $IPADDR -d 0/0 -j RETURN
iptables -A icmp-out -o $IFACE -p icmp --icmp-type 17 -s $IPADDR -d 0/0 -j RETURN

#
# Any ICMP not already allowed is logged and then dropped.
#
# We do not want to be alerted just by pings... So log them partially but not
# fully:
#
iptables -A INPUT -i $IFACE -p icmp --icmp-type 8 \
         $limD -j LOG ${LOGP}"-DROP-ICMP-ping-in: "
iptables -A INPUT -i $IFACE -p icmp --icmp-type 8 -j DROP
#
###why not? OUT should be ok...###iptables -A icmp-out -o $IFACE \
###why not? OUT should be ok...###-j LOG --log-level warning --log-tcp-options \
###why not? OUT should be ok...###         --log-ip-options --log-prefix \
###why not? OUT should be ok...###"P-Fw-DROP-ICMP-BAD-TYPE-OUT: "
###why not? OUT should be ok...###iptables -A icmp-out -o $IFACE -j DROP
#
iptables -A icmp-out -o $IFACE -j ACCEPT

#
# Now we have returned from the icmp-in chain allowing only certain types
# of icmp inbound, we can accept it if it is related to other connections
# (e.g a time exceed from a traceroute) or part of an established one
# (e.g. an echo reply)
#
iptables -A INPUT  -i $IFACE -p icmp -m state --state ESTABLISHED,RELATED \
         -j ACCEPT

#
# Now we have returned from the icmp-out chain allowing only certain types
# of icmp outbound, we can just accept it under all circumstances.
#
iptables -A OUTPUT -o $IFACE -p icmp -m state --state NEW,ESTABLISHED,RELATED \
         -j ACCEPT

#
#------------------------------------------------------------------------------
## ICMP 2
# This is the second part of 'ICMP' - I will do some more tests and possibly
# this part will replace the first part above. (uk)
#
# We accept icmp in if it is "related" to other connections (e.g a time
# exceeded (11) from a traceroute) or it is part of an "established" connection
# (e.g. an echo reply (0) from an echo-request (8)).
#
iptables -A INPUT -i $IFACE -p icmp -m state --state ESTABLISHED,RELATED \
         -j ACCEPT

#
# We always allow icmp out.
#
iptables -A OUTPUT -o $IFACE -p icmp -m state --state NEW,ESTABLISHED,RELATED \
         -j ACCEPT

#
#------------------------------------------------------------------------------
## DNS
# NOTE: DNS uses tcp for zone transfers, for transfers greater than 512 bytes
# (possible, but unusual), and on certain platforms like AIX (I am told), so
# you might have to add a copy of this rule for tcp if you need it
# Allow UDP packets in for DNS client from nameservers.
# I added NEW & RELATED, because if you send masses of queries to a DNS, another
# (alternate) nameserver might respond due to load-balancing and these packets
# are then DROPped, and we do not want this! Mhh, maybe we should completely
# remove the '-m state --state ...' (?)
# You may want the flexibility to change your preferred DNS, you may even get
# new DNS assigned if you start a VPN connection; so let's just accept tcp/udp
# packets coming from (remote) port 53, which is also recommended on
# http://www.usyd.edu.au/is/comms/security/accesslists.html   and
# http://www.siliconvalleyccie.com/linux-hn/iptables-intro.htm
# We also allow tcp, because replies larger than 512 bytes will come via tcp.
# For now, we (minimally) log such packets...
#
iptables -A INPUT -i $IFACE -p udp -s 0/0 --sport 53 --dport $UP_PORTS \
         -m state --state NEW,ESTABLISHED,RELATED \
         $limA -j LOG ${LOGP}"-ACCEPT-from_53-in: "
iptables -A INPUT -i $IFACE -p udp -s 0/0 --sport 53 --dport $UP_PORTS \
         -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -i $IFACE -p tcp -s 0/0 --sport 53 --dport $UP_PORTS \
         -m state --state NEW,ESTABLISHED,RELATED \
         $limA -j LOG ${LOGP}"-ACCEPT-from_53-in: "
iptables -A INPUT -i $IFACE -p tcp -s 0/0 --sport 53 --dport $UP_PORTS \
         -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

#
# Allow UDP packets to DNS servers from client.
#
iptables -A OUTPUT -o $IFACE -p udp -d 0/0 --dport 53 \
         -m state --state NEW,ESTABLISHED -j ACCEPT

#
#------------------------------------------------------------------------------
## SSH
# Allow ssh outbound.
#
iptables -A INPUT  -i $IFACE -p tcp --sport 22 -m state \
         --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 22 -m state \
          --state NEW,ESTABLISHED -j ACCEPT

#
#------------------------------------------------------------------------------
## WWW
# Allow www outbound to 80.
#
iptables -A INPUT  -i $IFACE -p tcp --sport 80 -m state \
         --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 80 -m state \
         --state NEW,ESTABLISHED -j ACCEPT

#
# Allow www outbound to 443.
#
iptables -A INPUT  -i $IFACE -p tcp --sport 443 -m state \
         --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 443 -m state \
         --state NEW,ESTABLISHED -j ACCEPT

#
#------------------------------------------------------------------------------
## TELNET
# Allow telnet outbound - should actually be forbidden ;-)
#
iptables -A INPUT  -i $IFACE -p tcp --sport 23 -m state \
         --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 23 -m state \
         --state NEW,ESTABLISHED -j ACCEPT

#
#------------------------------------------------------------------------------
## FTP
# Allow ftp outbound.
#
iptables -A INPUT  -i $IFACE -p tcp --sport 21 -m state \
         --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 21 -m state \
         --state NEW,ESTABLISHED -j ACCEPT

#
# Now for the connection tracking part of ftp. This is discussed more
# completely in the section on connection tracking on
# the page http://www.sns.ias.edu/~jns/security/iptables/
# 1) Active ftp.
# This involves a connection INbound from port 20 on the remote machine, to a
# local port passed over the ftp channel via a PORT command.
# The ip_conntrack_ftp module recognizes the connection as RELATED to the
# original outgoing connection to port 21 so we don't need NEW as a state match.
#
iptables -A INPUT  -i $IFACE -p tcp --sport 20 -m state \
         --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 20 -m state \
         --state ESTABLISHED -j ACCEPT

#
# 2) Passive ftp.
# This involves a connection outbound from a port >1023 on the local machine,
# to a port >1023 on the remote machine previously passed over the ftp channel
# via a PORT command. The ip_conntrack_ftp module recognizes the connection as
# RELATED to the original outgoing connection to port 21 so we don't need NEW
# as a state match.
#
iptables -A INPUT  -i $IFACE -p tcp --sport $UP_PORTS --dport $UP_PORTS \
         -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --sport $UP_PORTS --dport $UP_PORTS \
         -m state --state ESTABLISHED,RELATED -j ACCEPT

#
#------------------------------------------------------------------------------
## SMTP
# Allow smtp outbound.
#
iptables -A INPUT  -i $IFACE -p tcp --sport 25 -m state \
         --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o $IFACE -p tcp --dport 25 -m state \
         --state NEW,ESTABLISHED -j ACCEPT

#
#------------------------------------------------------------------------------
## AUTH server
# Reject ident probes with a tcp reset.
# I need to do this for a broken mailhost that won't accept my mail if I just
# drop its ident probe. (This is not from me (uk), but from another author)
# We leave this, according to http://www.seifried.org/security/ports/0/113.html
# and we also send a reset packet, but we log it:
#
iptables -A INPUT -i $IFACE -p tcp --dport 113 \
         $limD -j LOG ${LOGP}"-REJECT-AUTH-IN: "
iptables -A INPUT -i $IFACE -p tcp --dport 113 -j REJECT --reject-with tcp-reset

#
#------------------------------------------------------------------------------
## TRACEROUTE
# Outgoing traceroute anywhere.
# The reply to a traceroute is an icmp time-exceeded which is dealt with by the
# next rule.
#
iptables -A OUTPUT -o $IFACE -p udp --sport $TR_SRC_PORTS \
         --dport $TR_DEST_PORTS -m state --state NEW -j ACCEPT

#
#------------------------------------------------------------------------------
# DROP invalid packets - they may have been mangled...:
#
iptables -A INPUT -s 0.0.0.0/0.0.0.0 -d 0.0.0.0/0.0.0.0 -m state \
         --state INVALID \
         $limD -j LOG ${LOGP}"-INVALID-invalid-IN: "
iptables -A INPUT -s 0.0.0.0/0.0.0.0 -d 0.0.0.0/0.0.0.0 -m state \
         --state INVALID -j DROP

#
#------------------------------------------------------------------------------
# Accept all (?) outgoing packets:
#
iptables -A OUTPUT -o $IFACE -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

#
#------------------------------------------------------------------------------
## Packets that should be DROPped without logging; these are special cases,
# which cannot be handled in the file /etc/picofirewall/noise_nolog.cfg :

#
# DROP & do not log packets to 224.0.0.1...:
#
iptables -t mangle -A PREROUTING -d 224.0.0.1 -j DROP

#
# DROP & do not log the numerous udp packets from/to port 520:
# (in our case, they come from our nearest router)
#
iptables -t mangle -A PREROUTING -i $IFACE -p udp --sport 520 \
         -d 255.255.255.255 --dport 520 -j DROP

#
#------------------------------------------------------------------------------
## LOG ANYTHING NOT ALREADY ALLOWED
# You don't have to split up your logging like I do below, but I prefer to do it
# this way because one can then grep for things in the logs more easily.
# The default is now to only partially log things - you may change this by
# setting LIMIT_DROP_LOGGING to "no". This could e.g. be done while
# experimenting with your firewall or when you are looking for errors.
# (Part of the orig. text: "-m limit --limit 6/h --limit-burst 5")
# ??? In order to see what is going on, I usually log everything. If logging is
# restricted too much, port scans cannot be detected (e.g. by using
# 'picofirescan'; see http://www.seismo.ethz.ch/linux/picofirescan.html).
# 
#
# Any udp not already allowed is logged and then dropped.
#
iptables -A INPUT  -i $IFACE -p udp -m state --state NEW \
         $limD -j LOG ${LOGP}"-DROP-UDP-IN: "
iptables -A INPUT  -i $IFACE -p udp -m state --state NEW -j DROP
iptables -A OUTPUT -o $IFACE -p udp \
         $limD -j LOG ${LOGP}"-DROP-UDP-OUT: "
iptables -A OUTPUT -o $IFACE -p udp -j DROP

#
# Any icmp not already allowed is logged and then dropped.
#
iptables -A INPUT  -i $IFACE -p icmp -m state --state NEW \
         $limD -j LOG ${LOGP}"-DROP-ICMP-IN: "
iptables -A INPUT  -i $IFACE -p icmp -m state --state NEW -j DROP
iptables -A OUTPUT -o $IFACE -p icmp $limD -j LOG ${LOGP}"-DROP-ICMP-OUT: "
iptables -A OUTPUT -o $IFACE -p icmp -j DROP

#
# Any tcp not already allowed is logged and then dropped.
#
iptables -A INPUT  -i $IFACE -p tcp -m state --state NEW \
         $limD -j LOG ${LOGP}"-DROP-TCP-IN: "
iptables -A INPUT  -i $IFACE -p tcp -m state --state NEW -j DROP
iptables -A OUTPUT -o $IFACE -p tcp $limD -j LOG ${LOGP}"-DROP-TCP-OUT: "
iptables -A OUTPUT -o $IFACE -p tcp -j DROP

#
# Anything else not already allowed is logged and then dropped.
# It will be dropped by the default policy anyway ... but let's be careful...
# e.g. we once got the following packet:
# Nov 30 17:06:10 zak kernel: P-Fw-DROP-PROTOCOL-X-IN: IN=eth0 OUT= MAC=00:00:1c:b6:24:25:00:d0:bc:f0:ad:2c:08:00 SRC=147.51.166.174 DST=129.132.95.155 LEN=172 TOS=0x00 PREC=0x00 TTL=233 ID=0 PROTO=99
#
iptables -A INPUT  -i $IFACE $limD -j LOG ${LOGP}"-DROP-PROTOCOL-X-IN: "
iptables -A INPUT  -i $IFACE -j DROP
iptables -A OUTPUT -o $IFACE $limD -j LOG ${LOGP}"-DROP-PROTOCOL-X-OUT: "
iptables -A OUTPUT -o $IFACE -j DROP

#
#
#------------------------------------------------------------------------------
# end.