Entendendo e montando um Firewall no Linux

firewall O Linux, de uma forma geral, é relativamente imune a vírus, worms e trojans, que são a principal causa de invasões e dores de cabeça em geral no Windows. Isso não ocorre apenas porque o Windows é usado em mais máquinas e por isso um alvo maior, mas também porque os aplicativos disponíveis no Linux são, pela média, bem mais seguros.

Veja o caso do Apache, por exemplo. Ele é usado em uma percentagem muito maior de servidores que o IIS. Mesmo assim, o número de falhas críticas de segurança e invasões bem-sucedidas registradas contra servidores web rodando o IIS é bem maior do que nos mais numerosos servidores Apache.

Mesmo assim, brechas de segurança podem surgir onde menos se espera. Por exemplo, em 2004 foi descoberto um buffer overflow no servidor SSH, que poderia ser usado para desenvolver um exploit. Esta brecha não chegou a ser explorada, pois, assim que a possível vulnerabilidade foi descoberta, uma correção foi rapidamente disponibilizada e a notícia se espalhou pela web. Antes que alguém tivesse tempo de escrever um exploit, a maior parte dos servidores do mundo já estavam seguros.

A moral da história: é sempre muito melhor prevenir do que remediar, e a melhor forma de se proteger contra brechas deste tipo é manter um firewall ativo, permitindo apenas acesso aos serviços que você realmente deseja disponibilizar. Reduzindo os pontos vulneráveis, fica mais fácil cuidar da atualização dos serviços expostos e, assim, manter seu servidor seguro.

Imagine o firewall como a muralha que cercava muitas cidades na idade média. Mesmo que as casas não sejam muito seguras, uma muralha forte em torno da cidade garante a segurança. Se ninguém consegue passar pela muralha, não é possível chegar até as casas vulneráveis. Se, por acaso, as casas já são seguras, então a muralha aumenta ainda mais a segurança.

A idéia mais comum de firewall é como um dispositivo que fica entre o switch (ou hub) em que estão ligados os micros da rede e a internet. Nesta posição é usado um PC com duas placas de rede (eth0 e eth1, por exemplo), onde uma é ligada à internet e outra à rede local.

O firewall aceita as conexões vindas dos micros da rede local e roteia os acessos à internet. De dentro da rede você consegue acessar quase tudo, mas todas as tentativas de conexão vindas de fora são bloqueadas antes de chegarem aos clientes.

Imagine um micro com o Windows XP, onde o sistema acabou de ser instalado, sem nenhuma atualização de segurança e com o firewall inativo. Conectando este micro na internet diretamente, será questão de minutos até que ele comece a ser infectado por worms e se transforme em um zumbi a atacar outras máquinas ligadas a ele.

Entretanto, se houver um firewall no caminho, os pacotes nocivos não chegam até ele, de forma que ele fica em uma posição relativamente segura. Ele ainda pode ser infectado de formas indiretas, como ao acessar uma página que explore uma vulnerabilidade do IE ou ao receber um e-mail infectado através do Outlook, mas não mais diretamente, simplesmente por estar conectado à internet.

Opcionalmente, o servidor rodando o firewall pode ser equipado com um servidor Squid configurado para remover arquivos executáveis das páginas acessadas e um servidor Postfix, encarregado de bloquear mensagens infectadas, o que adiciona mais um nível de proteção.

Note que o firewall em si não protege contra vírus e trojans, mas apenas contra tentativas diretas de conexão. Ele cria uma barreira entre os micros da rede local e a internet, fazendo com que os recursos compartilhados na rede não sejam acessíveis de fora. No Linux, o firewall é incluído no próprio Kernel do sistema, na forma do Iptables, encontrado no Kernel 2.4 em diante. Isso garante um excelente desempenho e segurança em relação à maioria dos firewalls for Windows, que rodam em nível de aplicação.

Embora seja sempre mais seguro ter um servidor dedicado, você pode ter um nível de segurança muito bom simplesmente habilitando o firewall localmente. Todos os pacotes provenientes da internet passam primeiro pelo Iptables antes de serem encaminhados para os aplicativos. Por isso, um firewall local, bem configurado, garante uma segurança muito próxima à de um firewall dedicado.

