{"id":57,"date":"2011-01-16T22:52:00","date_gmt":"2011-01-16T22:52:00","guid":{"rendered":"http:\/\/artigos.marcomapa.com\/?p=57"},"modified":"2011-09-11T19:22:51","modified_gmt":"2011-09-11T19:22:51","slug":"escrevendo-um-script-de-firewall","status":"publish","type":"post","link":"https:\/\/marcomapa.com\/artigos\/escrevendo-um-script-de-firewall\/","title":{"rendered":"Escrevendo um script de firewall"},"content":{"rendered":"<p>Existem muitos firewalls gr\u00e1ficos for Linux, como o Shorewall e o Firestarter. Eles variam em n\u00edvel de facilidade e recursos, oferecendo uma interface amig\u00e1vel e gerando as regras do Iptables de acordo com a configura\u00e7\u00e3o feita. Voc\u00ea pode escolher entre usar o programa que melhor atenda suas necessidades ou configurar diretamente o Iptables com as regras desejadas. Neste caso, voc\u00ea pode formular as regras diretamente, definindo condi\u00e7\u00f5es onde os pacotes ser\u00e3o aceitos ou recusados, como em:<\/p>\n<p># iptables -A INPUT -s 192.168.1.0\/255.255.255.0 -j ACCEPT<\/p>\n<p>Estes comandos seguem uma sintaxe comum: tudo come\u00e7a com o comando \"iptables\", que \u00e9 o utilit\u00e1rio respons\u00e1vel por ler os par\u00e2metros e atualizar a configura\u00e7\u00e3o do firewall. Em seguida, vem uma condi\u00e7\u00e3o, indicada pela op\u00e7\u00e3o \"-A\". Neste exemplo usei \"INPUT -s 192.168.1.0\/255.255.255.0\", que se aplica a qualquer pacote de entrada (INPUT), proveniente dos micros da rede local (192.168.1.0\/255.255.255.0). Como n\u00e3o especifiquei o protocolo, a regra permitir\u00e1 o uso dos tr\u00eas protocolos, ou seja, TCP, UDP e ICMP, sem restri\u00e7\u00f5es.<\/p>\n<p>Note que aqui estou especificando uma faixa de endere\u00e7os e a m\u00e1scara de sub-rede (usada na rede local), fazendo com que a regra se aplique a todos os pacotes provenientes dela. No final, \u00e9 preciso dizer o que fazer com os pacotes que se enquadrarem nesta situa\u00e7\u00e3o, indicando uma a\u00e7\u00e3o. O \"-j ACCEPT\" diz que estes pacotes devem ser aceitos.<\/p>\n<p>Se por outro lado quisesse apenas bloquear um endere\u00e7o espec\u00edfico, usaria o par\u00e2metro \"-j REJECT\", como em:<\/p>\n<p># iptables -A INPUT -s 192.168.1.23 -j REJECT<\/p>\n<p>A primeira coisa a ter em mente \u00e9 que, assim como o Squid, o Iptables processa as regras de forma sequencial, permitindo ou recusando as conex\u00f5es conforme encontra uma regra que faz refer\u00eancia a ela. Se uma determinada regra diz que os pacotes provenientes de um determinado endere\u00e7o devem ser aceitos e outra logo depois diz que eles devem ser recusados, como neste exemplo:<\/p>\n<p># iptables -A INPUT -s 192.168.1.10 -j ACCEPT<\/p>\n<p># iptables -A INPUT -s 192.168.1.10 -j REJECT<\/p>\n<p>\u2026 vale a primeira, j\u00e1 que ao serem autorizados por ela, os pacotes s\u00e3o imediatamente aceitos, sem passarem pela segunda. Ao formular as regras para seu script de firewall, voc\u00ea deve colocar as regras mais espec\u00edficas primeiro, deixando as regras mais gerais por \u00faltimo. Se voc\u00ea quer permitir o acesso de todos os endere\u00e7os provenientes da rede local, bloqueando apenas um endere\u00e7o espec\u00edfico, voc\u00ea usaria:<\/p>\n<p># iptables -A INPUT -s 192.168.1.10 -j REJECT<\/p>\n<p># iptables -A INPUT -s 192.168.1.0\/255.255.255.0 -j ACCEPT<\/p>\n<p>Al\u00e9m de serem diretamente digitadas no terminal, as regras podem ser inclu\u00eddas dentro de scripts, de forma que voc\u00ea possa ativar o firewall rapidamente e\/ou configurar o sistema para carreg\u00e1-lo automaticamente durante o boot. O script de firewall nada mais \u00e9 do que um shell script comum, contendo os comandos que devem ser executados, um por linha. Voc\u00ea pode, por exemplo, criar o arquivo \"\/etc\/init.d\/firewall\". Outra op\u00e7\u00e3o seria simplesmente adicionar os comandos no final do arquivo \"\/etc\/rc.local\", de forma que eles sejam executados durante o boot.<\/p>\n<p>Este \u00e9 um exemplo de mini-script de firewall que pode ser usado em um desktop que simplesmente acessa a internet como cliente, sem rodar nenhum servidor, nem compartilhar a conex\u00e3o com outros micros:<\/p>\n<p>#!\/bin\/sh<\/p>\n<p>iptables -A INPUT -i lo -j ACCEPT<\/p>\n<p>iptables -A INPUT -p tcp --syn -j DROP<\/p>\n<p>A id\u00e9ia aqui \u00e9 que o micro possa acessar a internet sem ficar vulner\u00e1vel a acessos externos. Estes dois comandos fazem isso da forma mais simples poss\u00edvel.<\/p>\n<p>A primeira linha orienta o firewall a deixar passar os pacotes enviados atrav\u00e9s da interface de loopback (-i lo -j ACCEPT). \u00c9 importante que esta linha (ou outra com o mesmo efeito) sempre seja usada, em qualquer script de firewall que termine bloqueando todas as conex\u00f5es, pois no Linux a interface de loopback \u00e9 usada para comunica\u00e7\u00e3o entre diversos programas. Para ter uma id\u00e9ia, todos os programas gr\u00e1ficos a utilizam para se comunicarem com o X, os programas do KDE a utilizam para trocar mensagens entre si. Sem esta regra, muita coisa deixa de funcionar corretamente.<\/p>\n<p>Depois de abrir o firewall para as mensagens locais, usamos a segunda regra para bloquear todas as novas conex\u00f5es vindas de fora. O \"--syn\" faz com que o firewall aplique a regra apenas para tentativas de abrir novas conex\u00f5es (algu\u00e9m tentando acessar o servidor SSH que voc\u00ea esqueceu aberto, por exemplo), sem entretanto impedir que servidores remotos respondam a conex\u00f5es iniciadas por voc\u00ea. Isso permite que voc\u00ea continue navegando e acessando compartilhamentos em outros micros da rede local, com poucas limita\u00e7\u00f5es.<\/p>\n<p>Estas duas regras podem ser usadas como base para criar um firewall de bloqueio, onde voc\u00ea diz as portas que gostaria de abrir e ele fecha todas as demais. Ou seja, o firewall fecha por padr\u00e3o todas as portas, com exce\u00e7\u00e3o das que voc\u00ea disser explicitamente que deseja manter abertas. Isso garante uma configura\u00e7\u00e3o de firewall bastante segura com um m\u00ednimo de dor de cabe\u00e7a.<\/p>\n<p>Para testar, voc\u00ea pode executar o script no seu micro, ou em qualquer outro PC da rede e tentar acess\u00e1-lo via SSH (ou qualquer outro servi\u00e7o ativo). Como usamos o par\u00e2metro \"DROP\" na segunda regra, o PC simplesmente ignorar\u00e1 o chamado, fazendo com que o cliente fique um longo tempo tentando abrir a conex\u00e3o, para depois exibir um erro de timeout, como em:<\/p>\n<p>$ ssh 192.168.1.21<\/p>\n<p>ssh: connect to host 192.168.1.21 port 22: Connection timed out<\/p>\n<p>Para desativar o firewall e voltar a aceitar conex\u00f5es, use o comando \"iptables -F\", que limpa as regras do Iptables:<\/p>\n<p># iptables -F<\/p>\n<p>A partir deste script b\u00e1sico, voc\u00ea pode adicionar novas regras, abrindo portas, direcionando faixas de portas para micros da rede interna, fechando portas de sa\u00edda, de forma a bloquear o uso de determinados programas e assim por diante.<\/p>\n<p>Imagine que voc\u00ea est\u00e1 configurando o firewall do servidor da rede. Ele tem duas placas de rede, uma para a rede local e outra para a internet. Voc\u00ea precisa que ele fique acess\u00edvel sem limita\u00e7\u00f5es dentro da rede local, mas quer manter tudo fechado para quem vem da internet.<\/p>\n<p>Nesse caso, voc\u00ea poderia usar a regra que mostrei h\u00e1 pouco no seu script de firewall:<\/p>\n<p># Abre para uma faixa de endere\u00e7os:<\/p>\n<p>iptables -A INPUT -s 192.168.1.0\/255.255.255.0 -j ACCEPT<\/p>\n<p>O \"192.168.1.0\" indica a faixa de endere\u00e7os da rede local. A m\u00e1scara \"255.255.255.0\" indica que a \u00faltima parte do endere\u00e7o muda, ou seja, os micros da rede local usam endere\u00e7os entre 192.168.1.1 e 192.168.1.254. Tudo o que vier deles \u00e9 aceito.<\/p>\n<p>Note que esta faixa de endere\u00e7os n\u00e3o \u00e9 rote\u00e1vel, ela simplesmente n\u00e3o existe na internet. N\u00e3o existe a possibilidade de algum engra\u00e7adinho de outro estado tentar configurar seu micro para usar esta faixa de endere\u00e7os e enganar a regra do firewall.<\/p>\n<p>Como uma prote\u00e7\u00e3o adicional, as vers\u00f5es recentes do Iptables s\u00e3o capazes de ignorar pacotes aparentemente destinados a uma interface quando eles chegam em outra. Com duas placas, onde uma est\u00e1 ligada \u00e0 rede local (usando a faixa 192.168.1.x) e outra \u00e0 Internet, o firewall n\u00e3o aceitar\u00e1 que um pacote falseado, proveniente da Internet, com endere\u00e7o de emissor \"192.168.1.3\" (por exemplo), seja encaminhado a um micro da rede local, pois ele sabe que pacotes com este endere\u00e7o de emissor devem chegar apenas pela placa ligada \u00e0 rede local.<\/p>\n<p>Se o servidor possuir duas placas de rede, voc\u00ea poderia tornar a regra mais \u00e0 prova de falhas especificando a interface de origem em vez da faixa de endere\u00e7os, usando o par\u00e2metro \"-i\". Com isso, o firewall \u00e9 instru\u00eddo a aceitar pacotes recebidos na interface de rede local, independentemente da faixa de endere\u00e7os usada. Embora funcione de forma diferente, ela tem a mesma fun\u00e7\u00e3o da regra anterior. Ao us\u00e1-la, n\u00e3o esque\u00e7a de substituir o \"eth0\" pela interface de rede local, caso diferente:<\/p>\n<p># Aceita tudo na interface de rede local:<\/p>\n<p>iptables -A INPUT -i eth0 -j ACCEPT<\/p>\n<p>O par\u00e2metro \"-s\", usado na regra anterior pode tamb\u00e9m ser usado para permitir endere\u00e7os ou faixas de endere\u00e7os da internet. Imagine que voc\u00ea queira dar acesso aos hosts de uma das filiais da empresa, onde usam um link com o IP fixo \"200.220.234.12\". Voc\u00ea poderia abrir a faixa \"200.220.234.0\" ou apenas o IP \"200.220.234.12\", de forma que o firewall permitisse acessos vindos de l\u00e1, mas continuasse bloqueando o restante. Voc\u00ea pode abrir para v\u00e1rias faixas de endere\u00e7os distintas, basta repetir a linha adicionando cada uma das faixas desejadas.<\/p>\n<p>Imagine agora que este servidor foi instalado na sede de uma empresa para a qual voc\u00ea presta servi\u00e7os. Voc\u00ea precisa acess\u00e1-lo de vez em quando para corrigir problemas, mas naturalmente quer fazer isso via internet, sem precisar se deslocar at\u00e9 l\u00e1. Voc\u00ea pode configurar o firewall para abrir a porta 22 usada pelo SSH adicionando a regra:<\/p>\n<p># Abre uma porta (inclusive para a internet):<\/p>\n<p>iptables -A INPUT -p tcp --dport 22 -j ACCEPT<\/p>\n<p>Note que esta regra abre a porta 22 para todo mundo. Lembre-se do exemplo do SSH: todo servidor dispon\u00edvel para a internet \u00e9 um risco potencial de seguran\u00e7a, por isso s\u00f3 abra as portas para os servidores que voc\u00ea realmente for utilizar. O ideal seria usar um par de chaves, protegidas por uma passphrase para acessar o servidor e configur\u00e1-lo para n\u00e3o aceitar logins com senha (apenas com chaves), como veremos em detalhes no cap\u00edtulo sobre SSH.<\/p>\n<p>Ao abrir v\u00e1rias portas, voc\u00ea pode utilizar o par\u00e2metro \"-m multiport\" para especificar todas de uma vez, separadas por v\u00edrgula, sem precisar colocar uma em cada linha. Para abrir as portas 22, 80 e 443, por exemplo, voc\u00ea usaria a regra abaixo:<\/p>\n<p># Abre um conjunto de portas:<\/p>\n<p>iptables -A INPUT -m multiport -p tcp --dport 22,80,443 -j ACCEPT<\/p>\n<p>Se voc\u00ea presta suporte a partir de uma empresa que possui um link dedicado, com IP fixo, voc\u00ea pode tornar a regra mais espec\u00edfica, permitindo apenas o IP de onde voc\u00ea acessa:<\/p>\n<p># Abre uma porta para um IP espec\u00edfico:<\/p>\n<p>iptables -A INPUT -p tcp -s 200.231.14.16 --dport 22 -j ACCEPT<\/p>\n<p>Em um micro dom\u00e9stico, voc\u00ea pode abrir tamb\u00e9m as portas usadas pelo bittorrent (6881 a 6889) ou portas usadas por jogos multiplayer, por exemplo. Para abrir um intervalo de portas, use a regra:<\/p>\n<p># Abre um intervalo de portas:<\/p>\n<p>iptables -A INPUT -p tcp --dport 6881:6889 -j ACCEPT<\/p>\n<p>Este \u00e9 um exemplo de script completo, incluindo algumas regras adicionais para evitar ataques comuns. Ele inclui as fun\u00e7\u00f5es para aceitar os comandos \"start\", \"stop\" e \"restart\", de forma a se comportar como se fosse um servi\u00e7o de sistema:<\/p>\n<p>#!\/bin\/bash<\/p>\n<p>iniciar(){<\/p>\n<p># Abre para a faixa de endere\u00e7os da rede local:<\/p>\n<p>iptables -A INPUT -s 192.168.1.0\/255.255.255.0 -j ACCEPT<\/p>\n<p># Faz a mesma coisa, s\u00f3 que especificando a interface, pode ser<\/p>\n<p># usada em substitui\u00e7\u00e3o \u00e0 regra anterior:<\/p>\n<p># iptables -A INPUT -i eth0 -j ACCEPT<\/p>\n<p># Abre uma porta (inclusive para a internet):<\/p>\n<p>iptables -A INPUT -p tcp --dport 22 -j ACCEPT<\/p>\n<p># Ignora pings:<\/p>\n<p>iptables -A INPUT -p icmp --icmp-type echo-request -j DROP<\/p>\n<p># Protege contra IP spoofing:<\/p>\n<p>echo 1 &gt; \/proc\/sys\/net\/ipv4\/conf\/default\/rp_filter<\/p>\n<p># Descarta pacotes malformados, protegendo contra ataques diversos<\/p>\n<p>iptables -A INPUT -m state --state INVALID -j DROP<\/p>\n<p># Abre para a interface de loopback. Esta regra \u00e9 essencial para que<\/p>\n<p># o KDE e outros programas gr\u00e1ficos funcionem adequadamente.<\/p>\n<p>iptables -A INPUT -i lo -j ACCEPT<\/p>\n<p># Impede a abertura de novas conex\u00f5es, efetivamente bloqueando o acesso<\/p>\n<p># externo ao seu servidor, com exce\u00e7\u00e3o das portas e faixas de endere\u00e7os<\/p>\n<p># manualmente especificadas anteriormente.<\/p>\n<p>iptables -A INPUT -p tcp --syn -j DROP<\/p>\n<p>}<\/p>\n<p>parar(){<\/p>\n<p>iptables -F<\/p>\n<p>iptables -P INPUT ACCEPT<\/p>\n<p>iptables -P OUTPUT ACCEPT<\/p>\n<p>echo \"Regras de firewall desativadas\"<\/p>\n<p>}<\/p>\n<p>case \"$1\" in<\/p>\n<p>\"start\") iniciar ;;<\/p>\n<p>\"stop\") parar ;;<\/p>\n<p>\"restart\") parar; iniciar ;;<\/p>\n<p>*) echo \"Use os par\u00e2metros start ou stop\"<\/p>\n<p>esac<\/p>\n<p>Da forma como escrevi, o script suporta as fun\u00e7\u00f5es \"start\", \"stop\" e \"restart\", e pode ser usado como um servi\u00e7o de sistema. Salve-o dentro da pasta \"\/etc\/init.d\", como em \"\/etc\/init.d\/firewall\", e marque a permiss\u00e3o de execu\u00e7\u00e3o:<\/p>\n<p># chmod +x \/etc\/init.d\/firewall<\/p>\n<p>A partir da\u00ed, voc\u00ea pode ativar as regras usando o comando \"\/etc\/init.d\/firewall start\" e fazer com que altera\u00e7\u00f5es dentro do script entrem em vigor com um \"\/etc\/init.d\/firewall restart\".<\/p>\n<p>Para que o script seja executado durante o boot, crie um link para ele dentro da pasta \"\/etc\/rc5.d\":<\/p>\n<p># cd \/etc\/rc5.d<\/p>\n<p># ln -s ..\/init.d\/compartilhar S21compartilhar<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Existem muitos firewalls gr\u00e1ficos for Linux, como o Shorewall e o Firestarter. Eles variam em n\u00edvel de facilidade e recursos,<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,8],"tags":[],"class_list":["post-57","post","type-post","status-publish","format-standard","hentry","category-hardware","category-linux"],"_links":{"self":[{"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/posts\/57","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/comments?post=57"}],"version-history":[{"count":1,"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/posts\/57\/revisions"}],"predecessor-version":[{"id":116,"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/posts\/57\/revisions\/116"}],"wp:attachment":[{"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/media?parent=57"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/categories?post=57"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/marcomapa.com\/artigos\/wp-json\/wp\/v2\/tags?post=57"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}