Apresentação sobre routers Linux


Índice:

Problema a resolver
Configurar router Linux
Configurar dhcpd
Pequena adenda sobre IPv6
Pequena adenda sobre QoS


Problema:

Configurar um computador Linux com duas placas de rede para funcionar como router, que interliga a rede privada (eth0 172.16.33.0/24) à rede pública (eth1 com endereço dinâmico), e que se protege de ataques exteriores e a partir do interior.

Solução:


Configurar router Linux

Uma máquina Linux funciona como router desde que tenha o reenvio de pacotes activo (ip_forwarding). Esta funcionalidade fica activa cada vez que se cria o ficheiro /proc/sys/net/ipv4/ip_forward com o valor 1. Pode ser feito com o comando:

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

Para se obter um efeito persistente, ter-se-ia de colocar este comando num script de arranque da máquina (e.g. /etc/rc.local). Outra alternativa será modificar o ficheiro de configuração do núcleo Linux, em /etc/sysctl.conf:

net.ipv4.ip_forward = 1

Para o router realizar tradução de endereços é necessário ter o módulo netfilter instalado. Este módulo realiza a filtragem de pacotes, através de várias tabelas e cadeias de processamento. Para a filtragem de pacotes (firewall) é usada a tabela filter, com cadeias relacionadas com a entrada de pacotes (INPUT), com o reenvio de pacotes (FORWARD), com a saída de pacotes (OUTPUT). O suporte de tradução de endereços (NAT) é realizado no envio de pacotes, através da tabela nat, com três cadeias possíveis: antes de consultar a tabela de encaminhamento (PREROUTING),  após o encaminhamento (POSTROUTING), e na fila de output (OUTPUT).  É possível realizar a tradução do endereço/porto de origem (SNAT), para partilhar ligações de rede, ou tradução do endereço/porto de destino (DNAT), para redireccionar um porto do router para uma máquina na rede privada, ou para balancear tráfego entre vários servidores na rede privada. Finalmente, a tabela mangle permite modificar campos dos pacotes IP (e.g. definir classe de serviço DiffServ), incluindo cadeias antes de encaminhamento (PREROUTING) ou na saída da rede (OUTPUT).

As cadeias das três tabelas estão ordenadas segundo a seguinte ordem:

Para resolver o problema proposto vai ser necessário usar regras da tabela de nat e de filter.

A configuração das regras é feita usando o comando iptables.

iptables [-t table] command [match] [target]

O comando pode ter vários valores:

O campo opcional match especifica as características do pacote para obedecer a uma regra (protocolo, endereço IP de destino e origem, porto de origem e destino, etc.). Alguns exemplos são:

O campo opcional target especifica a acção a ser executada. Para a tabela filter, as acções incluem:

Para a tabela nat, as acções incluem:

Existem outras acções como LOG, REDIRECT, MARK, MIRROR etc., que não são relevantes para o problema que se pretende resolver.

Assim, para ligar a rede privada, na interface eth0, à rede pública, na interface eth1, poder-se-ia usar o seguinte conjunto de regras:

// Limpar entradas antigas
$ iptables -t nat -F
$ iptables -F
// Definir políticas por omissão
$ iptables -P FORWARD ACCEPT
$ iptables -P OUTPUT ACCEPT
$ iptables -P INPUT ACCEPT
// NAT
$ iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
// Proteger dos ataques externos
$ iptables -A INPUT -m state --state NEW,INVALID -i eth1 -j DROP
// Limitar acesso da rede interna a DNS (53, udp), a HTTP (80, tcp), a  SSH (22, tcp), a HTTPS (443, tcp), a FTP (21, tcp)
$ iptables -A FORWARD -o eth1 -p tcp --dport 80 -j RETURN

$ iptables -A FORWARD -o eth1 -p tcp --dport 21 -j RETURN
$ iptables -A FORWARD -o eth1 -p tcp --dport 22 -j RETURN
$ iptables -A FORWARD -o eth1 -p tcp --dport 443 -j RETURN
$ iptables -A FORWARD -o eth1 -p udp --dport 53 -j RETURN
$ iptables -A FORWARD -o eth1 -j DROP
// Limitar acesso do computador router a DNS (53, udp), a HTTP (80, tcp), a  SSH (22, tcp), a HTTPS (443, tcp), a FTP (21, tcp)
$ iptables -A OUTPUT -o eth1 -p tcp --dport 80 -j RETURN

$ iptables -A OUTPUT -o eth1 -p tcp --dport 21 -j RETURN
$ iptables -A OUTPUT -o eth1 -p tcp --dport 22 -j RETURN
$ iptables -A OUTPUT -o eth1 -p tcp --dport 443 -j RETURN
$ iptables -A OUTPUT -o eth1 -p udp --dport 53 -j RETURN
$ iptables -A OUTPUT -o eth1 -j DROP

Finalmente, falta guardar a configuração do iptables, para que o sistema arranque configurado.

    /sbin/iptables-save > /etc/sysconfig/iptables

Caso se pretenda tornar públicos serviços no encaminhador (e.g. web), deve-se abrir o conjunto de regras de INPUT e OUTPUT, por forma a deixar entrar pedidos da rede, e passar as respostas:

        // Deixar entrar pedidos da rede externa para o porto 80 (http)
    $ iptables -I INPUT -p tcp --dport 80 -j RETURN
   
// Deixar passar os pacotes de resposta a pedidos aos servidores locais
    $ iptables -I OUTPUT -m state --state ESTABLISHED,RELATED -o eth1 -j RETURN

Existiria ainda a possibilidade de mapear servidores da rede interna em portos do router, usando DNAT.  Neste caso seria necessário definir regras de PREROUTING, para redireccionar o tráfego anteriormente aberto, para outra máquina (e.g. o porto 80 para o porto 80 da máquina 172.16.33.7), e abrir uma regra de FORWARDING para deixar passar as respostas. Observe-se que a máquina remota (e.g. 172.16.33.7) tem de estar configurada com o endereço do router NAT interno par router por omissão, para que o sistema funcione correctamente.

        // Direccionar os pedidos ao porto 80 (http) para o servidor remoto na rede privada
    $ iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j DNAT --to 172.16.33.7:80
   
// Deixar passar os pacotes de resposta a pedidos aos servidores remotos
    $ iptables -I FORWARD -m state --state ESTABLISHED,RELATED -o eth1 -j RETURN

Para configurações mais complexas recomenda-se a leitura da documentação (The netfilter/iptables HOWTO's), ou a utilização de uma configuração genérica configurável, como a proposta em http://www.malibyte.net/iptables/scripts/fwscripts.html


Configurar dhcpd

Para correr o servidor DHCP é necessário ter um pacote dhcp instalado no sistema.

A configuração dos parâmetros  e da gama de endereços distribuídos é realizada no ficheiro /etc/dhcpd.conf. Apresenta-se em seguida um exemplo de configuração para o laboratório 3.3:

    ddns-update-style none;    // Compatibilidade com DNS
    subnet 172.16.33.0 netmask 255.255.255.0 {
        # default gateway
        option routers 172.16.33.3;
        option subnet-mask 255.255.255.0;
        option domain-name-servers 193.136.120.1;
 

        range dynamic-bootp 172.16.33.100 172.16.33.200;
        default-lease-time 21600;
        max-lease-time 43200;

        # Quando se quer ter endereços e nomes fixo
#       host tele33-1 {
#           option host-name "tele33-1";
#           hardware ethernet 12:34:56:78:AB:CD;
#           fixed-address 172.16.33.1;
#       }
    }

Também é necessário configurar o servidor DHCP para apenas funcionar na interface eth0. Essa configuração é realizada no ficheiro /etc/sysconfig/dhcpd. Para distribuições RedHat ou Fedora, o conteúdo do ficheiro será

    DHCPARGS=eth0

Para a distribuição Mandrake, bastará modificar o valor do símbolo INTERFACES neste ficheiro:

    INTERFACES="eth0"

As licenças são guardadas no ficheiro /var/lib/dhcp/dhcpd.leases. Para garantir que este ficheiro existe quando o serviço arranca, pode-se executar o comando touch sobre o ficheiro.

Falta, por fim, activar o serviço DHCP. Pode ser feito com o comando:

    /sbin/service dhcpd start


Pequena adenda sobre IPv6

Também é possível realizar um encaminhador semelhante para IPv6, embora com mais restrições.

Para que uma máquina funcione como encaminhador necessita de reencaminhar pacotes IPv6. É possível obter esta funcionalidade acrescentando a seguinte linha ao ficheiro "/etc/sysconfig/network":

    IP6FORWARDING=yes

Uma maneira simples de ter atribuição dinâmica de endereços dentro da rede interna é activar o servidor radvd.

A configuração é realizada no ficheiro "/etc/radvd.conf". Um exemplo de configuração para um encaminhador com o endereço Interno 2001:0690:2040:a303::5 seria:

interface eth0 { 
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
prefix 2001:0690:2005:a303::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr off;
};
};

A activação é feita de forma semelhante ao dhcpd, excepto que se troca "dhcpd" por "radvd".

Finalmente, a configuração de firewall seria feita utilizando o comando ip6tables. Neste caso existem mais limitações face ao iptables (para IPv4): apenas suporta as tabelas de mangle (manipulação de bits) e filter, não suportando funcionalidades de nat.

