4 de setembro de 1998 volume 2, número 7
  Roteando pela Origem com o Linux
 
 
Ivo de Carvalho Peixinho 
<ivocarv@ufba.br>



INTRODUÇÃO
PREPARANDO O AMBIENTE
INSTALANDO
RECOMPILANDO O KERNEL
RECOMPILANDO BINÁRIOS
TESTANDO O SISTEMA
CRIANDO ROTAS PELA ORIGEM
UMA APLICAÇÃO PRÁTICA
CONCLUSÃO
REFERÊNCIAS BIBLIOGRÁFICAS
SITES RELACIONADOS


Atualmente, é comum surgirem situações em que os recursos normais do TCP/IP não são suficientes para resolver certos problemas, tornando-se necessário, muitas vezes, a utilização de recursos extras para que as coisas funcionem a contento.

Este artigo trata de um recurso disponível no sistema operacional Linux que permite que a definição de regras de roteamento baseadas no endereço de origem e de destino, fugindo do padrão TCP/IP, que permite regras baseadas apenas no endereço de destino.


INTRODUÇÃO

Toda rede local, para se comunicar com outras redes, possui um gateway, que geralmente é constituído de um equipamento específico (roteador) ou simplesmente um computador com duas ou mais interfaces de rede. Utilizar um computador com um bom software de rede em certos casos pode ser mais interessante, pois torna-se mais fácil adicionar novos recursos ao mesmo.

O roteador possui uma tabela de rotas que serve para o mesmo decidir o próximo destino de um pacote de rede. No caso do TCP/IP, uma tabela de rotas é algo do tipo (os endereços são todos fictícios):

DESTINO MÁSCARA GATEWAY INTERFACE
192.168.1.0 255.255.255.0 192.168.0.2 Eth0
192.168.2.0 255.255.255.0 192.168.3.1 Eth1
0.0.0.0 0.0.0.0 192.168.0.3 Eth0

Cada endereço IP é dividido em duas partes, uma referente à rede a qual ele pertence, e outra referente ao numero do host (computador) naquela rede. O campo máscara (netmask) é o responsável por essa divisão. O roteador, para saber a rede a qual pertence certo destino, faz uma operação de AND com a máscara, tendo como resultado a rede.

Quando um pacote chega, o roteador examina o campo destino do mesmo, calcula a rede à qual pertence aquele destino, compara com a sua tabela de rotas, e encaminha o mesmo para o gateway correto. Perceba que existe um destino default (0.0.0.0), que será sempre atribuído caso o destino a ser analisado não esteja especificado na tabela.

Todo o roteamento na Internet funciona através do destino do pacote, e isso tem sido bastante eficiente, visto o tamanho atual desta rede. Porém, em alguns casos, precisa-se de algo mais. Os procedimentos que serão abordados neste artigo, propõem a inclusão de um novo campo origem, que serviria para casamentos na tabela, em conjunto com o campo destino. A tabela antiga se torna apenas um caso particular da nova, onde o campo origem contém o valor "0.0.0.0", significando qualquer origem. Sendo assim a tabela anterior ficaria assim:

ORIGEM DESTINO MÁSCARA GATEWAY INTERFACE
0.0.0.0 192.168.1.0 255.255.255.0 192.168.0.2 Eth0
0.0.0.0 192.168.2.0 255.255.255.0 192.168.3.1 Eth1
0.0.0.0 0.0.0.0 0.0.0.0 192.168.0.3 Eth0

Note que a tabela nova ainda tem todos os recursos da anterior, além de poder decidir gateways através da origem do pacote. Tal função pode ajudar a resolver problemas de roteamento em redes muito complexas. No final deste artigo, será descrito um caso real em que se aplica tal método.





PREPARANDO O AMBIENTE