Escrevendo um script de firewall

Existem muitos firewalls gráficos for Linux, como o GuardDog, o Shorewall e o Firestarter (que comento adiante). Eles variam em nível de facilidade e recursos, oferecendo uma interface amigável e gerando as regras do Iptables de acordo com a configuração feita. Você pode escolher entre usar o programa que melhor atenda suas necessidades ou configurar diretamente o Iptables com as regras desejadas. Neste caso, você pode formular as regras diretamente, definindo condições onde os pacotes serão aceitos ou recusados, como em:

# iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT

Estes comandos seguem uma sintaxe comum: tudo começa com o comando “iptables“, que é quem executará as opções incluídas no comando. Em seguida vem uma condição, indicada pela opção “-A”. Neste exemplo usei “INPUT -p tcp -s 192.168.0.0/255.255.255.0”, que se aplica a qualquer pacote de entrada (INPUT), utilizando o protocolo TCP (-p tcp), proveniente dos micros da rede local (192.168.0.0/255.255.255.0). Note que aqui estou especificando uma faixa de endereços e a máscara de sub-rede. No final, é preciso dizer o que fazer com os pacotes que se enquadrarem nesta situação, indicando uma ação. O “-j ACCEPT” diz que estes pacotes devem ser aceitos.

À primeira vista, isso parece bem complicado, assim como o arquivo de configuração original do Squid, com suas 3.000 e tantas linhas. Mas, as coisas ficam bem mais simples se começarmos com um script simples e formos incluindo novas regras aos poucos.

Este é um exemplo de script que pode ser usado em um desktop que simplesmente acessa a internet como cliente, sem rodar nenhum servidor, nem compartilhar a conexão com outros micros:

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -p tcp –syn -j DROP

A idéia aqui é que o micro possa acessar a internet sem que ninguém de fora possa invadi-lo de forma alguma. Esses dois comandos fazem isso da forma mais simples possível.

A primeira linha orienta o firewall a deixar passar os pacotes enviados através da interface de loopback (-i lo -j ACCEPT). É importante que esta linha (ou outra com o mesmo efeito) sempre seja usada, em qualquer script de firewall que termine bloqueando todas as conexões, pois no Linux a interface de loopback é usada para comunicação entre diversos programas. Para ter uma idéia, todos os programas gráficos 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.

Depois de abrir o firewall para as mensagens locais, usamos a segunda regra para bloquear todas as novas conexões vindas de fora. O “–syn” faz com que o firewall aplique a regra apenas para tentativas de abrir novas conexões (alguém tentando acessar o servidor SSH que você esqueceu aberto, por exemplo), mas sem impedir que servidores remotos respondam a conexões iniciadas por você. Isso permite que você continue navegando e acessando compartilhamentos em outros micros da rede local, com poucas limitações.

Para não precisar ficar digitando os comandos cada vez que precisar reiniciar o micro, você pode incluí-los em um dos arquivos de inicialização do sistema. Nas distribuições derivadas do Debian, você pode colocá-los no final do arquivo “/etc/init.d/bootmisc.sh” e, nas derivadas do Red Hat, no arquivo “/etc/rc.d/rc.local“.

Essas duas regras podem ser usadas como base para criar o que chamo de firewall de bloqueio. Ele segue uma idéia bastante simples: você diz as portas que gostaria de abrir e ele fecha todas as demais. Ou seja, o firewall fecha por padrão todas as portas, com exceção das que você disser explicitamente que deseja manter abertas. Isso garante uma configuração de firewall bastante segura com um mínimo de dor de cabeça.

Você pode adicionar novas regras, abrindo portas, direcionando faixas de portas para micros da rede interna, fechando portas de saída, de forma a bloquear o uso de programas como o ICQ e o MSN e assim por diante.

Imagine que você está configurando o firewall do servidor da rede. Ele tem duas placas de rede, uma para a rede local e outra para a internet. Você precisa que ele fique acessível sem limitações dentro da rede local, mas quer manter tudo fechado para quem vem da internet.

Nesse caso, você poderia usar a regra que mostrei há pouco no seu script de firewall:

