Balanceamento de links - Load balance + Failover + Failback

Após diversos artigos/tutorias seguidos passo a passo e sem resultado, me vi na situação desesperada de não conseguir fazer funcionar o balanceamento de links de internet (load balance), migração de links em caso de queda (failover) e restauração do link que voltou a funcionar (failback).

[ Hits: 25.130 ]

Por: Carpegieri Torezani em 03/08/2015


Introdução



Após diversos artigos/tutorias seguidos passo a passo e sem resultado, me vi na situação desesperada de não conseguir fazer funcionar:
  • Balanceamento de links de internet (load balance).
  • Migração de links em caso de queda de um link (failover).
  • Restauração do link que voltou a funcionar (failback).

Como minha necessidade era urgente adquiri o Roteador TP-Link TL-R470T, que me permitiu usufruir de todas essas funcionalidades, posso dizer que só tenho elogios ao mesmo. No entanto sempre tive o desejo de fazer funcionar com minhas próprias mãos e utilizando o GNU/Linux. Após muito tempo com inúmeras tentativas conseguir fazer funcionar todas essas funções, neste artigo mostrarei como fazê-las.

Este artigo será dividido em partes, de modo que, seguido todos os passos ou até apenas um, o leitor terá a capacidade de implementá-los. Todos os dados/comandos utilizados neste artigo foram obtidos da internet durante os últimos anos, desta forma existem dezenas de partes adquiridas de fontes diversas e algumas funções desenvolvidas por mim.

Primeiramente trabalharemos com o balanceamento de carga, permitindo que uma rede utilize dois links ou mais ao mesmo tempo. A maioria dos artigos não deixa claro os requisitos e as configurações para o correto funcionamento do balanceamento de carga. Mostraremos aqui todos os detalhes de modo que qualquer pessoa que seguir esse artigo possa implementar todos as funções de forma eficaz.

Requisitos:
  • iproute2
  • iptables

Configurações:

Criar as tabelas no arquivo rt_tables localizado em /etc/iproute2/rt_tables. Adicionando duas novas tabelas, como exemplo criaremos as duas tabelas abaixo, sabendo que as tabelas deve conter um número de identificação e o nome:

200 nome_tabela_1
201 nome_tabela_2

Observação: não defina nenhum gateway na configuração das placas de rede, pois o balanceamento não será reconhecido e o sistema utilizará apenas o gateway default.

Utilizaremos como base uma pasta criada na raiz do sistema com o nome internet, onde ficaram os arquivos para balanceamento de link e migração de link, ficando assim:
  • /internet/

Balanceamento de links de internet (load balance)

Para o script de balanceamento de carga, crie um novo arquivo com o nome "balanceamento.sh" na pasta padrão, sendo o arquivo acessado pelo seguinte endereço:
  • /internet/balanceamento.sh

Conteúdo do arquivo "balanceamento.sh":

# Dados da interfaces de rede conectadas com a internet - Link 1
placa_rede_1=eth0
tabela_1=nome_tabela_1
gateway_1=192.168.0.1
peso_balanceamento_link_1=30

# Dados da interfaces de rede conectadas com a internet - Link 2
placa_rede_2=eth1
tabela_2=nome_tabela_2
gateway_2=192.168.1.1
peso_balanceamento_link_2=70

# Dados da Rede Interna
placa_rede_interna=eth2
rede_interna=10.0.0.0/24

### Fim das Variáveis

#Carregar módulos
modprobe iptable_nat
modprobe ip_nat_ftp
modprobe ipt_MARK
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/ip_dynaddr

# O uso do rp_filter faz o firewall sempre responder aos pacotes na mesma interface da qual eles foram originados, prevenindo previne ataques diversos tentem tirar proveito da regra que permite conexões na interface de loopback.
# No entanto faz com que o balanceamento seja menor, obrigando os pacotes irem sempre pelas mesmas interfaces
# Zero (0) para desativado e (1) para ativado
echo "1" > /proc/sys/net/ipv4/conf/default/rp_filter
echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter

# Deletar a rota default
ip route del default

# Limpa as regras das tabelas
ip route flush table $tabela_1
ip route flush table $tabela_2

# Define a rota para as tabelas
ip route add default dev $placa_rede_1 via $gateway_1 table $tabela_1
ip route add default dev $placa_rede_2 via $gateway_2 table $tabela_2

# Define as regras para balanceamento dos links
ip route add default scope global nexthop via $gateway_1 dev $placa_rede_1 weight $peso_balanceamento_link_1 nexthop via $gateway_2 dev $placa_rede_2 weight $peso_balanceamento_link_2

# Aplicar as regras
ip route flush cache

