Automatic Firewall Hardening with Linux and IPTABLES

Written by Vasoo Veerapen (dive_mauritius@hotmail.com)  
Version 1.1, modified on the 20th of January 2002.
The original documents can always be found at http://www.islandsoft.net/veerapen.html

Please note that any content within this document is Copyrighted material at all times. Any reproduction, modification, or use of this document and/or contents from the islandsoft.net domain, in part or entirety, is prohibited  unless explicit permission is obtained from the author. 

The objective of this document is to show you how you can automatically harden your IPTABLES based firewall in real-time which is a technique used by commercial firewalls to prevent invalid packets from reaching protected networks. The content has been tested against Linux Mandrake 8.0 with Kernel 2.4.3 and IPTABLES 1.2.1a. Mandrake claim their distribution to be Red Hat compliant so the content in this article should be fully Red Hat compatible. I don't have any experience whatsoever with other distros, but then, I live on the island of Mauritius which is a hell of a journey from civilisation, and all of us here are scantily clad Zulu warriors :-) For more info about Mauritius click here

There are many books available on Linux Security. I like these ones.

Real World Linux Security (Intrusion, Prevention, Detection and Recovery)
Hacking Linux Exposed

Usually IPTABLES only logs messages via the SYSLOGD mechanism. Logs by themselves are fine for basic security but do not address advanced security issues. For advanced security you need to make your system run custom scripts as soon as illegal operations are logged by the firewall. Depending on the severity of the violations, you can program these scripts to perform various actions such as paging network admins or blocking offending IP addresses. All too often, firewall logs are checked once daily, or utilities such as LOGCHECK are used in scheduled CRON jobs to inform network admins of anything abnormal. By the time the logs are verified, the damage to your system is already done.

Linux SYSLOGD incorporates a neat feature which allows SYSLOGD to send the messages it receives to user defined pipes which can pass the message in turn to a script of your choice. The message flow is outlined below. 

IPTABLES > SYSLOGD > named pipe > custom script

 In the following exercise, I will show you how to add a DROP command to IPTABLES in order to block offending IP addresses in real-time as soon as a FIN scan is detected.  You could of course program  your scripts to do a multitude of other things as well. 

You can get the entire tarball for this exercise here.

Requirements for this exercise:

Machine X (192.168.0.1)
Needs IPTABLES, SYSLOGD enabled, the C shell(csh) and Apache. This is the machine that we will be tinkering with and where you will need to install the demo scripts.

Machine Y (192.168.0.2)
Install NMAP on Machine Y

This is what we will be doing:

(1) Create a firewall script using IPTABLES
(2) Create a named pipe.
(3) Create a firewall hardening script.
(4) Convey data from the named pipe to the firewall hardening script.
(5) Tell SYSLOGD to echo messages to the named pipe.
(6) Send SIGHUP to syslogd.
(7) Use NMAP to generate SYN/FIN scans

(1) Create a Firewall Script using IPTABLES

I have included the demo IPTABLES script as a text version for you to download. Make the script executable and run it. Don't forget to be logged in as root.

chmod 750 script_name
./script_name

      

#!/bin/sh
#
# Automatic Firewall Hardening
# by Vasoo Veerapen (dive_mauritius@hotmail.com)
# http://www.islandsoft.net/veerapen.html
#
# Please note that this script is Copyrighted material at all times.
# Any reproduction, modification or use of this document and/or its contents, 
# in part or entirety, is prohibited unless permission is obtained from the author.
#
# Maybe you are interested in scuba diving, marine conservation or my
# homeland, the paradise island of Mauritius where the Dodo used to live?
# Its simply
# http://www.islandsoft.net
#
# Revised on 1st of December 2001
#
# ----------------------------------------------------------------------
#
# This is a very basic IPTABLES script which checks for TCP scans with
# only the FIN bit set. FIN never occurs on its own and is an indication
# that someone is probably scanning your firewall and up to no good.
#
# If a scan is detected, it gets logged and the firewall is hardened
# against the offending IP address. This is a base for much more
# complex operations such as intrusion detection, paging  network
# admins, etc.
#
# The hardening is performed via syslogd which echoes messages
# to a named pipe rather than the screen. The named pipe then conveys
# data from syslogd to a hardening script of your choice.
#
# -----------------------------------------------------------------------
#
# Q: How do I generate SYN/FIN scans?
# A: Get NMAP at http://www.insecure.org/nmap
#
# Q: How do I create a named pipe?
# A: mknod /path/named_pipe p
#    chmod 600 /path/named_pipe
#
# Q: How do I tell syslogd to send data to the named pipe?
# A: Edit /etc/syslog.conf
#    Look for an entry starting like
#	*.info;mail.none;authpriv.none
#    Change the line to look like
#	*.info;mail.none;authpriv.none |/path/named_pipe
#
#	Replace the space between .none and | with a TAB!
#
# Q: How do I convey data from the named pipe to my script.
# A: (/path/my_script < /path/named_pipe)&
#    Then send kill -1 to syslogd.
#
#	Unless you want to type in this command every time you restart your
#	system I suggest that it be issued on system startup.
#	I use Red Hat/Mandrake, so in my case I put it into /etc/rc.d/rc.local

