Pular para o conteúdo

Gateway Linux com 2 links de internet usando iptables e iproute

Postado em 5 minutos de leitura

Imagine um cenário onde há um servidor que compartilha a internet para a rede interna, atuando como gateway, e por algum motivo foi contratado mais um link de internet. Ou então há 2 ou mais servidores proxy e se deseja definir para qual deles cada IP da rede interna deve seguir caminho. Outro cenário seria separar a parte de navegação dos demais serviços (msn, emule, e-mail…), cada uma usando um link diferente. Nesse artigo vou demonstrar que o Linux proporciona maneiras simples e eficientes de implementar esse tipo de roteamento.

As distribuições utilizadas foram Ubuntu Server 5.04 e Debian Lenny.

Funcionamento

O servidor que vou configurar é um gateway compartilhando a internet para vários clientes. O iptables realiza uma marcação para todos os pacotes oriundos de cada IP cliente e o iproute determina para qual link os pacotes deverão ser encaminhados de acordo com a marcação feita. Vou usar a marcação 1 para pacotes via link1, marcação 2 para pacotes à serem encaminhados para o link2 e a rota principal do próprio gateway será pelo link1.

Instalação

O iptables e iproute são pacotes presentes em quase todas as distribuições. O iptables vem instalado por padrão no Ubuntu e Debian. Então vou instalar apenas o iproute, via apt-get, que é o gerenciador de pacotes dessas distros:

sudo apt-get install iproute2

Criando a tabela de roteamento

Vou criar 2 tabelas chamadas link1 e link2, adicionando duas linhas ao final do arquivo /etc/iproute2/rt_tables, ficando assim:

cat /etc/iproute2/rt_tables

255 local
254 main
253 default
0 unspec
250 link1
251 link2

Agora vou criar o script /etc/init.d/rotas, que utiliza o iproute para definição das rotas:

#!/bin/bash
 
# DEFINICAO DOS GATEWAYS (IPs FICTICIOS)
GW_LINK1=189.12.34.1
GW_LINK2=200.56.78.1
 
# PLACAS DE REDE
ETH_LINK1=eth1
ETH_LINK2=eth2
 
function start() {
  # Limpa o cache de rotas
  ip route flush cache
  # Pacotes com marcacao 1 vao para o link1
  ip rule add fwmark 1 prio 20 table link1
  # Pacotes com marcacao 2 vao para o link2
  ip rule add fwmark 2 prio 20 table link2
  # Associa a rota do link1 a interface de rede e tabela correspondentes
  ip route add default via $GW_LINK1 dev $ETH_LINK1 table link1
  # Associa a rota do link1 a interface de rede e tabela correspondentes
  ip route add default via $GW_LINK2 dev $ETH_LINK2 table link2
  # Adiciona a rota padrao ao link1
  route add default gw $GW_LINK1
  echo "Tabela de roteamento criada."
}
 
function stop() {
  # Limpa o cache
  ip route flush cache
  # Deleta as regras de acordo com as marcacoes
  ip rule del fwmark 2
  ip rule del fwmark 3
  # Deleta a rota padrao
  route del default
  echo "Limpeza da tabela de roteamento concluida."
}
 
case $1 in
  'start') start; exit ;;
  'stop') stop; exit ;;
  'restart') stop; start; exit ;;
  *) start; exit ;;
esac

Reparem que o que o script rotas faz é dizer que pacotes marcados como 1 (fwmark 1) fazem parte da tabela link1 e marcados como 2 (fwmark 2) da tabela link2. Em seguida cria uma regra dizendo que os pacotes da tabela link1 seguem pelo gateway e interface de rede correspondentes. O mesmo para a tabela link2.

O próximo passo é fazer a marcação dos pacotes.

Marcando os pacotes com iptables

Esse script de firewall é apenas para demonstrar como fazer a marcação de pacotes. As regras devem ser incorporadas à um firewall melhor configurado e mais seguro. O iptables na verdade é um software que age como frontend para manipulação do firewall do Linux, chamado de netfilter. Esse por sua vez possui uma tabela chamada mangle que é onde ficam armazenadas as regras de marcação de pacotes e outra chamada nat, que contém as regras de NAT.

Criei o arquivo /etc/init.d/firewall conforme abaixo:

#!/bin/bash
 
# modprobe eh usado para carregar modulos do kernel
MOD=$(which modprobe)
 
# iptables
IPT=$(which iptables)
 
# Interfaces de rede
I_LINK1="eth1"
I_LINK2="eth2"
I_LAN="eth0"
 
function stop() {
  # Limpa a tabela mangle
  $IPT -t mangle -F
  $IPT -t mangle -X
 
  echo "Firewall parado."
}
 
function start() {
  # Carrega o modulo do kernel
  $MOD ip_tables
 
  # Limpa as regras anteriores
  stop;
 
  # Habilita redirecionamento de IP
  echo 1 > /proc/sys/net/ipv4/ip_forward
 
  # Clientes para o link1
  $IPT -t mangle -A PREROUTING -s 192.168.0.2 -i $I_LAN -j MARK --set-mark 1
  $IPT -t mangle -A PREROUTING -s 192.168.0.4 -i $I_LAN -j MARK --set-mark 1
 
  # Clientes para o link2
  $IPT -t mangle -A PREROUTING -s 192.168.0.3 -i $I_LAN -j MARK --set-mark 2
  $IPT -t mangle -A PREROUTING -s 192.168.0.5 -i $I_LAN -j MARK --set-mark 2
  $IPT -t mangle -A PREROUTING -s 192.168.0.6 -i $I_LAN -j MARK --set-mark 2
 
  # Apenas a navegacao vai para o link2. E-mail, msn e outros vao para o link1 que é a rota padrao.
  $IPT -t mangle -A PREROUTING -s 192.168.0.7 -i $I_LAN -p tcp --dport 80 -j MARK --set-mark 2
  $IPT -t mangle -A PREROUTING -s 192.168.0.7 -i $I_LAN -p tcp --dport ! 80 -j MARK --set-mark 1
 
  echo "Firewall iniciado."
}
 
case $1 in
  'start') start; exit ;;
  'stop') stop; exit ;;
  *) start; exit ;;
esac

E agora é só colocar os dois scripts para carregarem durante a inicialização do sistema. Há muitas maneiras de fazer isso, então vou fazer da mais preguiçosa possível porque isso varia de acordo com o administrador e a distribuição utilizada:

sudo chmod +x /etc/init.d/rotas
sudo chmod +x /etc/init.d/firewall
sudo ln -s /etc/init.d/rotas /etc/rcS.d/S79rotas
sudo ln -s /etc/init.d/firewall /etc/rcS.d/S80firewall

Conclusão

Apenas com esses 2 scripts não será possível compartilhar a internet. Porém o objetivo aqui é mostrar uma breve abordagem de como fazer roteamento no Linux. Artigos, dicas e scripts para compartilhar internet existem aos milhares na internet. Com uma rápida pesquisa no google e implementando o que foi descrito aqui, é possível criar um servidor de internet em Linux muito mais estável e eficiente do que um rodando Windows.