# Abre para uma faixa de endereços da rede local
iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT

O “192.168.0.0” indica a faixa de endereços da rede local. A máscara “255.255.255.0” indica que a última parte do endereço muda, ou seja, os micros da rede local usam endereços entre 192.168.0.1 e 192.168.0.254. Tudo o que vier deles (tanto TCP, quanto UDP, já que não indicamos o protocolo) é aceito.

Note que esta faixa de endereços não é roteável, ela simplesmente não existe na internet. Não existe a possibilidade de algum engraçadinho de outro estado tentar configurar seu micro para usar esta faixa de endereços e enganar a regra do firewall.

Como uma proteção adicional, as versões recentes do Iptables são capazes de ignorar pacotes aparentemente destinados a uma interface quando eles chegam em outra. Com duas placas, onde uma está ligada à rede local (usando a faixa 192.168.0.x) e outra à Internet, o firewall não aceitará que um pacote falseado, proveniente da Internet, com endereço de emissor “192.168.0.3” (por exemplo), seja encaminhado a um micro da rede local, pois ele sabe que pacotes com este endereço de emissor devem chegar apenas pela placa ligada à rede local.

Essa mesma regra pode ser usada também para abrir o firewall para endereços ou faixas de endereços da internet. Imagine que você queira dar acesso aos micros da filial da sua empresa em Macapá, onde usam um link com o IP fixo 200.220.234.12. Você 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á, mas continuasse bloqueando o restante. Você pode abrir para várias faixas de endereços distintas, basta repetir a linha adicionando cada uma das faixas desejadas.

Imagine agora que este servidor foi instalado na sede de uma empresa para a qual você presta serviços. Você precisa acessá-lo de vez em quando para corrigir problemas, mas naturalmente quer fazer isso via internet, sem precisar se deslocar até lá. Você pode configurar o firewall para abrir a porta 22 usada pelo SSH adicionando a regra:

# Abre uma porta (inclusive para a internet)
iptables -A INPUT -p tcp –dport 22 -j ACCEPT

Note que esta regra abre a porta 22 para todo mundo. Lembre-se do exemplo do SSH: todo servidor disponível para a internet é um risco potencial de segurança, por isso só abra as portas para os servidores que você realmente for utilizar. O ideal seria usar um par de chaves, protegidas por uma passphrase para acessar o servidor e configurá-lo para não aceitar logins com senha (apenas com chaves), como vimos no capítulo sobre SSH.

Ao abrir várias portas, você pode utilizar o parâmetro “-m multiport” para especificar todas de uma vez, separadas por vírgula, sem precisar colocar uma em cada linha. Para abrir as portas 21, 22 e 6881 (bittorrent), por exemplo, você usaria a regra abaixo:

# Abre um conjunto de portas
iptables -A INPUT -m multiport -p tcp –dport 21,22,6881 -j ACCEPT

Se você presta suporte a partir de uma empresa que possui um link dedicado, com IP fixo, você pode tornar a regra mais específica, permitindo apenas o IP de onde você acessa:

# Abre uma porta para um IP específico
iptables -A INPUT -p tcp -s 200.231.14.16 –dport 22 -j ACCEPT

Em um micro doméstico, você pode abrir também 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:

# Abre um intervalo de portas
iptables -A INPUT -p tcp –dport 6881:6889 -j ACCEPT

Além de trabalhar com endereços IP, é possível criar regras baseadas também em endereços MAC. Isso permite adicionar uma camada extra de proteção ao criar regras para a rede local. Para isso, usamos o parâmetro “-m mac –mac-source”, seguido pelo endereço MAC da placa do host desejado. Para permitir que o host “192.168.1.100” tenha acesso ao servidor, mas apenas se o endereço MAC da interface bater, você usaria uma regra como:

iptables -A INPUT -s 192.168.1.100 -m mac –mac-source 00:11:D8:76:59:2E -j ACCEPT

Note que agora, além do IP, especificamos o endereço MAC da placa. As duas regras são usadas em conjunto, de forma que o acesso é permitido apenas caso as duas informações estejam corretas. Isso dificulta as coisas para alguém que queira acessar o servidor trocando o IP de sua máquina. Você pode descobrir o MAC das máquinas da rede usando o próprio ifconfig ou o comando “arp -a”.

