IPtables Básico

O Firewall é um programa que como objetivo proteger a máquina contra acessos indesejados, tráfego indesejado, proteger serviços que estejam rodando na máquina e bloquear a passagem de coisas que você não deseja receber (como conexões vindas da Internet para sua segura rede local, evitando acesso aos dados corporativos de uma empresa ou a seus dados pessoais). No kernel do Linux 2.4, foi introduzido o firewall iptables (também chamado de netfilter) que substitui o ipchains dos kernels da série 2.2. Este novo firewall tem como vantagem ser muito estável (assim como o ipchains e ipfwadm), confiável, permitir muita flexibilidade na programação de regras pelo administrador do sistema, mais opções disponíveis ao administrador para controle de tráfego, controle independente do tráfego da rede local/entre redes/interfaces devido a nova organização das etapas de roteamento de pacotes.

O iptables é um firewall em nível de pacotes e funciona baseado no endereço/porta de origem/destino do pacote, prioridade, etc. Ele funciona através da comparação de regras para saber se um pacote tem ou não permissão para passar. Em firewalls mais restritivos, o pacote é bloqueado e registrado para que o administrador do sistema tenha conhecimento sobre o que está acontecendo em seu sistema.

Ele também pode ser usado para modificar e monitorar o tráfego da rede, fazer NAT (masquerading, source nat, destination nat), redirecionamento de pacotes, marcação de pacotes, modificar a prioridade de pacotes que chegam/saem do seu sistema, contagem de bytes, dividir tráfego entre máquinas, criar proteções anti-spoofing, contra syn flood, DoS, etc. O tráfego vindo de máquinas desconhecidas da rede pode também ser bloqueado/registrado através do uso de simples regras. As possibilidades oferecidas pelos recursos de filtragem iptables como todas as ferramentas UNIX maduras dependem de sua imaginação, pois ele garante uma grande flexibilidade na manipulação das regras de acesso ao sistema, precisando apenas conhecer quais interfaces o sistema possui, o que deseja bloquear, o que tem acesso garantido, quais serviços devem estar acessíveis para cada rede, e iniciar a construção de seu firewall.

O iptables ainda tem a vantagem de ser modularizável, funções podem ser adicionadas ao firewall ampliando as possibilidades oferecidas. Usei por 2 anos o ipchains e afirmo que este é um firewall que tem possibilidades de gerenciar tanto a segurança em máquinas isoladas como roteamento em grandes organizações, onde a passagem de tráfego entre redes deve ser minuciosamente controlada.

Um firewall não funciona de forma automática (instalando e esperar que ele faça as coisas por você), é necessário pelo menos conhecimentos básicos de rede tcp/ip, roteamento e portas para criar as regras que farão a segurança de seu sistema. A segurança do sistema depende do controle das regras que serão criadas por você, as falhas humanas são garantia de mais de 95% de sucesso nas invasões.

Enfim o iptables é um firewall que agradará tanto a pessoas que desejam uma segurança básica em seu sistema, quando administradores de grandes redes que querem ter um controle minucioso sobre o tráfego que passam entre suas interfaces de rede (controlando tudo o que pode passar de uma rede a outra), controlar o uso de tráfego, monitoração, etc.

Como devemos utilizar o iptables, como pode ser notado abaixo no help do iptables temos que utilizar o comando iptables + tabela + tipo de ação + cadeia + regra + opção

Usage: iptables -[AD] chain rule-specification [options]
       iptables -I chain [rulenum] rule-specification [options]
       iptables -R chain rulenum rule-specification [options]
       iptables -D chain rulenum [options]
       iptables -[LS] [chain [rulenum]] [options]
       iptables -[FZ] [chain] [options]
       iptables -[NX] chain
       iptables -E old-chain-name new-chain-name
       iptables -P chain target [options]
       iptables -h (print this help information)

Vamos abordar os tipos de ações que o iptables pode receber.

Obs: O iptables trabalha com cadeias para controle, ou seja em cada cadeia podemos ter varias regras e cada regra que é adiciona tem um número único que pode ser manipulado. Então caso eu crie uma regra número 1 negando o acesso Web e também criar a regra número 2 liberando o acesso Web, o iptables bloqueará o acesso Web pois ele sempre vai ler as regras em ordem numérica da cadeia.

-A ou --append: Está ação insere uma nova regra no controle do firewall na sequência da cadeia

Vamos ver um exemplo do uso da ação -A, na regra abaixo vamos efetuar a liberação do acesso a porta 22 SSH, as regras sempre vão seguir o padrão informado abaixo.

iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT 

Explicando: Aqui o que fizemos adicionamos uma regra na tabela de filtragem filter na chain INPUT que é a chain que controla o tráfego de entrada, no protocolo tcp, na porta 22 que é a porta padrão de SSH e com a opção -j nós informamos ao iptables o que deve ser feito ou seja DROP bloqueia o acesso.

Obs: Na regra acima utilizamos a tabela filter que é para a filtragem de pacotes, especificamos ela para o iptables com a opção -t filter porém se não informarmos a tabela com a opção -t filter o iptables assume por padrão que a tabela a ser utilizada vai ser a filter, porém no caso de que seja necessário a utilização de outra tabela temos que especificar para o iptables a tabela com a opção -t nome_tabela.

Agora vamos listar a nossa regra do iptables

iptables -L INPUT  -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Como pode ser notado a nossa regra tem o número 1, agora vamos criar mais uma regra para bloquear o acesso SSH

iptables -t filter -A INPUT -p tcp --dport 22 -j DROP

Agora vamos listar novamente as nossas regras

iptables -L INPUT  -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Como pode ser notado a regra de bloqueio recebeu o número 2 com isso o acesso vai ser liberado pois o iptables sempre vai ler a cadeia por ordem numérica.

Agora vamos fazer um teste de acesso ssh

ssh localhost
The authenticity of host '10.0.0.31 (::1)' can't be established.
RSA key fingerprint is a0:71:05:10:1c:b9:f1:5c:ff:50:c1:30:09:0d:2e:4c.
Are you sure you want to continue connecting (yes/no)? 

Como pode ser notado a segunda regra não adiantou, vamos refazer o nosso teste, mais antes vamos limpar as regras que já criamos.

iptables -F

Agora vamos criar primeiro a regra de bloqueio e depois a regra de liberação

iptables -t filter -A INPUT -p tcp --dport 22 -j DROP
iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT

Agora vamos listar as nossas regras novamente

iptables -L INPUT  -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Então agora é para o firewall bloquear o acesso a porta 22 de ssh e a segunda regra vai ser ignorada pois ele sempre vai ler as regras em ordem numérica, vamos fazer um teste de acesso ssh.

ssh 10.0.0.31
ssh: connect to host 10.0.0.31 port 22: Connection timed out

A conexão vai dar timeout pois o iptables vai bloquear o acesso.

Obs: A conexão vai ser aceita se você acessar ssh localhost que é o endereço de loopback da máquina, caso seja a mesma maquina que você esta implementando as regras e efetuando o acesso dela para ela mesma.

-I ou --insert: Insere uma regra no começo de nossa lista de regras ou na linha que for especificada

Limpe as regras do iptables novamente com

iptables -F

Agora vamos efetuar alguns testes com a opção -I, o primeiro teste a regra vai ser inserida na primeira linha da cadeia INPUT

iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT 

Vamos listar agora as nossas regras

iptables -L INPUT  -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Como pode ser notada na listagem do iptables a nossa regra teve ao numero 1, agora vamos inserir mais uma regra agora de bloqueio de SSH

iptables -t filter -I INPUT -p tcp --dport 22 -j DROP 

Vamos listar as regras novamente

iptables -L INPUT  -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Note aonde foi para a nossa regra de DROP, ela está com o número 1 então quando utilizarmos a ação -I a regra sempre vai ser colocada no início da cadeia.

Agora vamos inserir uma regra para bloquear a porta 80 na segunda posição da nossa chain

iptables -t filter -I INPUT 2 -p tcp --dport 80 -j DROP 

Vamos listar agora as regras novamente

iptables -L INPUT  -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Como pode ser notado nos especificamos a posição da nossa regra na cadeia INPUT.

-D ou --delete: Está ação deleta uma regra no controle do firewall pelo número definido.

Vamos ver um exemplo do uso da ação -D, na regra abaixo vamos remover a linha 2 na chain INPUT.

iptables -t filter -D INPUT 2

Agora vamos listar as regras novamente para verificar se foi excluída a linha 2 da chain INPUT.

iptables -L INPUT -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 

Agora vamos efetuar um teste tentar remover uma regra sem especificar o número

iptables -t filter -D INPUT
iptables: Bad rule (does a matching rule exist in that chain?).

Como pode ser notado recebemos um erro pois o iptables não reconheceu o número da regra, agora vamos tentar excluir a regra 1 e 2 com apenas um comando

iptables -t filter -D INPUT 1,2
iptables v1.4.10: Invalid rule number `1,2'
Try `iptables -h' or 'iptables --help' for more information.

Não conseguimos utilizando vírgula vamos tentar utilizar o hífen

iptables -t filter -D INPUT 1-2
iptables v1.4.10: Invalid rule number `1-2'
Try `iptables -h' or 'iptables --help' for more information.

Como pode ser notado não podemos remover mais de uma regra da chain com a ação -D.

-R ou --replace: Está ação substitui uma regra no controle do firewall pelo número definido.

Vamos ver um exemplo de substituição de regra.

Vamos criar uma regra como exemplo, pense que o gerente pediu para criar um regra para liberar o acesso web vamos la então

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

Agora vamos listar as regras para verificarmos se a regra foi inserida no controle do firewall.

iptables -L INPUT -n --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 

A nossa regra está la passamos para para o gerente testar e o mesmo acabou de se lembrar que o acesso é com criptografia ou seja esta trabalhando em https porta 443 e nós liberamos a porta 80 então vamos trocar a nossa regra.

iptables -t filter -R INPUT 3 -p tcp --dport 443 -j ACCEPT 

Agora vamos listar as regras novamente para verificar se as regras foram inseridas no controle do firewall.

iptables -L INPUT -n --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:443 

Como pode ser notado fizemos a substituição da regra 3 com sucesso.

-L ou --list: Está ação lista as regras da tabela filter.

Vamos efetuar um teste, vamos listar todas as regras do firewall

iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   

Como pode ser notado a ação -L sozinha nos traz as regras atualmente no firewall agora vamos listar as regras somente da chain INPUT

iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https 

Agora pense que você quer listar as regras da tabela nat que vamos ver mais a frente, então temos que passar mais a opção -t para especificar qual tabela que queremos listar.

iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination       
-F ou --flush: Está ação remove as regras das chains padrões do iptables

Vamos a um exemplo da utilização vamos criar um regra na chain FORWARD

iptables -A FORWARD -p tcp --dport 80 -j ACCEPT

Agora vamos listar as nossas regras para verificar se a nossa regra foi incluída no controle do firewall

iptables -L FORWARD --line-numbers -n
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80 

Agora vamos utilizar a ação -F para limpar a chain FORWARD

iptables -F FORWARD

Agora vamos listar novamente as nossas regras

iptables -L FORWARD --line-numbers -n
Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination  

Como pode ser notado não temos mais nenhuma regra, a diferença entre o -F e o -D é que o -F remove todas as regras enquanto o -D remove somente a regra informada pelo seu número.

Agora vamos limpar todas as regras do nosso firewall, mais primeiro vamos listar todas elas

iptables -L --line-numbers -n
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
2    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22 
3    ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:443 

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination  

Agora vamos limpar todas as regras

iptables -F

Agora vamos listar as regras novamente

iptables -L --line-numbers -n
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination   
-Z ou --zero: Está ação zera os contadores do nosso controle do firewall

Vamos listar as nossas regras no firewall

iptables -L -v
Chain INPUT (policy ACCEPT 4030 packets, 5678K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 3037 packets, 858K bytes)
 pkts bytes target     prot opt in     out     source               destination   

Como pode ser notado temos alguns contadores em nosso firewall que são os pacotes aceitos e a quantidade em bytes então podemos zerar esses contadores da seguinte forma

iptables -Z

Agora vamos listar as regras novamente

