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: 22.606 ]

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

Configurando o Rclone no CentOS 7

Configurações Básicas no CentOS 7

Nagios Core 4.0.8 com Debian 7 e Client Windows Server

SQUID com autenticação e permissões por grupos do Active Directory e relatórios com SARG

IPv6 completo Net Virtua

  
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


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