Note que limitar o acesso com base no endereço MAC adiciona uma camada extra de proteção, mas não é infalível. O endereço MAC pode ser trocado de forma quase tão simples quanto o endereço IP e, sniffando a rede, é possível descobrir os endereços IP e MAC dos micros com uma certa facilidade.

No Linux, você pode trocar o endereço MAC da placa de rede usando os comandos:

# ifconfig eth0 down
# ifconfig eth0 hw ether 00:11:D8:76:59:2E
# ifconfig eth0 up

Como vê, basta especificar o endereço desejado. O Iptables não é capaz de diferenciar máquinas com os endereços MAC falseados das reais, pois, se alguém desconectasse o micro 192.168.1.100 da rede e configurasse o seu para usar o mesmo IP e MAC, poderia acessar o servidor bipassando a regra de firewall. A única forma de ter uma segurança completa seria utilizar o SSH ou outro protocolo que utilize um algoritmo robusto de encriptação para o login e a transmissão dos dados.

Lembre-se de que o firewall é uma primeira barreira de proteção, mas não é uma garantia por sí só. É preciso combiná-lo com outras camadas de segurança para ter um servidor completamente seguro.

Outra limitação é que as regras baseadas em endereços MAC podem ser usadas apenas dentro da rede local. O endereço MAC é descartado do pacote quando ele é roteado para a Internet, ficando apenas o endereço IP. Ao acessar através de uma conexão compartilhada, todos os pacotes provenientes da Internet chegam com o endereço MAC do gateway da rede.

Este é um exemplo de script completo, incluindo algumas regras adicionais para evitar ataques comuns:

#!/bin/bash

iniciar(){

# Abre para uma faixa de endereços da rede local
iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT

# Abre uma porta (inclusive para a internet)
iptables -A INPUT -p tcp –dport 22 -j ACCEPT

# Ignora pings
iptables -A INPUT -p icmp –icmp-type echo-request -j DROP

# Protege contra IP spoofing (esta opção já vem ativada por padrão na
# maioria das distribuições atuais, mas não custa ter certeza)
echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter

# Descarta pacotes malformados, protegendo contra ataques diversos
iptables -A INPUT -m state –state INVALID -j DROP

# Abre para a interface de loopback. Esta regra é essencial para que
# o KDE e outros programas gráficos funcionem adequadamente.
iptables -A INPUT -i lo -j ACCEPT

# Impede a abertura de novas conexões, efetivamente bloqueando o acesso
# externo ao seu servidor, com exceção das portas e faixas de endereços
# manualmente especificadas anteriormente. Bloqueia tudo.
iptables -A INPUT -p tcp –syn -j DROP

}

parar(){
iptables -F
echo “Regras de firewall desativadas”
}

case “$1” in
“start”) iniciar ;;
“stop”) parar ;;
“restart”) parar; iniciar ;;
*) echo “Use os parâmetros start ou stop”
esac

A receber qualquer conexão, vinda de qualquer endereço, o firewall primeiro verifica todas estas regras, seqüencialmente, para decidir se o pacote passa ou não. Usando esse script de exemplo, teríamos o seguinte:

– Se o pacote vier da rede local, ele é aceito.
– Se o pacote for para porta 22 (do SSH), ele é aceito.
– Se for um ping, ele é recusado (de forma a dificultar um pouco para outros descobrirem que você está online).
– Pacotes danificados ou forjados (unclean) são recusados, protegendo os micros da rede interna.
– Se o pacote vier da sua própria máquina (um programa tentando mostrar alguma coisa na tela, por exemplo), ele é aceito.
– Se o pacote for uma resposta a uma conexão que você iniciou, como, por exemplo, o servidor do guiadohardware.net enviando a página do site que você está acessando, ele é aceito.
– Tentativas de conexão (toda conexão TCP é iniciada por um pacote syn) fora das condições especificadas acima são descartadas pelo firewall. A conexão nem sequer chega a ser estabelecida e o emissor não recebe qualquer resposta (DROP). Ele não sabe se o pacote foi recebido ou não, fica no vácuo, o que dá a impressão de que o seu micro nem está online.

