Redundância de links - Mon + Shell Script

Este script foi desenvolvido, de maneira simples, para sanar a necessidade de realizar redundância com dois links de Internet.

[ Hits: 15.882 ]

Por: Bruno Rodrigues Leite Correia em 03/12/2012


O script



Para uma melhor interpretação do script, deve-se considerar que:

1. Escolhi dois hosts de destino para teste, sendo o primeiro 8.8.8.8 e o segundo 8.8.4.4;

2. Adicionei uma rota para cada um dos hosts, onde o destino 8.8.8.8 é testado via fping pelo meu link primário, e o 8.8.4.4 é testado pelo meu link secundário;

3. Adicionei as linhas abaixo no arquivo /etc/network/interfaces para que as rotas sejam adicionadas na inicialização do serviço networking:

post-up route add -host 8.8.8.8 gw 189.10.11.12 dev eth1
post-up route add -host 8.8.4.4 gw 201.10.11.12 dev eth2

Por fim, edite o arquivo /usr/lib/mon/mon.d/availability.monitor e deixe-o da seguinte maneira:

#!/bin/bash

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH

# Host a ser pingado pela eth1
host_eth1="8.8.8.8"
# Host a ser pingado pela eth2
host_eth2="8.8.4.4"
# Gateway preferido
pref_gw="189.10.11.12"
# Gateway padrao atual
deflt_gw=$(/usr/bin/sudo /sbin/route -n | grep ^0.0.0.0 | awk '{print $2}' | /usr/bin/head -n1)
# Gateway do link da inetrface eth1
iface_eth1_gw="189.10.11.12"
# Gateway do link da interface eth2
iface_eth2_gw="201.10.11.12"
# Interface do link/gateway preferido
iface_pref_gw="eth1"
# Endereco de e-mail de administrador
admin="correiabrux@gmail.com"
# Data atual
date=$(date +%d-%m-%Y)
# Hora atual
time=$(date +%H:%M:%S)
# Endereco IP da interface eth1
iface_eth1_ip="189.10.11.13"
# Endereco IP da interface eth2
iface_eth2_ip=201.10.11.13

# Funcao para trocar para o link da interface eth1
link_iface_eth1() {

    /usr/bin/sudo  /sbin/route  del  default  gw  $iface_eth2_gw
    /usr/bin/sudo  /sbin/route  add  default  gw  $iface_eth1_gw  dev  eth1
    /usr/bin/sudo  /sbin/route  del  -host  $host_eth1  gw  $iface_eth1_gw  dev  eth1  ||  true
    /usr/bin/sudo  /sbin/route  del  - host  $host_eth2  gw  $iface_eth2_gw  dev  eth2  ||  true
    /usr/bin/sudo  /sbin/route  add  -host  $host_eth1  gw  $iface_eth1_gw  dev  eth1
    /usr/bin/sudo  /sbin/route  add  -host  $host_eth2  gw  $iface_eth2_gw  dev  eth2
    /usr/sbin/squid  -k  reconfigure
    for  mail  in  $admin  ;  do
    echo  "Link  primário  da  interface  eth1  ativado"  |  /usr/bin/mail  -s  "[Empresa]  Link  Internet  primário  da  interface  eth1  ativado  em  $date  as  $time"  $mail
    done
}

# Funcao para trocar para o link da interface eth2
link_iface_eth2() {

    /usr/bin/sudo  /sbin/route  del  default  gw  $iface_eth1_gw
    /usr/bin/sudo  /sbin/route  add  default  gw  $iface_eth2_gw  dev  eth2
    /usr/bin/sudo  /sbin/route  del  -host  $host_eth1  gw  $iface_eth1_gw  dev  eth1  ||  true
    /usr/bin/sudo  /sbin/route  del  -host  $host_eth2  gw  $iface_eth2_gw  dev  eth2  ||  true
    /usr/bin/sudo  /sbin/route  add  -host  $host_eth1  gw  $iface_eth1_gw  dev  eth1
    /usr/bin/sudo  /sbin/route  add  -host  $host_eth2  gw  $iface_eth2_gw  dev  eth2
    /usr/sbin/squid  -k  reconfigure
    for  mail  in  $admin  ;  do
    echo  "Link  secundário  da  interface  eth2 ativado"  |  /usr/bin/mail  -s  "[Empresa]  Link  Internet  secundário  da  interface  eth2 ativado  em  $date  as  $time"  $mail
    done

}


# Checa se ambos os links estao disponiveis ...
if  /usr/bin/fping  -q  $host_eth1  &&  /usr/bin/fping  -q  $host_eth2;  then

    if [  $deflt_gw  =  $pref_gw  ]  ;  then
            echo  "Links  OK!!"
    else
            link_iface_eth1
    fi

