Skip to main content

212.1 Configurando um Roteador


Introdução


Esse tópico tem como objetivo ensinar um pouco da parte de Roteamento para que possamos criar um Roteador usando o Linux.

Como boa parte do conteúdo teórico é o que cai na LPIC-1, leia o tópico 109.1 para ver sobre Classes de IP e máscaras, leia também o tópico 205.2 para ver como preparar o Ambiente para criar um laboratório para usar o IPTables.


Para os testes vou usar esse Vagrantfile para subir um servidor GW com dois clientes em Redes diferentes, já fazendo o MASQUERADE e o redirecionamento entre interfaces no GW (esse processo já foi descrito no link acima 205.2).

Só para deixar registrado, o forward para IPv6 é: echo 1 > /proc/sys/net/ipv6/conf/all/forward



Introdução ao Iptables


Um Firewall é um dispositivo de Rede que monitora tráfegos que entram e saem da rede (Firewall de Rede) ou que entram e saem da próprio máquina (Firewall de Host), o Firewall vai permite ou bloquear pacotes de dados sempre baseado nas regras que criarmos. O maior propósito do Firewall é criar barreira entre a rede interna e a rede externa ou outras redes internas, tudo para bloquear tráfego malicioso ou negar acessos a outras áreas.


Cada regra do Iptables é realizada numa tabelta específica, isso ajuda a manter a organização das regras criadas, segue as tabelas abaixo:

TabelaDescrição
FilterRegra responsável por determinar tudo o que entra e sai da máquina local (firewall de host);
NATUsado para dados que geram outra conexão, mascarar a internet, redirecionar requisições (firewall de rede);
MangleUsado para alterações especiais de pacote, como marcação para QOS e balanceamento de link.
RAWMarcar pacote para um rastreio, configurar exceções (é a primeira tabela a ser consultada);
SecurityUsado para regras de rede, para controle obrigatório de acesso, específica para integração com o SELinux.

Cada "cadeia" (Chain) é apenas um diretório (fazendo uma analogia), dentro da Chain será criado as regras de Firewall. O IPTABLES possuí algumas Chains default, mas você pode criar suas próprias Chains.


Por exemplo, uma Chain chamada Entrada_Funcional (regras apenas de entrada que estão estabelecidas) ou Gerencia (Rede de gerencia da empresa), dessa forma, você irá sempre saber do que se trata as regras que estão dentro da Chain.

TabelaChains default de cada tabela
FilterINPUT, OUTPUT, FORWARD
NATPREROUTING, POSTROUTING, INPUT, OUTPUT
MangleREROUTING, POSTROUTING, INPUT, OUTPUT, FORWARD
RAWPREROUTING, OUTPUT
SecurityINPUT, OUTPUT, FORWARD

Descrição das Chains

  • Input
    Aqui temos os pacotes destinados ao nosso sistema Linux, após o Kernel fazer um cálculo de roteamento, sempre depois de ter feito o roteamento.

  • OUTPUT
    É reservado para pacotes gerados pelo próprio Linux, ou seja, pacotes que saem da nossa própria máquina.

  • FORWARD
    São os pacotes roteados pelo nosso Linux (ou seja, quando o firewall do Iptables é usado para conectar mais de uma rede).

  • PREROUTING
    É usada para aplicar regras na tabela nat a pacotes que ainda não passaram pelo algoritmo de roteamento no kernel, a fim de determinar a interface na qual eles devem ser transmitidos. Os pacotes processados nesta Chain ainda não foram comparados com as Chain INPUT ou FORWARD na tabela filter.

  • POSTROUTING
    É responsável pelo processamento de pacotes depois que eles passam pelo algoritmo de roteamento no kernel e estão prestes a ser transmitidos na interface física. Os pacotes processados por essa Chain já passaram pelos requisitos das Chains OUTPUT ou FORWARD na tabela filter.


Políticas e Regras

  • ACCEPT
    Aceita os pacotes;

  • DROP
    Barra (Dropa) um pacote silenciosamente;

  • REJECT
    Barra (Dropa) um pacote mas devolve uma mensagem de erro ao remetente;

  • MASQUERADE
    Mascara o pacote (geralmente saindo da rede);

  • LOG
    Cria uma registro de LOG.

  • RETURN
    Parar de analisar as regras dessa "chain" e voltar à próxima regra da "chain" anterior. Geralmente é usada em conjunto com as sub-rotinas de tabela "DNAT" e "SNAT" para implementar uma política de firewall específica.