IPT="/sbin/iptables"

INT_IF="eth0"

LOG_LEVEL="notice"

$IPT -F INPUT
$IPT -F OUTPUT
$IPT -F FORWARD

$IPT -P INPUT ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD DROP

#*******************************************************************************
#FILTER_FLAGS
#*******************************************************************************
echo Entering FILTER_FLAGS
$IPT -N FILTER_FLAGS
$IPT -F FILTER_FLAGS
##----------------------------------------------------------------------------##
$IPT -A FILTER_FLAGS -p tcp --tcp-flags ALL FIN -m limit \
	--limit 5/minute -j LOG --log-level $LOG_LEVEL \
	--log-prefix "*SCAN*"
$IPT -A FILTER_FLAGS -p tcp --tcp-flags ALL FIN -j DROP

##----------------------------------------------------------------------------##
echo Leaving FILTER_FLAGS

#*******************************************************************************
# BANNED
#*******************************************************************************
echo Entering BANNED
$IPT -N BANNED
$IPT -F BANNED
##----------------------------------------------------------------------------##
# Leave blank
##----------------------------------------------------------------------------##
echo Leaving BANNED

	$IPT -A INPUT -j BANNED
	$IPT -A INPUT -j FILTER_FLAGS

	$IPT -A OUTPUT -j BANNED
	$IPT -A OUTPUT -j FILTER_FLAGS

#------------- End firewall script
      

(2) Create a Named Pipe

This creates a FIFO buffer which can store information coming from syslogd.

mknod /path/my_pipe p
chmod 600 /path/my_pipe

You could also use the mkfifo command. For more information, man is your friend.

(3) Create a Firewall Hardening Script

This script analyses the messages sent from SYSLOGD. If the messages contain the *SCAN* string, they get processed and the appropriate action is taken. I have included the demo script as a text version for you to download.


#!/bin/csh -f
#
# Please note that this script is Copyrighted material at all times.
# Any reproduction, modification or use of this document and/or its contents, 
# in part or entirety, is prohibited unless permission is obtained from the author.
#
loop:
set x="$<"

echo "$x" | grep -q '*SCAN*'
if ($status == 0 ) then
	set banned_ip=`echo "$x" | sed "s/.*SRC=\([^ ]*\) .*/\1/"`
	echo "# IP address $banned_ip was terminated."
	/sbin/iptables -A BANNED -s $banned_ip -j DROP
	/sbin/iptables -A BANNED -d $banned_ip -j DROP
endif

goto loop
#-----End shell script
      

(4) Convey Data from the Named Pipe to Script

At the command line, type in the following

(/path/my_script < /path/my_pipe)&

Unless you want to type in this command every time you restart your system I suggest that it be issued on system startup. In my case I placed the above line into /etc/rc.d/rc.local

(5) Tell syslogd to echo messages to the named pipe.

Backup and edit /etc/syslog.conf
Look for an entry starting like 
*.info;mail.none;authpriv.none


If you can't/can find the line then add/change the line to look like 
*.info;mail.none;authpriv.none |/path/my_pipe 

Remember the following points:
Make sure that you do not use spaces between authpriv.none and the pipe sign | Always use TAB.
Do not leave spaces between the pipe sign | and /path/my_pipe. They must be side by side without any spaces between them.

(6) Send SIGHUP to syslogd

Run ps -ax to find the pid of SYSLOGD. Issue a kill -1 to SYSLOGD

kill -1 [pid of syslogd]

(7) Use NMAP to send SYN/FIN scans

I have Apache (httpd) running on machine X (192.168.0.1) and I have installed my state-of-the-art IPTABLES firewall without forgetting my extremely intelligent C shell script.

On Machine Y (192.168.0.2) I open my favorite web browser.

On Y, I type in http://192.168.0.1/ and get my default Apache page. Nothing abnormal here. Now trying something slightly more evil, I go to the command line and type

nmap -sF -p 80 192.168.0.1

Taking a look at the screen on Machine X, I see

IP Address 192.168.0.2 was terminated.

Issue the command iptables -L on Machine X to verify if this is indeed the case.

Now try to get access to http://192.168.0.1 from Machine Y


Please note that any content within this document is Copyrighted material at all times. Any reproduction, modification, or use of this document and/or contents from the islandsoft.net domain, in part or entirety, is prohibited  unless explicit permission is obtained from the author.