#!/bin/sh
#
# Notes: This shell script is for iptables v1.2.6+ and 2.4.12+ kernels, as
# there are glaring problems in previous versions. It may work, but
# I would not guarantee it to work completely right.
#
# I am assuming that the public interface is an ISP and the private
# interface is static. Firewall serves as Private DHCP server, and
# uses DNS from the internet. I included services that some like to
# foolishly run... ;) You can comment out mail, ftp and web. I would
# leave ssh for obvious reasons
#
# By default this script DROPS everything, the rules allow exception,
# using stateful checking and allowing exisiting conversation to
# continue, so you can run this script witout interruption of stuff.
# Also by default the script trusts the private interface, allows
# any traffic or conversation started by the private side. IOW, it
# will block anything trying to come in, without you asking for it.
# function check
#
check() {
if test ! -x "$1"; then
echo "$1 not found or is not executable"
exit 1
fi
}
# function log
#
log() {
if test -x "$LOGGER"; then
logger -p info "$1"
fi
}
# exec locations
#
MODPROBE="/sbin/modprobe"
IPTABLES="/sbin/iptables"
IP="/sbin/ip"
LOGGER="/usr/bin/logger"
# making sure they exist
# and are executable
#
check $MODPROBE
check $IPTABLES
check $IP
# PUB_IF assumed ISP_dynamic
#
PUB_IF="eth0"
#PUB_IP="10.0.0.1"
#PUB_SNM="255.0.0.0"
#PUB_NET="10.0.0.0"
#PUB_SNML="8"
# PRIV_IF assumed static
#
PRIV_IF="eth1"
PRIV_IP="192.168.1.1"
PRIV_SNM="255.255.255.0"
PRIV_NET="192.168.1.0"
PRIV_SNML="24"
cd /etc || exit 1
# sending to syslog
#
log "Activating firewall script"
# turning off forwarding (temp)
#
echo "0" > /proc/sys/net/ipv4/ip_forward
# setting good defaults for traffic
#
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 0 > /proc/sys/net/ipv4/tcp_ecn
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
# flushing the toilet
#
$IP -4 neigh flush dev $PRIV_IF
# setting default policies of DROP
#
$IPTABLES -P OUTPUT DROP
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
# getting rid of any exisitng chains and tables
#
cat /proc/net/ip_tables_names | while read table; do
$IPTABLES -t $table -L -n | while read c chain rest; do
if test "X$c" = "XChain" ; then
$IPTABLES -t $table -F $chain
fi
done
$IPTABLES -t $table -X
done
# loading all the iptables modules
#
MODULE_DIR="/lib/modules/`uname -r`/kernel/net/ipv4/netfilter/"
MODULES=`(cd $MODULE_DIR; ls *_conntrack_* *_nat_* | sed 's/\.o.*$//')`
for module in $(echo $MODULES); do
if [ -e "${MODULE_DIR}/${module}.o" -o -e "${MODULE_DIR}/${module}.o.gz" ]; then
$MODPROBE ${module} || exit 1
fi
done
# Rule NAT
#
$IPTABLES -t nat -A POSTROUTING -o $PUB_IF -s $PRIV_NET/$PRIV_SNML -j MASQUERADE
$IPTABLES -t nat -A POSTROUTING -o $PRIV_IF -s $PRIV_NET/$PRIV_SNML -j SNAT --to-source $PRIV_IP
# Setting stateful inspection and allow already
# connected conversations to continue
#
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# public interface anti-spoofing rule so baddies claiming
# to be from the prviate network interface, can't make it in.
#
$IPTABLES -A INPUT -i $PUB_IF -s $PRIV_NET/$PRIV_SNML -j DROP
$IPTABLES -A FORWARD -i $PUB_IF -s $PRIV_NET/$PRIV_SNML -j DROP
# block fragments, a sure sign baddies are trying
#
$IPTABLES -A OUTPUT -p ip -f -j DROP
$IPTABLES -A INPUT -p ip -f -j DROP
$IPTABLES -A FORWARD -p ip -f -j DROP
# firewall uses DNS server on internet
#
$IPTABLES -A INPUT -p tcp -s $PRIV_IP --destination-port 53 -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -p udp -s $PRIV_IP --destination-port 53 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p tcp --destination-port 53 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp --destination-port 53 -m state --state NEW -j ACCEPT
# firewall serves as DHCP server for LAN (listen rule)
#
$IPTABLES -A INPUT -p udp -m multiport -s $PRIV_IP --destination-ports 68,67 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp -m multiport -d $PRIV_IP --destination-ports 68,67 -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -p udp -m multiport -s $PRIV_NET/$PRIV_SNML --destination-ports 68,67 -m state --state NEW -j ACCEPT
# firewall serves as DHCP server for LAN (response rule)
#
$IPTABLES -A INPUT -p udp -m multiport -s $PRIV_IP --destination-ports 68,67 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp -m multiport -d $PRIV_IP --destination-ports 68,67 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp -m multiport -d $PRIV_NET/$PRIV_SNML --destination-ports 68,67 -m state --state NEW -j ACCEPT
# 'masquerading' rule
#
$IPTABLES -A INPUT -s $PRIV_IP -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -s $PRIV_NET/$PRIV_SNML -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -m state --state NEW -j ACCEPT
$IPTABLES -A FORWARD -s $PRIV_NET/$PRIV_SNML -m state --state NEW -j ACCEPT
# firewall serves as mail server (for those that do this)
#
$IPTABLES -A OUTPUT -p tcp -m multiport -d $PRIV_IP --destination-ports 143,993,110,25,465 -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -p tcp -m multiport --destination-ports 143,993,110,25,465 -m state --state NEW -j ACCEPT
# firewall serves as mail relay (for those that do this)
#
$IPTABLES -A INPUT -p tcp -m multiport -s $PRIV_IP --destination-ports 143,993,110,25,465 -m state --state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p tcp -m multiport --destination-ports 143,993,110,25,465 -m state --state NEW -j ACCEPT
# firewall serves as web-server (for those that do this)
#
$IPTABLES -A OUTPUT -p tcp -m multiport -d $PRIV_IP --destination-ports 80,443 -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -p tcp -m multiport --destination-ports 80,443 -m state --state NEW -j ACCEPT
# firewall serves as ftp-server (for those that do this)
#
$IPTABLES -A OUTPUT -p tcp -m multiport -d $PRIV_IP --destination-ports 20,21 -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -p tcp -m multiport --destination-ports 20,21 -m state --state NEW -j ACCEPT
# ssh access to firewall (yes it's a global thing)
#
$IPTABLES -A OUTPUT -p tcp -d $PRIV_IP --destination-port 22 -m state --state NEW -j ACCEPT
$IPTABLES -A INPUT -p tcp --destination-port 22 -m state --state NEW -j ACCEPT
# 'catch all' rule to make sure
#
$IPTABLES -A OUTPUT -j DROP
$IPTABLES -A INPUT -j DROP
$IPTABLES -A FORWARD -j DROP
# turning forwarding back on
#
echo 1 > /proc/sys/net/ipv4/ip_forward