Last active
March 12, 2023 11:39
-
-
Save LuisPalacios/0d059a520bc10bb4ee39342d28f52c16 to your computer and use it in GitHub Desktop.
Comprueba conectividad del tunel ethernet bridge openvpn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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