Da forma como escrevi, o script suporta as funções “start”, “stop” e “restart”, e pode ser usado como um serviço de sistema. Salve-o dentro da pasta “/etc/init.d”, como em “/etc/init.d/firewall”, e marque a permissão de execução:

# chmod +x /etc/init.d/firewall

A partir daí, você pode ativar as regras usando o comando “/etc/init.d/firewall start” e fazer com que alterações dentro do script entrem em vigor com um “/etc/init.d/firewall restart”.

Se você está configurando um servidor dedicado remotamente, é importante que você teste o script antes de configurar o sistema para executá-lo automaticamente durante o boot. O motivo é simples: se houver alguma regra incorreta no script, que bloqueie seu acesso ao servidor, você poderá solicitar um reboot do servidor para que a configuração seja removida e você recupere o acesso. Entretanto, se o sistema for configurado para carregar o script durante o boot, o reboot não resolverá e você precisará abrir uma chamada de suporte, solicitando que um técnico se logue localmente no servidor e desative seu script (o que provavelmente resultará em uma taxa adicional).

Uma opção mais relaxada seria simplesmente colocar os comandos com as regras desejadas no final do arquivo “/etc/init.d/bootmisc.sh” ou “/etc/rc.d/rc.local”, mas isso não é tão recomendável, pois você perde a possibilidade de reiniciar o firewall rapidamente depois de alterar as regras.

Assim como nas regras do Squid, cada pacote que chega pela rede precisa passar por todas as regras, para que o firewall possa decidir o que fazer com ele. Quando aceito por uma das regras, ele é imediatamente encaminhado ao aplicativo, sem passar pelas demais. Por isso é necessário sempre colocar as regras mais restritivas por último, de preferência concluindo o script com uma regra que bloqueia todos os pacotes de entrada.

Outra dica é que você pode incluir os comandos para compartilhar a conexão e ativar o proxy transparente (que também são regras de firewall) no script, fazendo que ele desempenhe simultaneamente as duas funções. Nesse caso, tome o cuidado de sempre colocar as regras que compartilham a conexão e ativam o proxy transparente antes das regras que bloqueiam conexões.

Este é um exemplo de script de firewall que inclui as regras para compartilhar a conexão e ativar o proxy transparente. Ao usá-lo, comente as linhas que não se aplicam à sua instalação:

#!/bin/bash

iniciar(){

# Compartilha a conexão
modprobe iptable_nat
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -p tcp –tcp-flags SYN,RST SYN -m tcpmss –mss 1400:1536 \
-j TCPMSS –clamp-mss-to-pmtu
echo “Compartilhamento ativado”

# Proxy transparente
iptables -t nat -A PREROUTING -i eth1 -p tcp –dport 80 -j REDIRECT –to-port 3128
echo “Proxy transparente ativado”

# As regras de firewall que vimos há pouco:
iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT
iptables -A INPUT -p tcp –dport 22 -j ACCEPT
iptables -A INPUT -p icmp –icmp-type echo-request -j DROP
echo 1 > /proc/sys/net/ipv4/conf/default/rp_filter
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp –syn -j DROP

}

parar(){
iptables -F
iptables -t nat -F
echo “Regras de firewall e compartilhamento desativados”
}

case “$1” in
“start”) iniciar ;;
“stop”) parar ;;
“restart”) parar; iniciar ;;
*) echo “Use os parâmetros start ou stop”
esac

Outra dica importante são os comandos usados para limpar as regras do Iptables. É necessário executá-los sempre que você fizer alterações no seu script de firewall e quiser executá-lo novamente para que as novas regras entrem em vigor. No primeiro script de exemplo, por exemplo, uso o comando “iptables -F” como parte da função “stop”, que desativa o firewall. No segundo script, incluí também o “iptables -t nat -F”.

iptables -F: Limpa a tabela principal do iptables, onde vão os comandos para abrir e fechar portas, que vimos até aqui.

iptables -t nat -F: Limpa a tabela nat, que é usada por regras que compartilham a conexão e fazem forwarding de portas, como por exemplo:

