Script shell para banir um IP

8

Alguns dos IPs estão abrindo milhares de conexões do meu servidor. Eu tenho um servidor Ubuntu 14. Eu verifico o total de conexões usando o seguinte comando:

  

netstat -an | grep tcp | awk '{print $ 5}' | corte -f 1 -d: | classificar |   uniq -c | classificar -n

Então eu uso a seguinte regra do iptables para bloquear o IP culpado.

  

iptables -I INPUT 1 -s x.x.x.x -j DROP

Funciona muito bem e bloqueia o endereço IP. No entanto, não posso ficar online 24/7 para monitorar o servidor. Eu queria saber se existe algum script Shell que eu possa usar para fazer isso automaticamente? Por exemplo, se um IP abrir mais de um número X de conexões a qualquer momento, ele deve ser automaticamente banido pela regra acima do iptables.

    
por user3404047 09.10.2015 / 23:45

2 respostas

9

Primeiro de tudo, não reinvente a roda. É precisamente para isso que o denyhosts é:

   DenyHosts  is a python program that automatically blocks ssh attacks by
   adding entries to /etc/hosts.deny.  DenyHosts will  also  inform  Linux
   administrators  about  offending  hosts,  attacked users and suspicious
   logins.

Tanto quanto sei, denyhosts é apenas para ssh conexões, mas também há fail2ban que lida com praticamente tudo:

   Fail2Ban consists of a client, server and configuration files to  limit
   brute force authentication attempts.

   The  server  program  fail2ban-server is responsible for monitoring log
   files and issuing ban/unban commands.  It  gets  configured  through  a
   simple  protocol  by fail2ban-client, which can also read configuration
   files and issue corresponding configuration commands to the server.

Ambos estão disponíveis nos repositórios:

sudo apt-get install denyhosts fail2ban

Você também pode criar scripts, se quiser. Algo como:

#!/usr/bin/env sh
netstat -an | 
    awk -vmax=100 '/tcp/{split(,a,":"); if(a[1] > 0 && a[1]!="0.0.0.0"){c[a[1]]++}}
    END{for(ip in c){if(c[ip]>max){print ip}}}' |
        while read ip; do iptables -I INPUT 1 -s "$ip" -j DROP; done

O awk irá extrair os IPs e contá-los e imprimir somente aqueles que aparecerem mais de max times (aqui, -vmax=100 , altere-o de acordo). Os IPs são então alimentados para um loop while que executa a regra iptables relevante.

Para rodar este 24/7, eu faria um cronjob que executa o comando acima a cada minuto. Adicione esta linha a /etc/crontab

* * * * * root /path/to/script.sh
    
por terdon 10.10.2015 / 02:00
1

Uma opção alternativa possível é identificar e lidar com o problema de endereços IP, todos dentro do conjunto de regras iptables, usando o módulo recent . O desafio com esse método é o limite de hitcount padrão de 20, portanto é preciso desviar dos padrões ou criar contadores de carry de nível mais alto para alcançar um ponto de acionamento de contagem de pontos mais alto.

O exemplo abaixo é do meu conjunto de regras iptables, e irá banir um endereço IP por pouco mais de 1 dia se fizer 80 novas conexões TCP na porta 80 em menos de 12 minutos. Uma vez na lista de pessoas mal-intencionadas, qualquer tentativa de conexão redefinirá o contador de 1 dia para 0. Esse método pode atingir um máximo de 400 ocorrências antes que a expansão para outro carregamento seja necessária (e eu testei outra cadeia de transporte). Observe que o código como postado tem a infra-estrutura a ser usada para banir apenas por um longo tempo em vários gatilhos de tempo mais curtos. Atualmente, estou pronto para banir por um longo tempo após o primeiro disparo.

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in4
#
# A NEW Connection on port 80 part 4.
#
# multiple hits on the banned list means you get a one day ban.
# (I re-load the firewall rule set often, so going longer makes
# little sense.)
#
# Custom tables must exist before being referenced, hence the order
# of these sub-toutines.
#
# Place holder routine, but tested. Logs if a day ban would have
# been activated.
#
$IPTABLES -N http-new-in4
#$IPTABLES -A http-new-in4 -m recent --set --name HTTP_BAN_DAY

