Gateway Linux com 2 links de internet usando iptables e iproute
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.