Script de 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. 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 ENTRADA 1 -s xxxx -j DROP

Funciona bem e bloqueia o endereço IP. No entanto, não consigo ficar online 24/7 para monitorar o servidor. Eu queria saber se existe algum script do 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 deverá ser automaticamente banido pela regra acima do iptables.

user3404047
fonte
6
Você já olhou para ver se fail2ban atende às suas necessidades?
precisa saber é o seguinte
Desculpe meu conhecimento limitado. Fail2ban não é para autenticação ssh? Não tenho certeza de usá-lo na porta 80. Além disso, meu servidor é um servidor de bate-papo, para que um usuário possa tentar conectar / executar ping várias vezes. Nesse caso, o fail2ban criaria muitos alarmes falso-positivos e proibiria o tráfego legítimo. Alguma idéia?
user3404047

Respostas:

10

Primeiro de tudo, não reinvente a roda. É exatamente denyhostspara isso:

   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.

Até onde eu sei, denyhostsé apenas para sshconexões, mas também há fail2banpraticamente 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 escrever isso, se quiser. Algo como:

#!/usr/bin/env sh
netstat -an | 
    awk -vmax=100 '/tcp/{split($5,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

Ele awkextrairá os IPs e os contará e imprimirá apenas aqueles que aparecerem mais que o maxtempo (aqui -vmax=100, altere-o de acordo). Os IPs são então alimentados para um loop while que executa a iptablesregra relevante .

Para executar isso 24/7, eu faria um cronjob que executa o comando acima a cada minuto ou mais. Adicione esta linha a/etc/crontab

* * * * * root /path/to/script.sh
Terdon
fonte
Obrigado Terdon por uma resposta precisa. AFAIK, fail2ban é para autenticação ssh. Todas as conexões estão sendo abertas na porta 80. Explorarei se posso usar o fail2ban na porta 80. Para o script personalizado, como eu poderia executá-lo 24/7 em segundo plano? comando de tela? Ou instalar cron? Entre. Estou usando o servidor como servidor de bate-papo para que uma pessoa possa executar ping muitas vezes (ou abrir várias conexões) para que eu possa ir para o script personalizado que você forneceu.
user3404047
2
@ user3404047 você pode executá-lo como um cronjob, sim. Veja a resposta atualizada. No entanto, fail2bannão é apenas para ssh. Ele também funciona muito bem para a porta 80. Ver, por exemplo aqui , aqui e aqui .
terdon 10/10
1

Uma opção alternativa possível é identificar e lidar com os endereços IP do problema, todos dentro do conjunto de regras do iptables, usando o recentmódulo O desafio desse método é o limite de contagem de ocorrências padrão de 20, portanto, é necessário desviar-se dos padrões ou criar contadores de transporte de nível mais alto para obter um ponto de disparo de contagem de ocorrências mais alto.

O exemplo abaixo é do meu conjunto de regras do iptables e banirá um endereço IP por pouco mais de um dia se ele fizer 80 novas conexões TCP na porta 80 em menos de 12 minutos. Uma vez na lista de bandidos, qualquer tentativa de conexão redefinirá o contador de 1 dia para 0. Esse método pode atingir o máximo de 400 ocorrências antes que a expansão para outro transporte seja necessária (e eu testei outra cadeia de transporte). Observe que o código postado tem a infraestrutura para ser usada para banir apenas por um longo período de tempo após vários disparadores de tempo mais curto. Atualmente, eu tenho que definir para banir por um longo tempo após o primeiro gatilho.

#######################################################################
# 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
Doug Smythies
fonte