# Compartilha a conexão
iptables -t nat -A POSTROUTING -o $placa_rede_1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o $placa_rede_2 -j MASQUERADE

Migração e restauração de links em caso de quedas (failover + failback)

Nos dias atuais a redundância de links de internet é fundamental na estabilidade das empresas, onde poucos minutos sem conexão geram prejuízos gigantescos. A cada dia pequenas, médias e grandes empresas investem em tecnologias e redundância, com os links de acesso à internet não é diferente. Uma das dificuldades é como manter tudo funcionando e de forma redundante.

Para o script de migração e restauração de links em caso de quedas, crie um novo arquivo com o nome "failover.sh" na pasta padrão, sendo o arquivo acessado pelo seguinte endereço:
  • /internet/failover.sh.

#!/bin/bash

# Adicionar no rc.local nohup > /dev/null /internet/failover &

# Tempo esperado para testar a conexão novamente
tempo_espera=30

# Número de pacotes a ser pingados
numero_pacotes=2

# Nome das interfaces de rede conectadas com a internet
placa_rede_1=eth0
placa_rede_2=eth1

# Gateway das interfaces
gateway_1=192.168.0.1
gateway_2=192.168.1.1

# Endereço IP a ser pingado (8.8.8.8 é o DNS do Google)
endereco_ping=8.8.8.8

# Arquivo de balanceamento de links
arquivo=/internet/balanceamento.sh

# Não alterar nada daqui para baixo
# Variáveis destinadas ao controle
i=0
link1=1
link2=1

# Ativação do Balanceamento de Links
sh $arquivo > /dev/null

while [ $i -le 10 ];
do

if [ $link1 = 0 ] || [ $link2 = 0 ]; then
sh $arquivo > /dev/null
fi

if (ping -I $placa_rede_1 -c $numero_pacotes $endereco_ping > /dev/null)
then
link1="1"
else
ip route del default
ip route add default via $gateway_2
ip route flush cache
link1="0"
fi

if (ping -I $placa_rede_2 -c $numero_pacotes $endereco_ping > /dev/null)
then
link2="1"
else
ip route del default
ip route add default via $gateway_1
ip route flush cache
link2="0"
fi

sleep $tempo_espera

done

   

Páginas do artigo
   1. Introdução
Outros artigos deste autor

Colorindo o Shell

Leitura recomendada

Proxy Squid com SquidGuard + Controle de Banda e Autenticação NTLM no Samba 4 (CentOS 6.5 - 64 bits Minimal)

Conexão do Vindula com o Active Directory Server 2008 R2

Asterisk - Recebimento de Fax com encaminhamento por e-mail

Configurando serviço DHCP (Debian)

Docker - Containers em Linux

  
Comentários
[1] Comentário enviado por johnatanlopes em 03/08/2015 - 14:16h

O artigo está bem organizado, gostei, porém tenho a dúvida abaixo:

Em relacao ao acesso a sites seguros https, nao tem nenhuma regra para a porta 443???
Exemplo dos sites de bancos que são desconectados por receber requisicoes de dois locais diferentes.

[2] Comentário enviado por andr3ribeiro em 03/08/2015 - 15:40h

Acordei hoje e pensei: "Precisava pensar em um Failover la pra empresa, o provedor anda deixando a desejar!"
Aí aparece o gieri e salva o dia! rsrsrs

[3] Comentário enviado por chaplinux em 03/08/2015 - 16:02h

Muito bom o artigo. Parabens!

... mais tambem fiquei curioso quanto as conexoes HTTPS e etc.., ele ja faz tudo?

não teria um script com balanceamento de carga tambem ? viria a calhar!

[4] Comentário enviado por qxada07 em 03/08/2015 - 17:14h

Parabéns pela iniciativa....

Pena que não tenho ambiente para ver em produção... Mas curto muito!!!!!

Viva o Linux...

[5] Comentário enviado por wagnerfs em 03/08/2015 - 21:17h

Parabéns e obrigado por compartilhar o conhecimento.
_________________________
Wagner F. de Souza
Técnico/Instrutor de Informática
"GNU/Linux for human beings."
LPI ID: LPI000297782

[6] Comentário enviado por lDavidson em 04/08/2015 - 10:48h

Muito bom artigo, funcionou 100% aqui, incluindo o failback, quando o link principal volta ele é colocado como GW padrão novamente.

Somente um detalhe que tive que alterar, em /etc/rc.local, faltou o .sh no final do nome do arquivo failover, ficando então corretamente:
nohup > /dev/null /internet/failover.sh &

[7] Comentário enviado por johnatanlopes em 04/08/2015 - 11:57h

lDavidson

Poderia realizar testes acessando site de algum banco??
Att.

[8] Comentário enviado por gieri em 05/08/2015 - 13:00h


[1] Comentário enviado por johnatanlopes em 03/08/2015 - 14:16h

O artigo está bem organizado, gostei, porém tenho a dúvida abaixo:

Em relacao ao acesso a sites seguros https, nao tem nenhuma regra para a porta 443???
Exemplo dos sites de bancos que são desconectados por receber requisicoes de dois locais diferentes.


Você pode usar a seguinte regra:
#Adiciona a marcação nos links
ip rule add fwmark 0x10 lookup $tabela_1 prio 3
ip rule add fwmark 0x20 lookup $tabela_2 prio 3

#Marcando a saída das portas 110, 23 e 25 pelo link1 e 80, 443 (bancos) pelo link2
iptables -I PREROUTING -t mangle -i $placa_rede_interna -s $rede_interna -d 0/0 -p tcp -m multiport --dports 110,23,25 -j MARK --set-mark 0x10
iptables -I PREROUTING -t mangle -i $placa_rede_interna -s $rede_interna -d 0/0 -p tcp -m multiport --dports 80,443 -j MARK --set-mark 0x20

Alguns site necessitam também adicionar uma rota, execute esta regra de acordo com a tabela marcada
route add -host www.bb.com.br gw 192.168.1.1 dev eth1

[9] Comentário enviado por gieri em 05/08/2015 - 13:02h


[3] Comentário enviado por chaplinux em 03/08/2015 - 16:02h

Muito bom o artigo. Parabens!

... mais tambem fiquei curioso quanto as conexoes HTTPS e etc.., ele ja faz tudo?

não teria um script com balanceamento de carga tambem ? viria a calhar!


O script "balanceamento.sh" faz o balanceamento, em relação as regras de banco, olhe o comentário [8] Comentário que eu fiz.

[10] Comentário enviado por gieri em 05/08/2015 - 13:03h


[4] Comentário enviado por qxada07 em 03/08/2015 - 17:14h

Parabéns pela iniciativa....

Pena que não tenho ambiente para ver em produção... Mas curto muito!!!!!

Viva o Linux...


Obrigado, tenho ele funcionando aqui no meu serviço e funciona perfeitamente.

[11] Comentário enviado por gieri em 05/08/2015 - 13:05h


[6] Comentário enviado por lDavidson em 04/08/2015 - 10:48h

Muito bom artigo, funcionou 100% aqui, incluindo o failback, quando o link principal volta ele é colocado como GW padrão novamente.

Somente um detalhe que tive que alterar, em /etc/rc.local, faltou o .sh no final do nome do arquivo failover, ficando então corretamente:
nohup > /dev/null /internet/failover.sh &


Obrigado, Acabou passando esse detalhe, na hora que editei acredito que apaguei sem querer o ".sh".

[12] Comentário enviado por sergeimartao em 05/08/2015 - 13:56h

Muito interessante, parabéns!

[13] Comentário enviado por edipo.magrelo em 06/08/2015 - 10:10h

No script failover.sh vi que você faz teste de ping para saber se o link esta up ou down.
Já tentei fazer isso com ping uma vez, mas sempre acontecia do provedor ter uns loss na rede e meu failover ficava trocando de link.
Acabamos mudando a checagem de ping por consultas dns

[14] Comentário enviado por paulinhotobias em 11/08/2015 - 14:45h

Parabéns pelo artigo. Vou tentar implementá-lo.

[15] Comentário enviado por MarcosCarraro em 17/08/2015 - 20:12h

Boa noite,
Belo artigo, na parte de teste de conexão faria diferente, pois o DNS do google não responde full a todos pacotes, ele faz um controle onde bloqueia alguns pacotes, minha sugestão é teste vários ips diferentes, dns do google, ip de grandes portais, ip de alguns ptt, e também vale testar a conexão http (Usa CURL é fácil) pois pode responder mas não ter acesso www.
São algumas dicas para deixar o script mais parudo!
Abraços Marcos Carraro.

[16] Comentário enviado por slpond em 21/08/2015 - 14:51h

Excelente artigo ! só uma questão que estou precisando, gostaria de trabalhar com multilink sem balanceamento, tipo, tenho dois links e duas rede, gostaria que a rede um sai pelo link1 e a rede 2 pelo link2, exemplo: link1 na interface eth0 = 192.168.0.1, link2 na interface eth1 = 192.168.1.1, eth2 Lan com duas redes: 172.16.10.1/24 e 172.16.11.1/24, gostaria que computadores na faixa 172.16.10.1/24 saem pelo link1 e computadores na rede 172.16.11.1/24 saem polo link2, como seria ?

[17] Comentário enviado por gieri em 21/08/2015 - 15:03h


[16] Comentário enviado por slpond em 21/08/2015 - 14:51h

Excelente artigo ! só uma questão que estou precisando, gostaria de trabalhar com multilink sem balanceamento, tipo, tenho dois links e duas rede, gostaria que a rede um sai pelo link1 e a rede 2 pelo link2, exemplo: link1 na interface eth0 = 192.168.0.1, link2 na interface eth1 = 192.168.1.1, eth2 Lan com duas redes: 172.16.10.1/24 e 172.16.11.1/24, gostaria que computadores na faixa 172.16.10.1/24 saem pelo link1 e computadores na rede 172.16.11.1/24 saem polo link2, como seria ?


Faça assim:
iptables -F
iptables -F INPUT
iptables -F OUTPUT
iptables -F POSTROUTING -t nat
iptables -F PREROUTING -t nat
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -P FORWARD ACCEPT
iptables -A POSTROUTING -t nat -s 172.16.10.1/24 -o eth0 -j MASQUERADE
iptables -A POSTROUTING -t nat -s 172.16.11.1/24 -o eth1 -j MASQUERADE

[18] Comentário enviado por jhonsnull em 07/12/2015 - 13:06h

Excelente artigo!
Irei implementar esses dias.
Viva ao compartilhamento do conhecimento.
Viva o Linux.

[19] Comentário enviado por adalto em 21/12/2015 - 17:15h

Muito bom esse artigo aqui na empresa onde eu trabalho, tenho dois link de internet da oi veloz e funcionou numa boa, Valeu Tutorial.

[20] Comentário enviado por edurc em 03/05/2017 - 22:20h

Olá, gieri. Parabéns pelo tutorial! Muito bom!
Só uma dúvida: tem como utilizar o failover e o failback sem o balanceamento?
Neste exemplo o failover utiliza o balanceamento.sh. Como eu implementaria o failover e failback sem ele?
Abraços.

[21] Comentário enviado por tofoliluis em 26/08/2017 - 10:22h

Não funcionou para mim, alguém pode me ajudar? Segue as regras que eu utilizei.

Quando deixo o balanceamento como default a rede para, e na forma que está o host 192.168.10.254 respeita a tabela BALANCE para o qual eu marco os pacotes.


#!/bin/bash

# Variaveis
WAN0=wlan0
GW0=192.168.0.1
WAN1=wlan1
GW1=10.0.0.1
WAN2=wlan2
GW2=192.168.0.1
REDE=192.168.10.0/24

start(){
modprobe iptable_nat
modprobe ip_nat_ftp
modprobe ipt_MARK
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/ip_dynaddr

echo "1" > /proc/sys/net/ipv4/conf/default/rp_filter
echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter

stop

ip route add default via $GW0 dev $WAN0 table T_WLAN0
ip route add default via $GW1 dev $WAN1 table T_WLAN1
ip route add default via $GW2 dev $WAN2 table T_WLAN2

ip rule add fwmark 1 table T_WLAN0
ip rule add fwmark 2 table T_WLAN1
ip rule add fwmark 3 table T_WLAN2
ip rule add fwmark 9 table BALANCE

ip route add default via $GW1

ip route add default scope global table BALANCE \
nexthop via $GW0 dev $WAN0 weight 1 \
nexthop via $GW1 dev $WAN1 weight 1 \
nexthop via $GW2 dev $WAN2 weight 1

ip route flush cache

iptables -t mangle -P PREROUTING ACCEPT
iptables -t mangle -P INPUT ACCEPT
iptables -t mangle -P FORWARD ACCEPT
iptables -t mangle -P OUTPUT ACCEPT
iptables -t mangle -P POSTROUTING ACCEPT
iptables -t mangle -X
iptables -t mangle -A PREROUTING -s 192.168.10.254 -d 0/0 -j MARK --set-mark 9

iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -X
iptables -t nat -A POSTROUTING -o $WAN0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o $WAN1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o $WAN2 -j MASQUERADE
}

stop(){
ip route del default
ip route flush table T_WLAN0
ip route flush table T_WLAN1
ip route flush table T_WLAN2
ip route flush table BALANCE
ip route flush cache

iptables -t nat -F
iptables -t mangle -F
}

case "$1" in
"start") start ;;
"stop") stop ;;
"restart") stop; start ;;
*) echo "Use os parâmetros start ou stop"
esac

[22] Comentário enviado por mederix78 em 15/06/2020 - 13:57h

Muito bom o artigo!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts