Bloquear el tráfico de países específicos. ¿Cómo eliminar la conexión existente?

Bloquear el tráfico de países específicos. ¿Cómo eliminar la conexión existente?

Usando Linux Debian Bookworm.

Problema

Quiero bloquear todas las conexiones entrantes a mi servidor provenientes de países específicos.

Editar

Como alguien señaló en los comentarios, realmente no debería hacer esto con iptables, ya que esto detendrá mi servidor una vez que la lista de direcciones IP que bloquea crezca a un tamaño inmanejable (como miles de direcciones IP). En su lugar, debería usar ipset(para bloquear rangos enteros). El problema con esto es que depende de las listas que necesito descargar regularmente. Quiero algo que configuré una vez (preferiblemente).

Entonces, ¿cómo puedo detener las conexiones desde países específicos?El tráfico (y a veces los ataques de fuerza bruta) procedente de China y Rusia se está yendo de las manos. Ponen de rodillas a mi servidor con regularidad. No respetan el archivo robots.txt y rastrean el sitio de forma muy agresiva (con cientos, a veces miles de conexiones simultáneamente). Realmente necesito detener eso. Mi estimación es que más del 90% de todo el tráfico que maneja mi servidor es malicioso o tiene formato incorrecto.

Editar 2

Encontré algunos tutoriales en línea (como éste) cómo hacer esto, pero parece que estos tutoriales son bastante antiguos. Además, requiere descargar y compilar/instalar algunos módulos. Me preocupa que esto pueda fallar en el futuro (al actualizar otros paquetes o incluso la distribución) o que pueda convertirse en un riesgo de seguridad en el futuro. Mantengo mi servidor actualizado (ejecutando apt-get update / apt-get Upgrade / apt-get dist-upgrade regularmente).

Mensaje original

Encontré un script en línea que (en pocas palabras) obtiene una lista de direcciones IP de conexiones establecidas cada segundo y luego usa geoiplookup para obtener el país de la dirección IP. Si el país está en la lista de países que le gustaría bloquear, agrega la dirección IP a su filtro de firewall usando iptables. Hice algunos cambios leves en el script (para hacerlo más legible y porque no estaba interesado en este script, me enviaba un correo electrónico cada vez que bloqueaba una dirección IP). Luego, este script se ejecuta cada minuto a través de crontab:

#!/bin/bash
# Script found on lautenbacher.io"

end=$((SECONDS+55))

while [ $SECONDS -lt $end ]; do
  echo $SECONDS
  netstat -ant | egrep ':.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > testcc.txt
  sed 's/^[ t]*//' -i testcc.txt
  sed '/^$/d' -i testcc.txt

  while read c d; do

    if [[ $c > "0" ]]; then
      bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $d | awk -v ip="$d" '{FS=" "} {if($4 == "RU," || $4 == "CN," || $4 == "BLR,") {print 1}}')

      if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
        echo "running geolookup"
        echo checking ip $d
        geoiplookup $d

        isCloudflare=0
        # The original script made an exception for CLOUDFLARE. I don't want that exception
        # bGF1dGVuYmFjaGVyLmlX=$(whois $d)
        # if [[ "$bGF1dGVuYmFjaGVyLmlX" == *"CLOUDFLARE "* ]]; then
        #  isCloudflare=1
        #  echo Cloudflare detected
        # fi

        if [[ "$isCloudflare" != 1 ]]; then
          echo try to add ip $d to blocklist
          sudo iptables -I INPUT -s $d -j DROP
          ### I would like to sever the connection here ###
        fi

      fi

    fi
  done < testcc.txt

  sleep 1
    :
done

Por cierto, no tengo idea de por qué el autor del script usa nombres de variables tan extraños ("bGF1dGVuYmFjaGVyLmlv").

De todos modos, el problema es que cada vez que encuentra una conexión con una dirección IP de un país prohibido, ejecuta

sudo iptables -I INPUT -s $d -j DROP

en la dirección IP. Todo esto está bien, pero la mayoría de estas conexiones son algo persistentes, lo que significa que un segundo después se encuentra la misma dirección IP y se agrega nuevamente usando iptables. No estoy seguro de qué sucede (¿crea reglas duplicadas?), pero me gustaría interrumpir la conexión inmediatamente después de agregar la dirección IP con iptables.

En resumen: ¿Cómo puedo eliminar una(s) conexión(es) con una dirección IP?

Respuesta1

Desde hace varios años, el kernel de Linux tiene una API para eliminar por la fuerza los sockets IP existentes cualquiera que sea su estado. Se puede hacer con elsscomando y su sintaxis de filtro:

-K,--kill

Intenta cerrar los enchufes a la fuerza. Esta opción muestra los sockets que se cerraron exitosamente y omite silenciosamente los sockets que el kernel no admite cerrar. Solo admite sockets IPv4 e IPv6.

Puedes reemplazar:

### I would like to sever the connection here ###

con:

ss --kill -n dst = "$d"

Elfiltrar( dst = ...) es necesario, porque el comando eliminará cualquier socket que se muestre. Sin filtro eso sería más de lo pedido. El proceso local podría obtener un error poco común en su socket, como ECONNABORTED. El nodo remoto probablemente será notificado con un TCP RST a menos que también se agregue (temporalmente) una regla de SALIDA para evitarlo.

Vea también esta pregunta/respuesta (donde respondí):Elimine TODAS las conexiones TCP (ESTABLECIDAS, RELACIONADAS) en Ubuntu, donde OP intenta protegerse de ataques con unipset(y también tiene problemas con conexiones obsoletas y firewalls con estado).

información relacionada