Opções do Iptables:

OpçãoDescrição
-p (Protocol)(Protocol) Específica o protocolo
-L(list) Lista as regras
-t (table)(Table) Define 1 das 4 tabelas
-P (Chain)(Policy) Define a política da Chain
-S(list-rules) Lista a política de todas as Chains ou uma em específico. Se usado sozinho, sem o -L, lista as regras da mesma forma que criamos elas.
-A(Append) Adiciona a regra no final da lista de regras
-I(Insert) Adiciona a regra no inicio da lista de regras
-d (IP)(Destination) É o destino
-s (IP)(Source) É a origem
--line-numbersAdiciona um número a cada regra de cada Chain
-D (Chain) (Number)(Delete) Deleta uma regra
-R (Chain) (rulenum)(Replace) Altera uma regra já existente
-F(Flush) Deleta todas as regras de uma Chain
-N (Chain)(new) Crie uma nova Chain definida pelo usuário
-n(Numeric) Saída em forma de número de endereços e portas
-i (interface)(in-interface) Interface da qual um pacote foi recebido
-o (interface)(out-interface) Interface da qual um pacote será enviado
--sport (porta)(Source-port) Porta de origem do pacote
--dport (porta)(Destination-port) Porta de destino do pacote
-m (módulo)(Module) Usa um módulo
(Multiport) Podemos colocar várias portas
LOG --log-prefix(LOG) Cria um sistema de log

Observações sobre as opções -i e -o:

-i, --in-interface
Nome da interface em que o pacote entrou, a opção '-i' é utilizada para as Chains
em que o pacote entra, como as Chains: INPUT, FORWARD e PREROUTING.

Quando o cifrão "!" é usado como argumento antes do nome da interface, inverte-se o sentido. Se o nome da interface terminar com o sinal de adição "+", então qualquer interface que comece com esse nome corresponderá.

Se a opção '-i' for omitida, qualquer interface corresponderá.

-o, --out-interface
Nome da interface em que o pacote será enviado, a opção '-o' é utilizada para as Chains
em que o pacote será enviado, como as Chains: FORWARD, OUTPUT e POSTROUTING.

Quando o cifrão "!" é usado como argumento antes do nome da interface, inverte-se o sentido. Se o nome da interface terminar com o sinal de adição "+", então qualquer interface que comece com esse nome corresponderá.

Se a opção '-o' for omitida, qualquer interface corresponderá.

### Resumindo: ###

Usamos as Chains INPUT, FORWARD e PREROUTING quando estivermos usando a opção '-i';
Usamos as Chains FORWARD, OUTPUT e POSTROUTING quando estivermos usando a opção '-o'.


Iptables – Filtros


Vamos analisar a linha iptables -t filter -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT

OpçãoDescrição
iptables -tPrefixo que "sempre será usado";
filter -A INPUTOnde a regra é armazenada, é o local onde o kernel irá verificar a regra (Tabela + Chain);
-s 127.0.0.1 -d 127.0.0.1A regra que será aplicada, nesse caso IP Origem e Destino, pode conter porta, protocolo e etc;
-j ACCEPTA ação que será aplicada, se o pacote será aceito, dropado, rejeitado, direcionado e etc.

As políticas do firewall entra em ação se nenhuma regra der match com o pacote, uma das maneiras mais fáceis de trabalhar com Firewall é bloqueando tudo e permitindo somente o necessário, para isso vamos alterar as políticas das Chains para ver como faz. O padrão sem mudar nada é aceitar tudo, nesse caso, vamos negar tudo e passaremos a liberar somente o necessário.


Para definir uma política como DROP, REJECT ou ACCEPT usamos a opção -P e passamos a Chain com a tabela que queremos mudar a política:

## Vamos definir as políticas da tabela Table como DROP

# Definindo a politica das Chains como DROP na tabela FILTER:
\# iptables -t filter -P INPUT DROP
\# iptables -t filter -P OUTPUT DROP
\# iptables -t filter -P FORWARD DROP

Quando falamos de endereço loopback, o primeiro IP que vem a mente é 127.0.0.1, porém, esse é o endereço IP mais utilizado, a RCF 3330 explica melhor os Blocos de endereços reservados.


