Bloqueio de tráfego de países específicos. Como matar a conexão existente?

Bloqueio de tráfego de países específicos. Como matar a conexão existente?

Usando Linux Debian Bookworm.

Problema

Quero bloquear todas as conexões de entrada do meu servidor provenientes de países específicos.

Editar

Como alguém apontou nos comentários, eu realmente não deveria fazer isso com o iptables, pois isso paralisará meu servidor quando a lista de endereços IP que ele bloqueia crescer para um tamanho incontrolável (como milhares de endereços IP). Em vez disso, devo usar ipset(para bloquear intervalos inteiros). O problema é que depende das listas que preciso baixar regularmente. Quero algo que configurei uma vez (de preferência).

Então, como posso interromper conexões de países específicos?O tráfego (e por vezes ataques de força bruta) proveniente da China e da Rússia está a ficar fora de controlo. Eles colocam meu servidor de joelhos regularmente. Eles não aderem ao arquivo robots.txt e rastreiam o site de forma muito agressiva (com centenas, às vezes milhares de conexões simultaneamente). Eu realmente preciso parar com isso. Minha estimativa é que mais de 90% de todo o tráfego que meu servidor gerencia é malicioso/malformado.

Editar 2

Encontrei alguns tutoriais online (como este) como fazer isso, mas parece que esses tutoriais são bem antigos. Além disso, requer download e compilação/instalação de alguns módulos. Estou preocupado que isso possa falhar no futuro (ao atualizar/atualizar outros pacotes ou até mesmo a distribuição) ou possa se tornar um risco de segurança no futuro. Eu mantenho meu servidor atualizado e atualizado (executando apt-get update / apt-get upgrade / apt-get dist-upgrade regularmente).

mensagem original

Encontrei um script on-line que (em poucas palavras) obtém uma lista de endereços IP de conexões estabelecidas a cada segundo e depois usa o geoiplookup para obter o país do endereço IP. Se o país estiver na lista de países que você deseja bloquear, ele adiciona o endereço IP ao filtro do firewall usando iptables. Fiz algumas pequenas alterações no script (tornando-o mais legível e porque não estava interessado neste script me enviando um e-mail toda vez que bloqueava um endereço IP). Este script é executado a cada minuto através do 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

Aliás, não tenho ideia de por que o autor do script usa nomes de variáveis ​​tão estranhos ("bGF1dGVuYmFjaGVyLmlv").

De qualquer forma, o problema é que sempre que encontra uma conexão com um endereço IP de um país banido, ele executa

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

no endereço IP. Tudo bem, mas a maioria dessas conexões é um tanto persistente, o que significa que um segundo depois o mesmo endereço IP é encontrado e adicionado novamente usando iptables. Não tenho certeza do que acontece (isso cria regras duplicadas?), mas gostaria de interromper imediatamente a conexão após o endereço IP ser adicionado ao iptables.

Resumindo: como posso eliminar todas as conexões com um endereço IP?

Responder1

Há vários anos, o kernel do Linux tem uma API para eliminar à força os soquetes IP existentes, independentemente do seu estado. Isso pode ser feito com osscomando e sua sintaxe de filtro:

-K,--kill

Tentativas de fechar soquetes à força. Esta opção exibe os soquetes que foram fechados com sucesso e ignora silenciosamente os soquetes que o kernel não suporta o fechamento. Suporta apenas soquetes IPv4 e IPv6.

Você pode substituir:

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

com:

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

Ofiltro( dst = ...) é necessário porque o comando eliminará qualquer soquete que seja exibido. Sem filtro isso seria mais do que pedido. O processo local pode receber um erro raro em seu soquete, como ECONNABORTED. O nó remoto provavelmente será notificado com um TCP RST, a menos que uma regra OUTPUT também seja (temporariamente) adicionada para evitá-lo.

Veja também esta pergunta/resposta (onde respondi):Elimine TODAS as conexões TCP (ESTABELECIDAS, RELACIONADAS) no Ubuntu, onde o OP tenta se proteger de ataques com umipset(e também tem problemas com conexões obsoletas e firewall com estado).

informação relacionada