O nosso gateway irá abrigar o sistema operacional Linux. O Linux foi desenvolvido por um estudante da universidade de Helsinki na Finlândia. Ele é bastante utilizado devido à sua estabilidade, pelo fato de sua licença (GPL) permitir que o sistema operacional e seu código fonte sejam distribuídos gratuitamente e também por poder ser alterado, desde que sejam mantidos os respectivos direitos autorais. O Linux é disponibilizado sob a forma de distribuições. Existem diversas distribuições feitas por várias empresas no mundo. Provavelmente, qualquer uma delas serviria para o nosso gateway, porém a distribuição escolhida foi a slackware, versão 3.4.

A distribuição do Linux envolve os programas que acompanham o Linux, e o kernel, que é o núcleo do sistema, onde está o código para o gerenciamento dos processos, sistemas de arquivos, dispositivos, etc. Os kernels são identificados por um número, que representa sua versão. Tal número obedece à seguinte convenção:

  • X.Y.Z

O X representa o nível principal da versão do kernel, ele é modificado apenas quando mudanças muito significativas ocorrem. O Y representa o status do mesmo. Se ele for ímpar, representa um kernel em desenvolvimento, e não deve ser utilizado em situações de produção. Se ele for par, representa um núcleo estável. O Z indica a versão corrente do kernel. Um finger na máquina linux.kernel.org, retorna as versões mais recentes do kernel do Linux. Os kernels são os mesmos, independentes da distribuição, e podem ser atualizados sempre que necessário. Versões novas do mesmo são encontradas em ftp://ftp.kernel.org. No nosso exemplo será usada a versão 2.0.33.

O roteamento por origem consiste em um patch para o núcleo do Linux. O patch contém alterações no código fonte do kernel para adicionar o suporte desejado. No próximo tópico, serão detalhados os procedimentos de como aplicar o patch e recompilar o kernel. O pacote chama-se routing-2.0.33.tgz.

Por último teremos que recompilar os binários de rede para que o comando que manipula as tabelas de rotas, suporte os novos parâmetros. No pacote anterior temos também um patch para ele. O pacote que contém o código fonte dos binários de rede chama-se net-tools-1.33.tar.gz.

Devido à dificuldade de encontrá-los na Internet, os pacotes estão disponíveis em: ftp://ftp.ufba.br/pub/unix/linux/srcroute







INSTALANDO

Supondo que seu kernel geralmente é descompactado em /usr/src, e que os pacotes estão no diretório do root, os seguintes passos são necessários para a instalação (lembre-se de efetuar login como root):

  1. cd /usr/src
  2. rm linux
  3. tar –zxvf ~/linux-2.0.33.tar.gz
  4. mv linux linux-2.0.33
  5. ln –s linux-2.0.33 linux
  6. cd /root
  7. tar –zxvf routing-2.0.33
  8. tar –zxvf net-tools-1.33
  9. cd /usr/src
  10. patch –s –p0 < ~/routing-2.0.33/patch.kernel-2.0.33
  11. cd /root
  12. patch –s –p0 < ~/routing-2.0.33/patch.net-tools-1.33

NOTA: Se você usa glibc (versões novas da distribuição RedHat), um patch adicional para o route.h encontra-se no pacote. Instale-o com:

  1. cd /
  2. patch –s –p0 < ~/routing-2.0.33/patch.glibc-route.h







RECOMPILANDO O KERNEL

Para seguir adiante, teremos que recompilar o kernel do sistema, para incluir o roteamento pela origem.

  1. cd /usr/src
  2. make mrproper
  3. make menuconfig
  4. make dep ; make clean
  5. make zlilo
  6. make modules
  7. make modules_install

