Adicionando sleep / delay entre blocos iptables no shell script

1

Em um servidor, estamos tentando bloquear qualquer acesso para o país China.

Desejamos implementar isso com o iptables ao invés de via .htaccess.

O problema que estamos enfrentando, porém, é que ao adicionar múltiplos iptables de uma vez (e estamos falando de mais de 1000 sub-redes IP para a China aqui), um falhará (com erro 'iptables: erro desconhecido 18446744073709551615' e depois todos os outros depois falharão) o que significa que temos de iptables -F para continuar a adicionar estas regras.

Alguns testes concluem que o problema parece ser quando se tenta executar lotes de uma só vez (ou até mesmo 10+ de cada vez parece lançar o erro) em vez de o servidor simplesmente não gostar de algumas regras específicas.

Então me perguntei se tentar adicionar um sleep (ou algum outro atraso) entre cada regra do iptables em execução pode melhorar o processo?

Nós tentamos inúmeras maneiras de implementar estes iptables agora, mas nós gostaríamos, se possível, de usar este script do nixCraft , que pode ser visto abaixo.

#!/bin/bash
### Block all traffic from AFGHANISTAN (af) and CHINA (CN). Use ISO code ###
ISO="af cn"

### Set PATH ###
IPT=/sbin/iptables
WGET=/usr/bin/wget
EGREP=/bin/egrep

### No editing below ###
SPAMLIST="countrydrop"
ZONEROOT="/root/iptables"
DLROOT="http://www.ipdeny.com/ipblocks/data/countries"

cleanOldRules(){
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -P FORWARD ACCEPT
}

# create a dir
[ ! -d $ZONEROOT ] && /bin/mkdir -p $ZONEROOT

# clean old rules
cleanOldRules

# create a new iptables list
$IPT -N $SPAMLIST

for c  in $ISO
do
    # local zone file
    tDB=$ZONEROOT/$c.zone

    # get fresh zone file
    $WGET -O $tDB $DLROOT/$c.zone

    # country specific log message
    SPAMDROPMSG="$c Country Drop"

    # get 
    BADIPS=$(egrep -v "^#|^$" $tDB)
    for ipblock in $BADIPS
    do
       $IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
       $IPT -A $SPAMLIST -s $ipblock -j DROP
    done
done

# Drop everything 
$IPT -I INPUT -j $SPAMLIST
$IPT -I OUTPUT -j $SPAMLIST
$IPT -I FORWARD -j $SPAMLIST

# call your other iptable script
# /path/to/other/iptables.sh

exit 0

Eu não estou particularmente familiarizado com scripts de shell, e não tenho certeza em que ponto deste script eu poderia adicionar algum tipo de atraso entre o processamento do iptables, se possível. Por favor, alguém poderia me apontar na direção certa? Obrigado.

    
por zigojacko 27.08.2013 / 14:24

2 respostas

4

O Netfilter / iptables não é bem dimensionado quando usado com um número maior de regras, uma vez que elas devem ser combinadas sequencialmente. Mas desde o kernel Linux 2.6.36, existe um novo recurso chamado IP sets que ajuda a eliminar tais regras usando técnicas de hashing. Resumidamente, como funciona:

1) crie um conjunto de IP

ipset create set01 hash:net

2) adicione intervalos de IP ao conjunto

ipset add set01 192.168.1.0/24
ipset add set01 192.168.2.0/24
ipset add set01 192.168.3.0/24
ipset add set01 192.168.4.0/24
...
...

3) conecte o conjunto com a regra netfilter / iptables que rejeita qualquer pacote com endereço IP de origem do set01

iptables -A INPUT -m set --match-set set01 src -j REJECT

Como você pode ver, em vez de criar 4 quase as mesmas regras do iptables eu criei um conjunto IP set01, então adicionei alguns intervalos de IP a ele (apenas um exemplo, na verdade, pode haver milhões deles) e finalmente bloqueou-os por regra única iptables. Então, ao invés de manter uma longa lista de regras de iptables similares, crie um conjunto de IPs de acordo com os arquivos de zonas e, em seguida, bloqueie-o em uma única etapa.

Por favor, verifique a página do manual do ipset para mais detalhes.

    
por 27.08.2013 / 15:12
1

Concordo com dsumsky que você pode precisar de uma nova abordagem. Mas para atrasar 1 segundo para cada 4 entradas carregadas, o código a ser inserido seria algo assim:

i=0  # delay iterator

BADIPS=$(egrep -v "^#|^$" $tDB)
for ipblock in $BADIPS
do
   # delay to help rules load properly.
   if [[ $i == 5 ]]
   then
         sleep 1
         i=0
   fi

   i=$((i+1))

   $IPT -A $SPAMLIST -s $ipblock -j LOG --log-prefix "$SPAMDROPMSG"
   $IPT -A $SPAMLIST -s $ipblock -j DROP
done

Você pode experimentar o código com um bloco de código como este:

 #!/bin/bash
 i=0
 while [ 1 ]
 do
    i=$((i+1))
    if [[ $i == 5 ]]
    then
            sleep 1
            i=0
    fi


    echo hello $i
done
    
por 27.08.2013 / 15:45