#!/bin/sh
# define and function for rc.firewall script
# 
## STATIC DEFINE
PATH="/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin"


#### BEGIN check_iptables
# This function check if iptables exist, and if kernel version
# match 2.4

check_iptables() {
echo "- Sanity check"

# Root check
if [ "$UID" -ne 0 ]
     then
        echo "**************************************"
        echo "* You Must be root to use iptables   *"
        echo "* Please Login as root               *"
        echo "**************************************"
        echo Exiting...
        exit 1

     fi


KERNELVERSION="`uname -r`"
echo $KERNELVERSION | grep 2.4 >/dev/null
if ( test "$?" -eq "1" ) ; then
	echo "**************************************"
	echo "* Kernel version it's not correct    *"
	echo "* for iptables use: $KERNELVERSION   *"
        echo "**************************************"
        echo "        CHECK KERNEL CONFIGUATION !!! "
        echo Exiting...
        exit 1
else
	echo "  - Found kernel: $KERNELVERSION"
fi


IPTABLES="`which iptables`"
if ( test "$?" -eq "1" ) ; then
        echo "**************************************"
        echo "* Warning, cannot find iptables !!!  *"
        echo "**************************************"
        echo "        CHECK SYSTEM CONFIGUATION !!! "
        echo Exiting...
        exit 1
else
        echo "  - Found IPTables: $IPTABLES"
fi

# Iptables support
echo "  - Checking for iptables support."
if [ -f /lib/modules/`uname -r`/kernel/net/ipv4/netfilter/ip_tables.o ]
 then
  echo "   Found iptables module, loading it..."
  modprobe ip_tables
  modprobe iptable_filter
  modprobe iptable_mangle
  modprobe ipt_TOS
  modprobe ipt_unclean
  modprobe ip_conntrack
  modprobe ip_conntrack_ftp
  modprobe ip_conntrack_irc
  modprobe ip_conntrack_egg
  modprobe ipt_iplimit
  modprobe ipt_limit
  modprobe ipt_state
  echo "   Iptables ready!"
 else
  echo "     No module found, assuming netfilter compiled into the kernel."
fi



}
#### END check_iptables

#### BEGIN check_parameter
# This function check if parameter is "start" or "stop" and
# disable or enable the filter
check_parameter() {

first="$1"

case $first  in
        "start")
                 enable_fw
        ;;
        "stop")
                 disable_fw
                 echo "Done!"
        ;;
	*)
		 show_help
	;;
        esac
}

#### END check_parameter


#### BEGIN show_help
show_help() {
echo "Linux Netfilter Firewall v0.1"
echo "Usage $0 [options]"
echo "start       Enable Firewall"
echo "stop        Disable Firewall"
}
#### END show_help


#### BEGIN enable_fw
enable_fw() {

echo -e "\n\n"
echo "**************************************"
echo "*      LINUX NETFILTER               *"
echo "*      FIREWALL CONFIGURATION        *"
echo "*      No (c) naif 2001              *"
echo "**************************************"
echo -e "\n\n"

# Sanity check on system
check_iptables
# Tune some misc tcp/ip parameter
tune_tcpip
# Flush chains and rules
flush_rules
# Setup new chain based on INTERFACE variable
setup_chain
# Setup rules
rules_setup
# Logging function
log_it
}
#### END enable_fw

#### BEGIN disable_fw
disable_fw() {
# Sanity check on system
check_iptables
# Flush chains and rules
flush_rules
echo "Done!"
}
#### END disable_fw

#### BEGIN tune_tcpip
# This function tune some parameter of linux tcp/ip stack
# with performance and security in mind.