iptables -L -v
Chain INPUT (policy ACCEPT 2 packets, 298 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination   

Como pode ser notado os contadores já mudaram de valores porem entre o tempo de eu limpar as regras e listar novamente já tinham passado 2 pacotes pelo meu firewall.

Temos ainda a opção de limpar somente uma chain, vamos limpar somente a chain de OUTPUT como exemplo.

iptables -Z OUTPUT

Agora vamos listar as regras novamente

iptables -L -v
Chain INPUT (policy ACCEPT 11 packets, 834 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1 packets, 52 bytes)
 pkts bytes target     prot opt in     out     source               destination 

Como pode ser notado a chain de INPUT está com um valor bem maior do que o da chain OUTPUT que acabamos de limpar.

Agora se quisermos zerar todos os contadores da tabela nat, podemos fazer da seguinte forma.

iptables -t nat -Z
-N ou --new-chain: Está ação cria uma nova chain personalizada

Vamos criar como exemplo chain internet que vai servir para cadastrarmodetonautass os usuários com acesso a internet sem passar por proxy

iptables -N internet

Como já explicado anteriormente se não especificarmos uma tabela o iptables assume por padrão a tabela filter, vamos ver um exemplo especificando a tabela aonde desejamos criar a chain.

iptables -t filter -N internet

Até o momento nos somente trabalhamos com a chain INPUT que controla o fluxo de entrada.

Agora criamos a chain internet aonde vamos cadastrar os ips dos cliente que vão sair para a internet sem utilizar o proxy, mais como que funciona essa chain ? Nós cadastramos o que precisamos nela depois inserimos ela em alguma chain padrão por exemplo a chain INPUT.

Vamos cadastrar um cliente na nossa nova chain

iptables -A internet -s 10.0.0.20 -j ACCEPT

O primeiro passo já está ok, inserimos alguns dados em nossa nova chain e agora ? Agora precisamos fazer uma chamada para essa chain na chain INPUT

iptables -A INPUT -j internet 

Agora vamos listar as nossas regras

iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    internet   all  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain internet (1 references)
num  target     prot opt source               destination         
1    ACCEPT     all  --  10.0.0.20            0.0.0.0/0   

Note o nosso fluxo agora a primeira regra da chain INPUT é direcionada para a nossa chain internet então, vai ser executado tudo que estiver na chain internet e depois vai ser retornado para a 2ª regra da chain INPUT.

Agora pense que foi pedido para inserir mais uma maquina na regra de não passar pelo proxy o que precisamos fazer então é o seguinte

iptables -A internet -s 10.0.0.21 -j ACCEPT

Agora vamos listar as regras novamente

iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    internet   all  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain internet (1 references)
num  target     prot opt source               destination         
1    ACCEPT     all  --  10.0.0.20            0.0.0.0/0           
2    ACCEPT     all  --  10.0.0.21            0.0.0.0/0   

Com isso o firewall vai ler a chain INPUT e vai notar que a primeira regra é ir para a chain internet dai na chain internet executar o que estiver lá depois voltar para a regra número 2 na chain INPUT e continuar o seu fluxo.

-E ou --rename-chain: Está ação renomeia uma chain

Vamos renomear a nossa chain internet para sem-proxy

iptables -E internet sem-proxy

Agora vamos listar novamente as nossas regras

iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    sem-proxy  all  --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain sem-proxy (1 references)
num  target     prot opt source               destination         
1    ACCEPT     all  --  10.0.0.20            0.0.0.0/0           
2    ACCEPT     all  --  10.0.0.21            0.0.0.0/0  

Note que o iptables já mudou em nossa chain INPUT a chamada da chain internet para sem-proxy

-X ou --delete-chain: Está ação deleta uma chain

Para podemos deletar uma chain precisamos primeiro limpar a referência dela e depois excluir

iptables -D INPUT  1

Agora vamos excluir a chain

iptables -X sem-proxy
-P ou --policy: Está ação cria uma politica default

A politica default serve para quando um pacote não entra em nenhuma regra pré-definida no controle do firewall, ela siga está politica, por exemplo temos um acesso na porta 143, porém não temos nenhuma regra liberando ou bloqueando este acesso com isso se tivermos uma política default, ela que vai ser executada no caso de não termos uma regra padrão para o pacote.

Vamos ver como podemos definir uma politica de bloqueio para qualquer pacote que não contenha uma regra na chain INPUT.

iptables -P INPUT DROP

Neste caso todos os pacotes que não tiverem regras pré-definidas vão ser bloqueados.

Vamos ver agora um exemplo de uma politica de ACCEPT que vai aceitar um pacote caso ele não tenha uma regra pré-definida.

iptables -P INPUT ACCEPT

Neste caso caso o pacote não caia em nenhuma regra ele vai ser liberado no firewall, cuidado com este tipo de politica.

-v ou --verbose: Está opção mostra o modo detalhado é usada principalmente com a opção -L ou --list

Vamos a um exemplo da opção -v

iptables -t filter -L -v
Chain INPUT (policy ACCEPT 53295 packets, 125M bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 42001 packets, 6130K bytes)
 pkts bytes target     prot opt in     out     source               destination   

Agora vamos ver um exemplo de listagem de regras sem o -v, para notarmos a diferença.

iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 
-x ou --xact: Trabalha em conjunto com o -v porém nos mostra as informações de contadores em formato de bytes

Vamos a um exemplo desta opção

iptables -t filter -L -v -x
Chain INPUT (policy ACCEPT 58750 packets, 134020765 bytes)
    pkts      bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 46828 packets, 6913584 bytes)
    pkts      bytes target     prot opt in     out     source               destination 

-n ou --numeric: Está opção nos mostra informações em formato numérico ao invéz de resolver via DNS

Vamos ver um exemplo do uso do -n, vamos criar uma regra e depois listar sem o -n e depois com o -n

iptables -A FORWARD -p tcp -m multiport --dports 22,25,110,143,443,993,995 -s www.terra.com.br -j ACCEPT

Vamos listar a regra

iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  www.terra.com.br     anywhere            multiport dports ssh,smtp,pop3,imap2,https,imaps,pop3s 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination     

Como pode ser notado sem passarmos a opção -n os valores são mapeados para nomes, agora vamos utilizar a opção -n na listagem das regras

iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  200.154.56.80        0.0.0.0/0           multiport dports 22,25,110,143,443,993,995 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

Em um firewall com muitas regras aconselho a sempre usar a opção -n pois economizamos tempo nas listagens.

--line-number: Está opção mostra o número das regras

Vamos ver um exemplo de listagem de regras.

iptables -L --line-number
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     tcp  --  www.terra.com.br     anywhere            multiport dports ssh,smtp,pop3,imap2,https,imaps,pop3s 

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination  

Como pode ser notado na chain FORWARD temos somente uma regra e na primeira coluna da esquerda temos o número 1 que é o numero desta regra.

-m ou --modprobe: Está opção carrega um modulo do iptables

Vamos ver um exemplo de uso dessa opção, aqui vamos carregar o módulo de multiport do iptables que nos possibilita utilizar mais de uma porta na mesma regra.

iptables -t filter -A INPUT -p tcp -m multiport --dport 80,23 -j ACCEPT
-p ou --protocol: Este parâmetro informa o protocolo utilizado na regra

Vamos a um exemplo de uso deste parâmetro.

iptables -t filter -A INPUT -p tcp -j ACCEPT 

No exemplo acima informamos para o iptables que o protoloco utilizado na regra vai ser o tcp.

-s ou --src ou --source: Este parâmetro indica a origem dos pacotes