$IPTABLES -A http-new-in4 -j LOG --log-prefix "DAY80:" --log-level info
$IPTABLES -A http-new-in4 -j DROP

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in3
#
# A NEW Connection on port 80 part 3.
#
# carry forward to the actual banned list:
# Increment this count. Leave the previous count.
#
# Custom tables must exist before being referenced, hence the order
# of these sub-toutines.
#
$IPTABLES -N http-new-in3
$IPTABLES -A http-new-in3 -m recent --remove --name HTTP_02
$IPTABLES -A http-new-in3 -m recent --update --hitcount 1 --seconds 86400 --name HTTP_BAN -j http-new-in4
$IPTABLES -A http-new-in3 -m recent --set --name HTTP_BAN

$IPTABLES -A http-new-in3 -j LOG --log-prefix "BAN80:" --log-level info
$IPTABLES -A http-new-in3 -j DROP

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in2
#
# A NEW Connection on port 80 part 2.
#
# carry forward from previous max new connections per unit time:
# Increment this count and clear the lesser significant count.
#
$IPTABLES -N http-new-in2
$IPTABLES -A http-new-in2 -m recent --remove --name HTTP_01
$IPTABLES -A http-new-in2 -m recent --update --hitcount 3 --seconds 720 --name HTTP_02 -j http-new-in3
$IPTABLES -A http-new-in2 -m recent --set --name HTTP_02

$IPTABLES -A http-new-in2 -j LOG --log-prefix "CARRY80:" --log-level info
$IPTABLES -A http-new-in2 -j ACCEPT

#######################################################################
# USER DEFINED CHAIN SUBROUTINES:
#
# http-new-in
#
# A NEW Connection on port 80:
#
$IPTABLES -N http-new-in

echo Allowing EXTERNAL access to the WWW server

# . check the static blacklist.
#
# http related
$IPTABLES -A http-new-in -i $EXTIF -s 5.248.83.0/24 -j DROP
... delete a bunch on entries ...
$IPTABLES -A http-new-in -i $EXTIF -s 195.211.152.0/22 -j DROP
$IPTABLES -A http-new-in -i $EXTIF -s 198.27.126.38 -j DROP

# . check the dynamic banned list
#
# The 1 Hour banned list (bumped to more than a day):
$IPTABLES -A http-new-in -m recent --update --seconds 90000 --name HTTP_BAN --rsource -j LOG --log-prefix "LIM80:" --log-level info
$IPTABLES -A http-new-in -m recent --update --seconds 90000 --name HTTP_BAN --rsource -j DROP

# A generic log entry. Usually only during degugging
#
#$IPTABLES -A http-new-in -j LOG --log-prefix "NEW80ALL:" --log-level info

# Dynamic Badguy List. Least significant hit counter.  Detect and DROP Bad IPs that do excessive connections to port 80.
#
$IPTABLES -A http-new-in -m recent --update --hitcount 20 --seconds 240 --name HTTP_01 -j http-new-in2
$IPTABLES -A http-new-in -m recent --set --name HTTP_01

$IPTABLES -A http-new-in -j LOG --log-prefix "NEW80:" --log-level info
$IPTABLES -A http-new-in -j ACCEPT

... a bunch of stuff not included here

# Allow any related traffic coming back to the server in.
#
#
$IPTABLES -A INPUT -i $EXTIF -s $UNIVERSE -d $EXTIP -m state --state ESTABLISHED,RELATED -j ACCEPT

... the above is needed before the below ...

# If required, go to NEW HTTP connection sub-routine
#
$IPTABLES -A INPUT -i $EXTIF -m state --state NEW -p tcp -s $UNIVERSE -d $EXTIP --dport 80 -j http-new-in
    
por Doug Smythies 10.10.2015 / 17:17