iptables -t nat -A PREROUTING -i eth0 –dport 22 -j DNAT –to-dest 192.168.1.2

Todas as regras do Iptables que levam “-t nat” são armazenadas nesta segunda tabela, que precisa ser zerada separadamente. A idéia é que você pode limpar as regras principais do firewall sem desabilitar o compartilhamento da conexão e vice-versa.

iptables -L: Este comando lista a configuração atual, sem alterar nada. É interessante executá-lo depois de fazer alterações na configuração do firewall, para ter certeza que as regras surtiram o efeito esperado. Para ver as regras de forwarding e compartilhamento, use também o “iptables -t nat -L

Forwarding de portas

Você deve lembrar que, ao compartilhar uma conexão entre vários micros, apenas o servidor que está com a conexão recebe conexões vindas da internet. Os micros da rede local acessam via NAT e apenas recebem respostas para conexões iniciadas por eles.

Mas, imagine que você queira que um servidor web, escutando na porta 80 do micro 192.168.0.3 da rede local, fique disponível para a internet. Como o servidor é o único com um IP válido na internet, a única forma de fazer com que o 192.168.0.3 fique acessível é fazer com que o servidor “passe a bola” para ele ao receber conexões na porta 80. É justamente isso que fazemos ao configurar o forwarding de portas.

Uma vez feita a configuração, sempre que o servidor receber uma conexão qualquer na porta 80 (ou qualquer outra definida por você), ele a repassará para o micro 192.168.0.3. Isso é feito de forma completamente transparente, forma que o emissor nem percebe que quem respondeu à solicitação foi outro servidor.

Essa opção pode ser usada também para permitir que os micros da rede local fiquem com as portas do bittorrent abertas (de forma a baixar arquivos com um melhor desempenho), rodem servidores de games online ou qualquer outra tarefa onde seja necessária manter determinadas portas TCP ou UDP abertas. A limitação é que continua existindo uma única porta 80, uma única porta 21, etc. de forma que apenas um micro da rede interna pode receber cada porta de cada vez.

Veja um exemplo de como redirecionar as portas 6881 a 6889 usadas pelo Bittorrent para o micro 192.168.0.10 da rede local:

# Redireciona uma faixa de portas para um micro da rede local.
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp -i eth0 –dport 6881:6889 -j DNAT \
–to 192.168.0.10
iptables -t nat -A POSTROUTING -d 192.168.0.10 -j SNAT –to 192.168.0.1

Esta regra é um pouco mais complexa, pois trabalha em duas fases. A primeira faz com que o servidor encaminhe todas as conexões que receber na interface e porta especificada para o micro da rede local e a segunda faz com que os pacotes de resposta enviados por ele posam ser encaminhados de volta. Para que ambas funcionem, é necessário usar o comando “echo 1 > /proc/sys/net/ipv4/ip_forward”, que ativa o forwarding de portas. É o mesmo comando que usamos ao compartilhar a conexão.

Nos parâmetros que coloquei em negrito, a “eth0” é a placa de internet, onde chegam os pacotes, a “6881:6889” é a faixa de portas que estão sendo redirecionadas e o “192.168.0.10” é o IP do micro dentro da rede local que passa a receber as conexões destinadas a ela. Na segunda regra, temos repetido o IP do micro na rede local e, em seguida, o “192.168.0.1” que indica o IP do servidor, dentro da rede local.

Para redirecionar uma única porta, ao invés de uma faixa, basta citar a porta sem usar os “:”, como em:

# Redireciona uma única porta para um micro da rede local.
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp -i eth0 –dport 22 -j DNAT –to 192.168.0.10
iptables -t nat -A POSTROUTING -d 192.168.0.10 -j SNAT –to 192.168.0.1

É possível ainda indicar uma lista de portas (usando a opção -m multiport), como em:

# Redireciona um conjunto de portas
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp -i eth0 -m multiport –dport 21,22,80 -j DNAT \
–to-dest 192.168.0.10
iptables -t nat -A POSTROUTING -d 192.168.0.10 -j SNAT –to 192.168.0.1