IANA.IETF. Disponível em https://tools.ietf.org/html/rfc3330. Acesso em 12 Abril de 2020.

127.0.0.0/8 - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher level protocol to an address anywhere within this block should loop back inside the host. This is ordinarily implemented using only 127.0.0.1/32 for loopback, but no addresses within this block should ever appear on any network anywhere [RFC1700, page 5].

127.0.0.0/8 - Este bloco é atribuído para uso como endereço de host loopback da Internet. Um datagrama enviado por um protocolo de nível superior para um endereço em qualquer local dentro desse bloco deve ser retornado no host. Isso geralmente é implementado usando apenas 127.0.0.1/32 para loopback, mas nenhum endereço dentro desse bloco deve aparecer em nenhuma rede em qualquer lugar [RFC1700, página 5].

Dessa forma, para que no futuro possa utilizar esse bloco sem preocupações, vamos liberar o acesso a toda rede 128.0.0.0/8.

### Criando regras detalhadas ###
# Liberando os pacotes que entram:
\# iptables -t filter -A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT

# Liberando os pacotes que saem:
\# iptables -t filter -A OUTPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -j ACCEPT


### Criando uma regras mais simples ###
# Liberando os pacotes que entram:
\# iptables -t filter -A INPUT -i lo -j ACCEPT

# Liberando os pacotes que saem:
\# iptables -t filter -A OUTPUT -o lo -j ACCEPT

As portas são usadas na comunicação entre cliente e servidor, as portes usadas no servidor são portas fixas, que não mudam constantemente ou não mudam nunca dependendo da aplicação, por exemplo, um servidor web sempre vai rodar em 2 portas (80 e 443), existem casos onde isso muda, mas para um webserver da internet não vai, se não todos teriam que saber quais portas usar.


Existem aplicações em que podemos mudar as portas com mais facilidades como SSH, proxy etc. Essas portas que muito provavelmente irão rodar em ambiente interno e/ou externo, devem ser modificadas por segurança e como abrangem uma quantidade de pessoas mais limitadas (em comparação com toda a internet) é mais fácil notificar todos que vão usar. As portas variam de acordo com cada range e necessidade, segue algumas abaixo:

PortasTipo de portaDescrição
0-1023ReservadaPortas do sistema ou portas conhecidas (atribuídas pela IANA)
1024-49151LivrePortas de usuário ou portas registradas (atribuídas pela IANA)
49152-65535"Livre"Portas dinâmicas (nunca atribuídas), usadas aleatoriamente em conexão cliente/servidor

As portas podem estar em 3 estados diferentes, são eles:

  • Atribuído: atualmente, os números de porta atribuídos estão atribuídos ao serviço indicado no registro.

  • Não atribuído: atualmente, os números de porta não atribuídos estão disponíveis para atribuição mediante solicitação, conforme os procedimentos descritos neste documento.

  • Reservado: os números de porta reservados não estão disponíveis para atribuição regular; eles são "atribuídos à IANA" para fins especiais.


Quem cuida da atribuição de cada porta e serviço é a IANA, você pode ler a RFC 6335 para entender melhor esse processo ou a RFC1340 onde explica melhor a atribuição de portas.


O Linux tem um arquivo contendo as principais portas e serviços vinculadas a essas portas, o arquivo fica localizado em /etc/services.


Vamos ver como se faz para liberar algumas portas:

## Essas primeiras regras tem como objetivo entrar no firewall.

# vamos liberar tudo que entrar na porta 80 que seja tcp:
\# iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
# Estou aceitando apenas pacotes que tenham como destino a porta 80.

# vamos liberar tudo que entrar na porta 22 que seja tcp:
\# iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT

## As próxima regras tem como objetivo sair do do fw e ir para outro host.
# vamos liberar tudo que sair com destino a porta 80 que seja tcp:
\# iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT

# vamos liberar tudo que sair com destino a porta 22 que seja tcp:
\# iptables -t filter -A OUTPUT -p tcp --dport 22 -j ACCEPT

Com o módulo conntrack conseguimos verificar o estado da conexão, como foi dito em Firewall UTM - Stateful, essa geração já consegue distinguir conexões no firewall, sendo uma nova conexão, uma conexão estabelecida, relacionada entre outros. Existe também o módulo state, que possui algumas opções a menos que o conntrack, por isso não vou abordar ele aqui.