Vamos a um exemplo deste parâmetro,

iptables -t filter -A INPUT -p tcp -s 10.0.0.0/24 -j ACCEPT

Acima informamos ao iptables que a regra vai se aplica a origem 10.0.0.0/24

-d ou --dst ou --destination: Este parâmetro indica o destino do pacote

Vamos a um exemplo do uso do parâmetro -d

iptables -t filter -A INPUT -p tcp -d 10.0.0.0/24 -j ACCEPT 

No exemplo acima informamos ao iptables que esta regra se aplica ao destino 10.0.0.0/24

-i ou --in-interface: Este parâmetro especifica a interface de entrada de um pacote

Vamos a um exemplo do uso deste parâmetro.

iptables -t filter -A INPUT -p tcp -i eth0 -j ACCEPT 

No exemplo acima informamos ao iptables que esta regra se aplica a interface de entrada eth0

-o ou --out-interface: Este parâmetro especifica a interface de saída de um pacote

Vamos a um exemplo do uso deste parâmetro

iptables -t filter -A INPUT -p tcp -o eth0 -j ACCEPT

No exemplo acima informamos que esta regra se aplica a interface de saída eth0

-j ou --jump: Este parâmetro determina qual ação vai ser tomada por uma regra

Vamos a um exemplo do uso deste parâmetro

iptables -t filter -A INPUT -p tcp --dport 22 -j DROP

No exemplo acima informamos ao iptables que a ação a ser tomada é dropar(Bloquear) os pacotes para a porta 22

ACCEPT: Está ação permite a passagem de pacotes

Vamos a um exemplo desta ação

iptables -t filter -A INPUT -p tcp -j ACCEPT 

Na regra acima passamos ao iptables para ele aceitar pacotes do protocolo tcp

DROP: Está ação bloqueia a passagem de pacotes

Esta ação bloqueia a passagem de pacotes.

Vamos a um exemplo desta ação:

iptables -t filter -A INPUT -p tcp -j DROP 

Na regra acima, passamos ao IPtables para ele bloquear pacotes do protocolo TCP.

REJECT

Esta ação é similar ao DROP, porém, retorna um erro ICMP (o padrão é: port-unreachable).

Vamos a dois exemplos do uso desta ação:

iptables -t filter -A INPUT -p tcp -j REJECT 

Na regra acima, passamos ao IPtables para dropar pacotes, porém, retornar o port-unreachable.

iptables -t filter -A INPUT -p tcp -j REJECT reject-with tcp-reject 

Na regra acima, passamos ao IPtables para dropar o pacote e retornar uma mensagem TCP RST.

RETURN

Esta ação retorna o processo para chain anterior.

Vamos ver um exemplo do uso desta ação:

iptables -A INPUT -j ACCEPT
iptables -A INPUT -s host.com.br -d localhost -j RETURN
iptables -A INPUT -d localhost -j DROP 

Na regra acima, o pacote vai passar pela primeira regra e chegar à segunda, onde existe o alvo RETURN, então, retornará para a primeira regra onde será aceita.

LOG

Esta ação é utilizada para registrar eventos de log.

Vamos ver um exemplo desta opção:

iptables -t filter -A INPUT -j LOG 

Na regra acima, o IPtables irá gerar log de todas as entradas na chain de INPUT, as mensagens são logadas no arquivo /var/log/messages por padrão, com prioridade de WARN.

Podemos também utilizar a opção de descrição para os logs como exemplo:

iptables -t filter -A INPUT -p tcp --dport 22 -j LOG --log-prefix "ACESSO SSH " 

Na regra acima, nós mandamos o IPtables gerar logs de acesso à porta 22 e colocar a descrição de ACESSO SSH nos arquivos de logs.

Outra opção interessante é que podemos manipular o nível da mensagem que são os níveis do syslog. Podemos utilizar esta opção da seguinte forma:

iptables -t filter -A INPUT -p tcp --dport 22 -j LOG --log-level crit 

Também podemos combinar as opções de log, como exemplo:

iptables -t filter -A INPUT -p tcp --dport 22 -j LOG --log-prefix "ACESSO SSH " --log-level crit 

Obs.: Temos que, primeiro gerar o log, para depois liberar ou bloquear o acesso a uma determinada regra como o exemplo abaixo, vamos logar o acesso do SSH e liberar ele:

iptables -t filter -A INPUT -p tcp --dport 22 -j LOG --log-prefix "ACESSO SSH " --log-level crit
iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT 

Um outro parâmetro que vou passar, que acho muito interessante, é o de comentário nas regras do IPtables. Vamos a um exemplo de uma regra sem comentário:

iptables -t filter -A FORWARD -p tcp --dport 22 -s 172.17.0.250 -j ACCEPT 

Agora vamos listar a nossa regra:

iptables -L -n -v
Chain INPUT (policy ACCEPT 111 packets, 465K bytes)
 pkts bytes target     prot opt in     out     source       destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source       destination
    0     0 ACCEPT     tcp  --  *      *       172.17.0.250 0.0.0.0/0     tcp dpt:22

Chain OUTPUT (policy ACCEPT 98 packets, 5096 bytes)
 pkts bytes target     prot opt in     out     source       destination

Como pode ser notado, temos a nossa regra. Porém, se eu estiver em algum cliente com muitas máquinas, como eu vou me lembrar de quem é a máquina 172.17.0.250? Com isso, vamos utilizar a opção de comentário na regra. Limpe a sua regra e vamos criar ela novamente agora com comentário:

iptables -t filter -A FORWARD -p tcp --dport 22 -s 172.17.0.250 -j ACCEPT -m comment --comment "maquina do Diretor" 

Agora vamos listar as nossas regras novamente:

iptables -L -n -v
Chain INPUT (policy ACCEPT 66 packets, 266K bytes)
 pkts bytes target     prot opt in     out     source       destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source       destination
    0     0 ACCEPT     tcp  --  *      *       172.17.0.250 0.0.0.0/0    tcp dpt:22 /* maquina do Diretor */

Chain OUTPUT (policy ACCEPT 59 packets, 3068 bytes)
 pkts bytes target     prot opt in     out     source       destination

Como pode ser notado, depois do número da porta, temos o comentário para a regra. Com isso facilita muito a vida em uma listagem de regras. Mas comente apenas regras importantes para a sua listagem não ficar muito suja.

Tabela filter

Na tabela filter (tabela-padrão do netfilter), temos as chains INPUT, OUTPUT e FORWARD.

O início: Geralmente iniciamos com a criação de uma política-padrão de acesso, que na maioria dos casos, é negar, como o exemplo abaixo:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP 

