Ir para conteúdo
  • Cadastre-se

(proteção) Entendendo e montando um Firewall no Linux


maickbr1991

Posts recomendados

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

Link para o comentário
Compartilhar em outros sites


eu to com um projeto de abrir um servidor l2off interlude retail, pelo fato de ser novato na area de l2off e segurança na web, estava pesquisando sobre proteção e achei este tutorial e postei deve ajuda muita gente. aceito dicas

Editado por Bian
Link para o comentário
Compartilhar em outros sites

  • Registre-se

    Faça parte da maior e  mais antigas comunidades sobre Lineage2 da América Latina.





  • Patrocinadores

  • Quem Está Navegando

    • Nenhum usuário registrado visualizando esta página.
  • Posts

    • Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?     Teria como fazer do dusk shield e do zombie shield dessa maneira?    
    • muchas gracias muy lindos NPC 🙂
    • relaxa jovem gafanhoto, testa as quests. e posTa os erros indesejaveis.  
    • Se alguém pudesse me ensinar como codificar as missões, eu ficaria feliz em fazer isso sozinho ou pelo menos ajudar. Eu realmente quero jogar em um servidor onde todas as quests funcionem bem e melhor ainda se você puder fazer quests customizadas!
    • mas no interlude, nem todas as quests de class,  vai mostrar onde tem que ir, ate o reborn nao mostrava quando era interlude, só mostrou depois que eles colocaram client classic pra rodar, e ficou melhor ainda quando virou hellbound em diante, mas ha sim alguma chance de modificar isso direto no script para fazer igualmente, só basta te um pouco de paciencia e persistencia exato
    • 408_PathToElvenwizard dá Orion eu tive que mexer tbm, até modifiquei e consegui deixar ela igual do Classic, com a seta e a marcação no mapa. (não retail IL) Dá pra importar py de várias revs, o foda é que não da regular as quest py através do debug em tempo real, pelo menos eu não consegui rsrs
    • Hasta el momento todas las QUESTS son completables si te guias con un tutorial de youtube. El problema es que tienen bugs de locacion y de subquests que no avanzan o no te marcan correctamente a donde ir en el mapa, cosa que en Retail si se ve como corresponde.
    • estranho, mas pelo menos a galera nunca reclamo das quests quando tinha aberto 5x, geral fez class primeira e segunda job, poucos que compraram a class
    • en RUSaCis-3.5 data pack, las Quests estan en formato .java y son diferentes a como estan redactadas en jOrion y jFrozen 1.5 (ProyectX) package net.sf.l2j.gameserver.scripting.quest; import net.sf.l2j.commons.random.Rnd; import net.sf.l2j.gameserver.enums.Paperdoll; import net.sf.l2j.gameserver.enums.QuestStatus; import net.sf.l2j.gameserver.enums.actors.ClassId; import net.sf.l2j.gameserver.model.actor.Creature; import net.sf.l2j.gameserver.model.actor.Npc; import net.sf.l2j.gameserver.model.actor.Player; import net.sf.l2j.gameserver.network.serverpackets.SocialAction; import net.sf.l2j.gameserver.scripting.QuestState; public class Q224_TestOfSagittarius extends SecondClassQuest { private static final String QUEST_NAME = "Q224_TestOfSagittarius"; // Items private static final int BERNARD_INTRODUCTION = 3294; private static final int HAMIL_LETTER_1 = 3295; private static final int HAMIL_LETTER_2 = 3296; private static final int HAMIL_LETTER_3 = 3297; private static final int HUNTER_RUNE_1 = 3298; private static final int HUNTER_RUNE_2 = 3299; private static final int TALISMAN_OF_KADESH = 3300; private static final int TALISMAN_OF_SNAKE = 3301; private static final int MITHRIL_CLIP = 3302; private static final int STAKATO_CHITIN = 3303; private static final int REINFORCED_BOWSTRING = 3304; private static final int MANASHEN_HORN = 3305; private static final int BLOOD_OF_LIZARDMAN = 3306; private static final int CRESCENT_MOON_BOW = 3028; private static final int WOODEN_ARROW = 17; // Rewards private static final int MARK_OF_SAGITTARIUS = 3293; // NPCs private static final int BERNARD = 30702; private static final int HAMIL = 30626; private static final int SIR_ARON_TANFORD = 30653; private static final int VOKIAN = 30514; private static final int GAUEN = 30717; // Monsters private static final int ANT = 20079; private static final int ANT_CAPTAIN = 20080; private static final int ANT_OVERSEER = 20081; private static final int ANT_RECRUIT = 20082; private static final int ANT_PATROL = 20084; private static final int ANT_GUARD = 20086; private static final int NOBLE_ANT = 20089; private static final int NOBLE_ANT_LEADER = 20090; private static final int BREKA_ORC_SHAMAN = 20269; private static final int BREKA_ORC_OVERLORD = 20270; private static final int MARSH_STAKATO_WORKER = 20230; private static final int MARSH_STAKATO_SOLDIER = 20232; private static final int MARSH_STAKATO_DRONE = 20234; private static final int MARSH_SPIDER = 20233; private static final int ROAD_SCAVENGER = 20551; private static final int MANASHEN_GARGOYLE = 20563; private static final int LETO_LIZARDMAN = 20577; private static final int LETO_LIZARDMAN_ARCHER = 20578; private static final int LETO_LIZARDMAN_SOLDIER = 20579; private static final int LETO_LIZARDMAN_WARRIOR = 20580; private static final int LETO_LIZARDMAN_SHAMAN = 20581; private static final int LETO_LIZARDMAN_OVERLORD = 20582; private static final int SERPENT_DEMON_KADESH = 27090; public Q224_TestOfSagittarius() { super(224, "Test Of Sagittarius"); setItemsIds(BERNARD_INTRODUCTION, HAMIL_LETTER_1, HAMIL_LETTER_2, HAMIL_LETTER_3, HUNTER_RUNE_1, HUNTER_RUNE_2, TALISMAN_OF_KADESH, TALISMAN_OF_SNAKE, MITHRIL_CLIP, STAKATO_CHITIN, REINFORCED_BOWSTRING, MANASHEN_HORN, BLOOD_OF_LIZARDMAN, CRESCENT_MOON_BOW); addQuestStart(BERNARD); addTalkId(BERNARD, HAMIL, SIR_ARON_TANFORD, VOKIAN, GAUEN); addMyDying(ANT, ANT_CAPTAIN, ANT_OVERSEER, ANT_RECRUIT, ANT_PATROL, ANT_GUARD, NOBLE_ANT, NOBLE_ANT_LEADER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, MARSH_STAKATO_WORKER, MARSH_STAKATO_SOLDIER, MARSH_STAKATO_DRONE, MARSH_SPIDER, ROAD_SCAVENGER, MANASHEN_GARGOYLE, LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD, SERPENT_DEMON_KADESH); } @Override public String onAdvEvent(String event, Npc npc, Player player) { String htmltext = event; QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; // BERNARD if (event.equalsIgnoreCase("30702-04.htm")) { st.setState(QuestStatus.STARTED); st.setCond(1); playSound(player, SOUND_ACCEPT); giveItems(player, BERNARD_INTRODUCTION, 1); if (giveDimensionalDiamonds39(player)) htmltext = "30702-04a.htm"; } // HAMIL else if (event.equalsIgnoreCase("30626-03.htm")) { st.setCond(2); playSound(player, SOUND_MIDDLE); takeItems(player, BERNARD_INTRODUCTION, 1); giveItems(player, HAMIL_LETTER_1, 1); } else if (event.equalsIgnoreCase("30626-07.htm")) { st.setCond(5); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_1, 10); giveItems(player, HAMIL_LETTER_2, 1); } // SIR_ARON_TANFORD else if (event.equalsIgnoreCase("30653-02.htm")) { st.setCond(3); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_1, 1); } // VOKIAN else if (event.equalsIgnoreCase("30514-02.htm")) { st.setCond(6); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_2, 1); } return htmltext; } @Override public String onTalk(Npc npc, Player player) { String htmltext = getNoQuestMsg(); QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; switch (st.getState()) { case CREATED: if (player.getClassId() != ClassId.ROGUE && player.getClassId() != ClassId.ELVEN_SCOUT && player.getClassId() != ClassId.ASSASSIN) htmltext = "30702-02.htm"; else if (player.getStatus().getLevel() < 39) htmltext = "30702-01.htm"; else htmltext = "30702-03.htm"; break; case STARTED: int cond = st.getCond(); switch (npc.getNpcId()) { case BERNARD: htmltext = "30702-05.htm"; break; case HAMIL: if (cond == 1) htmltext = "30626-01.htm"; else if (cond == 2 || cond == 3) htmltext = "30626-04.htm"; else if (cond == 4) htmltext = "30626-05.htm"; else if (cond > 4 && cond < 8) htmltext = "30626-08.htm"; else if (cond == 8) { htmltext = "30626-09.htm"; st.setCond(9); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_2, 10); giveItems(player, HAMIL_LETTER_3, 1); } else if (cond > 8 && cond < 12) htmltext = "30626-10.htm"; else if (cond == 12) { htmltext = "30626-11.htm"; st.setCond(13); playSound(player, SOUND_MIDDLE); } else if (cond == 13) htmltext = "30626-12.htm"; else if (cond == 14) { htmltext = "30626-13.htm"; takeItems(player, BLOOD_OF_LIZARDMAN, -1); takeItems(player, CRESCENT_MOON_BOW, 1); takeItems(player, TALISMAN_OF_KADESH, 1); giveItems(player, MARK_OF_SAGITTARIUS, 1); rewardExpAndSp(player, 54726, 20250); player.broadcastPacket(new SocialAction(player, 3)); playSound(player, SOUND_FINISH); st.exitQuest(false); } break; case SIR_ARON_TANFORD: if (cond == 2) htmltext = "30653-01.htm"; else if (cond > 2) htmltext = "30653-03.htm"; break; case VOKIAN: if (cond == 5) htmltext = "30514-01.htm"; else if (cond == 6) htmltext = "30514-03.htm"; else if (cond == 7) { htmltext = "30514-04.htm"; st.setCond(8); playSound(player, SOUND_MIDDLE); takeItems(player, TALISMAN_OF_SNAKE, 1); } else if (cond > 7) htmltext = "30514-05.htm"; break; case GAUEN: if (cond == 9) { htmltext = "30717-01.htm"; st.setCond(10); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_3, 1); } else if (cond == 10) htmltext = "30717-03.htm"; else if (cond == 11) { htmltext = "30717-02.htm"; st.setCond(12); playSound(player, SOUND_MIDDLE); takeItems(player, MANASHEN_HORN, 1); takeItems(player, MITHRIL_CLIP, 1); takeItems(player, REINFORCED_BOWSTRING, 1); takeItems(player, STAKATO_CHITIN, 1); giveItems(player, CRESCENT_MOON_BOW, 1); giveItems(player, WOODEN_ARROW, 10); } else if (cond > 11) htmltext = "30717-04.htm"; break; } break; case COMPLETED: htmltext = getAlreadyCompletedMsg(); break; } return htmltext; } @Override public void onMyDying(Npc npc, Creature killer) { final Player player = killer.getActingPlayer(); final QuestState st = checkPlayerState(player, npc, QuestStatus.STARTED); if (st == null) return; switch (npc.getNpcId()) { case ANT: case ANT_CAPTAIN: case ANT_OVERSEER: case ANT_RECRUIT: case ANT_PATROL: case ANT_GUARD: case NOBLE_ANT: case NOBLE_ANT_LEADER: if (st.getCond() == 3 && dropItems(player, HUNTER_RUNE_1, 1, 10, 500000)) st.setCond(4); break; case BREKA_ORC_SHAMAN: case BREKA_ORC_OVERLORD: if (st.getCond() == 6 && dropItems(player, HUNTER_RUNE_2, 1, 10, 500000)) { st.setCond(7); giveItems(player, TALISMAN_OF_SNAKE, 1); } break; case MARSH_STAKATO_WORKER: case MARSH_STAKATO_SOLDIER: case MARSH_STAKATO_DRONE: if (st.getCond() == 10 && dropItems(player, STAKATO_CHITIN, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, REINFORCED_BOWSTRING)) st.setCond(11); break; case MARSH_SPIDER: if (st.getCond() == 10 && dropItems(player, REINFORCED_BOWSTRING, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case ROAD_SCAVENGER: if (st.getCond() == 10 && dropItems(player, MITHRIL_CLIP, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, REINFORCED_BOWSTRING, STAKATO_CHITIN)) st.setCond(11); break; case MANASHEN_GARGOYLE: if (st.getCond() == 10 && dropItems(player, MANASHEN_HORN, 1, 1, 100000) && player.getInventory().hasItems(REINFORCED_BOWSTRING, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case LETO_LIZARDMAN: case LETO_LIZARDMAN_ARCHER: case LETO_LIZARDMAN_SOLDIER: case LETO_LIZARDMAN_WARRIOR: case LETO_LIZARDMAN_SHAMAN: case LETO_LIZARDMAN_OVERLORD: if (st.getCond() == 13) { if (((player.getInventory().getItemCount(BLOOD_OF_LIZARDMAN) - 120) * 5) > Rnd.get(100)) { playSound(player, SOUND_BEFORE_BATTLE); takeItems(player, BLOOD_OF_LIZARDMAN, -1); addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } else dropItemsAlways(player, BLOOD_OF_LIZARDMAN, 1, 0); } break; case SERPENT_DEMON_KADESH: if (st.getCond() == 13) { if (player.getInventory().getItemIdFrom(Paperdoll.RHAND) == CRESCENT_MOON_BOW) { st.setCond(14); playSound(player, SOUND_MIDDLE); giveItems(player, TALISMAN_OF_KADESH, 1); } else addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } break; } } }  
×
×
  • Criar Novo...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.