Note que nos três exemplos usei o parâmetro “-p tcp”. Ele é necessário, mas faz com que a regra se aplique apenas a portas TCP. Caso você precise fazer forwarding de portas UDP, deve alterar o protocolo dentro da regra, como em:

# Redireciona uma porta UDP
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p udp -i eth0 –dport 53 -j DNAT –to 192.168.0.10
iptables -t nat -A POSTROUTING -d 192.168.0.10 -j SNAT –to 192.168.0.1

Bloqueando portas de saída

Mais um uso importante para o firewall é bloquear portas de saída, ou seja, bloquear portas no sentido rede local > internet. Isso permite bloquear o uso de determinados programas que utilizem estas portas.

O MSN, por exemplo, utiliza originalmente a porta 1863. Nas versões recentes ele é capaz de se conectar também através da porta 80 (ou através de sites como o meebo.com, que permitem acessar o MSN diretamente através do navegador). Por isso, ao bloquear a porta 1863, os clientes podem continuar conseguindo se conectar, porém, você obriga o tráfego a passar pela porta 80, onde tem a chance de fazê-lo passar por um servidor Squid, configurado como proxy transparente. Isso permite logar os acessos ou sabotar o sistema de autenticação do MSN, bloqueando os domínios “messenger.hotmail.com” e “webmessenger.msn.com”, além de outros sites que ofereçam clientes via web.

Hoje em dia, cada vez mais programas são capazes de acessar a Web através da porta 80, 443 (https) ou via proxy, o que torna difícil bloqueá-los. Em muitos casos, é preciso usar uma combinação de portas fechadas no firewall, bloqueio a endereços IPs específicos e bloqueio de determinados domínios no Squid.

Ao criar as regras do Iptables, existem duas opções. Bloqueando a porta para “FORWARD”, você impede o acesso a partir dos micros da rede local, que acessam através da conexão compartilhada pelo servidor. Bloqueando para “OUTPUT”, a porta é bloqueada no próprio micro onde o firewall está ativo. Você pode bloquear as duas situações, duplicando a regra:

iptables -A OUTPUT -p tcp –dport 1863 -j REJECT
iptables -A FORWARD -p tcp –dport 1863 -j REJECT

Você pode ainda bloquear intervalos de portas, separando-as por “:”, como em:

iptables -A FORWARD -p tcp –dport 1025:65536 -j REJECT

Como estamos criando regras para os micros da rede local e não para possíveis invasores provenientes da Internet, é aconselhável usar a regra “REJECT” ao invés de “DROP”. Caso contrário, os programas nos clientes sempre ficarão muito tempo parados ao tentar acessar portas bloqueadas, o que vai gerar reclamações e um certo overhead de suporte.

Você pode descobrir facilmente quais portas de saída são utilizados por cada programa fazendo buscas no Google, mas tentar bloquear um a um todos os programas indesejados acaba sendo tedioso. Ao invés disso, você pode experimentar um solução mais radical: inverter a lógica da regra, bloqueando todas as portas de saída e abrindo apenas algumas portas “permitidas”.

O mínimo que você precisa abrir neste caso são as portas 80 e 53 (dns). A partir daí, você pode abrir mais portas, como a 21 (ftp), 25 (smtp), 110 (pop3) e assim por diante. Um exemplo de configuração neste caso seria:

iptables -A FORWARD -p udp -i eth1 –dport 53 -j ACCEPT
iptables -A FORWARD -p tcp -i eth1 –dport 80 -j ACCEPT
iptables -A FORWARD -p tcp -i eth1 –dport 21 -j ACCEPT
iptables -A FORWARD -p tcp -i eth1 -j LOG
iptables -A FORWARD -p tcp -i eth1 -j REJECT

Veja que todas as regras especificam a interface da rede local (eth1 no exemplo), de onde serão recebidas as conexões dos clientes. Note que não incluí nenhum bloqueio para forwarding de pacotes provenientes da interface eth0 (da internet), pois a idéia é bloquear diretamente as requisições dos clientes e não as respostas. Em uma conexão TCP típica, o cliente envia a requisição na porta TCP usada pelo serviço, mas recebe a resposta em uma porta aleatória. Este é um exemplo de entrada no log do Iptables que mostra a resposta a uma conexão http normal. Veja que ela está endereçada à porta 45159 do cliente:

