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 o router Linux para:
usar NAT para permitir o acesso à Internet
encaminhar pacotes
apenas permitir o acesso ao porto 80 a partir da rede interna
apenas permitir o acesso à rede interna a partir de ligações NAT previamente estabelecidas- Configurar o dhcpd para:
suportar clientes dinâmicos na rede interna- Suportar IPv6
- Suportar QoS
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:
-A
ou--append
: Este comando acrescenta uma regra ao fim da cadeia de regras.
Exemplo:
$ iptables -A INPUT -s 205.168.0.1 -j ACCEPT
Este comando de exemplo acrescenta uma regra no fim da cadeia de INPUT (filter) para aceitar pacotes vindos do endereço 205.168.0.1.-D
ou--delete
: Este comando apaga uma regra da cadeia, especificando o conteúdo da regra, ou a posição da regra na cadeia. O exemplo seguinte ilustra as duas maneiras:
$ iptables -D INPUT --dport 80 -j DROP
$ iptables -D OUTPUT 3
O primeiro comando apaga a regra do INPUT que especifica que os pacotes para o porto 80 devem ser destruídos. O segundo comando apaga a regra número 3 da cadeia OUTPUT.-P
ou--policy
: Este comando especifica um comportamento por omissão para uma cadeia. Todos os pacotes que não obedeçam a nenhuma regra usam a politica da regra. Exemplo:
$ iptables -P INPUT DROP
Este comando especifica que a acção por omissão para a cadeia INPUT é DROP. Todos os pacotes que não obedeçam a alguma regra são apagados.-F
ou--flush
: Este comando apaga todas a regras numa cadeia, ou em todas as cadeias, se não for especificado nenhum nome de cadeia. Exemplos:
$ iptables -F FORWARD
$ iptables -F-L
or--list
: Lista todas as regras numa cadeia ou tabela. Exemplo:
$ iptables -t nat -L
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:
-i
ou--in-interface
: Permite fazer uma selecção por interface de entrada. Exemplo:
$ iptables -A INPUT -i eth0
Este exemplo selecciona todos os pacotes da interface eth0.
-o
ou--out-interface
: Permite fazer uma selecção por interface de saída. Exemplo:
$ iptables -t nat -A POSTROUTING -o eth0
Este exemplo selecciona todos os pacotes da interface eth0.
-p
ou--protocol
: Permite fazer uma selecção por protocolos. Exemplos de protocolos sãoTCP
,UDP
,ICMP
, lista delimitada por virgulas de combinações destes três protocolos, e ALL (todos). A opção pode ser invertida com !. Exemplos:
$ iptables -A INPUT -p TCP, UDP
$ iptables -A INPUT -p ! ICMP
Nestes exemplos, ambos seleccionam todos os pacotes dos protocolos TCP e UDP.-s
ou--source
: Permite fazer selecção por endereço IP de origem, gama de endereços, podendo ser invertido com !. Por omissão, selecciona todos os endereços IP. Exemplos:
$ iptables -A OUTPUT -s 192.168.1.1 // só 192.168.1.1
$ iptables -A OUTPUT -s 192.168.0.0/24 // de 192.168.0.0 a 192.168.0.255
$ iptables -A OUTPUT -s ! 203.16.1.89 // todos excepto 203.16.1.89-d
ou--destination
: Permite fazer selecção por endereço IP de destino, gama de endereços, podendo ser invertido com !. Por omissão, selecciona todos os endereços IP. Exemplos:.
$ iptables -A INPUT -d 192.168.1.1
$ iptables -A INPUT -d 192.168.0.0/192.168.0.100 // de 192.168.0.0 a 192.168.0.100
$ iptables -A OUTPUT -d ! 203.16.1.89--sport
: Permite fazer selecção por porto de origem, para protocolos TCP e UDP.--dport
: Permite fazer selecção por porto de destino, para protocolos TCP e UDP.-m state -- state X
: Permite fazer selecção por estado de ligação. X pode ser: NEW (origina nova ligação), ESTABLISHED (ligação activa), RELATED (relacionado com ligação existente, e.g. ligação de dados em sessão FTP), INVALID (origina ligação inválida).O campo opcional target especifica a acção a ser executada. Para a tabela filter, as acções incluem:
ACCEPT
: O pacote é aceite - termina a avaliação da cadeia de regras na cadeia. É especificado como-j ACCEPT
.DROP
: O pacote é bloqueado. É especificado como-j DROP
.REJECT
: É semelhante aDROP
, mas envia uma mensagem (ICMP) de erro para o emissor. É especificado como-j REJECT
. Exemplo:
$ iptables -A FORWARD -p TCP --dport 22 -j REJECT
RETURN
: Termina o percorrer da cadeia de regras - é usada a política por omissão. É especificado como-jump RETURN
. Exemplo:
$ iptables -A FORWARD -d 203.16.1.89 -jump RETURN
Para a tabela nat, as acções incluem:
SNAT
: substituir o endereço e porto de origem. Cria uma entrada (com o estado ESTABLISHED) na tabela de ligações activas, disponível em /proc/net/ip_conntrack. É especificado como-j SNAT --to 10.1.50.61
[:port]D
NAT
: substituir o endereço de destino. O pacote é aceite - termina a avaliação da cadeia de regras na cadeia. É especificado como-j DNAT --to 10.1.50.61
[:port]MASQUERADE
: é equivalente a SNAT, mas não é necessário definir o endereço. Substitui pelo endereço da interface de saída, atribuindo um porto externo livre à ligação. É especificado como-j MASQUERADE
. Exemplo:
$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
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
// Definir políticas por omissão
$ iptables -F
$ iptables -P FORWARD ACCEPT
// NAT
$ iptables -P OUTPUT ACCEPT
$ iptables -P INPUT ACCEPT
// Proteger dos ataques externos
$ iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
// Limitar acesso da rede interna a DNS (53, udp), a HTTP
$ iptables -A INPUT -m state --state NEW,INVALID -i eth1 -j DROP
(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)
// Deixar passar os pacotes de resposta a pedidos
$ iptables -I INPUT -p tcp --dport 80 -j RETURN
aos servidores locais
$ iptables -I OUTPUT -m state --state ESTABLISHED,RELATED -o eth1 -j RETURNExistiria 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
// Deixar passar os pacotes de resposta a pedidos
$ iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth1 -j DNAT --to 172.16.33.7:80
aos servidores remotos
$ iptables -I FORWARD -m state --state ESTABLISHED,RELATED -o eth1 -j RETURNPara 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 4Pode 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