else
    if [  $deflt_gw  =  $iface_eth2_gw  ]  ;  then
            echo  "Scundário  Ativo"
    else
    if  /usr/bin/fping  -q  $host_eth2  ;  then
            link_iface_eth2
    fi
    fi
fi

Finalizo por aqui meu primeiro artigo, salientando a simplicidade e eficiência deste método nos ambientes onde implantei.

Espero ter ajudado de alguma forma.

Abraço.

Página anterior    

Páginas do artigo
   1. Instalando o Mon
   2. O script
Outros artigos deste autor

Elastix - Instalando, criando ramais e SIP Trunk Vono

Consumo de link com Cacti

Leitura recomendada

Linux com boot no Pendrive, com todas as facilidades: Smart-USB_Key-Mania, PLOP Boot Manager e outros métodos

Automatizando a conexão com Internet via ADSL com PPPoE no OpenBSD

KeepAlive para conexão discada (ou não)

Criando uma ISO bootável do OpenBSD

Convertendo TXT ou HTML em OGG

  
Comentários
[1] Comentário enviado por danniel-lara em 03/12/2012 - 09:54h

Parabéns pelo artigo

[2] Comentário enviado por correiabrux em 03/12/2012 - 11:52h

Obrigado pelo incentivo Daniel.

Abraço.

[3] Comentário enviado por ragen em 03/12/2012 - 16:05h

Bruno,

Como você faria no caso de um link com ppp0? Por exemplo um link de ADSL sem ip fixo, por via de regra, a cada nova autenticação o GW da interface ppp0 pode variar.

Tem uma idéia de qual seria uma boa saída para este problema?

Abs

[4] Comentário enviado por correiabrux em 03/12/2012 - 17:15h

Olá Ragen.

Tenho uma sugestão para o seu caso sim.
Estou considerando que as suas configurações para conexão ppp estejam ok.

Nas distribuições baseadas em Debian, quando um ip é atribuído por DHCP, existe um arquivo que armazena os ips atribuídos, além de rotas, DNS e etc...

O aruiqvo é o dhclient.leases e fica em /var/lib/dhcp/

/var/lib/dhcp/dhclient.leases

Desse arquivo você pode coletar os dados para as variáveis do script de redundância.

Por exemplo:

# Gateway do link da interface eth2
iface_eth2_gw=`/bin/cat /var/lib/dhcp/dhclient.leases | /bin/grep route | /usr/bin/tail -n1 | /usr/bin/awk {'print $3'}| /usr/bin/cut -d ";" -f 1`

# Endereco IP da interface eth2
iface_eth2_ip=`/bin/cat /var/lib/dhcp/dhclient.leases | /bin/grep fixed-address | /usr/bin/tail -n1 | /usr/bin/awk {'print $2'} | /usr/bin/cut -d ";" -f 1`

Note que utilizei `(crase)`, pois assim o script entenderá o resultado do comando cat, que está filtrando somente o ip e rota utilizando awk e cut.

Como não tenho um ambiente parecido aqui pra testes, não posso afirmar com certeza se somente essas intervenções no script resolveriam o seu problema.

Espero ter ajudado, abraço !

[5] Comentário enviado por ragen em 03/12/2012 - 20:19h

Olá Bruno,

Ajudou muito! No meu ambiente o dhclient.leases não armazena ip e rota, mas usando um "ifconfig" em tenho o ip e gw da interface ppp0 - o script que irei montar deriva-se do seu raciocínio. Não tinha pensado nesta possibilidade de usar este script inline (com crases).

Cara muito obrigado mesmo pela idéia, simples e tenho quase certeza que resolverá meu problema!

Abs

[6] Comentário enviado por correiabrux em 03/12/2012 - 20:23h

Maravilha Ragen, boa sorte aí, qualquer coisa entra em contato de novo.

Abraço.

[7] Comentário enviado por canovato em 05/12/2012 - 12:22h

Bruno,

Utilizo o linux a pouco tempo, gostei do seu artigo, mas quero tirar umas dúvidas antes de tentar utilizá-lo. Por isso peço a sua ajuda.

1. No arquivo /etc/network/interfaces você disse para adicionar as linhas abaixo. Mas isso é antes ou depois de configurar a rede eth0, eth1 e eth2,

post-up route add -host 8.8.8.8 gw 189.10.11.12 dev eth1
post-up route add -host 8.8.4.4 gw 201.10.11.12 dev eth2

No meu caso quero trabalhar com a rede assim:

eth0 - rede interna
eth1 - link 1
eth2 - link 2


