LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   optimizing this bash script (http://www.linuxquestions.org/questions/programming-9/optimizing-this-bash-script-719129/)

yah0m 04-14-2009 06:17 PM

optimizing this bash script
 
Basically, the script uses netstat to scan for SYN_RECV and then bans them. However, the script can lag/hang up the server due to using netstat. Is there a better way to do this?


Code:

#!/bin/sh
load_conf()
{
    CONF="/usr/local/synd/synd.conf"
    if [ -f "$CONF" ] && [ ! "$CONF" ==    "" ]; then
        source $CONF
    else
        head
        echo "\$CONF not found."
        exit 1
    fi
}

head()
{
    echo
}

showhelp()
{
    head
    echo 'Usage: synd.sh [OPTIONS] [N]'
    echo 'N : number of SYN_RECV connections (default 10)'
    echo 'OPTIONS:'
    echo '-h | --help: Show    this help screen'
    echo '-c | --cron: Create cron job to run this script regularly (default 1 mins)'
    echo '-k | --kill: Block the offending ip making more than N SYN_RECV connections'
    echo 'syndc | Commmand to edit the configuration file with nano'
}

add_to_cron()
{
    rm -f $CRON
    sleep 1
    service crond restart
    sleep 1
    echo "SHELL=/bin/sh" > $CRON
    if [ $FREQ -le 2 ]; then
        echo "0-59/$FREQ * * * * root /usr/local/synd/synd.sh >/dev/null 2>&1" >> $CRON
    else
        let "START_MINUTE = $RANDOM % ($FREQ - 1)"
        let "START_MINUTE = $START_MINUTE + 1"
        let "END_MINUTE = 60 - $FREQ + $START_MINUTE"
        echo "$START_MINUTE-$END_MINUTE/$FREQ * * * * root /usr/local/synd/synd.sh >/dev/null 2>&1" >> $CRON
    fi
    service crond restart
}


load_conf
while [ $1 ]; do
    case $1 in
        '-h' | '--help' | '?' )
            showhelp
            exit
        ;;
        '--cron' | '-c' )
            add_to_cron
            exit
        ;;
        '--kill' | '-k' )
            KILL=1
        ;;
        *[0-9]* )
            NO_OF_CONNECTIONS=$1
        ;;
        * )
            showhelp
            exit
        ;;
    esac
    shift
done

TMP_PREFIX='/tmp/synd'
TMP_FILE="mktemp $TMP_PREFIX.XXXXXXXX"
BANNED_IP_MAIL=`$TMP_FILE`
BANNED_IP_LIST=`$TMP_FILE`
echo "Banned the following ip addresses on `date`" > $BANNED_IP_MAIL
echo >>    $BANNED_IP_MAIL
BAD_IP_LIST=`$TMP_FILE`
netstat -ntu | grep SYN_RECV | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LIST
cat $BAD_IP_LIST
if [ $KILL -eq 1 ]; then
    IP_BAN_NOW=0
    while read line; do
        CURR_LINE_CONN=$(echo $line | cut -d" " -f1)
        CURR_LINE_IP=$(echo $line | cut -d" " -f2)
        if [ $CURR_LINE_CONN -lt $NO_OF_CONNECTIONS ]; then
            break
        fi
        IGNORE_BAN=`grep -c $CURR_LINE_IP $IGNORE_IP_LIST`
        if [ $IGNORE_BAN -ge 1 ]; then
            continue
        fi
        IP_BAN_NOW=1
        echo "$CURR_LINE_IP with $CURR_LINE_CONN SYN_RECV connections" >> $BANNED_IP_MAIL
        echo $CURR_LINE_IP >> $BANNED_IP_LIST
        echo $CURR_LINE_IP >> $IGNORE_IP_LIST
        if [ $CSF_BAN -eq 1 ]; then
            $CSF -d $CURR_LINE_IP
        else
            $IPT -I INPUT -s $CURR_LINE_IP -j DROP
        fi
    done < $BAD_IP_LIST
    if [ $IP_BAN_NOW -eq 1 ]; then
        dt=`date`
                hn=`hostname`
        if [ $EMAIL_TO != "" ]; then
            cat $BANNED_IP_MAIL | mail -s "IP addresses banned on $dt $hn" $EMAIL_TO
        fi
    fi
fi
rm -f $TMP_PREFIX.*


1337 04-15-2009 01:14 AM

I'm not entirely sure, but netcat might be a better option.

yah0m 04-17-2009 11:53 AM

I guess I could look into how CSF does it... all I know is when I get hit by a major syn flood (some ips opening over 30k connections each), the server totally locks up for about a minute and this is an 8core machine.

unSpawn 04-17-2009 12:07 PM

Why are you using something interpreted instead of compiled? Are you sure there's no OTS solution? Ever tried iptables?

yah0m 04-17-2009 01:27 PM

OTS?

unSpawn 04-17-2009 06:14 PM

Uh. Sorry. Off The Shelf. Ready-made. Available.

yah0m 04-17-2009 07:42 PM

CSF actually worked fine, but for some reason these big SYN Floods crap it out(blocks everyone from accessing the server when you view top), so I've been running this script on the side of CSF along with some custom IPTable rules.


All times are GMT -5. The time now is 02:35 AM.