Opções mais usadas:

  • ESTABLISHED

    O pacote pertence a uma conexão já existente. Cria-se uma conexão estabelecida após receber o SYN+ACK, por mais que o cliente ainda não tenha enviado um ACK, nesse momento o servidor já aloca recursos para esse aperto de mão.

  • RELATED

    O pacote tem relação indireta com outro pacote de uma conexão já estabelecida.

  • NEW

    Uma nova conexão, é criado uma nova conexão quando recebemos um pacote SYN.

  • INVALID

    Pacotes que não é de nenhuma conexão acima,

# Existem algumas regras que devam ficar no começo, são duas, liberando loopback
# e essas duas:
\# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
\# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

# Com a 1° regras, vou aceitar todos os pacotes que estiverem entrando e que já estejam estabelecido (O processo de Three-way Handshake já foi feito).
# Isso é bastante útil porque podemos deixar aberto toda a saída e usar essa regra para permitir apenas pacotes que inicialmente foram gerados pela máquina onde o firewall está ativo.

# Exemplo, Com essa regra não preciso permitir pacotes de consulta DNS, DHCP, HTTP, NTP entre outros, porque todos foram gerados pelo firewall, então uma conexão já foi estabelecida.

# A segunda regra não vai permitir pacotes que não se enquadram em NEW, ESTABLISHED e RELATED.


Iptables SNAT e DNAT


Um servidor Linux pode atuar como roteador e firewall, permitindo que os dispositivos de uma rede interna acessem outras redes, como a Internet.


Além de encaminhar os pacotes entre interfaces, ele pode aplicar regras de filtragem, registrar eventos em log, alterar endereços de origem ou destino e realizar redirecionamentos de portas.



NAT


O NAT (Network Address Translation) modifica informações de endereçamento dos pacotes. Dependendo da regra aplicada, ele pode alterar o endereço de origem, o endereço de destino ou até mesmo as portas utilizadas na comunicação.


Em redes IPv4, um uso comum do NAT é permitir que vários dispositivos com endereços privados compartilhem um único endereço IPv4 público. Nesse caso, o sistema também diferencia as conexões pelas portas de origem, comportamento frequentemente chamado de PAT (Port Address Translation).


Rede interna                    Internet

192.168.1.10 ─┐
192.168.1.20 ─┼── Roteador/NAT ── 203.0.113.10
192.168.1.30 ─┘

Dessa forma, vários dispositivos internos podem acessar a Internet utilizando o mesmo endereço público.


Apesar de ter ajudado a prolongar o uso do IPv4, o NAT também quebra o modelo de comunicação fim a fim, dificulta algumas conexões iniciadas externamente e não deve ser considerado um mecanismo de segurança por si só.



Habilitando o encaminhamento IPv4


Antes de encaminhar pacotes entre interfaces, é necessário habilitar o roteamento IPv4 no kernel:

sudo sysctl -w net.ipv4.ip_forward=1

Essa alteração permanece ativa apenas até a próxima reinicialização. Para torná-la persistente, podemos criar um arquivo dentro de /etc/sysctl.d/:

echo 'net.ipv4.ip_forward = 1' |
sudo tee /etc/sysctl.d/99-ip-forward.conf

Aplique a configuração:

sudo sysctl --system

Para consultar o valor atual:

sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

Habilitar o encaminhamento no kernel não libera automaticamente os pacotes. As regras da chain FORWARD também precisam permitir o tráfego.



SNAT


O SNAT (Source Network Address Translation) altera o endereço de origem de um pacote. Ele é normalmente aplicado na chain POSTROUTING da tabela nat, depois que o kernel já decidiu por qual interface o pacote será enviado.

Rede interna

PREROUTING

Decisão de roteamento

FORWARD

POSTROUTING — SNAT

Interface de saída

Exemplo:

sudo iptables -t nat -A POSTROUTING \
-o enp0s3 \
-j SNAT \
--to-source 203.0.113.10

Nesse exemplo, os pacotes enviados pela interface enp0s3 terão o endereço de origem alterado para 203.0.113.10.


Também podemos limitar a regra à rede interna:

sudo iptables -t nat -A POSTROUTING \
-s 192.168.1.0/24 \
-o enp0s3 \
-j SNAT \
--to-source 203.0.113.10