Quem não tiver familiaridade com o kernel do Linux, irá sentir uma certa dificuldade no passo 3. Para mais informações sobre o kernel, consulte o KERNEL-HOWTO (http://sunsite.unc.edu/mdw/HOWTO/Kernel-HOWTO.html).






RECOMPILANDO BINÁRIOS

Após o correto funcionamento do novo núcleo, chegou a hora de compilar os binários modificados. Para o funcionamento do roteamento pela origem, o binário route é suficiente.

  1. cd /root/net-tools-1.33
  2. make config (recomenda-se aceitar todos os defaults da configuração).
  3. make
  4. cp route /usr/local/bin/route.source

Note que o passo make install foi suprimido, e o binário foi copiado manualmente com outro nome, para evitar erros e facilitar a desinstalação do pacote. Em alguns sistemas, o pacote não compila direito por falta de dependências. Caso este seja seu caso, inclua a seguinte linha em todos os arquivos que derem erro:

#include <linux/timer.h>






TESTANDO O SISTEMA

Experimente pedir o help do comando route.source:

router:# /usr/local/bin/route.source –h –A inet
Usage: inet_route [-vF] del {-host|-net} Target [gw Gw] [metric M]
[src Source [srcmask SM]] [dev] If]
inet_route [-vF] add {-host|-net} Target [gw Gw] [metric M]
[netmask N] [src Source [srcmask SM]] [mss Mss]
[window W] [irtt I] [mod] [dyn] [reinstate][[dev] If]
inet_route [-vF] add {-host|-net} Target [srcSource[srcmaskSM]]
[metric M] reject
inet_route [-FC] flush NOT supported

Note a diferença dos comandos para a versão original do route:

router:# route -h -A inet
Usage: inet_route [-vF] del {-host|-net} Target [gw Gw] [metric M] [[dev]If]
inet_route [-vF] add {-host|-net} Target [gw Gw] [metric M]
[netmask N] [mss Mss] [window W] [irtt I]
[mod] [dyn] [reinstate] [[dev] If]
inet_route [-vF] add {-host|-net} Target [metric M] reject
inet_route [-FC] flush NOT aupported

Veja que a única diferença é a presença dos campos src e srcmask. Agora, verifique se o seu kernel está com o suporte corretamente instalado. Isto pode ser verificado com o seguinte comando:

router:# cat /proc/net/route | head -2
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT Source SrcMask
eth0 40EC12C8 7D01A8C0 03 0 2810 0 C0FFFFF1500 0 0 00000000 00000000

Verifique, na primeira linha, se os campos Source e SrcMask estão presentes. Terminadas as verificações, seu sistema está pronto para utilizar o roteamento pela origem.







CRIANDO ROTAS PELA ORIGEM

Normalmente, para definir uma rota para uma rede específica usaríamos:

  • /sbin/route add –net <rede> netmask <máscara_da_rede> gateway <ip_do_gateway>

Uma rota pra o Classe C 192.168.1.0, tendo como gateway a máquina com IP 192.168.2.1, seria:

  • /sbin/route add –net 192.168.1.0 netmask 255.255.255.0 gateway 192.168.2.1

Agora, imagine que se quer essa rota disponível apenas para as máquinas que estão na rede 192.168.3.0. Então, teríamos:

  • /usr/local/bin/route.source –net 192.168.1.0 gw 192.168.2.1 netmask 255.255.255.0 src 192.168.3.0 srcmask 255.255.255.0.

Perceba que criar as novas rotas não tem segredo nenhum. Infelizmente, o comando netstat –rn não mostra os campos src e srcmask, para visualizar, temos que examinar o /proc/net/route com o comando:

  • more /proc/net/route







UMA APLICAÇÃO PRÁTICA

Considerando a seguinte situação:

O roteador Linux tem três interfaces de rede, sendo uma na rede comercial, uma na rede acadêmica, e uma na rede privada, para acesso das redes privadas internas. Suponha que a instituição queira separar tráfego de acordo com a rede, ou seja, a Rede1 acessa a Internet pela RNP e a Rede2 acessa Internet pela Embratel.

Tal problema pode ser facilmente resolvido, usando o sistema de roteamento por origem descrito acima, combinado com algum sistema de NAT (Network Address Translation). O roteador com suporte a NAT troca o endereço de rede pelo próprio, e, internamente, guarda uma tabela para mapear o endereço original no retorno do pacote. No exemplo, será utilizado o IP Masquerading, já existente no Linux, pela sua facilidade e sua eficácia já comprovada. Repare que sem um NAT, teríamos problemas de roteamento no retorno do pacote, pois cada provedor (Embratel ou RNP) possui seu próprio bloco de endereçamento IP.

