Para conectarme a internet uso un router Wifi D-Link DSL-G624T regalado al contratar el ADSL con Ya.com. No es un mal router una vez configurado un poco, pero sufre algunos problemas para mantener la conexión a internet cuando se calienta en exceso o cuando la mula está encendida.
Sus cuelgues son curiosos, pues la Wireless sigue funcionando, pero la conexión a internet se cierra y el acceso al router por Web también. En cambio el acceso por telnet sigue operativo. Normalmente lo reseteo físicamente y en un par de minutos todo vuelve a la normalidad. El problema viene cuando no estoy en casa y no tengo acceso a él, con lo que no puedo restaurar la conexión a internet de la casa hasta que no vuelvo.
Chafardeando el router me encontré con que internamente funciona con un BusyBox pequeñito, que no deja de ser un mini-Linux con sus funcionalidades básicas…
En este artículo explico cómo realizar un script en nuestro servidor casero que comprueba el aceso a internet, y si no lo hay, que acceda al router y lo reinicie.
En primer lugar debo dar las gracias a i compañero Alex, pues me enseñó la forma de automatizar la conexión al router por telnet y su reseteo para embedirlo en un script Bash.
El truco consiste en un par de scripts: uno que efectúa el reseteo del router y otro que controla la lógica del programa. De hecho, se podría confeccionar un sólo script que haga todo el trabajo pero me gusta tener el script de reseteo por separado por si lo uso atómicamente en otra tarea.
Empezando por el script de reseteo, consiste en una sucesión de instrucciones que abren un telnet y le printan en su consola las instrucciones que queremos, esperando unos segundos entre instrucción e instrución para darle tiempo al shell de darnos los prompts necesarios.
En primer lugar creamos un archivo llamado restart_router.sh dentro de nuestro directorio de nuestras utilidades del sistema (en mi caso en /server/utils):
$ touch /server/utils/restart_router.sh
y entonces lo abrimos para editarlo:
$ vim /server/utils/restart_router.sh
Una vez abierto escribimos lo siguiente:
(sleep 3; echo “admin”; sleep 3; echo “contrasenya_router”; sleep 3; echo “/sbin/reboot”; sleep 3; echo “exit”) | telnet 192.168.1.1
Vamos a explicarlo… En primer lugar vemos que al final de la línea hay un telnet 192.168.1.1. Ésta es la instrucción que nos conecta con el router. A ella le pasaremos seguidamente el usuario (porque lo primero que hace es preguntarnos el usuario), la contraseña, y justo después la instrucción a ejecutar, haciendo luego un exit para que cierre la conexión. La forma de automatizar el proceso es pasarle las instrucciones mediante el pipe al telnet, hacer un echo de las instrucciones a ejecutar (deben estar entre dobles comillas) y separar las instrucciones con una pausa para darle tiempo a sacar el prompt (de ahí el sleep de 3 segundos). Deberemos sustituir la dirección IP de aquí con la IP de nuestro router y “contrasenya_servidor” con la contraseña que usamos para entrar al router. Debemos asegurarnos que está todo en una misma línea y que los parámetros están todos entre un mismo paréntesis.
Una vez guardado el archivo, debemos darle permisos de ejecución al archivo con, por ejemplo:
$ chmod +x /server/utils/restart_router.sh
A continuación, vamos a por el segundo script. Éste debe decidir si hay acceso a internet o no. Para ello haremos ping a un host de internet (por ejemplo a Google) y capturaremos la salida. De la salida nos quedamos con el número del porcentaje de paquetes perdidos que será lo que usaremos para distinguir si hay internet o no. Así que primero de todo creamos el archivo:
$ touch /server/utils/adsl_keep_online.sh
Y lo abrimos para editarlo:
$ vim /server/utils/adsl_keep_online.sh
Allí escribimos la cabecera del intérprete de comandos:
#!/bin/bash
Y ejecutamos el ping seleccionando la parte que nos interesa (el número del porcentaje de paquetes perdidos) y lo almacenamos en una variable llamada result:
result=`ping -c 5 www.google.com | grep “packet loss” | awk ‘{printf (”%d”,$6)}’`
En primer lugar, notemos que no hay espacios antes y después del signo igual. Luego, toda la línea del comando (lo que va después del igual) va encerrado entre acentos abiertos sin carácter (dándole al acento y luego un espacio). No confundirlo con comilla simple! La instrución ping la ponemos con el parámetro -c 5, que significa que sólo enviará 5 paquetes (si no ponemos nada, va enviando paquetes hasta el infinito). La salida la dirigimos al grep para que seleccione la línea que contiene “packet loss” (encerrado entre comillas dobles). La salida de ésto la dirigimos al awk, que nos saque sólamente la columna 6, formateándolo en decimal para quitar el símbolo del porcentaje.
A continuación, miramos con un if si el resultado del ping es mayor al 50% en paquetes perdidos. Si es así ejecutamos nuestro primer script para reiniciar el router. Además, aprovecho la salida para redirigirla a un archivo log situado en /server/logs/adsl.log y dejar constancia así de las verificaciones que se lleban a cabo cada vez que se ejecuta el programa. El archivo queda finalmente así:
#!/bin/bash
result=`ping -c 5 www.google.com | grep “packet loss” | awk ‘{printf (”%d”,$6)}’`
if [ “$result” -gt “50″ ]; then
echo “`date` [KO]: $result% perdido. Rebotando Router” >> /server/logs/adsl.log
echo “————————————>>>>>>>>>>>>>” >> /server/logs/adsl.log
/home/utils/restart_router.sh >> /server/logs/adsl.log
echo “<<<<<<<<<<<<<------------------------------------" >> /server/logs/adsl.log
else
echo “`date` [OK]: $result% perdido” >> /server/logs/adsl.log
fi
Después de guardar debemos setar el archivo como ejecutable:
$ chmod +x /server/utils/adsl_keep_online.sh
Y ya por último queda por incluir este script en la lista de tareas a realizar periódicamente. Yo lo tengo ejecutando cada media hora. Así, debemos editar el archivo de cron:
$ crontab -e
Y añadir una línea de la siguiente forma:
0,30 * * * * /server/utils/adsl_keep_online.sh
Y ya lo tenemos funcionando. Ahora, cada media hora se va a ejecutar un ping de 5 paquetes. Si el resultado en paquetes perdidos es mayor que el 50% se reiniciará el router.
Los más sibaritas en sistemas me podrán decir que reiniciar el router entero por haber perdido la conexión a internet es demasiado bruto. Es verdad, pero aún no he hecho suficientes pruebas para encontrar cuál sería la mejor forma de llevar el objetivo a cabo. Si entramos por telnet al router y ejecutamos un ipconfig podremos ver que existe una interfície llamada ppp0 que es la relativa a el ADSL, pero reiniciar dicha interfície no solucionaría el cuelgue de la administración Web. Seguiré investigando.
Salud!
Tags: Bash, BusyBox, Linux, Router, Script, Sistemas, Telnet
Escribe un Comentario