- Directorios: PascalCase (p2601_dasuten → P2601_Dasuten) - Planes: numeración pura (P2601_6.1.A → P2601.06.01) - Sin caracteres especiales en nombres de archivo - 07_proyectos.md: convención RFC-ADN-01 integrada, P2604/P2605 agregados - evento:listar: nueva opción --detalle para descripciones completas
338 lines
11 KiB
Bash
338 lines
11 KiB
Bash
#!/bin/bash
|
|
# Script de diagnóstico automático para red local
|
|
# Uso: ./diagnostico_red_local.sh [interface]
|
|
# Ejemplo: ./diagnostico_red_local.sh vmbr0
|
|
|
|
set -e
|
|
|
|
# Colores para output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Variables
|
|
INTERFACE="${1:-vmbr0}"
|
|
LOG_FILE="/tmp/diagnostico_red_local_$(date +%Y%m%d_%H%M%S).log"
|
|
REPORT_FILE="/tmp/reporte_red_local_$(date +%Y%m%d_%H%M%S).md"
|
|
|
|
# Funciones de utilidad
|
|
log() {
|
|
echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
|
|
}
|
|
|
|
check_dependencies() {
|
|
local deps=("ip" "ping" "awk" "grep" "tee")
|
|
local missing=()
|
|
|
|
for dep in "${deps[@]}"; do
|
|
if ! command -v "$dep" &> /dev/null; then
|
|
missing+=("$dep")
|
|
fi
|
|
done
|
|
|
|
if [ ${#missing[@]} -gt 0 ]; then
|
|
error "Dependencias faltantes: ${missing[*]}"
|
|
return 1
|
|
fi
|
|
|
|
# Dependencias opcionales
|
|
if command -v "nmap" &> /dev/null; then
|
|
HAS_NMAP=true
|
|
else
|
|
HAS_NMAP=false
|
|
warning "nmap no encontrado. El escaneo de red será limitado."
|
|
fi
|
|
|
|
if command -v "jq" &> /dev/null; then
|
|
HAS_JQ=true
|
|
else
|
|
HAS_JQ=false
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
check_interface() {
|
|
if ! ip link show "$INTERFACE" &> /dev/null; then
|
|
error "Interfaz $INTERFACE no encontrada"
|
|
echo "Interfaces disponibles:"
|
|
ip link show | awk -F': ' '/^[0-9]+:/ {print $2}' | grep -v lo
|
|
return 1
|
|
fi
|
|
|
|
if [ "$(cat /sys/class/net/"$INTERFACE"/operstate 2>/dev/null)" != "up" ]; then
|
|
warning "Interfaz $INTERFACE no está activa (operstate: $(cat /sys/class/net/"$INTERFACE"/operstate 2>/dev/null))"
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
get_interface_info() {
|
|
log "Obteniendo información de la interfaz $INTERFACE..."
|
|
|
|
echo "=== INFORMACIÓN DE INTERFAZ ===" | tee -a "$REPORT_FILE"
|
|
ip addr show "$INTERFACE" | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
|
|
# Extraer IPs configuradas
|
|
IPS=$(ip addr show "$INTERFACE" | awk '/inet / {print $2}')
|
|
if [ -z "$IPS" ]; then
|
|
warning "No hay IPs configuradas en $INTERFACE"
|
|
else
|
|
success "IPs configuradas:"
|
|
echo "$IPS" | while read -r ip; do
|
|
echo " - $ip"
|
|
done | tee -a "$REPORT_FILE"
|
|
fi
|
|
}
|
|
|
|
get_routing_info() {
|
|
log "Obteniendo información de enrutamiento..."
|
|
|
|
echo "=== TABLA DE RUTAS ===" | tee -a "$REPORT_FILE"
|
|
ip route show | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
|
|
# Detectar gateway predeterminado
|
|
DEFAULT_GW=$(ip route show default | awk '/default/ {print $3}')
|
|
if [ -n "$DEFAULT_GW" ]; then
|
|
success "Gateway predeterminado: $DEFAULT_GW"
|
|
echo "Gateway: $DEFAULT_GW" | tee -a "$REPORT_FILE"
|
|
|
|
# Probar conectividad al gateway
|
|
log "Probando conectividad al gateway $DEFAULT_GW..."
|
|
if ping -c 3 -W 2 "$DEFAULT_GW" &> /dev/null; then
|
|
success "Gateway alcanzable"
|
|
echo "Gateway alcanzable: Sí" | tee -a "$REPORT_FILE"
|
|
else
|
|
warning "Gateway no alcanzable"
|
|
echo "Gateway alcanzable: No" | tee -a "$REPORT_FILE"
|
|
fi
|
|
else
|
|
warning "No se encontró gateway predeterminado"
|
|
echo "Gateway: No encontrado" | tee -a "$REPORT_FILE"
|
|
fi
|
|
|
|
# Detectar subred local
|
|
LOCAL_SUBNET=$(ip route show | grep "link src" | awk '{print $1}' | head -1)
|
|
if [ -n "$LOCAL_SUBNET" ]; then
|
|
success "Subred local detectada: $LOCAL_SUBNET"
|
|
echo "Subred local: $LOCAL_SUBNET" | tee -a "$REPORT_FILE"
|
|
else
|
|
warning "No se pudo detectar subred local"
|
|
echo "Subred local: No detectada" | tee -a "$REPORT_FILE"
|
|
fi
|
|
}
|
|
|
|
check_dhcp_info() {
|
|
log "Verificando información DHCP..."
|
|
|
|
echo "=== INFORMACIÓN DHCP ===" | tee -a "$REPORT_FILE"
|
|
|
|
# Verificar archivos de lease DHCP
|
|
DHCP_FILES=("/var/lib/dhcp/dhclient.leases" "/var/lib/dhclient/dhclient.leases")
|
|
for file in "${DHCP_FILES[@]}"; do
|
|
if [ -f "$file" ]; then
|
|
log "Analizando $file..."
|
|
if grep -q "interface.*$INTERFACE" "$file" 2>/dev/null; then
|
|
success "Se encontraron leases DHCP para $INTERFACE"
|
|
echo "Archivo DHCP: $file" | tee -a "$REPORT_FILE"
|
|
|
|
# Extraer información relevante
|
|
grep -A10 -B2 "interface.*$INTERFACE" "$file" | \
|
|
grep -E "(lease|starts|ends|option|fixed-address)" | \
|
|
head -20 | tee -a "$REPORT_FILE"
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if ! grep -q "Archivo DHCP:" "$REPORT_FILE"; then
|
|
warning "No se encontraron leases DHCP para $INTERFACE"
|
|
echo "DHCP: No se encontraron leases" | tee -a "$REPORT_FILE"
|
|
fi
|
|
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
}
|
|
|
|
scan_local_network() {
|
|
if [ -z "$LOCAL_SUBNET" ]; then
|
|
warning "No se puede escanear red local (subred no detectada)"
|
|
return 1
|
|
fi
|
|
|
|
log "Escaneando red local $LOCAL_SUBNET..."
|
|
|
|
echo "=== ESCANEO DE RED LOCAL ===" | tee -a "$REPORT_FILE"
|
|
|
|
if [ "$HAS_NMAP" = true ]; then
|
|
# Escaneo rápido con nmap
|
|
log "Ejecutando escaneo rápido con nmap..."
|
|
nmap -sn "$LOCAL_SUBNET" 2>/dev/null | \
|
|
grep "Nmap scan report" | \
|
|
head -20 | \
|
|
tee -a "$REPORT_FILE"
|
|
|
|
# Contar dispositivos
|
|
DEVICE_COUNT=$(nmap -sn "$LOCAL_SUBNET" 2>/dev/null | grep "Nmap scan report" | wc -l)
|
|
success "Dispositivos detectados: $DEVICE_COUNT"
|
|
echo "Total dispositivos: $DEVICE_COUNT" | tee -a "$REPORT_FILE"
|
|
else
|
|
# Método alternativo usando ping y arp
|
|
warning "Usando método básico de detección (sin nmap)..."
|
|
|
|
# Ping a broadcast (puede no funcionar en todas las redes)
|
|
log "Probando detección básica..."
|
|
ping -c 2 -b "$(echo "$LOCAL_SUBNET" | cut -d'/' -f1 | sed 's/0$/255/')" &> /dev/null || true
|
|
|
|
# Mostrar tabla ARP
|
|
ip neigh show | grep -v "FAILED" | \
|
|
head -20 | \
|
|
tee -a "$REPORT_FILE"
|
|
|
|
DEVICE_COUNT=$(ip neigh show | grep -v "FAILED" | wc -l)
|
|
echo "Dispositivos en tabla ARP: $DEVICE_COUNT" | tee -a "$REPORT_FILE"
|
|
fi
|
|
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
}
|
|
|
|
check_tailscale() {
|
|
log "Verificando estado de Tailscale..."
|
|
|
|
echo "=== ESTADO TAILSCALE ===" | tee -a "$REPORT_FILE"
|
|
|
|
if command -v tailscale &> /dev/null; then
|
|
tailscale status 2>/dev/null | tee -a "$REPORT_FILE"
|
|
|
|
# Extraer IP de Tailscale
|
|
TAILSCALE_IP=$(tailscale status --json 2>/dev/null | \
|
|
$([ "$HAS_JQ" = true ] && echo "jq -r '.Self.TailscaleIPs[0]'" || echo "grep -oE '100\.[0-9]+\.[0-9]+\.[0-9]+' | head -1"))
|
|
|
|
if [ -n "$TAILSCALE_IP" ]; then
|
|
success "Tailscale IP: $TAILSCALE_IP"
|
|
echo "IP Tailscale: $TAILSCALE_IP" | tee -a "$REPORT_FILE"
|
|
else
|
|
warning "Tailscale no parece estar conectado"
|
|
echo "Tailscale: No conectado" | tee -a "$REPORT_FILE"
|
|
fi
|
|
else
|
|
warning "Tailscale no está instalado"
|
|
echo "Tailscale: No instalado" | tee -a "$REPORT_FILE"
|
|
fi
|
|
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
}
|
|
|
|
generate_recommendations() {
|
|
log "Generando recomendaciones..."
|
|
|
|
echo "=== RECOMENDACIONES ===" | tee -a "$REPORT_FILE"
|
|
|
|
# Recomendación de IP local
|
|
if [ -n "$LOCAL_SUBNET" ]; then
|
|
BASE_NET=$(echo "$LOCAL_SUBNET" | cut -d'/' -f1 | cut -d'.' -f1-3)
|
|
|
|
echo "Para configuración local entre srv-dasu y pc-dasu0:" | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
echo "1. **IPs recomendadas (fuera de rango DHCP común):**" | tee -a "$REPORT_FILE"
|
|
echo " - srv-dasu: ${BASE_NET}.205/24" | tee -a "$REPORT_FILE"
|
|
echo " - pc-dasu0: ${BASE_NET}.100/24" | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
echo "2. **Configuración de red:**" | tee -a "$REPORT_FILE"
|
|
echo " - Gateway: $(echo "$DEFAULT_GW" || echo "[gateway-del-router]")" | tee -a "$REPORT_FILE"
|
|
echo " - Máscara: 255.255.255.0 (/24)" | tee -a "$REPORT_FILE"
|
|
echo " - DNS Primario: 10.0.100.10 (dc-dasuten)" | tee -a "$REPORT_FILE"
|
|
echo " - DNS Secundario: 8.8.8.8" | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
echo "3. **Verificaciones previas:**" | tee -a "$REPORT_FILE"
|
|
echo " - Confirmar que ${BASE_NET}.205 y ${BASE_NET}.100 no están en uso" | tee -a "$REPORT_FILE"
|
|
echo " - Verificar que el firewall permite ICMP y puertos necesarios" | tee -a "$REPORT_FILE"
|
|
echo " - Tailscale debe permanecer activo como respaldo" | tee -a "$REPORT_FILE"
|
|
else
|
|
echo "No se pudo generar recomendaciones específicas (subred no detectada)" | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
echo "Recomendaciones generales:" | tee -a "$REPORT_FILE"
|
|
echo "1. Identificar manualmente la subred del router ISP" | tee -a "$REPORT_FILE"
|
|
echo "2. Usar IPs estáticas fuera del rango DHCP del router" | tee -a "$REPORT_FILE"
|
|
echo "3. Mantener Tailscale como ruta de failover" | tee -a "$REPORT_FILE"
|
|
fi
|
|
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
}
|
|
|
|
generate_summary() {
|
|
echo "=== RESUMEN DEL DIAGNÓSTICO ===" | tee -a "$REPORT_FILE"
|
|
echo "Fecha: $(date)" | tee -a "$REPORT_FILE"
|
|
echo "Hostname: $(hostname)" | tee -a "$REPORT_FILE"
|
|
echo "Interfaz analizada: $INTERFACE" | tee -a "$REPORT_FILE"
|
|
echo "Estado interfaz: $(cat /sys/class/net/"$INTERFACE"/operstate 2>/dev/null || echo "desconocido")" | tee -a "$REPORT_FILE"
|
|
echo "Gateway: ${DEFAULT_GW:-No detectado}" | tee -a "$REPORT_FILE"
|
|
echo "Subred local: ${LOCAL_SUBNET:-No detectada}" | tee -a "$REPORT_FILE"
|
|
echo "Tailscale: $(if command -v tailscale &> /dev/null; then echo "Instalado"; else echo "No instalado"; fi)" | tee -a "$REPORT_FILE"
|
|
echo "" | tee -a "$REPORT_FILE"
|
|
echo "Archivos generados:" | tee -a "$REPORT_FILE"
|
|
echo " - Log detallado: $LOG_FILE" | tee -a "$REPORT_FILE"
|
|
echo " - Reporte completo: $REPORT_FILE" | tee -a "$REPORT_FILE"
|
|
}
|
|
|
|
main() {
|
|
echo "========================================="
|
|
echo " DIAGNÓSTICO DE RED LOCAL - srv-dasu"
|
|
echo "========================================="
|
|
echo ""
|
|
|
|
# Inicializar archivos
|
|
> "$LOG_FILE"
|
|
> "$REPORT_FILE"
|
|
|
|
# Verificar dependencias
|
|
if ! check_dependencies; then
|
|
exit 1
|
|
fi
|
|
|
|
# Verificar interfaz
|
|
if ! check_interface; then
|
|
exit 1
|
|
fi
|
|
|
|
# Ejecutar diagnósticos
|
|
get_interface_info
|
|
get_routing_info
|
|
check_dhcp_info
|
|
scan_local_network
|
|
check_tailscale
|
|
generate_recommendations
|
|
generate_summary
|
|
|
|
echo ""
|
|
success "Diagnóstico completado exitosamente"
|
|
echo ""
|
|
echo "Para configurar IP local en $INTERFACE, edite:"
|
|
echo " sudo nano /etc/network/interfaces"
|
|
echo ""
|
|
echo "Agregue las líneas (adaptando la IP según recomendaciones):"
|
|
echo " post-up ip addr add 192.168.1.205/24 dev $INTERFACE"
|
|
echo " pre-down ip addr del 192.168.1.205/24 dev $INTERFACE"
|
|
echo ""
|
|
echo "Luego reinicie el servicio de red:"
|
|
echo " sudo systemctl restart networking"
|
|
}
|
|
|
|
# Ejecutar script principal
|
|
main "$@"
|