Estas regras irão bloquear qualquer pacote que tente acessar, passar ou sair pelo nosso firewall. Neste momento você não conseguirá fazer nada.

Revisão:

  • INPUT: Controla a entrada em nosso firewall, ou seja, o acesso no firewall;
  • OUTPUT: Controla a saída em nosso firewall, ou seja, o acesso efetuado pelo nosso firewall;
  • FORWARD: Controla o acesso que passa pelo nosso firewall com direção a uma máquina ou rede, não sendo o firewall.

Vamos agora começar a liberar acesso necessário em nosso firewall.

Vamos liberar conexões provindas da rede 10.0.0.0/24:

iptables -A INPUT -s 10.0.0.0/24 -j ACCEPT 

Agora vamos rejeitar os pacotes, saindo do nosso kernel com o destino ao IP 200.154.56.80 (www.terra.com.br) com a opção: icmp-host-unreachable

Porém, antes de rejeitar, vamos logar toda a passagem:

iptables -A OUTPUT -d 200.154.56.80 -j LOG --log-prefix "ACESSO AO TERRA " --log-level warn
iptables -A OUTPUT -d 200.154.56.80 -j REJECT --reject-with icmp-host-unreachable 

Agora vamos fazer um teste, vamos pingar neste IP:

ping 200.154.56.80 -c 3
PING 200.154.56.80 (200.154.56.80) 56(84) bytes of data.
From 10.0.0.20 icmp_seq=1 Destination Host Unreachable
From 10.0.0.20 icmp_seq=1 Destination Host Unreachable
From 10.0.0.20 icmp_seq=1 Destination Host Unreachable --- 200.154.56.80 ping statistics ---
0 packets transmitted, 0 received, +3 errors 

Como pode ser notado, a nossa regra funcionou corretamente.

Usaremos agora uma interface específica para assegurar que todos os pacotes provindos da minha rede 192.168.0.0 possam entrar, passar e sair pelo firewall através da interface eth0:

iptables -A INPUT -s 192.168.0.0/24 -i eth0 -j ACCEPT
iptables -A FORWARD -d 192.168.0.0/24 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/24 -o eth0 -j ACCEPT 

Como pode ser notado, é isso que vamos ter que ir fazendo para o que necessitar de acesso, vamos ver mais opções logo abaixo.

Parâmetros TCP/UDP

Os parâmetros são específicos para o protocolo e são disponíveis apenas quando trabalhamos com pacotes e stream TCP. Para usá-lo, é necessário utilizar os parâmetros “-p” ou “-protocol tcp” ou “udp” junto com o IPtables.

Especificando porta de origem

--sport ou --source-port: Estes parâmetros verificam a porta de origem. 

Eles podem trabalhar com um nome de serviço, como: www, ftp etc. Os nomes dos serviços podem ser consultados em /etc/services.

Pode-se usar um range de portas, por exemplo, da mesma porta 22 até a porta 80 seria algo como 22:80. Da mesma forma, podemos usar a forma de exceção, como por exemplo, todas as portas, menos as inclusas desde 22 a 80. Seria algo com: ! 22:80

iptables -A INPUT -p tcp ! --sport 1024:65535 -j ACCEPT 

Nesta regra, estamos aceitando tudo o que entra de origem qualquer, com portas de origens diferentes de portas altas do TCP, ou seja, quando requisitamos uma conexão a um servidor Web, temos como porta de destino a porta 80.

E com certeza, quando a conexão retornar, terá porta de origem 80 e destino uma porta alta em nosso host, desta forma, não aceitaremos conexões em portas baixas que são usadas para serviços específicos.

Da mesma forma que usamos o TCP, poderemos utilizar o UDP:

iptables -A INPUT -p udp ! --sport 53 -j REJECT 

Especificando porta de destino

--dport ou --destination-port: Estes parâmetros verificam a porta de destino. 

Esta opção verificará o serviço ou porta de destino. Pode ser usada também com a opção de exceção “!”. Outro item de grande importância, é o uso de várias portas com o caractere “:“.

Se omitirmos um dos lados, o IPtables assumirá automaticamente um valor de início ou fim. Por exemplo, :80 significa o início e portas 0 até 80, ou ainda 80:, significa início porta 80 até 65535.

iptables -A INPUT ! -s 192.168.0.0/24 -p tcp --dport 22 -j REJECT 

Neste exemplo, todo tráfego que não estiver vindo da rede interna com destino ao processo local na porta 22, será rejeitado.

Especificando Flags TCP

tcp-flags mask comp: Esta opção compara as flags do TCP (SYN,ACK,FIN,RST,PSH,URG,ALL,NONE) com as flags marcadas em comp. 

Elas serão comparadas quando as flags de mask estiverem com o estado das flags em comp. As flags inseridas em comp deverão estar ativas no pacote para que coincidam com a regra. Por exemplo, ALL ACK, neste caso ela casará quando a flag ACK estiver setada. A opção ”!” usará exceção para as flags em comp.

Outro detalhe é a separação entre flags que é feita por vírgulas e a separação entre mask e comp é feita através de espaços.

iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN --dport 22 -j DROP 

O pacotes com as flags SYN e ACK serão verificados e se estiverem com a opção de SYN setada e com destino à porta 22 serão descartados. Quando executamos uma solicitação de conexão, mandamos um SYN e o servidor nos responde um SYN/ACK.

No caso anterior, estamos dropando tentativas de conexão na porta 22, pois não enviamos um SYN. Podemos considerar neste caso, um scanner tentando localizar as portas abertas.

Especificando Flags TCP de início de conexão

syn : Esta opção concilia pacotes que tenham no datagrama as flags SYN ligadas e ACK e RST desligadas. Seria um tipo de tcpflags com as seguintes opções: SYN, ACK, RST SYN verificando por solicitação de conexão, também possui a possibilidade de utilizar “!” com exceção.

iptables -A INPUT -i eth0 -p tcp --dport 22 --syn -j LOG 

Nestas regras estaremos logando todas as conexões com flags SYN ligadas, entretanto pela eth0 na porta destino 22.

Especificando Flags TCP através de valores

tcp-option número: Compara se a opção está ligada. 

Onde as opções são:

  • CWR:128
  • ECE:64
  • URG:32
  • ACK:16
  • PSH:8
  • RST:4
  • SYN:2
  • FIN:1

Com certeza você está se perguntando o que é essa tal de CWR e ECE. Simples, a CWR (Congestion Windows Reduced) é uma janela de congestionamento reduzida, e a ECE (Explicit Congestion Notification Echo) é uma mensagem de notificação de congestionamento explícita.

Vamos a um exemplo de uso:

iptables -A INPUT -p tcp ! --tcp-option 2 -j REJECT --reject-with tcp-reset 

Nesta regra estamos verificando o tráfego de entrada com a flag diferente de dois (SYN) e rejeitando com o item de tcp-reset, ou um pacote RST. Normalmente, encontramos muitos firewalls com o uso desta opção, mas explicitamente rejeitando pacotes com as flags 64 e 128 habilitadas.

Parâmetros ICMP

Temos um parâmetro para o ICMP, este parâmetro é usado com a opção “-p” ou "--protocol", seguida do tipo de ICMP.

--protocol icmp --icmp-type: Esta opção serve para especificarmos o tipo de ICMP. 

Os tipos de ICMP pode ser consultados em: http://support.microsoft.com/kb/170292/pt-br

Podemos utilizar o ICMP pelo nome ou pelo número que corresponde a determinado tipo.

Note que os pacotes ICMP são reclassificados dentro de sua tabela, por exemplo, “destination-unreachable” (destino inalcançável), que é um tipo de classificação e dentro desta classificação, temos tipos específicos como host-unreachable e network-unreachable.

A classe destino inalcançável tem um valor específico, neste caso 3, e os tipos internos têm outra classificação interna (código). Nos outros dois casos, seriam 0 e 1.

Para ficar mais claro, veja da seguinte forma: o host-unreachable e network-unreachable são do tipo destination-unreachable. Posso fazer referência a ambos informando no IPtables o tipo 3, ele casará com todos os códigos de 0 a 15.

Não há problema algum usar desta forma, aliás, na prática, sempre usamos assim. Caso deseje especificar apenas um código e não o tipo inteiro, basta mencioná-lo diretamente após “icmp-type”, por exemplo, network-unreachable ou 3/0.

Vamos a um exemplo:

iptables -A INPUT -p icmp --icmp-type 8 -j DROP
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP 

Nos dois exemplos citados estamos dropando todos os pacotes ICMP do tipo 8 (ping) enviados ao nosso firewall, e como foi visto podemos utilizar o 8 ou echo-request.

Veremos alguns exemplos do uso de regras de firewall do IPtables na tabela filter para permitir o acesso a serviços externos, ou até permitir serviços que respondem no firewall, embora não seja recomendado termos serviços no próprio firewall.

Permitindo que o firewall acesse o DNS

Neste caso, vamos supor que nossa interface de rede para Internet seja a eth0, e que o nosso firewall poderá fazer requisições para um DNS qualquer.

Note que poderíamos ser mais específicos e detalhar qual seria o DNS permitido. Outro item importante é pensarmos que quando fazemos uma conexão, temos a ida e volta, então devemos liberar o INPUT e o OUTPUT.

Vamos à regra:

iptables -A INPUT -i eth0 -p udp --sport 53 --dport 1024:65535 -j ACCEPT
iptables -A OUTPUT -o eth0 -p udp --dport 53 --sport 1024: -j ACCEPT 

Recorde-se que se informarmos 1024:65535, é o mesmo que “1024:”, pois estamos especificando onde começa a porta de destino, sendo que se depois dos “:” não informarmos nada, ele vai até a última porta, ou seja 65535.

Permitindo WWW e SSH no firewall

Esta regra permite o acesso ao servidor web e SSH que se encontra no próprio firewall. Utilizaremos um módulo que verificará o estado da conexão. Não se preocupe com este item específico, pois será visto adiante.

Esta primeira regra permitirá conexões de saída que já foram estabelecidas anteriormente, ou seja, já tenha relação com conexões existentes. Normalmente vinculadas à alguma regra de entrada, utilizada no INPUT.

Um exemplo interessante:

  • Criarmos uma regra de entrada para conexões SSH;
  • Deveremos criar uma regra de saída também para conexão SSH;
  • Criamos uma regra de entrada para conexões em um servidor web (www);
  • Deveremos criar uma regra de saída também para conexões em um servidor web (www).

Agora, utilizando-se do “--state“:

  • Criamos uma regra de entrada para conexões SSH;
  • Criamos uma regra de entrada para conexões em um servidor web (www);
  • Criamos uma regra de saída baseada em conexões de entradas que foram permitidas, ou seja, existe uma conexão de entrada, então haverá permissão para saída através do módulo state.

Vamos à regra de saída do firewall (logo abaixo vou explicar as regras):

iptables -A OUTPUT -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT 

Agora, liberamos as portas 80 (HTTP) e 22 (SSH), desde que o estado seja uma nova conexão:

iptables -A INPUT -p tcp -i eth0 --dport 22 --sport 1024: -m state NEW -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 --sport 1024: -m state NEW -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -i eth0 -p tcp -j ACCEPT 

Explicação: Quando estabelece uma comunicação, o estado da conexão poderá ser NEW (novo), ESTABLISHED (uma conexão já estabelecida) ou RELATED (tem relação com uma conexão nova ou estabelecida).

Nesta regra, estamos utilizando este mesmo esquema para permitir pacotes que já tenham uma conexão preestabelecida ou tenha relação como uma conexão nova efetuada anteriormente. Mas não permitiremos uma nova conexão, que seria o estado de NEW. E ainda especificamos que sejam pacotes chegando na interface eth0.

Regra por tempo

Vamos a um exemplo de uma regra de IPtables controlada por tempo:

iptables -A INPUT -p tcp --dport 22 -m time --datestart 2012-01-16T16:00 --datestop 2012-01-16T23:59:59 -j ACCEPT 

Aqui estou deixando passar o tráfego na porta 22 no intervalo de tempo de 16/01/2012-12:00 até 16/01/2012-23:59:59.

Permitindo acesso ao firewall da rede interna

Nesta regra estaremos liberando qualquer protocolo e porta para nossa rede interna. Note que não é necessário especificar porta e protocolo, conforme o exemplo:

iptables -A INPUT -p all -s 192.168.1.0/24 -i eth1 -j ACCEPT
iptables -A OUTPUT -p all -d 192.168.1.0/24 -o eth1 -j ACCEPT 

Esta regra funcionaria também da seguinte forma:

iptables -A INPUT -j ACCEPT -s 192.168.1.0/24 -i eth1
iptables -A OUTPUT -j ACCEPT -d 192.168.1.0/24 -o eth1 

Bloqueando ping

Bloquearemos os pings oriundos de qualquer lugar, mas ainda podemos fazer isso através do sistema proc em /proc, mas neste momento usaremos as regras de IPtables:

iptables -A FORWARD -p icmp --icmp-type echo-request -j DROP 

Poderíamos fazer uma regra de firewall, onde bloqueamos os pings com exceção da rede interna:

iptables -A FORWARD ! -s 192.168.0.0/24 -p icmp --icmp-type echo-request -j DROP 

No exemplo acima, queremos bloquear o ping (icmp - echo request), menos de nossa rede interna.

Mas não criamos regras para permitir que o nosso servidor consiga pingar ou responder pings, de forma que até o próprio firewall não conseguiria utilizar o protocolo ICMP para pingar outros hosts.

A seguir, um modelo de script que poderia funcionar:

iptables -A INPUT -s 192.168.0.0/24 -p icmp --icmp-type echo-request -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/24 -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A FORWARD -s 192.168.0.0/24 -p icmp --icmp-type echo-request -j ACCEPT 

No exemplo acima, liberamos o firewall responder a requisições de ping, o firewall pode também solicitar requisições de ping, e pode efetuar o repasse de requisições de ping para a sua rede.

O que é NAT

O NAT (Network Address Translation) é o responsável por traduzir endereços para que as redes distintas consigam se comunicar, ou seja, é responsável pela comunicação dos hosts de uma empresa com o mundo, a Internet, por exemplo.

Também serve para que o acesso externo chegue a seu servidor Web localizado em sua rede interna, DMZ. Na prática, usamos muito o NAT para mascarar conexões, proxies transparentes, fazer SNAT (NAT Origem) e DNAT (NAT destino), redirecionamentos de portas etc.

Redes Privadas

Antes de começarmos a analisar as regras de NAT, devemos lembrar das nossas redes privadas.

Mas, para quê precisamos relembrar redes privadas?

Como visto anteriormente, uma das funções do NAT é compartilhar a Internet com uma rede privada, desta forma só para relembrar, podemos ver a seguir as redes privadas disponíveis:

  • 10.0.0.0 - 10.255.255.255 ou 10.0.0.0/8 (máscara de rede 255.0.0.0)
  • 172.16.0.0 - 172.31.255.255 ou 172.16.0.0/16 (máscara de rede 255.255.0.0)
  • 192.168.0.0 - 192.168.255.255 ou 192.168.0.0/24 (máscara de rede 255.255.255.0)

As redes privadas não trafegam na Internet. Para isso, precisamos de um dispositivo que atue entre a rede privada e a Internet. Neste momento, entra em cena o nosso roteador GNU/Linux com NAT. A solução com Linux é bem mais econômica do que outras soluções, como usar ferramentas proprietárias ou até hardwares. Assim, torna-se viável o uso do Linux com sistema de NAT.

Como o NAT trabalha ?

O NAT trabalha reescrevendo os IPs de origem ou destino, que atravessam o firewall, então, quando um pacote é encaminhado para um servidor Web, o firewall reescreve o endereço IP de origem para que os pacotes possam chegar até o destino.

E quando este pacotes voltar, ele retornará como sendo endereço de destino, o nosso servidor (não teria como saber para quem realmente é este pacote sem as connection tracks). Como o servidor já tem armazenadas informações sobre esta conexão, então ele reescreve os IPs de destino e os encaminha para quem os solicitou.

O nosso IPtables pode trabalhar em vários cenários diferentes, por exemplo:

  • 1:1 - Um para um → Quando traduzimos um IP privado para um IP público;
  • 1:N - Um para muitos → Quando traduzimos um IP privado por vários IPs públicos, por exemplo, se temos várias conexões com a Internet ou pelo menos mais de uma.
  • N:1 - Muitos para um → Esse é o mais comum, pois temos uma rede privada para um IP público;
  • N:N - Muitos para muitos → neste caso específico, temos mitos IPs privados ou uma rede, onde será traduzido para vários IPs públicos.

Após termos visto todos estes itens, podemos verificar os alvos comuns utilizados na tabela NAT. No NAT trabalhamos com três chains: PREROUTING, POSTROUTING e OUTPUT, e temos também alguns alvos específicos, como: DNAT, SNAT e MASQUERADE.

Utilizando SNAT

O SNAT faz parte da tabela NAT, ele faz a tradução de endereços e altera os endereços de origem (source nat).

Então, o SNAT é responsável por alterar os endereços de uma rede, e enviar para outra rede. Esta tradução poderá ser feita nos cenários que citamos: 1:1, 1:N etc.

Habilitando forwarding no kernel

Um item importantíssimo é habilitar o nosso kernel para permitir o encaminhamento de pacotes (IPv4 forward). Este item pode ser habilitado através da inserção do número 1 dentro do arquivo /proc/sys/net/ipv4/ip_forward.

Podemos usar também o comando:

sysctl -w net.ipv4.ip_forward=1 

É importante atentar que, nas duas situações, as habilitações são perdidas após reiniciarmos as máquinas, desta forma devemos criar um script do tipo:

echo 1 > /proc/sys/net/ipv4/ip_forward

Podemos fazer da seguinte forma também:

systcl -w net.ipv4.ip_forward=1

Também podemos editar o arquivo /etc/sysctl.conf e adicionar a seguinte linha:

net.ipv4.ip_forward=1

Assim não teremos problemas quando houver necessidade de reiniciarmos o GNU/Linux, não perdendo a ativação de encaminhamentos de pacotes.

Compartilhando a Internet para uma máquina

Vamos supor que precisamos dar acesso a um IP na rede privada através da nossa interface de rede com “IP FIXO” público no GNU/Linux.

iptables -t nat -A POSTROUTING -s 192.168.0.4 -d 0/0 -j SNAT --to 200.200.200.1 

Neste exemplo, os pacotes que passarem pelo nosso firewall de origem 192.168.0.4 com destino a qualquer lugar, serão alterados com endereço de origem para 200.200.200.1.

Note que usamos a opção ”-t nat”, que indica que a tabela que será adicionada à regra, será a tabela NAT. Temos que especificar a tabela, pois caso contrário, o IPtables iria inserir na tabela filter, que não possui chain POSTROUTING e geraria um erro.

Compartilhando a Internet para uma rede

Neste exemplo, iremos fazer a alteração do endereço de destino para uma rede inteira:

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to 200.200.200.1 

No exemplo anterior, todos os pacotes com origem na rede privada 192.168.0.0 que irão sair pela interface eth0, terão seus endereços de origem alterados para 200.200.200.1.

Comunicação entre redes privadas

Podemos nos utilizar dessa regra para fazer duas redes distintas privadas comunicarem-se.

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to 10.0.0.1 

A nossa rede inteira 192.168.0.0 poderá comunicar-se com a rede 10.0.0.0 através da alteração do endereço de origem para 10.0.0.1.

Usando SNAT para um range de IPs

Podemos utilizar o esquema N:N, ou seja, vários IPs para vários IPs.

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to 10.0.0.1-10.0.0.10 