É possível definir um intervalo de endereços:

sudo iptables -t nat -A POSTROUTING \
-s 192.168.1.0/24 \
-o enp0s3 \
-j SNAT \
--to-source 203.0.113.10-203.0.113.20

Para os protocolos TCP e UDP, também podemos definir um intervalo de portas de origem:

sudo iptables -t nat -A POSTROUTING \
-s 192.168.1.0/24 \
-o enp0s3 \
-p tcp \
-j SNAT \
--to-source 203.0.113.10:1024-65535

O SNAT é normalmente utilizado quando o endereço da interface externa é conhecido e permanece estável.



DNAT


O DNAT (Destination Network Address Translation) altera o endereço de destino de um pacote. Para pacotes recebidos pela rede, ele é normalmente aplicado na chain PREROUTING, antes da decisão de roteamento. Isso permite que o kernel tome a decisão de encaminhamento com base no novo endereço de destino.

Pacote externo

PREROUTING — DNAT

Decisão de roteamento

FORWARD

Servidor interno

Um uso comum do DNAT é o redirecionamento de portas, também conhecido como port forwarding.



MASQUERADE


O MASQUERADE é uma forma especializada de SNAT que utiliza automaticamente o endereço IP atual da interface de saída.


Ele é especialmente útil quando o endereço externo é atribuído dinamicamente, como em conexões feitas por DHCP, PPPoE ou redes móveis.

sudo iptables -t nat -A POSTROUTING \
-s 192.168.1.0/24 \
-o enp0s3 \
-j MASQUERADE

Nesse exemplo, os pacotes originados da rede 192.168.1.0/24 e enviados pela interface enp0s3 terão o endereço de origem substituído pelo endereço atual dessa interface.


Para permitir o encaminhamento das conexões, também podemos usar:

sudo iptables -A FORWARD \
-i enp0s8 \
-o enp0s3 \
-s 192.168.1.0/24 \
-m conntrack \
--ctstate NEW,ESTABLISHED,RELATED \
-j ACCEPT

sudo iptables -A FORWARD \
-i enp0s3 \
-o enp0s8 \
-d 192.168.1.0/24 \
-m conntrack \
--ctstate ESTABLISHED,RELATED \
-j ACCEPT

Nesse cenário:

  • enp0s8 é a interface da rede interna;
  • enp0s3 é a interface conectada à Internet.

Embora MASQUERADE também possa funcionar com endereço estático, o SNAT costuma ser mais adequado quando o endereço externo é fixo.



REDIRECT


O alvo REDIRECT é uma forma especializada de DNAT. Ele altera o destino do pacote para o próprio computador que está executando o iptables.


É frequentemente utilizado para encaminhar conexões recebidas para um serviço local, como um proxy transparente.

sudo iptables -t nat -A PREROUTING \
-i enp0s8 \
-p tcp \
--dport 80 \
-j REDIRECT \
--to-ports 4156

Nesse exemplo, conexões TCP destinadas à porta 80 e recebidas pela interface enp0s8 são redirecionadas para a porta local 4156.

A opção correta é --to-ports, no plural.


Para encaminhar conexões externas para um servidor web interno:

sudo iptables -t nat -A PREROUTING \
-i enp0s3 \
-p tcp \
--dport 80 \
-j DNAT \
--to-destination 192.168.5.8:80

sudo iptables -t nat -A PREROUTING \
-i enp0s3 \
-p tcp \
--dport 443 \
-j DNAT \
--to-destination 192.168.5.8:443


Persistência das regras


As regras criadas com iptables permanecem na memória do kernel. Se não forem salvas por algum mecanismo da distribuição, elas serão perdidas após a reinicialização.


O comando iptables-save exibe as regras atuais em um formato que pode ser posteriormente lido pelo iptables-restore.


Para salvar:

sudo iptables-save > /backup/firewall.rules

Para restaurar:

sudo iptables-restore < /backup/firewall.rules

Em distribuições Debian-like, também pode ser utilizado o pacote iptables-persistent:

sudo apt install iptables-persistent

Os arquivos normalmente utilizados são:

/etc/iptables/rules.v4
/etc/iptables/rules.v6

Em distribuições atuais, o comando iptables pode utilizar o backend nftables. Isso pode ser verificado com iptables --version.