2. Como fica o arquivo do firewall?
Hoje quando tenho problemas eu faço a troca manual de link, o que é totalmente trabalhoso e errado, por isso seu artigo seria ideal para eu utilizar aqui.

O que eu tenho de fazer no firewall para ele entender que pode haver a troca de link, assim como o mascaramento entender isso também?

O meu firewall está + ou - como descrito abaixo, sendo que ele só trata da rede interna com um link ativo.


#!/bin/sh

# Variaveis
# -------------------------------------------------------
iptables=/sbin/iptables
IF_INTERNA=eth0
IF_EXTERNA=eth1

# Ativa moulos
# -------------------------------------------------------
/sbin/modprobe iptable_nat
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_REJECT
/sbin/modprobe ipt_MASQUERADE

# Ativa roteamento no kernel
# -------------------------------------------------------
echo "1" > /proc/sys/net/ipv4/ip_forward

# Zera regras
# -------------------------------------------------------
$iptables -F
$iptables -X
$iptables -F -t nat
$iptables -X -t nat
$iptables -F -t mangle
$iptables -X -t mangle

# Determina a politica padrao
# -------------------------------------------------------
$iptables -P INPUT DROP
$iptables -P OUTPUT DROP
$iptables -P FORWARD DROP

#################################
#várias regras abaixo disso

# Ativa mascaramento de saida
# -------------------------------------------------------
$iptables -A POSTROUTING -t nat -o $IF_EXTERNA -j MASQUERADE

# Proxy transparente
# -------------------------------------------------------
$iptables -t nat -A PREROUTING -i $IF_INTERNA -p tcp --dport 80 -j REDIRECT --to-port 3128
$iptables -t nat -A PREROUTING -i $IF_INTERNA -p tcp --dport 8080 -j REDIRECT --to-port 3128


Pode me ajudar?

[8] Comentário enviado por correiabrux em 05/12/2012 - 12:57h

Olá Carlos, tudo bem ?
Vi no seu perfil que é do Rio de Janeiro, estive aí recentemente a trabalho, lugar maravilhoso!!

Bom, vamos ao que interessa...
.
Sobre as rotas em /etc/network/interfaces, acredito que possa colocar as rotas no rodapé do arquivo, após as configurações de ip e gateway de cada interface. Mas costumo configurar da seguinte maneira, somente por questão de organização:

auto eth1
iface eth1 inet static
address 189.10.11.13
netmask 255.255.255.252
gateway 189.10.11.12
post-up route add -host 8.8.8.8 gw 189.10.11.12 dev eth1

auto eth2
iface eth2 inet static
address 201.10.11.13
netmask 255.255.255.252
gateway 201.10.11.12
post-up route add -host 8.8.4.4 gw 201.10.11.12 dev eth2

Sobre o script de firewall, eu faria alterações nas regras que fazem referência as interfaces de internet, como no exemplo abaixo:

## Antiga regra de mascaramento de saída
## $iptables -A POSTROUTING -t nat -o $IF_EXTERNA -j MASQUERADE

## Nova regra de mascaramento de saída
$iptables -A POSTROUTING -s $REDE_INTERNA -t nat -j MASQUERADE

Dessa maneira o mascaramento será feito considerando somente a rota padrão atual atribuída pelo script, independente da interface que detém a default route no momento.

Espero ter ajudado, abraço !

[9] Comentário enviado por thaleseduardo em 29/12/2012 - 18:05h

Beleza correiabrux, muito bom o artigo parabens. Mas gostaria de deixar uma "correçãozinha" na checagem se ambos os links estao disponiveis.

Do jeito que tá se o link 1 cair o link 2 assume. ok!!!
Caso o link 2 tambem caia ficando: link 1 off e link 2 off.

Quando o link 1 "voltar", não vai ser ativado pelo script por causa da checagem:
"if /usr/bin/fping -q $host_eth1 && /usr/bin/fping -q $host_eth2; then "

Então fiz umas alteração e que deram certo. Olha só como ficou:

if /usr/bin/fping -q $host_eth1 ; then

if [ $deflt_gw = $pref_gw ]; then
echo " Primario Ativo "
if /usr/bin/fping -q $host_eth2 ; then
echo " Secundario OK"
echo " LINKS OK "
else
echo " Secudario Down "
fi
else
link_iface_eth1
fi

else
if /usr/bin/fping -q $host_eth2 ; then

if [ $deflt_gw = $iface_eth2_gw ]; then
echo " Secundario Ativo "
echo " Primario Down "
else
link_iface_eth2
fi
else
echo " Primario Down "
echo " Secudario Down "
fi
fi

Depois testa. valeu

[10] Comentário enviado por correiabrux em 29/12/2012 - 18:18h

Legal Thales, obrigado!

[11] Comentário enviado por phomix em 25/02/2013 - 21:40h

olá amigos.

Trabalho com linux a algum tempo, mas sei tenho um conhecimento limitado.

Não consegui fazer funcionar o Script no MON, por isso o adaptei e inseri no crontab para executar a cada minuto, ai ta funcionando blz.

Segue o script.

#!/bin/bash

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH

# Host a ser pingado pela eth0
host_eth0="8.8.8.8"
# Host a ser pingado pela eth1
host_eth1="8.8.4.4"
# Gateway preferido
pref_gw="192.168.0.254"
# Gateway padrao atual
deflt_gw=$(/sbin/route -n | grep ^0.0.0.0 | awk '{print $2}' | /usr/bin/head -n1)
# Gateway do link da inetrface eth0
iface_eth0_gw="192.168.0.254"
# Gateway do link da interface eth1
iface_eth1_gw="192.168.1.254"
# Interface do link/gateway preferido
iface_pref_gw="eth0"
# Endereco de e-mail de administrador
admin="davi_tec_clientes@yahoo.com.br"
# Data atual
date=$(date +%d-%m-%Y)
# Hora atual
time=$(date +%H:%M:%S)
# Endereco IP da interface eth0
iface_eth0_ip="192.168.0.253"
# Endereco IP da interface eth1
iface_eth1_ip="192.168.1.253"

# Funcao para trocar para o link da interface eth1
link_iface_eth0() {

/sbin/route del default gw $iface_eth1_gw
/sbin/route add default gw $iface_eth0_gw dev eth0
/sbin/route del -host $host_eth0 gw $iface_eth0_gw dev eth0 || true
/sbin/route del -host $host_eth1 gw $iface_eth1_gw dev eth1 || true
/sbin/route add -host $host_eth0 gw $iface_eth0_gw dev eth0
/sbin/route add -host $host_eth1 gw $iface_eth1_gw dev eth1
/usr/sbin/squid3 -k reconfigure
for mail in $admin ; do
echo "Link prim�rio da interface eth0 ativado" | /usr/bin/mail -s "[Empresa] Link Internet prim�rio da int$done
}

# Funcao para trocar para o link da interface eth0
link_iface_eth1() {

/sbin/route del default gw $iface_eth0_gw
/sbin/route add default gw $iface_eth1_gw dev eth1
/sbin/route del -host $host_eth0 gw $iface_eth0_gw dev eth0 || true
/sbin/route del -host $host_eth1 gw $iface_eth1_gw dev eth1 || true
/sbin/route add -host $host_eth0 gw $iface_eth0_gw dev eth0
/sbin/route add -host $host_eth1 gw $iface_eth1_gw dev eth1
/usr/sbin/squid -k reconfigure
for mail in $admin ; do
echo "Link secund�rio da interface eth1 ativado" | /usr/bin/mail -s "[Empresa] Link Internet secund�rio da $done

}

# Checa se ambos os links estao disponiveis ...
if (/bin/ping -I eth0 -c1 $host_eth0 && /bin/ping -I eth1 -c1 $host_eth1); then

if [ $deflt_gw = $pref_gw ] ; then
echo "Links OK!!"
else
link_iface_eth0
echo "PREFERENCIAL UP, VOLTANDO LINK PRIMARIO"
echo "PREFERENCIAL UP,VOLTANDO LINK PRIMARIO" >> /var/log/reduntante.log
date >> /var/log/reduntante.log
a $fi

else
if [ $deflt_gw = $iface_eth1_gw ] ; then
echo "USANDO LINK SECUNDARIO, PRIMARIO DOWN"
else
if (/bin/ping -I eth1 -c1 $host_eth1) ; then
link_iface_eth1
echo "LINK PRIMARIO DOWN, ATIVANDO SECUNDARIO"
echo "LINK PRIMARIO DOWN, ATIVANDO SECUNDARIO" >> /var/log/reduntante.log
date >> /var/log/reduntante.log
else
echo "UTILIZANDO LINK PRIMARIO, SECUNDARIO DOWN"
echo "UTILIZANDO LINK PRIMARIO, SECUNDARIO DOWN" >> /var/log/reduntante.log
date >> /var/log/reduntante.log
fi
fi
fi


Caso tenham alguma informação de como fazer funcionar no MON aguardo resposta, e caso alguem veja uma forma de melhorar o scrip sugestoes são bem vindas.


Abraços.

[12] Comentário enviado por phomix em 25/02/2013 - 21:42h

A detalhe, nao sei porque o Fping nao estava conseguindo pingar os endereços, por isso troquei pelo ping...


Contribuir com comentário