Os pacotes de origem 10.0.0.0/8 terão seus endereços de origem alterados para os endereços entre 10.0.0.1 até 10.0.0.10.

Usando exceções

As exceções também funcionam na tabela NAT. Utilizando normalmente o “!” para fazer uma exceção.

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 ! -d 192.168.0.0/24 -j SNAT --to 200.200.200.1 

Neste exemplo, estamos utilizando o sinal “!”. Seu significado quer dizer “diferente de”, por exemplo, 192.168.0.1 significa todos menos o endereço 192.168.0.1.

A regra anterior especifica que os pacotes com origem da rede 192.168.0.0/24, e destino, que não seja ela mesma (diferente de 192.168.0.0/24), especificado através do item “! -d 192.168.0.0/24”, terão a origem alterada para 200.200.200.1 (utilizando-se da tabela NAT).

Esta alteração de endereço de 192.168.0.0/24 para 200.200.0.1 é necessária, pois endereços desse tipo não podem acessar a rede pública da Internet.

Utilizando MASQUERADING

Agora você deve estar se perguntando: se meu IP é dinâmico, com conexões ADSL que trabalham com PPPoE, ou o próprio PPP, como eu vou fazer um SNAT, já que tenho que especificar o IP?

Neste caso, podemos utilizar o masquerading para mascarar nossas conexões.

O masquerading é como um SNAT, compartilha a Internet, mas é usado para casos de IP dinâmico, como conexões PPP, PPPoE, entre outras. No caso do SNAT, atua com a chain POSTROUTING. Da mesma forma que no SNAT, é necessário habilitar o encaminhamento de pacotes através da alteração do arquivo “ip_forward”, ou utilizando a configuração do arquivo /etc/sysctl.conf.

Usando como alvo o MASQUERADE:

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE 

Estamos mascarando toda a rede 192.168.0.0 que sai pela interface de saída (notem o -o) ppp0. Com isso, todas as nossas máquinas internas vão conseguir usar a conexão PPP, no caso de precisarem utilizar a internet. Ainda sim, poderíamos permitir apenas alguns IPs ou protocolos específicos.

iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -p tcp --dport 53 -j MASQUERADE 

O exemplo acima segue o mesmo conceito dos itens vistos anteriormente, ou seja, haverá um NAT. Mas neste exemplo, só permitiremos o NAT quando a porta TCP for específica, neste exemplo a porta 53 está relacionada a DNS.

Utilizando DNAT

O DNAT, similar ao SNAT, é responsável por trocar os endereços de destino dos pacotes (destination nat). É muito usado para acesso à aplicações internas ou até balanceamento de carga de servidores.

Normalmente as solicitações têm origem de um meio externo (IP público) para o firewall, então o firewall, antes de rotear para o destino final, altera as informações de destino. Todas as informações do SNAT são válidas para o DNAT, como portas, endereços de origem e destino, protocolos, interfaces etc.

Mas a chain utilizada pelo DNAT é do pré-roteamento, ou seja, PREROUTING. Lembre-se de que o roteamento ocorre em dois momentos destintos: Quando os pacotes estão entrando no firewall; E quando estão saindo do firewall.

Então, se estamos utilizando SNAT e MASQUERADE, usamos POSTROUTING. No caso do DNAT, utilizamos PREROUTING.

Usando DNAT para um único servidor

Todas as solicitações de conexões providas da Internet em nosso roteador serão encaminhadas para um IP específico, indiferente do tipo de protocolo ou serviço (porta).

iptables -t nat -A PREROUTING -s 200.200.200.1 -i eth1 -j DNAT --to 192.168.10.1 

Quando os pacotes chegarem de 200.200.200.1 pela interface de entrada eth1, todos eles serão enviados para 192.168.10.1.

Fazendo DNAT para um web server

Quando utilizamos o DNAT, podemos utilizar para uma porta específica, por exemplo, um servidor web:

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 192.168.10.1 

Fazendo DNAT para um terminal service

Para fazermos DNAT para um terminal service, é necessário especificarmos a porta 3389:

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 3389 -j DNAT --to 192.168.10.2 

Como podemos verificar, existem duas regras de DNAT:

  • Encaminhando solicitações HTTP para o servidor 192.168.10.1;
  • Encaminhando pacotes para um servidor terminal service.

Isso é interessante, pois os usuários solicitantes da conexão só terão acesso ao serviço específico, não podendo explorar falhas de outros serviços, tais como banco de dados, SSH, telnet, e-mail etc.

Utilizando REDIRECT

O alvo REDIRECT é usado para redirecionar pacotes em uma mesma máquina. Muito utilizado no redirecionamento de pacotes com destino à porta 80, quando temos um proxy (o Squid, por exemplo) que utiliza a porta 3128.

Então, redirecionamos todos os pacotes da porta 80 para a porta 3128, e fazemos com isso um proxy transparente, onde os usuários nem imaginam que estão utilizando um proxy, e que tudo que é feito é logado ou bloqueado no próprio proxy.

Os pacotes têm a sua porta destino reescrita para poderem ser encaminhados.

Os alvos do REDIRECT são válidos nas chains de PREROUTING e OUTPUT, e nas chains criadas. Essas chains foram as que o administrador criou.

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3128 

Neste exemplo, estamos redirecionando os pacotes com destino à porta 80 do nosso firewall para a porta 3128, que comumente é do proxy Squid.

Mas não tratamos de onde provêm os pacotes, deixando uma brecha para que todos tenham acesso (até endereços de fora da nossa rede local). Podemos utilizar o esquema de interface, no caso usando a interface de entrada como sendo a da nossa rede local, ou especificando diretamente nossa rede local.

iptables -t nat -A PREROUTING -p tcp -s 192.168.0.0/24 --dport 80 -j REDIRECT --to-port 3128 

Utilizando o NETMAP

Este target é utilizado para mapear uma rede em outra. Por exemplo, temos uma rede 192.168.0.0/24 e queremos que cada IP seja enviado como um SNAT para um IP 192.168.1.0/24, ou ainda IPs públicos.

Quando usaríamos isso?

Podemos ter situações onde estas redes têm que se comunicar, por exemplo, em uma VPN. De um lado 192.168.0 e de outro, 192.168.1.

O uso é bem simples:

iptables -t nat -A PREROUTING -s 192.168.0.0/24 -j NETMAP --to 192.168.1.0/24 

Note que a rede origem e destino tem 254 hosts. Isso ocorre para podermos mapear corretamente, sendo assim, o IP 192.168.0.4 será mapeado para 192.168.1.4.

Espero que esse HOWTO consiga tirar as dúvidas do pessoal que apanha um pouco do IPtables. ;)

Referências