Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

1. Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Jhony Cesar
cesarjhony

(usa Coyote)

Enviado em 22/12/2012 - 20:30h

Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Estou aprendendo shell script, quero montar um script para inserir valores dentro de um script do iptables, por exemplo.
Da seguinte maneira:
##########################################################
#!/bin/sh

BLOCKQ() {
echo "BLOCK... $IP2"
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 20:79 -j DROP" >> /partition/jhony
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 81:909 -j DROP" >>/partition/jhony
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 914:8179 -j DROP" >>/partition/jhony
}
##########################################################

Onde as variáveis $IP estão em um arquivo e o $SITE em outro.
Como concluir esse script para que seje gerado algo como:

/usr/sbin/iptables -A FORWARD -s 10.1.1.9 -d 8.8.8.8 --dport 20:79 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.9 -d 8.8.8.8 --dport 81:909 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.9 -d 8.8.8.8 --dport 914:8179 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.9 -d 8.8.4.4 --dport 20:79 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.9 -d 8.8.4.4 --dport 81:909 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.9 -d 8.8.4.4 --dport 914:8179 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.55 -d 8.8.8.8 --dport 20:79 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.55 -d 8.8.8.8 --dport 81:909 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.55 -d 8.8.8.8 --dport 914:8179 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.55 -d 8.8.4.4 --dport 20:79 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.55 -d 8.8.4.4 --dport 81:909 -j DROP
/usr/sbin/iptables -A FORWARD -s 10.1.1.55 -d 8.8.4.4 --dport 914:8179 -j DROP

Obrigado.


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 25/12/2012 - 02:17h

Um for dentro do outro funciona, sim. Não entendi por que se disse o contrário -- a não ser que se esteja falando de um shell que eu não conheça.

Com relação à construção "comando | while read variavel", eu recomendo um pouco de cuidado. No caso em questão é claro que funciona sem problemas, mas ela tem um problema quando usada de outras formas.

Quando você faz um pipe para um comando interno do próprio bash (como o comando while), o bash executa esse comando interno num processo separado, que vai terminar assim que terminar o loop. Nesse caso, se você alterar o valor de uma variável dentro do loop, ele não se refletirá no script quando o loop acabar. Para ter uma ideia do que estou falando, veja o seguinte código, que tenta ser um contador da quantidade de linhas em /etc/passwd.

nlinhas=0
cat /etc/passwd | while read linha; do
((nlinhas++))
done
echo $nlinhas


O script acima, executado dentro do bash, sempre produzirá como saída o valor "0", porque o valor de nlinhas é alterado num subprocesso que termina assim que o loop chega ao final do arquivo de usuários.

A forma mais segura de trabalhar com loops que leem linhas de arquivos é associar os arquivos ou a saída de subprocessos a descritores do script que executa no processo original, e então fazer a entrada ou saída no descritor correspondente à operação desejada. Desse modo, o exemplo do próprio "cesarjhony" poderia ficar do seguinte modo.

# Redireciono a saída uma vez só, para não ter de reabrir o
# mesmo arquivo de saída em modo "append" (>>) várias vezes.
exec 3>> /partition/jhony

# Agora redireciono o sort do arquivo de IPs locais, por meio do
# operador especial "<(" do bash, e faço o loop externo pegar os dados
# desse descritor.
# NOTE PORÉM QUE é meio "burro" rodar o sort toda vez que o script
# for executado, especialmente se o arquivo não variar muito. Seria
# melhor rodar o sort logo após o arquivo original ser alterado, e
# fazer o script ler do arquivo já ordenado.
# NOTE PORÉM QUE (2) talvez essa ordenação por IPs seja ruim para o
# firewall: melhor seria que viessem primeiro os IPs que fazem os
# acessos mais frequentes, para economizar tempo médio de processamento
# do filtro de pacotes.
exec 4< <(sort /partition/iplocal)

while read IP <&4; do

# Removi o sort do arquivo de IPs bloqueados não apenas para mostrar que
# o redirecionamento fica mais simples, mas também porque esse sort seria
# executado várias vezes, tantas vezes quantas linhas houver no arquivo
# usado no loop mais externo. Mais do que antes, valem os comentários
# sobre gerar a ordenação no momento da edição, ou nem mesmo ter de
# preocupar-se com isso.
exec 5< /partition/ipsexo

while read SITE <&5; do
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 20:79 -j DROP" >&3
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 81:909 -j DROP" >&3
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 914:8179 -j DROP" >&3
done

# Fecha o descritor 5.
exec 5<&-

done

# Fecha os descritores 3 e 4
exec 4<&-
exec 3<&-


3. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Luís Fernando C. Cavalheiro
lcavalheiro

(usa Slackware)

Enviado em 22/12/2012 - 20:55h

Pesquisa sobre for, while e until.


4. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Jhony Cesar
cesarjhony

(usa Coyote)

Enviado em 22/12/2012 - 22:50h

Procurando antes mesmo de abrir o tópico. O mais simples é o uso do for, creio eu. Estou aprendendo, bem engatinhando


5. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Luís Fernando C. Cavalheiro
lcavalheiro

(usa Slackware)

Enviado em 23/12/2012 - 00:57h

For, while e until atingem os mesmos resultados, mas com sintaxes diferentes.

FOR

for i in lista; do ... ; done

Executa os comandos do loop para todos os itens lista

WHILE

while [ controle ] ; do ... ; done

Executa os comandos do loop enquanto a condição controle seja verdadeira. Ótima para loops infinitos:

 while [ 0 ]; do ... ; done  

Ótimo para menus criados com o dialog ;-)

UNTIL

until [ controle ]; don ... ; done

Executa os comandos do loop enquanto a condição controle for falsa.


6. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Jhony Cesar
cesarjhony

(usa Coyote)

Enviado em 23/12/2012 - 19:13h

Dá erro quando tento assim:

for IP in $(cat /partition/regrasjhony/dirteste/tipsite)
do
for IP2 in $(cat /partition/regrasjhony/dirteste/tip)
echo "BLOCK... $IP2 para sites $IP"
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 20:79 -j DROP" >> /partition/regrasjhony/dirteste/feito
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 81:909 -j DROP" >> /partition/regrasjhony/dirteste/feito
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 914:8179 -j DROP" >> /partition/regrasjhony/dirteste/feito
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 8182:65535 -j DROP" >> /partition/regrasjhony/dirteste/feito
done
done

Tem como utilizar "for i in" dentro de "for i2 in"?


7. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/12/2012 - 23:38h

Faltou um do no segundo for. Pode ter sido só erro de transcrição de sua parte, mas seria legal se você dissesse qual foi o erro que apareceu para você, para que nós não tenhamos de adivinhar o problema.


8. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Luís Fernando C. Cavalheiro
lcavalheiro

(usa Slackware)

Enviado em 24/12/2012 - 04:27h

cesarjhony escreveu:

Dá erro quando tento assim:

for IP in $(cat /partition/regrasjhony/dirteste/tipsite)
do
for IP2 in $(cat /partition/regrasjhony/dirteste/tip)
echo "BLOCK... $IP2 para sites $IP"
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 20:79 -j DROP" >> /partition/regrasjhony/dirteste/feito
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 81:909 -j DROP" >> /partition/regrasjhony/dirteste/feito
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 914:8179 -j DROP" >> /partition/regrasjhony/dirteste/feito
echo "/usr/sbin/iptables -A FORWARD -s $IP2 -d $IP --dport 8182:65535 -j DROP" >> /partition/regrasjhony/dirteste/feito
done
done

Tem como utilizar "for i in" dentro de "for i2 in"?


Faltou os do que nem o amigo disse antes, e não... não dá certo um for dentro de um for ;-)


9. Obrogado gente, foi de grande luz.

Jhony Cesar
cesarjhony

(usa Coyote)

Enviado em 24/12/2012 - 21:42h

Usei o WHILE, para esta tarefa.

sort /partition/iplocal | while read IP; do
sort /partition/ipsexo | while read SITE; do

echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 20:79 -j DROP" >> /partition/jhony
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 81:909 -j DROP" >> /partition/jhony
echo "/usr/sbin/iptables -A FORWARD -s $IP -d $SITE --dport 914:8179 -j DROP" >> /partition/jhony

done
done

E sim, dá pra colocar um loop dentro de outro, porém, o desempenho vai diminuindo conforme a quantidade de objetos nas variaveis... aprendi muito nessa questão.

Obrigado


10. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Paulo
paulo1205

(usa Ubuntu)

Enviado em 25/12/2012 - 03:26h

Faz tempo que não mexo com firewall, mas já que o assunto veio à baila, permita-me dar uns pitacos (que podem até estar errados -- e, nesse caso, eventuais correções e sugestões serão bem-vindas).

Procure evitar esse conjunto de regras muito grandes e com teor semelhante, especialmente se, além dele, seu firewall contiver outras coisas. Quanto maior o arquivo de regras, mais CPU o kernel gasta processando cada pacote, e se o seu conjunto de regras for realmente grande, você vai começar a sentir em suas aplicações o atraso provocado por essa montoeira de regras, principalmente se a sua aplicação tiver o azar de acionar apenas uma das regras que estão no final da lista.

