Skip to content

Instantly share code, notes, and snippets.

@LuisPalacios
Last active March 12, 2023 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LuisPalacios/0d059a520bc10bb4ee39342d28f52c16 to your computer and use it in GitHub Desktop.
Save LuisPalacios/0d059a520bc10bb4ee39342d28f52c16 to your computer and use it in GitHub Desktop.
Comprueba conectividad del tunel ethernet bridge openvpn
#!/bin/bash
#
# /usr/bin/watch_eth_bridge.sh
#
# Un ejemplo de caso de uso está descrito en este apunte:
# https://www.luispa.com/linux/2014/10/19/bridge-ethernet.html
#
#
# Este script comprueba conectividad del tunel ethernet bridge openvpn entre
# dos servidores. Primero se asegura de tener las entradas correctas en el
# fichero /etc/hosts y después rearranca el servicio openvpn si ve que es
# necesario (básicamente si el PING a las IP's privadas no funciona)
#
# Ejemplo de llamada en "norte" (hace de servidor, según apunte técnico de arriba)
# watch_eth_bridge.sh -l norte.midominio.com -r sur.midominio.com \
# -b br206 -s 192.168.206.1 -t 192.168.206.2 \
# -O openvpn-server@norte_bridge_ethernet_server
#
# Ejemplo de llamada en "sur" (hace de cliente, según apunte técnico de arriba)
# watch_eth_bridge.sh -l sur.midominio.com -r norte.midominio.com \
# -b br206 -s 192.168.206.2 -t 192.168.206.1 \
# -O openvpn-client@sur_cliente_bridge_ethernet_de_norte
#
# IMPORTANTE: Incluir el dominio (midominio.com) en los argumentos -l y -r
#
# Modificar para hacer logging
#
LOG=true
# =============================================================
# No modificar a partir de aquí
# =============================================================
# Función para mostrar información en el fichero de log
log_echo() {
if [ "${LOG}" = true ]; then printf "${1}\n" >> ${logfile}; fi
}
# Función para actualizar la IP de un nombre de host en /etc/hosts
#
# Entrada: $1 Dirección IP
# $2 Nombre del hosts
#
actualiza_etc_hosts () {
# Guardo la dirección IP y el Nombre del Host
if [[ ! ${1+x} ]]; then return; fi # $1 is not set at all
if [[ ! ${2+x} ]]; then return; fi # $2 is not set at all
ip=$1
name=$2
line=$(printf "%-15s %s" "${ip}" "${name}")
# Check if already there
out=$(grep ${name} /etc/hosts)
if [ ${?} -ne 0 ]; then
# Añado una entrada nueva en /etc/hosts
log_echo "Añado /etc/hosts: ${line}"
printf "%s\n" "${line}" >> /etc/hosts
else
# Actualizo el /etc/hosts solo si ha cambiado la dirección IP
ip_en_etc_hosts=`echo $out | awk '{print $1}'`
if [[ ! "${ip_en_etc_hosts}" == "${ip}" ]]; then
log_echo "Actualizo /etc/hosts: ${line}"
sed -i "/${name}/ s/.*/${line}/g" /etc/hosts
fi
fi
}
# Mostra como se usa este programa
#
uso() {
basename=`basename "$0"`
echo "${basename}. Copyright (c) 2021 Luis Palacios"
echo "Actualizar /etc/hosts con los equipos involucrados en Ethernet Bridge openvpn"
echo
echo "Uso: ${basename} -b <dev> [-h]"
echo " -l <name> Nombre DNS Público del localhost (i.e. local.midominio.com)"
echo " -r <name> Nombre DNS Público del host remoto (i.e. remoto.midominio.com)"
echo " -b <interface> Nombre del interfaz utilizado para montar el BRIDGE"
echo " -s <IP> Dirección IP local en el bridge (s)ource"
echo " -t <IP> Dirección IP remota en el bridge (t)arget"
echo " -O <servicio> Nombre del servicio en systemd a rearrancar si el ping no funciona."
echo " -h help"
echo " "
exit 1 # Salimos
}
# Analisis de las opciones
while getopts "hl:r:b:s:t:O:" Option
do
case $Option in
# EOM, no comments
h ) uso;; # Se muestra como usar el programa y hace un exit
# Nombre DNS Público del localhost
l )
localhost_wan_dns=$OPTARG # local.midominio.com
localhost_wan_host="${localhost_wan_dns%%.*}" # local
localhost_wan_domain="${localhost_wan_dns#*.}" # midominio.com
;;
# Nombre DNS Público del host remoto
r )
remotehost_wan_dns=$OPTARG # remoto.midominio.com
remotehost_wan_host="${remotehost_wan_dns%%.*}" # remoto
remotehost_wan_domain="${remotehost_wan_dns#*.}" # midominio.com
;;
# Nombre del Interfaz Bridge a través del cual llegamos al otro servidor
b )
bridge_dev=$OPTARG
;;
# Dirección IP del host local en el Bridge
s )
localhost_bridge_ip=$OPTARG
;;
# Dirección IP del host remoto en el Bridge
t )
remotehost_bridge_ip=$OPTARG
;;
# Nombre del Servicio OpenVPN a rearrancar en el caso de no llegar al otro lado del tunel
O )
systemd_service=$OPTARG
;;
# Resto
* )
# Si ocurre algo raro nos salimos
uso
;;
esac
done
# Analizo los parámetros que me han pasado.
#
if [[ ! ${bridge_dev+x} ]]; then log_echo "ERROR: Falta el argumento -b"; uso; fi
if [[ ! ${localhost_wan_dns+x} ]]; then log_echo "ERROR: Falta el parámetro -l"; uso; fi
if [[ ! ${remotehost_wan_dns+x} ]]; then log_echo "ERROR: Falta el parámetro -r"; uso; fi
if [[ ! ${localhost_bridge_ip+x} ]]; then log_echo "ERROR: Falta el parámetro -s"; uso; fi
if [[ ! ${remotehost_bridge_ip+x} ]]; then log_echo "ERROR: Falta el parámetro -t"; uso; fi
if [[ ! ${systemd_service+x} ]]; then log_echo "ERROR: Falta el parámetro -O"; uso; fi
# Logfile
logfile="/var/log/watch-${systemd_service}.log"
logfileSizeMax=10485760
logfileSize=`du -b ${logfile} | tr -s '\t' ' ' | cut -d' ' -f1`
if (( "${logfileSize}" > "${logfileSizeMax}" ));then
savelog -n -c 7 ${logfile} >/dev/null 2>&1
fi
# Inicializo el fichero de log
hora=`date`
if [[ "${LOG}" == true ]]; then printf '%s\n' '---' >> ${logfile}; fi
if [[ "${LOG}" == true ]]; then printf "${hora} - " >> ${logfile}; fi
# Preparo variables de trabajo
#
hostname=`hostname`
if [[ ! ${hostname+x} ]]; then log_echo "ERROR: No tengo mi propio \`hostname\`"; exit 1; fi
#localhost_wan_dev=`ip route show default | awk '{print $3}'`
localhost_wan_dev=`ip route show default | awk '{for (I=1;I<NF;I++) if ($I == "dev") print $(I+1)}'`
if [[ ! ${localhost_wan_dev+x} ]]; then log_echo "ERROR: No tengo interfaz WAN"; exit 1; fi
localhost_wan_ip=`ip addr show dev ${localhost_wan_dev} | grep inet | awk '{print $2}' | sed 's;\/.*;;'`
if [[ ! ${localhost_wan_ip+x} ]]; then log_echo "ERROR: No tengo dirección IP en la interfaz WAN"; exit 1; fi
# Termino de preparar
localhost_bridge_dns="${localhost_wan_host}-${bridge_dev}.${localhost_wan_domain}"
remotehost_bridge_dns="${remotehost_wan_host}-${bridge_dev}.${remotehost_wan_domain}"
# Tengo que tener internet para poder seguir, hago un pequeño check
if [[ ! ${localhost_wan_dev+x} ]]; then log_echo "ERROR: Me falta el interfaz WAN"; exit; fi
# Parece que si tengo el WAN interface, pero hago un double check
if ! ping -c 1 8.8.8.8 &> /dev/null; then log_echo "ERROR: No tengo internet (ping 8.8.8.8 no funciona)"; exit; fi
# Devolveré error si NO consigo llegar al otro lado del tunel.
retVal=1
#
# Compruebo el tunel OpenVPN Eth Bridge
ping -4 -W 2 -c 1 -I ${localhost_bridge_ip} ${remotehost_bridge_ip} >/dev/null 2>&1
if [ "${?}" -ne 0 ]; then
# El PING no llega, rearranco el servicio OpenVPN... (-O)
log_echo "ERROR: DESCONECTADO (ping ${remotehost_bridge_ip} no funciona)"
# Si el ping no llega lo primero que hago es actualizar mi /etc/hosts con
# las direcciones IP de los nombres DNS correctos
log_echo "Actualizo nombres DNS en mi /etc/hosts"
# Actualizo la IP pública del host remoto
remotehost_wan_ip=$(dig +short ${remotehost_wan_dns} @dinamic1.cdmon.net | grep '^[.0-9]*$')
if [[ ! ${remotehost_wan_ip+x} ]]; then log_echo "ERROR: No tengo la IP de ${remotehost_wan_dns}"; exit 1; fi
actualiza_etc_hosts ${localhost_bridge_ip} ${localhost_bridge_dns}
actualiza_etc_hosts ${localhost_wan_ip} ${localhost_wan_dns}
actualiza_etc_hosts ${remotehost_bridge_ip} ${remotehost_bridge_dns}
actualiza_etc_hosts ${remotehost_wan_ip} ${remotehost_wan_dns}
log_echo " Soy : ${hostname}"
log_echo " localhost_wan_dev : ${localhost_wan_dev}"
log_echo " localhost_wan_dns : ${localhost_wan_dns}"
log_echo " localhost_wan_host : ${localhost_wan_host}"
log_echo " localhost_wan_ip : ${localhost_wan_ip}"
log_echo " localhost_bridge_dns : ${localhost_bridge_dns}"
log_echo " localhost_bridge_ip : ${localhost_bridge_ip}"
log_echo " localhost_wan_domain : ${localhost_wan_domain}\n"
log_echo " remotehost_wan_host : ${remotehost_wan_host}"
log_echo " remotehost_wan_dns : ${remotehost_wan_dns}"
log_echo " remotehost_wan_ip : ${remotehost_wan_ip}"
log_echo " remotehost_wan_domain : ${remotehost_wan_domain}"
log_echo " remotehost_bridge_dns : ${remotehost_bridge_dns}"
log_echo " remotehost_bridge_ip : ${remotehost_bridge_ip}"
log_echo ""
log_echo "Rearranco: systemctl restart ${systemd_service} <<<"
systemctl restart ${systemd_service}
# Tras re-arrancar el servicio me quedo unos segundos probando el túnel
# y si conecta actualizo el log
for run in {1..15}; do
if ping -4 -W 2 -c 1 -I ${localhost_bridge_ip} ${remotehost_bridge_ip} >/dev/null 2>&1; then log_echo "Bridge CONECTADO tras ${run} segundos!!"; exit; fi
sleep 1
done
else
# El PING Funciona, nos piramos porque no hay nada más que hacer
log_echo "Bridge ${remotehost_bridge_dns} (${remotehost_bridge_ip}) CONECTADO !!"
retVal=0
fi
# Game Over
# echo "retVal=${retVal}"
exit ${retVal}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment