quarta-feira, 7 de julho de 2010

IPFW - Criação de regras no IPFIREWALL

Para este artigo foi utilizado o FreeBSD 7.2 e o IPFW2.

Se o seu servidor FreeBSD ainda não tem o IPFW compilado no kernel, então acesse o link abaixo e veja como configura-lo e instala-lo em seu kernel:


Inicialmente é bom informar as duas formas de funcionamento do firewall IPFW, no que diz respeito ao tratamento que é dado aos pacotes que trafegam por ele.

Os modos em que o IPFIREWALL pode funcionar são:

Modo Filtro de pacotes:

- Restringir o tráfego baseado no endereço IP de origem ou destino, através das portas de comunicação TCP ou UDP.


Modo Firewall stateful:

- Herda as característica do firewall em modo filtro de pacotes e implementa o filtro por estado da sessão; Nesse caso o firewall armazena os estados das conexões e aplica o filtro de bloqueio ou permissão para o pacote passante com base nesses estados. O firewall armazena em uma tabela os detalhes das conexões existentes (IP de origem, IP de destino, porta de origem, porta de destino, tempo restante para essa conexão na tabela stateful)  que estão sendo efetuadas no momento e inspeciona o tráfego evitando que pacotes ilegítimos tenham acesso a serviços de rede ganhando mais velocidade e segurança, evitando, por exemplo, técnicas hacker como: ip spoofing.

Construção do conjunto de regras(Ruleset):

Primeiramente será apresentado o conjunto de regras que são pré-definidas para o IPFW, essas são regras que já vem prontas para serem utlizadas no Firewall.

Ruleset pré-definidas:

A variável do /etc/rc.conf que gerencia qual o conjunto de regras pré-definidas será carregada pelo firewall é a firewall_type=" " . Exitem 5 tipos de regras pré-definidas disponíveis:

"OPEN" -  O firewall permiti todo tráfego em suas interfaces, ou seja, não bloqueia nenhuma tráfego.

"CLIENT" - Essa definição de tipo de firewall (firewall_type) permite todo o tráfego proveniente da rede local (por exemplo, uma rede interna atrás de NAT) pra ela mesma. Bloqueia pacotes fragmentados, permite que mensagens de email, resoluções de nomes (DNS) e NTP sejam enviadas pra dentro e fora da rede, e não permite nenhuma máquina que esteja fora da rede interna iniciar conexões TCP com máquinas dentro da rede. Se a rede estiver por trás de uma implementação básica de NAT sem nenhuma opção de proxie carregada isso já seria impossível. Esse tipo de firewall funciona com política aberta ou fechada, definida no kernel, ou seja, não faz diferença se você colocou IPFIREWALL_DEFAULT_TO_ACCEPT ou IPFIREWALL_DEFAULT_TO_DENY como padrão.

"SIMPLE" - Esse tipo de firewall é uma contradição. Apesar do nome SIMPLE, ele é muito mais complexo que a definição CLIENT, e requer que o usuário tenha algum conhecimento nos padrões RFC de Internet pra poder entender suas definições de regras de firewall. Essa regra vai evitar spoofing (técnica onde uma máquina se faz passar por outra, alterando seu endereçamento IP) não permitindo a entrada de nenhum pacote que tenha um endereço de retorno igual ao endereço de qualquer host dentro da rede interna. Vai bloquear todos os pacotes endereçados como de redes privadas, conforme definido na RFC 1928, evitando o tráfego pra dentro ou fora da rede, e vai bloquear ainda todas as redes não-roteaveis, conforme definido no Internet-Drafts da IETF (disponível em http://www.ietf.org/internet-drafts/draft-manning-dsua-03.txt). Esse tipo de firewall vai permitir tráfego de e-mail, de WWW, de DNS, e NTP, e vai permitir também pacotes fragmentados, e em relação às conexões TCP iniciadas por hosts fora da rede, o firewall não vai apenas bloquear, como na definição CLIENT, vai também logar todas essas tentativas.

"CLOSED" - Tecnicamente essa definição não é um conjunto de regras de firewall, porque não adiciona nenhuma regra. Na verdade, aqui acontece tudo que nós insistimos que você deve evitar, ou seja, estabelece uma política fechada, negando todo e qualquer tráfego da rede (exceto o tráfego via lo0 que nós vimos anteriormente que é controlado por padrão). Essa definição simplesmente desabilita todos os serviços IP na rede, a não ser que no seu kernel você tenha adicionado a regra de política aberta. Então, ajustar o firewall pra CLOSED vai ser necessário em casos *extremos* onde você prefere (ainda que temporariamente) tirar toda a sua rede de funcionamento. Ou seja, não defina como padrão no rc.conf.

"UNKNOWN" - Desabilita o carregamento de regras do ipfirewall.

Agora iremos abordar a construção do conjuto de regras personalizaveis para o IPFW utilizaremos neste momento o modo filtro de pacotes. Para isso é necessário criar um arquivo onde será colocado as nossas regras, que será onde o IPFW irá ler as mesmas. Para isso iremos criar o arquivo de regras, como mostra abaixo:

# mkdir -p /tools/firewall

# touch /tools/firewall/rules.fw

Iremos editar o arquivo rules.fw:
# vi /tools/firewall/rules.fw

Agora iremos começar a escrever as nossas regras, mas como é a sintaxe para se escrever as regras no IPFIREWALL?
Abaixo uma breve explicação sobre a sintaxe das regras do IPFW:
CMD [número_regra] [prob probalilidade] ação [log [logamount número] ] corpo_regra

CMD =
add, delete(Os mais utilizados)


add: adicionar uma nova regra ao firewall;
delete: deletar uma regra do firewall;

[número_regra]
=
Quando um pacote entra no firewall ele é comparado com a primeira regra no conjunto de regras e avança uma regra de cada vez, que se deslocam de cima para baixo do conjunto em ordem crescente do número de seqüência das regras. Quando o pacote se adequa a seleção de parâmetros de uma regra, o campo de ação é executada e a busca do conjunto de regras termina para o pacote. Isto é referido como "o primeiro que se adequa ganha" do metodo de procura. Se o pacote não corresponde a nenhuma das regras, ele é pego pela regra padrão obrigatório IPFW, número 65.535, que nega todos os pacotes e descarta-los sem qualquer resposta de volta para o remetente, a não ser que se coloque na regra para que o IPFW envie uma mensagem de resposta.
O número de regras varia de 1 a 65535 e indica a sequência em que as regras serão processadas, sendo que a regra de número 65535 é a padrão utilizada pelo firewall, ou seja exclusiva do firewall, essa regra padrão pode ser aceitar tudo(tcp, udp e ip) de qualquer lugar para qualquer lugar ou negar tudo(todos os protocolos tcp, udp e ip) de qualquer lugar para qualquer lugar. Essa regra é especificada antes da compilação do firewall é uma linha que você especifica no kernel IPFIREWALL_DEFAULT_TO_ACCEPT ou IPFIREWALL_DEFAULT_TO_DENY.


[prob probabilidade]
=
Uso opcional, Define uma probabilidade para aplicar a regra. Varia de 0 a 1.

ação =
"allow, accept, pass e permit"
Tem a mesma função, aceitar pacote que chegam ao firewall e que se adequem a regra. E a leitura das regras termina.

"deny, drop
"
Tem a mesmo função, descartar pacotes silenciosamente(sem enviar resposta ao remetente) que correspondem a regra. E a leitura das regras termina.

"check-state"- Checa o pacote contra um conjunto de regras dinâmicas, isto é para modo statefull do firewall que ainda iremos ver.

"count" - Todos os pacotes que combinarem com uma regra cuja ação seja "count", determinará que o ipfirewall incremente o contagem de pacotes, ou seja, a saída de "ipfw show" indicará mais uma ocorrência de pacotes nessa regra. Motivos estatísticos óbvios. O processamento das regras do firewall continuam a buscar por outras regras que combinem com os pacotes.

"divert porta" - Redireciona o pacote para a porta especificada, utilizando um socket "divert". Pode ser especificado número ou nome, veja /etc/services.

"fwd ip[,porta]" - Sinônimo de forward, encaminha o pacote para o ip especificado. Se o ip for local será encaminhado para a porta especificada, se o ip não for local a porta será ignorada. O pacote não é alterado, e isto inclui o ip de destino, então se o pacote for encaminhado para outro host provavelmente será rejeitado. Caso seja encaminhado para um ip local, desta máquina, o socket que irá receber o pacote terá o seu endereço alterado para coincidir com o endereço de destino do pacote, aceitando desta forma o mesmo.

"pipe número" - Passa o pacote através de um "pipe" dummynet, para controle de tráfego.

"queue número" - Passa o pacote para uma "queue" dummynet, para controle de tráfego utilizando WF2Q+.

"reset" - Quando um pacote encontra uma regra com essa ação, o pacote é bloqueado, e o ipfirewall tenta enviar um sinal (flag) de TCP Reset (RST) pro endereço de origem do pacote. O processamento das regras pra esse pacote termina. Como esse tipo de regra apenas se aplica pra pacotes TCP, o protocolo especificado na regra deve ser "tcp", para que apenas tais pacotes sejam processados por essa regra, e não todos (proto "all") os protocolos de pacotes IP.

"skipto " - Todos os pacotes que combinem com uma regra cuja ação seja "skipto " vão fazer com que o ipfirewall(4) continue processando esse pacote e buscando ocorrência nas regras que sejam de ordem maior ou igual ao indicado pela ação.

"reject" - Essa ação é pouco utilizada atualmente. Quando um pacote combina com uma regra cuja ação seja "reject", então o ipfirewall(4) bloqueia esse pacote e responde com uma mensagem ICMP do tipo "host unreachable", dando a impressão que a máquina se encontra fora da rede. Essa é uma forma não silenciosa de negar o tráfego pelo firewall, contudo, assim como a ação "reset", essa ação também aumenta o uso da sua banda de rede.

"tee porta" - Aceita o pacote e envia uma cópia do mesmo para a porta especificada, via socket "divert".

"unreach código" - Descarta o pacote, e tenta enviar uma resposta "ICMP unreachable" com o código especificado. O código deve ser entre 0 e 255, ou alguma destas palavras chave: net, host, protocol, port, needfrag, srcfail, net-unknown, host-unknown, isolated, net-prohib, host-prohib, tosnet, toshost, filter-prohib, host-precedence ou precedence-cutoff.

[log [logamount número]] =
Uso opcional, caso mencionada a palavra log, cada vez que um pacote coincidir com esta regra será feito um log através do syslog.

corpo_regra =
Contém uma ou mais exigências que o pacote precisa coincidir para a regra ser atendida. Essa especificação pode incluir endereço ip de origem, endereço ip de destino, porta de origem, porta de destino, protocolo, interface de rede de entrada, interface de rede de saída etc. O corpo da regra pode possuir uma ou mais opções. Essas opções podem ser precedidas de "not", como negação, ou serem agrupadas em blocos OR, entre chaves, por exemplo: { dst-port 50 or dst-port 51 or not src-port 52 }. Descreveremos cada uma dela abaixo:

"dst-ip endereço" - Endereço IP de destino do pacote.
"dst-port porta" - Porta(s) de destino do pacote. Se for especificada mais de uma porta, separar por vírgula (50, 51, 52), ou em faixa de portas (50-60).
"established"
Se o pacote tiver os bits RST ou ACK.
"frag"
fragmentos de pacotes, não sendo o primeiro fragmento.
"gid grupo"
Pacotes TCP ou UDP enviados ou recebidos pelo grupo. O grupo pode ser especificado pelo nome ou pelo GID.
"icmptypes tipo"
Tipo(s) de pacotes ICMP. Se for mais de um, separar por vírgula. Os tipos podem ser: echo reply (0), destination unreachable (3), source quench (4), redirect (5), echo request (8), router advertisement (9), router solicitation (10), time-to-live exceeded (11), IP header bad (12), timestamp request (13), timestamp reply (14), information request (15), information reply (16), address mask request (17) e address mask reply (18).
"in | out"
Pacotes de entrada ou de saída. Note que isto significa que os pacotes estão entrando ou saindo da máquina, então mesmo que um pacote venha da rede interna, estará entrando na máquina antes de sair.
"keep-state"
Quando um pacote coincidir com uma regra que tiver esta opção, será criada uma regra dinâmica, cujo comportamento será coincidir o tráfego bidirecional entre este ip/porta de origem e ip/porta de destino, no mesmo protocolo. A regra dinâmica expira após um certo tempo. Dessa forma, pode-se definir uma regra "check-state" anterior a esta, liberando este fluxo de pacotes, e teremos um firewall "stateful".
"limit {ip-origem | porta-origem | ip-destino | porta-destino} número"
Serão permitidas apenas o número especificado de conexões com os parâmetros especificados.
"mac mac-destino mac-origem"
Pacotes com o endereço MAC de destino e/ou de origem especificados. Se não for especificado algum deverá ser usada a palavra "any", para coincidir com todos os endereços.
"proto protocolo"
Pacotes com o protocolo (IP) especificado. Veja /etc/protocols.
"recv interface | xmit interface | via interface"
Pacotes recebidos pela interface de rede especificada (recv xl0), pacotes transmitidos pela interface especificada (xmit fxp0), ou pacotes passando pela interface, independentemente de entrar ou sair (via xl0). Quando xmit for utilizado é requerida a opção "out", já que o pacote estará saindo.
"setup"
Pacotes com o bit SYN mas sem o bit ACK.
"src-ip endereço"
Endereço IP de origem do pacote.
"src-port porta"
Porta(s) de origem do pacote.
"tcpflags flags"
Flags dos pacotes TCP, separadas por vírgula. As possíveis são: fin, syn, rst, psh, ack e urg. A negação pode ser feita por um "!".
"uid usuário"
Pacotes TCP ou UDP enviados ou recebidos pelo usuário. O usuário pode ser especificado pelo username ou pelo UID.
"vrrevpath"
Pra pacotes de entrada, é feita uma consulta ao endereço de origem na tabela de roteamento. Se a interface na qual o pacote entrou é a mesma de saída especificada pela rota, então a regra coincide. Isto pode ser utilizado para criar regras anti-spoofing. Os pacotes de saída não são submetidos à verificação.
PARA UMA LEITURA MAIS AVANÇADA ACESSE OS FONTES DO TEXTO ACIMA:
http://www.freebsd-howto.com/HOWTO/Ipfw-HOWTO

http://www2.unijui.tche.br/~heini/freebsd/ipfw2.html

Exemplos práticos:
### Liebrar udp da rede 192.168.0.0/24  para a rede 192.168.1.0/24
add 00100 allow udp from 192.168.0.0/24 to 192.168.1.0/24 in
### Regra para o INPUT do trafego SSH
add 00200 allow tcp from any to 192.168.1.1/32 22 in
### Regras para o INPUT do VNC da rede 192.168.1.0/24 para VNCs na rede 192.168.1.0/24
add 00300 allow tcp from 192.168.1.0/24 to 192.168.0.0/24 5900 in setup
### Bloquear todos os pacotes vindo de qualquer lugar para qualquer lugar e logar os mesmo
add 64534 deny log all from any to any
Resumindo a sintaxe das regras no IPFW:

# O comando entre colchetes é opcional
command   [rule number]   action   proto   from   source[port]   to   destination[port] [Complemento: in,out,via... etc]

Seguidores