Objetivos desse Documento:
O objetivo principal desse documento é tentar elucidar os
conceitos envolvidos e as técnicas utilizadas na
construção de um firewall.
Não nos responsabilizamos pelo perfeito funcionamento do
seu firewall e pela segurança que o mesmo irá prover
para a sua rede.
Referências dos documentos Para elaborar esse documento
foram utilizados os seguintes documentos:
Conceitos Iniciais
O firewall no linux é feito através da filtragem
de pacotes. O tamanho de cada pacote é definido de acordo
com as características da sua rede, geralmente nas redes
ethernet o tamanho é de 1500 bytes. Então se por
exemplo for feito um download de um arquivo de 1 MB, o que
realmente estará acontecendo é que o seu computador
receberá vários pequenos pacotes (fragmentos) de 1500
bytes e no final irá agrupá-los para formar o arquivo
original.
Um pacote é composto por duas partes:
- Header (cabeçalho): é nessa parte do pacote que
o firewall vai atuar, possui informações importantes
como:
-
origem do pacote
-
destino do pacote
-
entre outras
- Body (corpo): é a parte que contêm os dados
propriamente ditos.
Como explicado anteriormente é importante conhecer esses
conceitos sobre pacotes pois o firewall no linux irá atuar
diretamente sobre eles fazendo a filtragem dos mesmos.
Ferramentas Utilizadas
Todo o controle de firewall (filtragem dos pacotes) é
feito no kernel, porém algumas ferramentas são
utilizadas para controlar essas regras (controlar essas
características). Nos kernels das séries 2.0.x era
utilizado o ipfwadm, porém o mesmo apresentava vários
problemas e falhas então uma nova versão foi
implementada que se chama ipchains e é utilizada atualmente
nos kernels 2.2.x.
Para verificar se o seu kernel está apto a filtrar os
pacotes basta verificar se existe o arquivo
/proc/net/ip_fwchains. Caso não exista então
é necessário fazer a recompilação do
kernel e habilitar a opção de firewall (verificar em
/usr/doc/HOWTO/IPCHAINS-HOWTO).
IP Masquerading
Masquerading funciona da seguinte maneira. Quando uma
máquina da rede local faz uma conexão com um host
externo (Internet), passa antes por uma máquina gateway que
vai re-escrever o cabeçalho do pacote. Dessa forma quem faz
o acesso ao host externo é a máquina gateway. Quando
o host externo responde enviando pacotes para aquela máquina
que fez a conexão, o masquerading sabe disso, e re-escreve
novamente o cabeçalho do pacote, para que ela o receba. Com
isso, toda sua rede local fica conectada a Internet e sendo
controlada pela máquina gateway que irá fazer a
ligação entre as redes.
Essa tecnologia permite que um conjunto de máquinas
acesso transparente a internet atrás de um sistema de
gateway, que nesse caso é o único sistema que
está ligado diretamente a internet.
Páginas web, telnet funcionam perfeitamente utilizando
IP-Masquerade. FTP, IRC e Real Audio precisam de um tratamento
especial, para isso devem trabalhar juntamente com módulos
específicos.
As regras de filtragem (firewall) podem ser aplicadas a todos
computadores, e você precisa manter a máquina gateway
bem segura, por que é ela quem faz a ligação
entre as duas redes, e esta vulnerável aos ataques
Internet.
_ __ _
| \/ \/ |
/ Internet \
\_/\_/\_/\_/
|
|
| 200.10.15.1
| /
| /
__________
| |
| Firewall | <-- Gateway
| System |
|__________|
|\
| \
| 192.168.0.1
| 255.255.255.0
|
_____________________________________________
| | |
| | |
| | |
| | |
_____________ _____________ _____________
| | | | | |
| Workstation | | Workstation | | Workstation |
|_____________| |_____________| |_____________|
192.168.0.2 192.168.0.3 192.168.0.4
255.255.255.0 255.255.255.0 255.255.255.0
|
Como funcionam as regras de firewall
O kernel inicia-se com 3 listas de regras, essas regras
são chamadas de firewall chains ou apenas chains. Quando um
pacote chega a placa de rede da sua máquina, o kernel usa as
regras de INPUT para decidir o que fazer. Se o pacote consegue
atravessar as regras de input, o kernel decide para onde enviar o
pacote, isso chama-se roteamento do pacote. Se o destino do pacote
for outra máquina, estamos usando o chain chamado de
FORWARD, e por fim, os pacotes que saem da sua máquina usam
as regras de OUTPUT chain.
Dá para perceber que cada chain é uma
verificação de regras. Se a regra está
definida, o kernel sabe o que fazer com o pacote. Se nao existe
definição para aquela espécie de pacote, o
kernel consulta o chain POLICY para decidir o que fazer, rejeitando
ou aceintando o pacote que não possuí uma
específica.
----------------------------------------------------------------
| ACCEPT/ lo interface |
v REDIRECT |
--> C --> S --> ______ --> D --> ~~~~~~~~ --> local? -----> _______ -->
h -> a |input | e {Routing } __|____ |output |ACCEPT
e | n |Chain | m {Decision} |forward|---->|Chain |
c | i |______| a ~~~~~~~~ |Chain | ^ |_______|
k | t | s | ^ |_______| | |
s | y | q | | | | |
u | | v e v | | | v
m | | DENY/ r Local Process v | DENY/
| | v REJECT a | DENY/ | REJECT
| |DENY d | REJECT |
v | e -------+---------------------
DENY| |
------------------------------
|
Checksum:
É um teste feito para verificar se o pacote está
corrompido de alguma forma. Caso esteja, então ele é
descartado (DENY).
Sanity:
Nesse estágio é feito testes de sanidade, se o
pacote está mal formado ele pode confundir uma regra de
checagem então ele já é logo descartado
(DENY).
input chain:
Esta é o primeiro conjunto de regras de controle do
firewall. Os pacotes que chegarem a esta regra serão
testados, se os pacotes NÃO forem rejeitados (DENY)
então ele prosseguirá adiante.
Demasquerade:
Se o pacote em questão for um pacote previamente
mascarado, ele será desmascarado e então irá
direto para o conjunto de regras output. E como ele sabe que
é um pacote mascarado ? Pois ele guarda em uma tabela quais
pacotes saíram e que foram mascarados.
Se não foi utilizado IP Masquerading é
possível mentalmente apagar este estágio do diagrama
acima.
Routing decision:
O campo destino do pacote é analisado pelo código
de roteamento para decidir se o pacote é destinado a um
processo local (Local Process) ou é para ser repassado para
uma máquina remota.
Local process:
Um processo local é aquele que está sendo
executado na sua máquina e pode receber pacotes que
já passaram pelo estágio de "routing decision".
Também podem enviar pacotes que passam novamente pelo
estágio de "routing Decision" e depois pela conjunto de
regras output.
lo interface:
Se os pacotes provenientes de um processo local tem como destino
um processo local, eles irão através do conjunto de
regras (chain) output com interface igual a 'lo', então eles
retornarão para a chain input também como interface
'lo'. A interface 'lo' é usualmente chamada de inteface de
loopback.
local:
Se o pacote não foi criado por um processo local,
então o próximo passo do pacote será o chain
forward, caso contrário o pacote irá para o chain
output.
forward chain:
Esse conjunto de regras é sempre acessada por todos os
pacotes que estão passando por essa máquina com o
destino para uma outra.
output chain:
Esse conjunto de regras é sempre acessada por todos os
pacotes que serão enviados para outra máquina.
IPCHAINS
Abaixo segue um explicativo de utilização do
ipchains, para maiores informações veja em
IPCHAINS-HOWTO ou em man ipchains.
Para listar todas as regras:
[root@eclipse /root]# ipchains -L
Chain input (policy ACCEPT):
Chain forward (policy ACCEPT):
Chain output (policy ACCEPT):
|
(nesse exemplo não aparece nenhuma regra pois ainda
não foi definida nenhuma).
Para criar uma nova regra:
# ipchains -A input
output
forward
-p TCP
UDP
ICMP
ALL
-s IP/MASQ PORTA:PORTA
-d IP/MASQ PORTA:PORTA
-j REJECT
ACCEPT
DENY
MASQ
RETURN
-P input ACCEPT
output DENY
forward MASQ
REDIRECT
onde, A = significa que quer adicionar uma nova regra
p = especifica o protocolo a ser utilizado
s = especifica a origem do pacote
d = especifica o destino do pacote
j = especifica a ação a ser tomada
P = tipo de política(controla se o padrão vai ser proibído/liberado)
|
Valores possíveis para as opções
's','d':
-s 192.168.0.0/255.255.255.0 ou
-s 192.168.255.0/24
|
(especificar todos os pacotes vindos de uma rede classe C)
-d www.conectiva.com.br
(especificartodos pacotes com destino para domínio
conectiva)
-s ! localhost
(especificar todos os pacotes que não tenham vindo de
localhost)
-d localhost 60000:61000
(especificar todos os pacotes com destino as portas 60.000 a
61.000 inclusive, da máquina localhost)
-s 0.0.0.0/0 :1023
(especificar todos os pacotes vindos de portas entre 0 a 1023
inclusive de qualquer máquina)
-s 0.0.0.0/0 1023:
(especificar todos os pacotes vindos de portas entre 1023 a
65535 inclusive de qualquer máquina)
-d ! 192.168.1.1 www
(especifica todos pacotes na porta www em qualquer
máquina menos na 192.168.1.1)
-d 192.168.1.1 ! www
(especifica todos pacotes para qualquer porta (menos www) na
máquina 192.168.1.1)
-d ! 192.168.1.1 ! www
(especifica todos pacotes para qualquer porta menos a www em
qualquer máquina menos na 192.168.1.1)
Vamos criar uma situação, na qual você
queira que sua máquina rejeite todos os pacotes ICMP
provenientes do endereço 127.0.0.1 (lo). A vantagem de usar
o endereço loopback 127.0.0.1 é que qualquer um pode
testar essas definições, mesmo que não esteja
conectado a uma rede. Os pacotes ICMP podem ser gerados com o
programa PING. Um programa de teste de comunicação
entre máquinas.
testando primeiramente o ping sem nenhuma regra de firewall:
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=0.2 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
|
- agora acrescentaremos uma regra e veremos o
resultado:
# ipchains -A input -s 127.0.0.1 -j DENY
|
# ipchains -L
Chain input (policy ACCEPT):
target prot opt source destination ports
DENY all ------ localhost anywhere n/a
Chain forward (policy ACCEPT):
Chain output (policy ACCEPT):
[root@eclipse /root]# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
^^^^^^
|
Essa regra adicionada diz para barrar (DENY) todos os pacotes
vindos do endereço IP 127.0.0.1 e com destino para qualquer
lugar. Neste exemplo fica claro que quando não se especifica
algum dos campos então ele pega os valores default.
Para apagar uma regra:
Aqui estaremos apagando a primeira regra contida no chain input,
neste exemplo estaremos apagando a regra que foi criada acima.
Existe uma outra forma de apagar regras, simplesmente trocando o
parâmetro -A por -D. Abaixo segue um exemplo para facilitar a
compreensão:
Para verificar as estatísticas de uma regra:
Por exemplo, se aquela regra acima (ipchains -A input -s
127.0.0.1 -j DENY) não estivesse sido apagada, então
para verificar as estatísticas é necessário
executar:
Chain input (policy ACCEPT: 345756 packets, 343117380 bytes):
pkts bytes target prot opt tosa tosx ifname mark outsize source destination ports
1 84 DENY all ------ 0xFF 0x00 any localhost anywhere n/a
Chain forward (policy ACCEPT: 0 packets, 0 bytes):
Chain output (policy ACCEPT: 383055 packets, 350725853 bytes):
|
O mais importante de tudo é que:
essa regra foi válida somente para um pacote, ou seja,
nesse caso negou somente um pacote, pois somente executamos um
ping: ping -c 1 127.0.0.1
o tamanho total de bytes foram 84
Para registrar log no sistema
Para que o sistema faça um log de todos as
ações de suas regras basta acrescentar o
parâmetro -l na composição da regra, nesse
nosso exemplo eu retirei todas as regras que existiam e criei uma
nova com esse comando:
[root@eclipse /root]# ipchains -A input -s 127.0.0.1 -j DENY -l
[root@eclipse /root]# ipchains -L
Chain input (policy ACCEPT):
target prot opt source destination ports
DENY all ----l- localhost anywhere n/a
Chain forward (policy ACCEPT):
Chain output (policy ACCEPT):
Ao executar o comando : ping -c1 127.0.0.1 podemos verificar no arquivo
/var/log/messages o log que foi gerado e que segue abaixo:
Jun 29 16:44:24 eclipse kernel: Packet log: input DENY lo PROTO=1
127.0.0.1:8 127.0.0.1:0 L=84 S=0x00 I=29645 F=0x0000 T=64 (#1)
|
Obs.: Na Versão Conectiva Linux 5.0, para que se consiga
fazer logs é necessário obter uma
atualização, que pode ser econtrada em:
http://www.conectiva.com.br/suporte/atualizacoes
Para criar novas chains:
# ipchains -N Test
# ipchains -L
Chain input (policy ACCEPT):
Chain forward (policy ACCEPT):
Chain output (policy ACCEPT):
Chain Test (0 references):
|
É para criar uma nova chain. As principais chains
que já vem por padrão são: input, output,
forward.
Deletar uma chain vazia
Apagar todas as regras de uma chain:
Estamos apagando todas as regras contidas na chain input.
Um exemplo com um chain criado pelo usuário
Suponha esses dois conjuntos de regras, o chain input e um outro
chain chamado 'Test' definido pelo próprio
usuário.
`input' `Test'
---------------------------- ----------------------------
| Regra1: -p ICMP -j REJECT| | Regra1: -s 192.168.1.1 |
|--------------------------| |--------------------------|
| Regra2: -p TCP -j Test | | Regra2: -d 192.168.1.1 |
|--------------------------| ----------------------------
| Regra3: -p UDP -j DENY |
----------------------------
|
Considerando um pacote TCP vindo da máquina
192.168.1.1 e com destino para 1.2.3.4. Primeiramente ele entra na
chain input e a Regra1 é testada, como ela não se
encaixa à Regra 1 então o pacote prossegue para a
próxima regra.
Comparando com a segunda regra o pacote se encaixa pois o mesmo
é um pacote tcp. Então agora a regra diz para ele ir
para o chain Test (TARGET) onde será submetido as regras
lá definidas.
Comparando agora com a Regra1 do chain Test o pacote
também se encaixa pois tem como origem a máquina
192.168.1.1, mas como não tem nenhum TARGET definido
então ele pula para a Regra2.
A Regra2 não se encaixa no perfil do pacote e nós
chegamos ao fim do chain Test, então agora retornaremos a
Regra3 do input.
Como essa última regra (Regra3, input) também
não se encaixa o pacote prossegue para o próximo
estágio.
Redirecionamento de portas.
É possível redirecionar uma porta da
máquina firewall para dentro de sua rede, podendo por tanto
protejer além de suas máquinas, seus servidores de
apache ou ftp.
Para redirecionar um pacote, primeiramente é
necessário indicar o redirecionamento, como por exemplo:
ipmasqadm portfw -a -P tcp -L 10.0.0.1 23 -R 192.168.0.3 23 -p 10
|
onde: a adciona uma nova regra
d para deletar
P para especificar o protocolo
L para especificar o endereço de entrada de dados
R para especificar em que host e porta vai ser redirecionado
p especifica a preferência
|
E logo após deve ser incluída uma regra para
que seja possível que a máquina interna acesse a
externa. Fazendo com isso que a máquina quando estiver
retornando o pacote externo, possa completar a
comunicação.
[root@localhost]# ipchains -P forward MASQ
|