Já que você está ordenando origens e destinos, considere uma ordenação que leve em consideração a frequência de tráfego gerado, procurando deixar quem fala mais e quem é mais requisitado próximo do topo de sua respectiva lista. Isso fará com que, em média, seja menor o número de regras tem de consultar para descobrir o que fazer com cada pacote, otimizando o processamento no firewall e o tempo de resposta sentido pela aplicação.

Talvez não se aplique diretamente a você neste momento mas, em geral, aproveite o fato de que você pode criar suas próprias chains com o iptables e use a técnica de dividir para conquistar, fazendo match parcial de pacotes para acelerar o acesso a regras de outros protocolos. Por exemplo: digamos que a expansão dos seus arquivos produzisse 3000 regras distintas, e que depois dessas 3000 regras para HTTP você ainda tivesse de adicionar regras para FTP, SMTP, POP3, IMAP4 e outros protocolos menos comuns. Para não fazer os usuários desses serviços sofrerem com um desempenho ruim, você poderia fazer mais ou menos o seguinte: na chain FORWARD, você coloca apenas uma regra (ou três, no seu caso) que pegue as artes do pacote que são comuns àquelas 3000, e faz com que elas desviem para uma segunda chain, e coloca nesta chain aquelas partes específicas de cada origem ou destino particular; desse modo, você divide por 3000 a quantidade de regras percorridas em FORWARD antes de chegar à parte dos demais protocolos, e possivelmente ainda reduz a quantidade de regras também na chain secundária. Veja o exemplo abaixo.

# Regras para HTTP tratadas numa chain separada
iptables -A FORWARD -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport 80 -j my_fwd_chain
iptables -A FORWARD -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport 443 -j my_fwd_chain
iptables -A FORWARD -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport 8080 -j my_fwd_chain

# Regras para POP3
iptables -A FORWARD -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport 110 -j DROP

# Regras para SSH
iptables -A FORWARD -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 --dport 22 -j ACCEPT


### Agora aquelas milhares de regras. Note que não é mais necessário
### testar a porta de destino, porque ela já foi verificada no momento
### em que se decidiu desviar o teste para esta chain.
iptables -A my_fwd_chain -p tcp -s 10.1.1.1 -d 192.0.45.56 -j DROP
iptables -A my_fwd_chain -p tcp -s 10.1.1.1 -d 146.164.10.2 -j DROP
iptables -A my_fwd_chain -p tcp -s 10.2.2.2 -d 192.0.45.56 -j DROP
iptables -A my_fwd_chain -p tcp -s 10.2.2.2 -d 146.164.10.2 -j DROP
# ...



11. Dou meus cinceros Parabens!

Jhony Cesar
cesarjhony

(usa Coyote)

Enviado em 26/12/2012 - 04:16h

A atenção do Paulo1205 e do lcavalheiro foi digna de APLAUSOS! Muito melhor que muitos professores.
Me sinto honrado de mim ter fornecido esse gancho ao Paulo1205, que com certeza ajudara outros com problemas na mesma parte que a minha. Abriu minha mente sobre chains.
Paulo1205, infelizmente estou engatinhando nos comandos/programação em shell, e Ainda não dei conta de compreender todo o seu feito (os caracteres empregados), que foi de grande valia para mim e para a comunidade.
Muito obrigado pela Generosa Atenção e Dedicação devotado a esse tópico e ao FORUM.


12. Re: Como fazer Script de loop, de uma linha com duas variáveis chamadas a partir de arquivos distintos.

Luís Fernando C. Cavalheiro
lcavalheiro

(usa Slackware)

Enviado em 26/12/2012 - 06:04h

cesarjhony escreveu:

A atenção do Paulo1205 e do lcavalheiro foi digna de APLAUSOS! Muito melhor que muitos professores.
Me sinto honrado de mim ter fornecido esse gancho ao Paulo1205, que com certeza ajudara outros com problemas na mesma parte que a minha. Abriu minha mente sobre chains.
Paulo1205, infelizmente estou engatinhando nos comandos/programação em shell, e Ainda não dei conta de compreender todo o seu feito (os caracteres empregados), que foi de grande valia para mim e para a comunidade.
Muito obrigado pela Generosa Atenção e Dedicação devotado a esse tópico e ao FORUM.


Disponha sempre, cara. Querendo aprender a gente explica ;-)

paulo, eu não disse que não funcionava, eu disse que não dava certo. Dependendo do objetivo que ele tivesse em mente, e por questões didáticas, não custava nada fazer essa ressalva (tal como você oportunamente fez com relação ao while e ao until)



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts