Script de Shell para prohibir una IP

8

Algunas de las IP están abriendo miles de conexiones de mi servidor. Tengo un servidor Ubuntu 14. Compruebo las conexiones totales usando el siguiente comando:

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

Luego uso la siguiente regla de iptables para bloquear la IP culpable.

iptables -I INPUT 1 -s xxxx -j DROP

Funciona bien y bloquea la dirección IP. Sin embargo, no puedo permanecer en línea las 24 horas, los 7 días de la semana para monitorear el servidor. Me preguntaba si hay algún script de Shell que pueda usar para hacerlo automáticamente. Por ejemplo, si una IP abre más de X número de conexiones en cualquier momento, debería quedar automáticamente prohibida por la regla de iptables anterior.

usuario3404047
fuente
66
¿Has mirado para ver si fail2ban satisface tus necesidades?
John1024
Disculpe mi conocimiento limitado. ¿No es fail2ban para la autenticación ssh? No estoy seguro de usarlo en el puerto 80. Además, mi servidor es un servidor de chat, por lo que un usuario puede intentar conectarse / hacer ping varias veces. En este caso, fail2ban crearía muchas alarmas positivas falsas y prohibiría el tráfico legítimo. ¿Cualquier pensamiento?
user3404047

Respuestas:

10

En primer lugar, no reinventes la rueda. Eso es precisamente para lo que denyhostssirve:

   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.

Hasta donde yo sé, denyhostses solo para sshconexiones, pero también hay fail2banque lidiar con casi cualquier cosa:

   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án disponibles en los repositorios:

sudo apt-get install denyhosts fail2ban

También puedes escribir esto, si quieres. 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

El awkextraerá las IPs y contarlos y sólo imprimir los que aparecen más maxveces (en este caso, -vmax=100, cambie en consecuencia). Las IP se alimentan a un ciclo while que ejecuta la iptablesregla relevante .

Para ejecutar esto las 24 horas del día, los 7 días de la semana, haría un trabajo cron que ejecuta el comando anterior cada minuto más o menos. Agregue esta línea a/etc/crontab

* * * * * root /path/to/script.sh
terdon
fuente
Gracias terdon por una respuesta precisa. AFAIK, fail2ban es para autenticación ssh. Todas las conexiones se están abriendo en el puerto 80. Exploraré si puedo usar fail2ban en el puerto 80. Para el script personalizado, ¿cómo podría ejecutarlo 24/7 en segundo plano? comando de pantalla? O instalar cron? Por cierto. Estoy usando el servidor como un servidor de chat para que una persona pueda hacer ping muchas veces (o abrir varias conexiones) para que pueda elegir el script personalizado que me proporcionó.
user3404047
2
@ user3404047 podría ejecutarlo como un cronjob, sí. Ver respuesta actualizada. Sin embargo, fail2banno es solo para ssh. También funciona muy bien para el puerto 80. Véase, por ejemplo, aquí , aquí y aquí .
terdon
1

Una posible opción alternativa es identificar y tratar las direcciones IP problemáticas dentro del conjunto de reglas de iptables, utilizando el recentmódulo. El desafío con este método es el límite de hitcount predeterminado de 20, por lo que uno debe desviarse de los valores predeterminados o crear contadores de acarreo de mayor nivel para lograr un punto de activación de hitcount más alto.

El siguiente ejemplo es de mi conjunto de reglas iptables, y prohibirá una dirección IP por poco más de 1 día si realiza 80 nuevas conexiones TCP en el puerto 80 en menos de 12 minutos. Una vez en la lista de tipos malos, cualquier intento de conexión restablecerá el contador de 1 día a 0. Este método podría llegar a un máximo de 400 visitas antes de que se requiriera la expansión a otro transporte (y he probado otra cadena de transporte). Tenga en cuenta que el código publicado tiene la infraestructura que se utilizará para prohibir solo durante mucho tiempo en múltiples desencadenantes de tiempo más cortos. Actualmente, lo tengo configurado para prohibir durante mucho tiempo en el primer disparador.

#######################################################################
# 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
fuente