Several people asked me for these scripts, so I'm posting them. Perhaps
frittering my week on this was not a waste after all. But really I
should be out looking for a job.
Take a look. I'm very open to comments. My sh skills are rough.
To make the init script part of the SuSE init system, I added a var in
/etc/rc.config: START_IPTABLES_FW, I made links in /etc/init.d/rc#.d
and a link for rciptables in /use/sbin:
root@rose:~ >ls -l /usr/sbin/rciptables
lrwxrwxrwx 1 root root 20 May 2 11:06
/usr/sbin/rciptables -> /etc/init.d/iptables
root@rose:~ >ls -lR /etc/init.d/rc*.d/*iptables
lrwxrwxrwx 1 root root 11 May 2 10:27
/etc/init.d/rc2.d/K17iptables -> ../iptables
lrwxrwxrwx 1 root root 11 May 2 10:28
/etc/init.d/rc2.d/S04iptables -> ../iptables
lrwxrwxrwx 1 root root 11 May 2 11:02
/etc/init.d/rc3.d/K17iptables -> ../iptables
lrwxrwxrwx 1 root root 11 May 2 11:01
/etc/init.d/rc3.d/S04iptables -> ../iptables
root@rose:~ >grep FW /etc/rc.config
START_FW="no"
START_IPTABLES_FW="yes"
And definately have a look at James Stephen's iptables tutorial:
http://www.cs.princeton.edu/~jns/security/iptables/
#!/bin/sh
#set -x
#
# ==================================================================
#
# Iptables startup script
# /etc/init.d/iptables
#
# For use on rose.ashnet SuSE7.1
# by ashley 4/30/2001
IPTABLES=/usr/sbin/iptables
IPTABLES_CONFIG=/sbin/iptables.rules
. /etc/rc.config
# Determine the base and follow a runlevel link name.
base=${0##*/}
link=${base#*[SK][0-9][0-9]}
# Force execution if not called by a runlevel directory.
# I added a var in /etc/rc.config
test $link = $base && START_FW=yes
test "$START_IPTABLES_FW" = yes && START_FW="yes"
test "$START_FW" = yes || exit 0
# Let's test that everything is in place
echo "Ashley's iptables firewall: "
return=$rc_done
# check we have the iptables executable
if [ ! -x $IPTABLES ]; then
echo " Can't find $IPTABLES:$rc_failed"
return=$rc_failed && exit 1
fi
# check we have the right kernel version
KERNELMAJ=`uname -r | sed -e 's,\..*,,'`
KERNELMIN=`uname -r | sed -e 's,[^\.]*\.,,' -e 's,\..*,,'`
if [ "$KERNELMAJ" -lt 2 ] || [ "$KERNELMAJ" -eq 2 -a "$KERNELMIN" -lt 3 ] ; then
echo " No iptables support in kernel `uname -r`:$rc_failed"
return=$rc_failed && exit 1
fi
# Check if ipchains is already running
if /sbin/lsmod 2>/dev/null |grep -q ipchains ; then
echo " module ipchains already loaded:$rcfailed"
return=$rc_failed && exit 1
fi
# Check if iptables modules are already loaded
iptables_loaded="no"
if /sbin/lsmod 2>/dev/null |grep -q ip_tables ; then
iptables_loaded="yes"
fi
# Looks good, let's get started
case "$1" in
start | restart)
# We don't have the rules script?
if [ ! -f $IPTABLES_CONFIG ]; then
echo -n " Can't find firewall rules file $IPTABLES_CONFIG: "
return=$rc_failed
else
echo -n " Loading rules: "
$IPTABLES_CONFIG > /dev/null 2>&1 || return=$rcfailed
fi
echo -e "$return"
;;
stop)
if [ $iptables_loaded = yes ]; then
echo " Flushing all chains, removing user defined chains and"
echo " Resetting built-in chains to the default ACCEPT policy:"
echo -n " The filter table: "
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
$IPTABLES -F
$IPTABLES -X
$IPTABLES -Z
echo -e "$rc_done"
echo -n " The nat table: "
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
$IPTABLES -t nat -F
$IPTABLES -t nat -X
$IPTABLES -t nat -Z
echo -e "$rc_done"
# Not in use
#echo -n " The mangle table: "
#$IPTABLES -t mangle -P PREROUTING ACCEPT
#$IPTABLES -t mangle -P OUTPUT ACCEPT
#$IPTABLES -t mangle -F
#$IPTABLES -t mangle -X
#$IPTABLES -t mangle -Z
#echo -e "$rc_done"
#echo -n " Stop forwarding and unload all the iptables modules: "
#echo 0 > /proc/sys/net/ipv4/ip_forward
#/sbin/rmmod `lsmod | awk '{print $1}' | grep '^ip'`
#echo -e "$rc_done"
else
echo " No iptables modules loaded."
fi
;;
status)
# I recommend piping this to `less`
if [ $iptables_loaded = yes ]; then
echo
echo ' FILTER TABLE'
echo
$IPTABLES -t filter -L -v --line-numbers
echo
echo ' NAT TABLE'
echo
$IPTABLES -t nat -L -v --line-numbers
echo
#echo ' MANGLE TABLE'
#echo
#$IPTABLES -t mangle -L -v --line-numbers
#echo
else
echo " No iptables modules loaded."
fi
;;
panic)
if [ $iptables_loaded = yes ]; then
echo " PANIC! Change all target policies to DROP: "
echo -n " The filter table: "
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -F
$IPTABLES -X
$IPTABLES -Z
echo -e "$rc_done"
echo -n " The nat table: "
$IPTABLES -t nat -P PREROUTING DROP
$IPTABLES -t nat -P OUTPUT DROP
$IPTABLES -t nat -P POSTROUTING DROP
$IPTABLES -t nat -F
$IPTABLES -t nat -X
$IPTABLES -t nat -Z
echo -e "$rc_done"
# Not in use
#echo -n " The mangle table: "
#$IPTABLES -t mangle -P PREROUTING DROP
#$IPTABLES -t mangle -P OUTPUT DROP
#$IPTABLES -t mangle -F
#$IPTABLES -t mangle -X
#$IPTABLES -t mangle -Z
#echo -e "$rc_done"
echo -n " Stop forwarding and unload all the iptables modules: "
echo 0 > /proc/sys/net/ipv4/ip_forward
/sbin/rmmod `lsmod | awk '{print $1}' | grep '^ip'`
echo -e "$rc_done"
else
echo " No iptables modules loaded."
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status|panic}"
exit 1
esac
# Inform the caller not only verbosely and set an exit status.
test "$return" = "$rc_done" || exit 1
exit 0
#!/bin/bash
##============================================================
# Iptables firewall rules loading script
# /sbin/iptables.rules
#
##ag Adapted form the tutorial by James C. Stephens
##ag for use on rose.ashnet 4/30/2001 by ashley.
##ag My comments look like this ##ag
#
##ag This is the K I S S version.
##ag I cut out James' wonderful comments for readablity.
##ag Look for full documentation at James' site:
##ag http://www.cs.princeton.edu/~jns/security/iptables/
IPTABLES=/usr/sbin/iptables
MODPROBE=/sbin/modprobe
ECHO=/bin/echo
# Load appropriate modules.
#$MODPROBE ip_tables
#$MODPROBE ip_conntrack
#$MODPROBE ip_conntrack_ftp
##ag The above calls aren't needed if the MASQ module is loaded;
##ag it brings them with it.
$MODPROBE ipt_MASQUERADE
# Flush rules
$IPTABLES -F
$IPTABLES -X
$IPTABLES -Z
$IPTABLES -t nat -F
$IPTABLES -t nat -X
$IPTABLES -t nat -Z
# Default policy
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -t nat -P PREROUTING ACCEPT
$IPTABLES -t nat -P OUTPUT ACCEPT
$IPTABLES -t nat -P POSTROUTING ACCEPT
## ===========================================================
## Some definitions:
##ag ashnet locals
INT_NET="192.168.0.0/24"
INT_IPADDR="198.168.0.1"
INT_IFACE="eth0"
EXT_IFACE="ppp0"
INT_MAIL="192.168.0.2"
##ag my isp stuff
NAMESERVER_1="207.172.3.10"
NAMESERVER_2="207.172.3.11"
POP3_HOST="208.59.199.22"
SMTP_MAIL_RELAY=
##ag general
P_PORTS="0:1023"
UP_PORTS="1024:65535"
TR_SRC_PORTS="32769:65535"
TR_DEST_PORTS="33434:33523"
## ============================================================
## Kernel flags
#echo kernel flags
$ECHO "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
$ECHO "0" > /proc/sys/net/ipv4/conf/all/accept_source_route
$ECHO "0" > /proc/sys/net/ipv4/conf/all/accept_redirects
$ECHO "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
##ag Don't I need to do this _after_ my ppp0 interface comes up?
#for interface in /proc/sys/net/ipv4/conf/*/rp_filter; do
# $ECHO "1" > ${interface}
#done
##ag Instead I'll just do the 'all' version
$ECHO "1" > /proc/sys/net/ipv4/conf/all/rp_filter
$ECHO "1" > /proc/sys/net/ipv4/conf/all/log_martians
$ECHO "1" > /proc/sys/net/ipv4/ip_forward
## ============================================================
# RULES
#===================================================================
## The FORWARD chain
#echo The FORWARD chain
# I'm masquerading everything from my internal lan
$IPTABLES -t nat -A POSTROUTING -o $EXT_IFACE -j MASQUERADE
#$IPTABLES -A FORWARD -i $INT_IFACE -m state --state NEW,RELATED,ESTABLISHED -j LOG --log-prefix "ACCEPT FORWARD --state NEW,E,R:"
$IPTABLES -A FORWARD -i $INT_IFACE -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
#$IPTABLES -A FORWARD -i $EXT_IFACE -m state --state RELATED,ESTABLISHED -j LOG --log-prefix "ACCEPT FORWARD --state E,R:"
$IPTABLES -A FORWARD -i $EXT_IFACE -m state --state RELATED,ESTABLISHED -j ACCEPT
# Log the losers
$IPTABLES -A FORWARD -i $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -j LOG --log-prefix "DROP FORWARD IN-PPP0: "
$IPTABLES -A FORWARD -i $EXT_IFACE -j DROP
#==============================================================================
# Local Processes on Rose
#echo Local Processes on Rose
## LOOPBACK
#echo LOOPBACK
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT
## SYN-FLOODING PROTECTION
#echo SYN-FLOODING PROTECTION
##ag Probably I don't need this, as I have no servers running.
$IPTABLES -N syn-flood
$IPTABLES -A INPUT -p tcp --syn -j syn-flood
$IPTABLES -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN
$IPTABLES -A syn-flood -j DROP
## Make sure NEW tcp connections are SYN packets
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
## FRAGMENTS
#echo FRAGMENTS
# Log fragments just to see if we get any, and deny them too.
$IPTABLES -A INPUT -f -j LOG --log-prefix "IPTABLES FRAGMENTS: "
$IPTABLES -A INPUT -f -j DROP
## SPOOFING
##ag I cut out this section
##ag I'll rely on the kernel flags
## DNS
#echo DNS
# Allow UDP packets in for DNS client from nameservers. No tcp.
$IPTABLES -A INPUT -i $EXT_IFACE -p udp -s $NAMESERVER_1 --sport 53 -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A INPUT -i $EXT_IFACE -p udp -s $NAMESERVER_2 --sport 53 -m state --state ESTABLISHED -j ACCEPT
# Allow UDP packets to DNS servers from client.
$IPTABLES -A OUTPUT -o $EXT_IFACE -p udp -d $NAMESERVER_1 --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -o $EXT_IFACE -p udp -d $NAMESERVER_2 --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
## SSH
#echo SSH
# Allow ssh outbound all interfaces.
$IPTABLES -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
##ag Allow connections from internal lan (and log while testing)
#$IPTABLES -A INPUT -i $INT_IFACE -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j LOG --log-prefix "ACCEPT ssh from internal --state NEW,E,R: "
$IPTABLES -A INPUT -i $INT_IFACE -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
#$IPTABLES -A OUTPUT -o $INT_IFACE -p tcp --sport 22 -m state --state ESTABLISHED -j LOG --log-prefix "ACCEPT ssh from internal --state E,R: "
$IPTABLES -A OUTPUT -o $INT_IFACE -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
## WWW
##ag I'll include this when I get my squid proxy up
#echo WWW
# Allow www outbound to 80.
#$IPTABLES -A INPUT -i $EXT_IFACE -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
#$IPTABLES -A OUTPUT -o $EXT_IFACE -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# Allow www outbound to 443.
#$IPTABLES -A INPUT -i $EXT_IFACE -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
#$IPTABLES -A OUTPUT -o $EXT_IFACE -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
## FTP
##ag For future ftp proxy
#echo FTP
# Allow ftp outbound.
#$IPTABLES -A INPUT -i $EXT_IFACE -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT
#$IPTABLES -A OUTPUT -o $EXT_IFACE -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
# 1) Active ftp.
#$IPTABLES -A OUTPUT -o $EXT_IFACE -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT
# 2) Passive ftp.
#$IPTABLES -A INPUT -i $EXT_IFACE -p tcp --sport $UP_PORTS --dport $UP_PORTS -m state --state ESTABLISHED -j ACCEPT
#$IPTABLES -A OUTPUT -o $EXT_IFACE -p tcp --sport $UP_PORTS --dport $UP_PORTS -m state --state ESTABLISHED,RELATED -j ACCEPT
## SMTP
#echo SMTP
##ag Allow smtp outbound to internal lan only.
$IPTABLES -A INPUT -i $INT_IFACE -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT
$IPTABLES -A OUTPUT -o $INT_IFACE -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
## TRACEROUTE
#echo TRACEROUTE
# Outgoing traceroute to internet.
$IPTABLES -A OUTPUT -o $EXT_IFACE -p udp --sport $TR_SRC_PORTS --dport $TR_DEST_PORTS -m state --state NEW -j ACCEPT
## ICMP
#echo ICMP
##ag This is where netfilter really shines. It is sooo much easier!
##ag rose can ping either interface and accepts pings from internal
$IPTABLES -A INPUT -i $EXT_IFACE -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $INT_IFACE -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $EXT_IFACE -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $INT_IFACE -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
## LOGGING
#echo LOGGING
##ag Rate limit the logging
# Any udp not already allowed is logged and then dropped.
$IPTABLES -A INPUT -i $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -p udp -j LOG --log-prefix "DROP UDP-IN: "
$IPTABLES -A INPUT -i $EXT_IFACE -p udp -j DROP
$IPTABLES -A OUTPUT -o $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -p udp -j LOG --log-prefix "DROP UDP-OUT: "
$IPTABLES -A OUTPUT -o $EXT_IFACE -p udp -j DROP
# Any icmp not already allowed is logged and then dropped.
$IPTABLES -A INPUT -i $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -p icmp -j LOG --log-prefix "DROP ICMP-IN: "
$IPTABLES -A INPUT -i $EXT_IFACE -p icmp -j DROP
$IPTABLES -A OUTPUT -o $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -p icmp -j LOG --log-prefix "DROP ICMP-OUT: "
$IPTABLES -A OUTPUT -o $EXT_IFACE -p icmp -j DROP
# Any tcp not already allowed is logged and then dropped.
$IPTABLES -A INPUT -i $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -p tcp -j LOG --log-prefix "DROP TCP-IN: "
$IPTABLES -A INPUT -i $EXT_IFACE -p tcp -j DROP
$IPTABLES -A OUTPUT -o $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -p tcp -j LOG --log-prefix "DROP TCP-OUT: "
$IPTABLES -A OUTPUT -o $EXT_IFACE -p tcp -j DROP
# Anything else not already allowed is logged and then dropped.
$IPTABLES -A INPUT -i $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -j LOG --log-prefix "DROP PROTOCOL-X-IN: "
$IPTABLES -A INPUT -i $EXT_IFACE -j DROP
$IPTABLES -A OUTPUT -o $EXT_IFACE -m limit --limit 6/h --limit-burst 5 -j LOG --log-prefix "DROP PROTOCOL-X-OUT: "
$IPTABLES -A OUTPUT -o $EXT_IFACE -j DROP
# THE END
# ==================================================================
--
-ashley
One of these days I'm going to completely organize my life.