IN=eth0 OUT=eth1 SRC=64.233.169.99 DST=192.168.0.10 LEN=40 TOS=0x00 PREC=0x00 TTL=239 ID=36813 PROTO=TCP SPT=80 DPT=45159 WINDOW=8190 RES=0x00 ACK FIN URGP=0

No caso da porta 53 (DNS) estou especificando o protocolo UDP, ao invés de TCP, pois as requisições são feitas usando portas UDP para ganhar tempo. Embora os servidores DNS escutem tanto na porta 53 TCP, quanto UDP, na prática quase sempre é usada a porta 53 UDP, pois o tempo de resposta é menor. No UDP a requisição é simplesmente respondida da forma mais rápida possível, enquanto que no TCP é necessário abrir e encerrar a conexão.

A regra “iptables -A FORWARD -j LOG” é uma boa opção durante a fase de testes, pois ela faz com que o Iptables logue todos os pacotes que forem encaminhados (tanto envio, quanto resposta), permitindo que você verifique o que está ocorrendo quando algo não estiver funcionando. Você pode acompanhar o log usando o comando “dmesg”.

Colocado nesta posição (depois das regras que autorizam as conexões nas portas 53 e 80), ele vai mostrar apenas as requisições bloqueadas pelo firewall, dando-lhe a chance de acompanhar os acessos dos clientes e permitir portas adicionais sempre que necessário.

Por exemplo, esta estrada (no log) mostra uma tentativa de conexão de um cliente MSN rodando no micro “192.168.0.10” que foi bloqueada pelo firewall:

IN=eth1 OUT=eth0 SRC=192.168.0.10 DST=207.46.28.77 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=21328 DF PROTO=TCP SPT=38119 DPT=1863 WINDOW=5840 RES=0x00 SYN URGP=0

A opção “DTP” indica a porta usada. Se quisesse autorizar o uso do programa, você adicionaria a regra “iptables -A FORWARD -p tcp -i eth1 –dport 1863 -j ACCEPT” em seu script.

Outra opção, para não precisar abrir tantas portas e ter um melhor controle sobre o tráfego de saída é usar um servidor Squid configurado como proxy transparente (interceptando o tráfego da porta 80) e rodar servidores locais para DNS e e-mail (você pode configurar um servidor Postfix como sistema satélite, de forma que ele envie os e-mails dos usuários da rede usando o SMTP do provedor), de forma que qualquer acesso precise necessariamente passar por algum dos serviços ativos no servidor, sujeito a log e aos bloqueios que configurar.

Neste caso, desabilite o compartilhamento da conexão (ou bloqueie o forward de todas as portas) e configure os clientes para utilizarem o IP do servidor como DNS, servidor SMTP, POP e outros serviços que tenha ativado. Mesmo ao ser configurado como proxy transparente, o Squid continua funcionando como um proxy tradicional, através da porta 3128. Você pode configurar clientes de FTP e outros programas com suporte a proxy para acessarem através dele. A vantagem sobre o acesso direto é que ao passar pelo proxy, tudo fica registrado e todo acesso precisa passar pelos filtros de domínios, formatos de arquivos, limitação de banda, etc. definidos por você.

Complementando o bloqueio de portas, você pode também bloquear o acesso de determinados endereços IP, como em:

# Bloqueia o acesso à web a partir de um determinado IP
iptables -A FORWARD -p tcp -s 192.168.0.67 -j REJECT

Esta regra deve ir logo no início do script, antes das regras que abrem portas de saída, caso contrário não surtirá efeito. Lembre-se de que o Iptables processa as regras seqüencialmente: se uma compartilha a conexão com todos os micros da rede, não adianta tentar bloquear para determinados endereços depois. As regras com as exceções devem sempre vir antes da regra mais geral.

Fonte: Desmonta&CIA

Anúncios

Tags:,

About Desmonta&CIA

Somos um blog que busca informar aos apaixonados por tecnologia tudo sobre o mundo de TI.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: