você está aqui: Home  → Arquivo de Mensagens

Balanceamento de links com ip dinamico

Colaboração: Altemir Braz Dantas Junior

Data de Publicação: 10 de outubro de 2011

Sempre fiz balanceamento de links com ip fixo usando iproute2 + iptables, até que um cliente que tinha 3 links de internet com ip dinamico, ai pensei "puts vai zoar as rotas do balanceamento toda hora que trocar o gateway, vou ter que criar varios scripts para ficar monitorando e trocar a rota, vamos googlear".

O google é meu pastor e nada me faltará. rsrsrsr

Achei o que queria e vou apresentar-lo meu salvador dhclient-script, disponível a partir da versão 3 do dhclient.

Verifiquei que através dele eu poderia pegar informações importantes como as do exemplo abaixo

OBS: Nao mencionarei regras de iptables (INPUT, OUTPUT, FORWARD , MASQUERADE e etc) aqui, somente a criacao das rotas

  reason='RENEW'
  interface='eth1'
  medium=''
  alias_ip_address=''
  new_ip_address='189.xxx.xxx.xxx'
  new_subnet_mask='255.255.240.0'
  new_domain_name=''
  new_domain_search=''
  new_domain_name_servers='8.8.8.8 4.2.2.2'
  new_routers='189.xxx.xxx.1'
  new_static_routes=''
  old_ip_address='189.yyy.yyy.yyy'
  old_subnet_mask='255.255.240.0'
  old_domain_name='spo.virtua.com.br'
  old_domain_search=''
  old_domain_name_servers='8.8.8.8 4.2.2.2'
  old_routers='189.yyy.yyy.1'
  old_static_routes=''

E o melhor ele me retorna como variaveis para eu usar no meu shell script na hora de cada ação

O dhclient-script usa o Bourne Shell.

Para voces entenderem melhor leiam o man.

Ambiente

  • eth0 - rede interna
  • eth1 - link1 100MG
  • eth2 - link2 20MG
  • eth3 - link3 4MG
  • link1 usei a marca 1 e peso 6
  • link2 usei a marca 2 e peso 3
  • link3 usei a marca 3 e peso 1

Como uso debian vou mostrar como fiz nesta distribuição.

Instalando pacotes necessários

  apt-get install dhclient3 ipcalc iproute2

Primeiramente vou criar as tabelas no iproute2

  echo "201	link1" >>  /etc/iproute2/rt_tables
  echo "202	link2" >>  /etc/iproute2/rt_tables
  echo "203	link3" >>  /etc/iproute2/rt_tables

Agora cria minhas functions

  mkdir /etc/scripts
  vi /etc/scripts/function.sh

Contendo o seguinte

  # recebe a interface da rede e retorna o nome da tabela cadastrada
  pega_tabela(){
       DEV=$1
       case $DEV in
       eth1)
               TABELA="link1"
               return 1
               break
               ;;
       eth2)
               TABELA="link2"
               return 1
               break
               ;;
       eth3)
               TABELA="link3"
               return 1
               break
               ;;
       esac
  }
  
  # recebe a interface da rede e retorna o numero da marcacao para poder usar rotas pela marcacao feita pelo iptables
  pega_marca(){
       DEV=$1
       case $DEV in
       eth1)
               MARK="1"
               return 1
               break
               ;;
       eth2)
               MARK="2"
               return 1
               break
               ;;
       eth3)
               MARK="3"
               return 1
               break
               ;;
       esac
  }
  
  # recebe a interface da rede e retorna o peso para fazer o balanceamento
  
  pega_peso(){
       DEV=$1
       case $DEV in
       eth1)
               PESO="6"
               return 1
               break
               ;;
       eth2)
               PESO="3"
               return 1
               break
               ;;
       eth3)
               PESO="1"
               return 1
               break
               ;;
       esac
  }
  
  # recebe a tabela e retorna o ip do gateway da mesma
  pega_gateway(){
       TABELA=$1
       GATEWAY=$(ip route show table $TABELA | grep default | awk -F' ' '{ print $3 }')
  }
  
  
  # recebe a tabela e deleta todas as rotas da mesma
  del_rotas(){
       /sbin/ip route flush table $1
  }
  
  # recebe a tabela e deleta todas as regras  da mesma
  del_regras(){
       ip rule show | grep $1 | cut -d : -f2 | while read RULES;  do ip rule del $RULES ; done
  }
  
  # recebe a tabela,ip,marca  e cria regras de roteamento para aquela tabela
  add_regras(){
       TABELA=$1
       IP=$2
       MARK=$3
       ip rule add fwmark $MARK table $TABELA
       ip rule add from $IP table $TABELA
  }
  
  # recebe a tabela,ip,interface,ip da rede e o ip do gateway  para criar as rotas para aquela tabela
  add_rotas(){
       TABELA=$1
       IP=$2
       DEV=$3
       REDE=$4
       GW=$5
       /sbin/ip route add $REDE dev $DEV src $IP table $TABELA
       /sbin/ip route add default via $GW dev $DEV table $TABELA
  }
  
  # deleta todas as rotas padrao
  del_rotas_padrao(){
       # deletando as rotas default
       # deleta a rota criada pelo dhcp
       /sbin/ip route del default
       # deleta a rota do balanceamento
       /sbin/ip route del default
  }
  
  # recebe interface,ip do gateway e peso para criar as regras de balanceamento
  add_rota_balanceamento(){
       DEVNEW=$1
       GWNEW=$2
       PESONEW=$3
  
       case $DEVNEW in
       eth1)
               pega_tabela eth2
               pega_peso eth2
               pega_gateway $TABELA
               TABELA2=$TABELA
               PESO2=$PESO
               GW2=$GATEWAY
               DEV2=eth2
  
               pega_tabela eth3
               pega_peso eth3
               pega_gateway $TABELA
               TABELA3=$TABELA
               PESO3=$PESO
               GW3=$GATEWAY
               DEV3=eth3
               ;;
  
       eth2)
               pega_tabela eth1
               pega_peso eth1
               pega_gateway $TABELA
               TABELA2=$TABELA
               PESO2=$PESO
               GW2=$GATEWAY
               DEV2=eth1
  
               pega_tabela eth3
               pega_peso eth3
               pega_gateway $TABELA
               TABELA3=$TABELA
               PESO3=$PESO
               GW3=$GATEWAY
               DEV3=eth3
               ;;
       eth3)
               pega_tabela eth1
               pega_peso eth1
               pega_gateway $TABELA
               TABELA2=$TABELA
               PESO2=$PESO
               GW2=$GATEWAY
               DEV2=eth1
  
  					 pega_tabela eth2
               pega_peso eth2
               pega_gateway $TABELA
               TABELA3=$TABELA
               PESO3=$PESO
               GW3=$GATEWAY
               DEV3=eth2
               ;;
       esac
  
  
       if [ "$GWNEW" == "0" ]; then
               if [ "$GW2" != "" -a $GW3 != "" ]; then
                       /sbin/ip route add default nexthop via $GW2 dev $DEV2 weight $PESO2 nexthop via $GW3 dev $DEV3 weight $PESO3
               else
                       if [ "$GW2" != "" ]; then
                               /sbin/ip route add default via $GW2
                       else
                               /sbin/ip route add default via $GW3
                       fi
               fi
       else
               if [ "$GW2" != "" -a $GW3 != "" ]; then
                       /sbin/ip route add default nexthop via $GWNEW dev $DEVNEW weight $PESONEW nexthop via $GW2 dev $DEV2 weight $PESO2 nexthop via $GW3 dev $DEV3 weight $PESO3
               else
                       if [ "$GW2" != "" ]; then
                               /sbin/ip route add default nexthop via $GWNEW dev $DEVNEW weight $PESONEW nexthop via $GW2 dev $DEV2 weight $PESO2
                       else
                               if [ "$GW3" != "" ]; then
                                       /sbin/ip route add default nexthop via $GWNEW dev $DEVNEW weight $PESONEW nexthop via $GW3 dev $DEV3 weight $PESO3
                               else
                                       /sbin/ip route add default via $GWNEW
  											fi
  
                       fi
               fi
  
       fi
       return 1;
  }

Criado o arquivo das functions agora vou criar os scripts para o dhclient-script

Dentro do diretorio /etc/dhcp/ existem dois diretorios o dhclient-enter-hooks.d/ e o dhclient-exit-hooks.d/ e o arquivo dhclient.conf

No arquivo dhclient.conf procure a linha comentada

  #prepend domain-name-servers

Descomente e coloque os seguintes DNS publicos

  prepend domain-name-servers 8.8.8.8 4.2.2.2;

Assim toda vez que o servidor dhcp nos atribuir seus servidores DNS ele vai adicionar esses 2 antes do dele.

Em relação aos diretorios antes dele, fazer alteracoes em nosso /etc/resolve.conf o dhclient script vai checar se há scripts primeiramente dentro de dhclient-enter-hooks.d/ usando o "." (ponto).

Quem usa Bourne Shell (bash) sabe que é como um include no diretorio. Depois de executar ele faz a mesma operacao no diretorio dhclient-exit-hooks.d/

Para mais informações

  man dhclient-script

Criei então o seguinte script dentro do diretorio dhclient-enter-hooks.d/:

  vi /etc/dhcp/dhclient-enter-hooks.d/rotas_avancadas

Contendo

  
  # da um include na minha function
  . /etc/scripts/function.sh
  
  # ok = 0 -> link fora - deleta rotas para esse link
  # ok = 1 -> link ok e novo ip - altera rotas desse link
  # ok = 2 -> link ok e o ip nao mudou portanto nao faca nada
  
  # setei ok = 2 para nao fazer nada
  
  ok=2
  
  if [ "$reason" == "REBOOT" -o "$reason" == "RENEW" -o "$reason" == "BOUND" -o "$reason" == "REBIND" ]; then
      
       # Se o novo ip for igual a nada setar ok = 0
       if [ "$new_ip_address" == "" ]; then
               ok=0
       fi
      
       # Se o novo ip tem o inicio igual 192 quer dizer que o dhcp me deu ip porem esta sem internet entao seta ok = 0
       inicioip=$(echo $new_ip_address | cut -d "." -f 1)
       if [ "$inicioip" == "192" ]; then
               ok=0
       fi
  
  		  # se o ok continua igua a 2 é porque ele passou dos itens acima
       if [ "$ok" == "2" ];then
       			 # se o ip diferente do antigo seto o ok=1
               if [ "$new_ip_address" != "$old_ip_address" ];then
                       ok=1;
               fi
       fi
  
  fi
  
  # Se aontecer uma das acoes abaixo é que o servidor dhcp falhou entao seto o ok=0
  if [ "$reason" == "FAIL" -o "$reason" == "TIMEOUT" -o "$reason" == "EXPIRE" ]; then
       ok=0;
  fi

Depois disso criei o seguinte script

  vi /etc/dhcp/dhclient-exit-hooks.d/rotas_avancadas

Contendo

  
  # ja tenho os meus ok definidos no script anterior e minha functions incluidas tambem ai faco minhas acoes
  if [ "$ok" == "1" ]; then
  		  # pego minhas variaveis
  		  pega_tabela $interface
       pega_marca $interface
       pega_peso $interface
     
  		  # calcula o ip da rede       
       ipcalcule=$(echo "$new_ip_address/$new_subnet_mask")
       my_new_network=$(ipcalc -n $ipcalcule | grep Network | cut -b 12-32)
      
       # deleta regra antiga e cria regras novas
       del_regras $TABELA
       add_regras $TABELA $new_ip_address $MARK
      
       #deleta rotas antigas e cria novas
       del_rotas $TABELA
       add_rotas $TABELA $new_ip_address $interface $my_new_network $new_routers
       del_rotas_padrao
       add_rota_balanceamento $interface $new_routers $PESO
    
  fi
  
  if [ "$ok" == "0" ]; then
       pega_tabela $interface
       del_rotas $TABELA
       del_regras $TABELA
       del_rotas_padrao
       add_rota_balanceamento $interface 0 0
  fi
  
  

Agora é só executar

  dhclient -v eth1
  dhclient -v eth2
  dhclient -v eth3

Olhar como ficou as rotas

  ip route show
  ip route show table link1
  ip route show table link2
  ip route show table link3

Para ver como ficaram as regras:

  ip rule show

Para testar com o ip route get para ver qual a rota que ele usaria para sair para um determinado destino:

  ip route get 8.8.8.8
  ip route get 4.2.2.2
  ip route get 174.120.154.93

E fazer seus testes

Altemir Braz Dantas Junior (jocajuni) http://acessa.me/@joca, http://acessa.me - crie seu atendimento online gratuito

Linux e Mercado

Colaboração: Fátima Conti

Visto em http://visualoop.tumblr.com/post/9430080645/linux-market-shares



Veja a relação completa dos artigos de Altemir Braz Dantas Junior

 

 

Opinião dos Leitores

jmuramatsu
06 Dez 2011, 08:26
Olá Joca, outra coisa que percebi é que no script você marca o link1 com o fwmark 1 e o link2 com o fwmark 2, então no firewall eu teria que criar na tabela mangle a marca das saídas, por exemplo, sites https assim:

#iptables -t mangle -A PREROUTING -p tcp --dport 443 -d 0.0.0.0/0.0.0.0 -j MARK --set-mark 1

Pra todos IPs internos sairem pelo link1, certo? Fora isso tem outro jeito, já que tentei assim e não consegui?

Valeu
jmuramatsu
05 Dez 2011, 14:26
Olá Joca, blz?

O balanceamento está ok, funcionando normalmente.

Agora tenho um problema, veja se vc consegue me ajudar, como tem 2 links as vezes eu entro em algum site que tenha login (banco, etc) e depois de logar se eu clico em algum link ele volta pra tela pra fazer login novamente, acho que ele foi por um link e depois balanceou pra outro link, na tabela eu tentei colocar um IP interno pra acessar somente por um link com o comando "ip rule add from 10.10.10.101 lookup speedy" e "ip route flush cached" mas não funcionou, se eu testo pelo www.meuip.com.br ele retorna os 2 IPs diferentes (speedy e virtua), vc saberia me dizer como eu seto um IP ou site especifico pra sair somente por um IP (speedy ou virtua)?

Obrigado
Altemir Braz Dantas Junior
18 Out 2011, 14:10
Pode comentar sim pois ele estará pegando o dhclient pelo rc.local

#auto eth0
#iface eth0 inet dhcp

#auto eth1
#iface eth1 inet dhcp

[]s
Altemir Braz Dantas Junior - Jocajuni
jmuramatsu
18 Out 2011, 11:11
Altemir, muito obrigado, era isso mesmo que faltava, valeu mesmo. Agora está dividindo a conexão entre os links.

Outra coisa, o interfaces está assim:
auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet dhcp

Tá certo isso, né? Ou posso retirar a linha "iface ethx inet dhcp" pra ele pegar pelo "dhclient -v ethx"?

Muito obrigado pela ajuda cara.

[]'s
Altemir Braz Dantas Junior
17 Out 2011, 16:05
Isso realmente não tinha testado se no boot ele nao executa,
na teoria era para funcionar , entao vamos fazer o seguinte.

Quando vc executa na mao funciona ne?

Faca o seguinte teste coloque essas 2 linhas no seu /etc/rc.local antes da linha do exit 0;

dhclient -v eth0
dhclient -v eth1
exit 0

e reboota e veja se funciona

[]s
Altemir Braz Dantas Junior (Jocajuni)

jmuramatsu
17 Out 2011, 07:32
Olá Altemir, adicionei o echo mas não aparece nada no boot, pelo que vi ele não roda o /etc/dhcp/dhclient-enter-hooks.d/rotas_avancadas no boot, porque depois de logado dei o comanado # dhclient -v eth0 e ele apareceu o echo e depois adicionou a rota. Isso não era pra rodar no boot, na hora que ele pega o IP pelo DHCP? Olha o que aparece no boot:

Listening on LPF/eth0/00:0x:5x:65:x3:7x
Sending on LPF/eth0/00:0x:5x:65:x3:7x
Sending on Socket/fallback
DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5
Setting kernel variables ...done.
DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 5
DHCPOFFER from 189.19.216.1
DHCPREQUEST on eth0 to 255.255.255.255 port 67
DHCPACK from 189.19.216.1
bound to 189.19.216.98 -- renewal in 36381 seconds.
Internet Systems Consortium DHCP Client 4.1.1-P1
Copyright 2004-2010 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/eth1/00:0x:5x:65:x9:xx
Sending on LPF/eth1/00:0x:5x:65:x9:xx
Sending on Socket/fallback
DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 4
DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 7
DHCPOFFER from 189.47.144.1
DHCPREQUEST on eth1 to 255.255.255.255 port 67
DHCPACK from 189.47.144.1
bound to 189.47.144.99 -- renewal in 42891 seconds.
done.

[]'s
Altemir Braz Dantas Junior
14 Out 2011, 13:11
Realmete deve tger algo de errado.

faca o seguinte coloque nas functions os ecos dos comandos exemplo

add_rotas(){
TABELA=$1
IP=$2
DEV=$3
REDE=$4
GW=$5
/sbin/ip route add $REDE dev $DEV src $IP table $TABELA
/sbin/ip route add default via $GW dev $DEV table $TABELA
echo "/sbin/ip route add $REDE dev $DEV src $IP table $TABELA"
echo "/sbin/ip route add default via $GW dev $DEV table $TABELA"

}

veja se ele imprime o comando corretamente se imprimir corretamente copia e cole e veja se da erro ao executar

[]s
Joca

jmuramatsu
14 Out 2011, 07:33
Então Altemir, coloquei os pesos igual a 1 e continua igual, notei que alguns comandos não estão retornando o conteúdo das tabelas, veja:

# ip route show
189.19.216.0/24 dev eth0 proto kernel scope link src 189.19.216.98 #link virtua
189.47.144.0/24 dev eth1 proto kernel scope link src 189.47.144.99 #link speedy
10.10.10.0/24 dev eth2 proto kernel scope link src 10.10.10.254 #rede interna sendo o 10.10.10.254 o firewal/squid
default via 189.47.144.1 dev eth1 #placa speedy
default via 189.19.216.1 dev eth0 #placa virtua

# ip route show table virtua
Não retorna nada

# ip route show table speedy
Não retorna nada também

# ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default

Não deveria aparecer as tabelas virtua e speedy que eu criei no /etc/iproute2/rt_tables?

Estou achando que a minha /etc/scripts/function.sh tem algum pau, ela não deveria setar essas 2 tabelas com os IPs/Gateways?

OBS: meu /etc/rc.local só tem exit 0, é isso mesmo? Não tem que adicionar nada aqui?

Obrigado pela ajuda.
Altemir Braz Dantas Junior
13 Out 2011, 18:54
Fez Certinho.

Faça um teste coloca os dois pesos como 1
levante as regras novas
baixe 4 downloads simultaneos

Veja os resutados

[]s
Altemir Braz Dantas Junior (Jocajuni)
jmuramatsu
13 Out 2011, 14:30
Olá Altemir, muito bom o seu artigo.

Eu tenho 2 links (Virtua e Speedy) e fiz algumas alterações nos scripts, veja se está certo:

Ambiente:
eth0 - link1 10Mb
eth1 - link2 4Mb
eth2 - rede interna

link1 usei a marca 1 e peso 4
link2 usei a marca 2 e peso 1

Criei 2 novas entradas na /etc/iproute2/rt_tables:
201 virtua #equivalente ao link1
202 speedy #equivalente ao link2


Alterei a /etc/scripts/function.sh pra 2 placas (eth0-virtua e eth1-speedy), está certo ou fiz alguma besteira?

# recebe a interface da rede e retorna o nome da tabela cadastrada
pega_tabela(){
DEV=$1
case $DEV in
eth0)
TABELA="virtua"
return 1
break
;;
eth1)
TABELA="speedy"
return 1
break
;;
esac
}

# recebe a interface da rede e retorna o numero da marcacao para poder usar rotas pela marcacao feita pelo iptables
pega_marca(){
DEV=$1
case $DEV in
eth0)
MARK="1"
return 1
break
;;
eth1)
MARK="2"
return 1
break
;;
esac
}

# recebe a interface da rede e retorna o peso para fazer o balanceamento

pega_peso(){
DEV=$1
case $DEV in
eth0)
PESO="4"
return 1
break
;;
eth1)
PESO="1"
return 1
break
;;
esac
}

# recebe a tabela e retorna o ip do gateway da mesma
pega_gateway(){
TABELA=$1
GATEWAY=$(ip route show table $TABELA | grep default | awk -F' ' '{ print $3 }')
}


# recebe a tabela e deleta todas as rotas da mesma
del_rotas(){
/sbin/ip route flush table $1
}

# recebe a tabela e deleta todas as regras da mesma
del_regras(){
ip rule show | grep $1 | cut -d : -f2 | while read RULES; do ip rule del $RULES ; done
}

# recebe a tabela,ip,marca e cria regras de roteamento para aquela tabela
add_regras(){
TABELA=$1
IP=$2
MARK=$3
ip rule add fwmark $MARK table $TABELA
ip rule add from $IP table $TABELA
}

# recebe a tabela,ip,interface,ip da rede e o ip do gateway para criar as rotas para aquela tabela
add_rotas(){
TABELA=$1
IP=$2
DEV=$3
REDE=$4
GW=$5
/sbin/ip route add $REDE dev $DEV src $IP table $TABELA
/sbin/ip route add default via $GW dev $DEV table $TABELA
}

# deleta todas as rotas padrao
del_rotas_padrao(){
# deletando as rotas default
# deleta a rota criada pelo dhcp
/sbin/ip route del default
# deleta a rota do balanceamento
/sbin/ip route del default
}

# recebe interface,ip do gateway e peso para criar as regras de balanceamento
add_rota_balanceamento(){
DEVNEW=$1
GWNEW=$2
PESONEW=$3

case $DEVNEW in
eth0)
pega_tabela eth1
pega_peso eth1
pega_gateway $TABELA
TABELA2=$TABELA
PESO2=$PESO
GW2=$GATEWAY
DEV2=eth1
;;

eth1)
pega_tabela eth0
pega_peso eth0
pega_gateway $TABELA
TABELA2=$TABELA
PESO2=$PESO
GW2=$GATEWAY
DEV2=eth0
;;
esac


if [ "$GWNEW" == "0" ]; then
if [ "$GW2" != "" ]; then
/sbin/ip route add default nexthop via $GW2 dev $DEV2 weight $PESO2
else

/sbin/ip route add default via $GW2
fi
else
if [ "$GW2" != "" ]; then
/sbin/ip route add default nexthop via $GWNEW dev $DEVNEW weight $PESONEW nexthop via $GW2 dev $DEV2 weight $PESO2
else
if [ "$GW2" != "" ]; then
/sbin/ip route add default nexthop via $GWNEW dev $DEVNEW weight $PESONEW nexthop via $GW2 dev $DEV2 weight $PESO2
else
/sbin/ip route add default via $GWNEW

fi
fi

fi
return 1;
}

Bom, o resto ficou igual.

No Firewall eu adicionei as linhas:

# INICIO - load balance
# Variaveis para compartilhamento
### Multi WAN ###
ETH="eth+"

### Rede Lan ###
LAN="10.10.10.0/24" #rede interna

# Ativa o compartilhamento
iptables -t nat -A POSTROUTING -o $ETH -s $LAN -j MASQUERADE

# Ativa acessos que podem ir de uma interface mas que voltam por outra
# Fundamental estar desabilitado para funcionar o roteamento com 2 links.
echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter

# Tempo maximo que o kernel espera ate tentar uma nova rota quando perceber que a atual esta morta.
echo 10 > /proc/sys/net/ipv4/route/gc_timeout
# FIM - load balance

Quando testo no Debian ele funciona, se desligo o cabo da eth0 (virtua) ele fica com a eth1 (speedy) funcionando, se desligo o cabo da eth1 ele funciona a eth0, até ai tudo bem.

Agora a dúvida, quando utilizo uma estação com Win XP e baixo algum arquivo pelo DownThemAll do Firefox (ou qualquer outro download) ele só funciona o eth0, não divide o tráfego, tipo 4 conexões pra eth0 e 1 pra eth1, o modem do Speedy (eth1) fica parado, só funciona quando desligo a eth0, é assim mesmo?

Valeu
*Nome:
Email:
Me notifique sobre novos comentários nessa página
Oculte meu email
*Texto:
 
  Para publicar seu comentário, digite o código contido na imagem acima
 


Powered by Scriptsmill Comments Script