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.766 ]

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


Instalando o Mon



Para melhor funcionamento do script desenvolvido, optei por fazer a chamada deste script a partir do Mon, que é uma ferramenta muito utilizada para fins de monitoramento de disponibilidade.

Utilizando distribuições baseadas em Debian, execute o seguinte comando:

# aptitude install mon

O Debian deve, automaticamente, executar o Mon nas próximas reinicializações.

Edite o arquivo /etc/mon/mon.cf e deixe-o da seguinte maneira:

# Definições globais
serverbind = localhost
trapbind = localhost
cfbasedir = /etc/mon
alertdir = /usr/lib/mon/alert.d
mondir = /usr/lib/mon/mon.d
maxprocs = 20
histlength = 100
randstart = 30s
logdir = /var/log/mon
dtlogfile = /var/log/mon/downtime.log
dtlogging = yes
monerrfile = /var/log/mon/error

# Definição do hostgroup de nome "localnode"
# contendo o host local (localhost)

hostgroup localnode localhost

# Monitorar hostgroup de nome "localnode"
watch localnode
   # Serviços  a  serem  checados
   service  availability
      description  Checagem de disponibilidade dos links Internet
      interval  5s
      monitor   availability.monitor
      period    wd  {Mon-Sun}

O script irá atuar testando os links para tomar ações de remoção e adição de rotas conforme disponibilidade dos links.

Abaixo, as possibilidades e ações que o script irá tomar:
  1. Link 1 OK | Link2 OK → Verifica as rotas e mantém como rota padrão a rota apontada na variável: $pref_gw
  2. Link1 Down | Link 2 Ok → Verifica as rotas e mantém como rota padrão a rota apontada na variável: $iface_eth2_gw
  3. Link1 OK | Link2 Down → O script não toma ações. Para este caso, mantenho um servidor Zabbix que monitora os links e informa as falhas do secundário mesmo que não seja a rota padrão.

Segue o script na página seguinte.

    Próxima página

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

Script de backup full + diferencial + compactador + restauração

XML de NF-e ou CT-e ou MDF-e - Como validar usando os pacotes de esquemas do Governo

Brincando com vetores - complemento

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

Formatando o bash com cores e efeitos

  
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