Para facilitar, iremos atribuir IP’s fictícios para cada elemento da rede:

  • Roteador da RNP – 200.18.240.1
  • Roteador da Embratel – 200.223.67.1
  • Roteador Linux
    • RNP – 200.18.240.2
    • Embratel – 200.223.67.2
    • Privado – 192.168.1.1
  • Roteador Interno
    • 192.168.1.2 (Rede do Linux)
    • 192.168.2.1 (Rede1)
    • 192.168.3.1 (Rede2)

Sendo assim, para configurar a tabela de rotas do Linux temos a seguinte seqüência de comandos:

router:# /sbin/route add –net 192.168.1.0 netmask 255.255.255.0 eth0
router:# /sbin/route add –net 200.223.67.0 netmask 255.255.255.0 eth1
router:# /sbin/route add –net 200.18.240.0 netmask 255.255.255.0 eth2
router:# /sbin/route add –net default gw 200.18.240.1 netmask 0.0.0.0 metric 1

NOTA: O Roteador Linux pode ter apenas um gateway. No exemplo acima ele foi colocado na rede da RNP, então qualquer pacote endereçado a ele especificamente irá trafegar pela RNP.

Após termos o Linux funcionando na rede, para configurar o Masquerading:

router:# ipfwadm –F –p deny
router:# ipfwadm –F -a accept -m -P all -S 192.168.2.0/24 -D 0.0.0.0/0 –V 200.18.240.2
router:# ipfwadm –F –a accept –m –P all –S 192.168.3.0/24 –D 0.0.0.0/0 –V 200.223.67.2

Os comandos acima definem a política default do sistema como deny (não permitir), e definem masquerading para as duas redes internas. Para maiores informações sobre o comando ipfwadm, consulte a man page do mesmo.

Finalmente, definindo as rotas pela origem:

router:# /usr/local/bin/route.source add default gw 200.18.240.1 src 192.168.2.0 srcmask 255.255.255.0 dev eth2
router:# /usr/local/bin/route.source add default gw 200.223.67.1 src 192.168.3.0 srcmask 255.255.255.0 dev eth1

Sendo assim a sub-rede 192.168.2.0 terá como saída a interface eth2, em direção ao gateway 200.18.240.1, que corresponde ao roteador da RNP. Note que o endereço de origem será trocado para 200.18.240.2, que é o IP da interface eth2, encontrada no lado da RNP, garantindo o retorno do pacote pelo mesmo caminho.

Igualmente, a sub-rede 192.168.3.0 terá como saída a interface eth1, com gateway 200.223.67.1. Novamente o endereço de origem será trocado, agora para o endereço 200.223.67.2, que é o endereço da interface eth1, presente no lado da Embratel.







CONCLUSÃO

O roteamento pela origem pode servir para resolver problemas que normalmente iriam requerer uma criação de um A.S. (Autonomous System), e utilização de complicados protocolos de roteamento como BGP.

Com a solução apresentada neste artigo, pode-se reduzir custos na arquitetura da rede, além de simplificá-la, visto que não é feito o uso de nenhum protocolo de roteamento para i gateways (BGP, IGRP, etc). Infelizmente, como o resto dos roteadores da Internet não suporta o recurso de roteamento por origem, ele não funciona em soluções mais globais, a menos que se utilize um mecanismo de tradução de endereços, como foi explicado acima. Apesar disso, ele pode ser um excelente recurso dentro de redes privadas.





REFERÊNCIAS BIBLIOGRÁFICAS

Internetworking with TCP/IP Vol. 1
D. Comer, Prentice Hall

TCP/IP Network Administration, 2nd Edition
By Craig Hunt
1997, O’Reilly and Associates, In
c.





SITES RELACIONADOS

http://ipmasq.home.ml.org (Linux IP Masquerade Resource)
http://www.linux.org (Linux Online)
srcroute@mail.linux.org (Lista sobre Source Routing)
masq-subscribe@indyramp.com (Lista sobre IP Masquerading)
http://www.freshmeat.net (Notícias sobre Linux)