Por exemplo, para bloquear todos os pacotes IPv6 vindos da rede externa a configuração seria:

ip6tables -A INPUT -i eth0 -j DROP

Pode-se encontrar mais informações no HowTo de IPv6 sobre Linux, ou na página de manual.

 


Pequena adenda sobre QoS

Utilizando um encaminhador Linux é possível realizar funcionalidades de suavização de tráfego e de reserva de largura de banda. Os fluxos são definidos através do filtro MANGLE, e podem ser identificados automaticamente por filtros de nível 7 ou pelo IP:porto dos feixes. Por omissão, apenas estão disponíveis filtros por ip:porto, mas podem-se acrescentar filtros de nível aplicação, para identificação automática de fluxos (e.g. http://l7-filter.sourceforge.net/).

O modelo de fila de espera mais usado é um balde de testemunhos hierárquico (HTB). Este modelo define a partilha da largura de banda total por vários fluxos organizada em um ou mais níveis hierárquicos. A largura de banda não usada por cada fluxo individual é redistribuída pelos restantes grupos de fluxos dentro de cada hierarquia. No exemplo seguinte, a largura de banda total do Link seria partilhada por cinco classes com os seguintes limites mínimos e máximos. A soma dos limites mínimos é igual à capacidade total da ligação, e define a largura de banda garantida para cada classe. O limite máximo define como é que a largura de banda livre é redistribuída pelas restantes classes.

 

A configuração de suavização de tráfego é realizada utilizando-se o comando "tc". O exemplo anterior poderia ser programado com a seguinte sequência de comandos:

###ROOT###
### // 
Define a largura de banda total de saída
tc qdisc add dev eth0 root handle 1: htb default 50
###HTBs###
### // Define a hierarquia de
suavizadores de tráfego HTB
tc class add dev eth0 parent 1: classid 1:1 htb rate 500kbps ceil 500kbps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 464kbps ceil 500kbps
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 20kbps ceil 20kbps
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 10kbps ceil 500kbps
tc class add dev eth0 parent 1:1 classid 1:40 htb rate 5kbps ceil 500kbps
tc class add dev eth0 parent 1:1 classid 1:50 htb rate 1kbps ceil 500kbps
###QDISCs###
### // Define as filas individuais como SFQ
tc qdisc add dev eth0 parent 1:10 handle 100: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 200: sfq perturb 10
tc qdisc add dev eth0 parent 1:30 handle 300: sfq perturb 10
tc qdisc add dev eth0 parent 1:40 handle 400: sfq perturb 10
tc qdisc add dev eth0 parent 1:50 handle 500: sfq perturb 10
###HANDLEs###
### // Define filtros tc para diferentes flowid
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 1 fw flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 2 fw flowid 1:20
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 3 fw flowid 1:30
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 4 fw flowid 1:40
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 5 fw flowid 1:50
###MARKING###
### // Associa flowid aos vários fluxos através do iptrable
iptables -t mangle -A POSTROUTING -j MARK --set-mark 5
iptables -t mangle -A POSTROUTING -p udp --dport 1234 -j MARK --set-mark 1
iptables -t mangle -A POSTROUTING -m layer7 --l7proto shoutcast -j MARK --set-mark 2
iptables -t mangle -A POSTROUTING -m layer7 --l7proto http -j MARK --set-mark 3
iptables -t mangle -A POSTROUTING -m layer7 --l7proto edonkey -j MARK --set-mark 4

Pode encontrar mais informações na página Linux Advanced Routing & Traffic Control HOWTO, ou na página de manual do comando "tc".


Bibliografia

The netfilter/iptables HOWTO's.  http://www.netfilter.org/documentation/

YoLinux, "Using Linux and iptables or ipchains to set up an internet gateway / firewall / router for home or office". http://www.yolinux.com/TUTORIALS/LinuxTutorialIptablesNetworkGateway.html

IP-Masquerade-HOWTO. http://www.tldp.org/HOWTO/IP-Masquerade-HOWTO/index.html

Masquerading-Simple-HOWTO. http://www.tldp.org/HOWTO/Masquerading-Simple-HOWTO/index.html

Red Hat, "Configuring a DHCP Server". http://www.redhat.com/docs/manuals/linux/RHL-7.3-Manual/custom-guide/s1-dhcp-configuring-server.html

"Linux Advanced Routing & Traffic Control" home page: http://lartc.org/

l7-filter, "Application Layer Packet Classifier for Linux" home page: http://l7-filter.sourceforge.net/


Luís Bernardo
Copyright © 2011 FCT-UNL. All rights reserved.
Last Revision: 21-nov-2017