[ Home | Liste | F.A.Q. | Risorse | Cerca... ]


[ Data: precedente | successivo | indice ] [ Argomento: precedente | successivo | indice ]


Archivio: Giugno 2005 ml@sikurezza.org
Soggetto: Re: [ml] Brute force attacks su ssh: a script to block them
Mittente: Igor Falcomata'
Data: Tue, 21 Jun 2005 21:38:40 +0200 (CEST)
On Mon, Jun 20, 2005 at 09:31:46PM +0200, Paolo Nason wrote:

> Uso da un paio di mesi lo script, e (per me) funziona bene.
> Il mio sistema e' Fedora 3; per altri sistemi il formato
> dei logfile potrebbe essere diverso, il firewall diverso, etc.

Sorry, problema coi filtri; forwardo lo script di Paolo a mano.

Disclaimer  generico:  non  e'  roba  mia,  e'  solo  l'attachement  del
messaggio originale  che si e' perso  nei filtri di moderazione:  non ho
letto lo  script e generalmente  sono allergico  a queste cose  fatte in
shell script.

thnx
Koba (moderatore)
#!/bin/bash
# P. Nason, may 2005
# script to block IP addresses with a recent history of sshd
# login failures. If more than maxbadness failures have appeared,
# separated by less than gracetime secobnds the IP
# address is blocked by the firewall.

maxbadness=4
gracetime=1000

function addip {
# if not already present, adds the given ip ( $1) to the list
# of ip's previously stored, together with the time of storage, and returns 1.
# If the ip was already there, and was added less than 1000 seconds
# ago, it adds 1 to the "badness" index if the ip, and returns the
# current badness (number of failures separated by less than 1000 seconds).
# Otherwise, it resets the badness to 1 (to avoid that login failures
# spread over a long time would block access from a legal user)
    now=`date +%s`
    i=0
    while ! [ a${iparr[$i]} = a ]
    do
      if [ ${iparr[$i]} = $1 ]
	  then
	  last=${timearr[$i]}
	  if [ $[$now-$last] -lt $gracetime ]
# new failure less than gracetime seconds from last failure
	      then
	      badnessarr[$i]=$[${badnessarr[$i]}+1];
	      timearr[$i]=$now
	      return ${badnessarr[$i]}
	  else
# no failures in the last gracetime seconds: restart with one failure from now;
	      timearr[$i]=$now
	      badnessarr[$i]=1
	  fi
      fi
      i=$[$i+1]
    done
    if [ $i -gt 1000 ]
	then unset badnessarr iparr timearr
	return 0
    fi
    iparr[$i]=$1
    badnessarr[$i]=1
    timearr[$i]=$now
    return 1
}

unset badnessarr iparr timearr

# We now follow the messages file. The file is logrotated
# every so often. So, we must make sure that we switch to
# the new file when logrotated. Be aware that tail -f
# keeps following the renamed file, and so it doesn't work.
# tailf works properly: if messages is renamed it follows
# the new file.
#
# We wrap the whole thing in a while : do; just in case
# tailf fails...
while :
do
  /usr/bin/tailf /var/log/messages | while :
    do
    read line
    if [ a"$line" = a ]
	then break
    fi
    fail=n
    h=n
    ssh=n
    for i in $line
      do
      case $i in
	  rhost=*) h=y ; host=`echo $i | cut -d= -f2`;;
	  failure*) fail=y;;
	  sshd*) ssh=y;;
      esac
    done
    if [ $fail = y ] && [ $h = y ] && [ $ssh = y ]
	then
	addip $host
	howmany=$?
	if [ $howmany -gt $maxbadness ]
	    then # blacklist!
	    echo $line
# first delete a matching rule, if any (shouldn't be there anyhow...)
# softer option: /sbin/iptables -I INPUT -i eth0 -p tcp --dport 22 -j DROP -s $host
	    /sbin/iptables -D INPUT -i eth0 -j DROP -s $host > /dev/null 2>&1
	    /sbin/iptables -I INPUT -i eth0 -j DROP -s $host
	    echo /sbin/iptables -I INPUT -i eth0 -j DROP -s $host
	fi
    fi
  done
# something went wrong with tailf; retry
  sleep 10
done
	



[ Home | Liste | F.A.Q. | Risorse | Cerca... ]

www.sikurezza.org - Italian Security Mailing List
(c) 1999-2005