tune_tcpip() {

echo ""
echo "- TCP/IP Tuning and Security parameter..."

echo "  - Activating rp_filter - antispoofing... "
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
    echo 1 > $f
done

#
echo "  - Activating IP Forwarding..."
if [ -w /proc/sys/net/ipv4/ip_forward ] ; then
	echo 1 > /proc/sys/net/ipv4/ip_forward
fi
echo "  - Activating IP Syn Cookies protection"
if [ -w /proc/sys/net/ipv4/tcp_syncookies ] ; then
	echo 1 > /proc/sys/net/ipv4/tcp_syncookies
fi
# Disable windows scaling
if [ -w /proc/sys/net/ipv4/tcp_window_scaling ] ; then
	echo 0 > /proc/sys/net/ipv4/tcp_window_scaling
fi
# Disable Selective Acnoledgment
if [ -w /proc/sys/net/ipv4/tcp_sack ] ; then
	echo 0 > /proc/sys/net/ipv4/tcp_sack
fi
if [ -w /proc/sys/net/ipv4/tcp_dsack ] ; then
	echo 0 > /proc/sys/net/ipv4/tcp_dsack
fi
# Disable ECN
if [ -w /proc/sys/net/ipv4/tcp_ecn ] ; then
	echo 0 > /proc/sys/net/ipv4/tcp_ecn 
fi
# Enable logging of bogus icmp
if [ -w /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses ] ; then
	echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
fi
# Disable tcp_timestamp ( who need it? )
if [ -w /proc/sys/net/ipv4/tcp_timestamps ] ; then
	echo 0 > /proc/sys/net/ipv4/tcp_timestamps
fi
# Enlarge tcp Syn backlog
if [ -w /proc/sys/net/ipv4/tcp_max_syn_backlog ] ; then
	echo 4096 > /proc/sys/net/ipv4/tcp_max_syn_backlog
fi
# Log packet with impossible source
if [ -w /proc/sys/net/ipv4/conf/all/log_martians ] ; then
	echo 1 > /proc/sys/net/ipv4/conf/all/log_martians
fi
# Disable icmp redirect
if [ -w  /proc/sys/net/ipv4/conf/all/accept_redirects ] ; then
	for redirect in /proc/sys/net/ipv4/conf/*/accept_redirects ; do
		echo 0 > $redirect
	done
fi
# Disable shared_media redirect
if [ -w /proc/sys/net/ipv4/conf/all/shared_media ] ; then
	for shared_media in /proc/sys/net/ipv4/conf/*/shared_media ; do
		echo 0 > $shared_media
	done
fi
# Disable secure_redirects
if [ -w /proc/sys/net/ipv4/conf/all/secure_redirects ] ; then
	for secure_redirects in /proc/sys/net/ipv4/conf/*/secure_redirects ; do
		echo 0 > $secure_redirects
	done
fi
# Disable secure_redirects
if [ -w /proc/sys/net/ipv4/conf/all/send_redirects ] ; then
	for send_redirects in /proc/sys/net/ipv4/conf/*/send_redirects ; do
		echo 0 > $send_redirects
	done
fi
# Disable accept_source_route
if [ -w /proc/sys/net/ipv4/conf/all/accept_source_route ] ; then
	for accept_source_route in /proc/sys/net/ipv4/conf/*/accept_source_route ; do
		echo 0 > $accept_source_route
	done
fi
# We hate icmp broadcast
if [ -w /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts ] ; then
	echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
fi
# By default iptables handle only 2048 connection...
if [ -w /proc/sys/net/ipv4/ip_conntrack_max ] ; then
	echo "8192" > /proc/sys/net/ipv4/ip_conntrack_max
fi
# Change local port range ( 30000 to 60000 )
if [ -w /proc/sys/net/ipv4/ip_local_port_range ] ; then
	echo -e "30000\t60000" > /proc/sys/net/ipv4/ip_local_port_range
fi

#
echo "  - Tuning Windows Size"
if [ -w /proc/sys/net/core/rmem_default ] ; then
echo  131070 > /proc/sys/net/core/rmem_default
echo  131070 > /proc/sys/net/core/rmem_max
echo  131070 > /proc/sys/net/core/wmem_default
echo  131070 > /proc/sys/net/core/wmem_max
echo ""
fi
}
#### END tune_tcpip

#### BEGIN flush_rules
# This function using $INTERFACE variable flush and delete
# every tables in the filter
flush_rules() {

echo "- Cleaning netfilter items"
echo "  - Flushing Rules"
echo "  - Deleting chains"
# First delete default chain
$IPTABLES -F INPUT
$IPTABLES -F OUTPUT
$IPTABLES -F FORWARD
$IPTABLES -F -t mangle
$IPTABLES -X -t mangle
$IPTABLES -F -t nat
$IPTABLES -X -t nat
# then delete all other chain "interface dependant"
 for chain in $INTERFACE ;
	 do
     $IPTABLES -F $chain-in 2> /dev/null
     $IPTABLES -X $chain-in 2> /dev/null
     $IPTABLES -F $chain-out 2> /dev/null
     $IPTABLES -X $chain-out 2> /dev/null
	done
# and finally delete all other shit
$IPTABLES -X

# Zero traffic counter of every chain
echo "  - Zeroing counter"
$IPTABLES -Z
$IPTABLES -t nat -Z PREROUTING
$IPTABLES -t nat -Z POSTROUTING
$IPTABLES -t nat -Z OUTPUT
# Change default policy so we could disable the firewall
echo "  - Restoring default policy to: ACCEPT"
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
echo ""
}
#### END flush_rules

#### BEGIN setup_chain
# This function setup two chains for every interface
# because we have traffic flowing in and out
# ex: eth0-in eth0-out
# then we apply the policy to each chain
#
# ADVANCED: we create a a chain that modify TOS value
# of packet according to RFC 1060/1349 and we apply it
# to OUTPUT chain insted of applying it on every table .
# Minimize-Delay 16 (0x10)
# Maximize-Throughput 8 (0x08)
# Maximize-Reliability 4 (0x04)
# Minimize-Cost 2 (0x02)
# Normal-Service 0 (0x00)
# ADVANCED: we check for particular TCP Flags that are malicious
# in the PREROUTING TABLE for every interface.

setup_chain() {

echo "- Setup"
echo "  - Adjusting tos for packet flowing to internet"
# create mangle table for chaing tos value
$IPTABLES -t mangle -N adjust_tos
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 20 -j TOS --set-tos 8
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 21 -j TOS --set-tos 16
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 22 -j TOS --set-tos 16
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 23 -j TOS --set-tos 16
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 25 -j TOS --set-tos 16
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 53 -j TOS --set-tos 16
$IPTABLES -t mangle -A adjust_tos -p tcp --dport 80 -j TOS --set-tos 8
$IPTABLES -t mangle -A adjust_tos -p udp --dport 53 -j TOS --set-tos 16

# Modify tos value of packet going to internet
$IPTABLES -t mangle -A OUTPUT -o $EXTERNAL_INTERFACE -j adjust_tos

# check for particular TCP Flags that are obviously evil
# First log, then DROP.
echo "  - Check for evil tcp flags in PREROUTING table"
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,URG,PSH -j LOG \
           --log-prefix "NMAP-XMAS SCAN:" --log-tcp-options --log-ip-options

$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j LOG \
           --log-prefix "NMAP-NULL SCAN:" --log-tcp-options --log-ip-options

$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j LOG \
           --log-prefix "SYN/RST SCAN:" --log-tcp-options --log-ip-options

$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags SYN,FIN SYN,FIN -j LOG \
           --log-prefix "SYN/FIN SCAN:" --log-tcp-options --log-ip-options
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-option 64 -j LOG \
           --log-prefix "Illegal TCP Flags: 64" --log-tcp-options --log-ip-options
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-option 128 -j LOG \
           --log-prefix "Illegal TCP Flags: 128" --log-tcp-options --log-ip-options

$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-option 128 -j DROP
$IPTABLES -t mangle -A PREROUTING -p tcp --tcp-option 64  -j DROP

# check for packet not part of a session before setting up chain

# create chain for every interface...
echo "  - Setting up input/output chain per interface"
for interface in $INTERFACE ; do

        $IPTABLES -N $interface-in
        $IPTABLES -N $interface-out
        $IPTABLES -A INPUT  -i $interface -j $interface-in
        $IPTABLES -A OUTPUT -o $interface -j $interface-out
done

# set default policy to DENY
echo "  - Setting DEFAULT POLICY: DENY ( except loopback ) "
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

# Loopback policy
$IPTABLES -A lo-in -j ACCEPT
$IPTABLES -A lo-out -j ACCEPT

}
#### END setup_chain


#### BEGIN log_it
# This function enable logging for all packet dropped
log_it() {
$IPTABLES -A INPUT -j LOG --log-ip-options
$IPTABLES -A OUTPUT -j LOG --log-ip-options
$IPTABLES -A FORWARD -j LOG --log-ip-options
}
#### END log_it

