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

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

Consumo de link com Cacti

Elastix - Instalando, criando ramais e SIP Trunk Vono

Leitura recomendada

Colocado o "Motion" na inicialização do Ubuntu 7.04

Convertendo TXT ou HTML em OGG

Configurando OpenSSH no Windows Server 2003 para autenticação por chave (sem senha)

KDialog com Shell Script - Conversão de slides JPG para projetores com suporte a miniaturas de imagens

Impressora PDF via Samba para estações Windows

  
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




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts