Configuraciones de Red Automatizadas

Scripts avanzados para automatizar la configuración y gestión de redes en Linux

Módulo 9 ⏱️ 40-45 min ⚙️ Automatización 🔧 Sysadmin 📊 Avanzado

Automatización de Red con Bash

La automatización de configuraciones de red es fundamental en entornos de producción donde se manejan múltiples servidores y configuraciones complejas. Con Bash podemos crear scripts robustos que configuren interfaces, establezcan rutas, gestionen servicios de red y mantengan la coherencia en toda la infraestructura.

En esta lección aprenderemos a crear scripts que automaticen tareas comunes de red, desde configuraciones básicas hasta implementaciones más complejas con validación de errores y logging avanzado.

Beneficios de la Automatización
  • Consistencia: Elimina errores humanos en configuraciones repetitivas
  • Escalabilidad: Permite gestionar cientos de servidores fácilmente
  • Documentación: Los scripts sirven como documentación ejecutable
  • Recuperación: Facilita la restauración rápida en caso de fallos

Configuración Automatizada de Interfaces

Script Base para Configuración de Interfaces

Script completo para configurar interfaces de red con validación y logging.

configure_interface.sh Copiar
#!/bin/bash

# Script para Configuración Automatizada de Interfaces de Red
# Uso: ./configure_interface.sh -i interface -a address -m mask [-g gateway] [-d dns]

# Variables por defecto
SCRIPT_DIR=$(dirname "$0")
LOG_FILE="/var/log/network_config.log"
BACKUP_DIR="/etc/network/backups"
INTERFACE=""
IP_ADDRESS=""
NETMASK=""
GATEWAY=""
DNS_SERVERS=""
DHCP_MODE=false

# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# Función de logging
log_message() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
    
    case $level in
        ERROR)   echo -e "${RED}[ERROR]${NC} $message" ;;
        SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
        WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
        INFO)    echo -e "${BLUE}[INFO]${NC} $message" ;;
    esac
}

# Función de ayuda
show_help() {
    cat << EOF
Uso: $0 [OPCIONES]

OPCIONES:
    -i, --interface INTERFACE    Interfaz de red (ej: eth0, enp0s3)
    -a, --address IP_ADDRESS     Dirección IP
    -m, --mask NETMASK          Máscara de red (ej: 255.255.255.0 o /24)
    -g, --gateway GATEWAY       Gateway predeterminado
    -d, --dns DNS_SERVERS       Servidores DNS (separados por coma)
    --dhcp                      Configurar interfaz para DHCP
    -h, --help                  Mostrar esta ayuda

EJEMPLOS:
    $0 -i eth0 -a 192.168.1.100 -m 255.255.255.0 -g 192.168.1.1 -d 8.8.8.8,8.8.4.4
    $0 -i eth0 --dhcp
EOF
}

# Validar si se ejecuta como root
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_message "ERROR" "Este script debe ejecutarse como root"
        exit 1
    fi
}

# Validar parámetros
validate_parameters() {
    if [[ -z "$INTERFACE" ]]; then
        log_message "ERROR" "Debe especificar una interfaz con -i"
        show_help
        exit 1
    fi
    
    # Verificar si la interfaz existe
    if ! ip link show "$INTERFACE" &>/dev/null; then
        log_message "ERROR" "La interfaz $INTERFACE no existe"
        exit 1
    fi
    
    # Validación para configuración estática
    if [[ "$DHCP_MODE" == false ]]; then
        if [[ -z "$IP_ADDRESS" || -z "$NETMASK" ]]; then
            log_message "ERROR" "Para configuración estática necesita IP (-a) y máscara (-m)"
            exit 1
        fi
        
        # Validar formato de IP
        if ! [[ $IP_ADDRESS =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
            log_message "ERROR" "Formato de IP inválido: $IP_ADDRESS"
            exit 1
        fi
    fi
}

# Crear backup de configuración actual
backup_config() {
    log_message "INFO" "Creando backup de configuración actual..."
    
    mkdir -p "$BACKUP_DIR"
    local backup_file="$BACKUP_DIR/interface_${INTERFACE}_$(date +%Y%m%d_%H%M%S).backup"
    
    # Backup de configuración IP actual
    ip addr show "$INTERFACE" > "$backup_file"
    ip route show dev "$INTERFACE" >> "$backup_file"
    
    log_message "SUCCESS" "Backup creado: $backup_file"
}

# Configurar interfaz estática
configure_static() {
    log_message "INFO" "Configurando $INTERFACE con IP estática: $IP_ADDRESS"
    
    # Limpiar configuración actual
    ip addr flush dev "$INTERFACE"
    
    # Asignar nueva IP
    if ip addr add "$IP_ADDRESS/$NETMASK" dev "$INTERFACE"; then
        log_message "SUCCESS" "IP $IP_ADDRESS asignada a $INTERFACE"
    else
        log_message "ERROR" "Falló la asignación de IP"
        return 1
    fi
    
    # Activar interfaz
    if ip link set "$INTERFACE" up; then
        log_message "SUCCESS" "Interfaz $INTERFACE activada"
    else
        log_message "ERROR" "Falló la activación de interfaz"
        return 1
    fi
    
    # Configurar gateway si se especificó
    if [[ -n "$GATEWAY" ]]; then
        if ip route add default via "$GATEWAY" dev "$INTERFACE" 2>/dev/null; then
            log_message "SUCCESS" "Gateway $GATEWAY configurado"
        else
            log_message "WARNING" "Gateway ya existe o falló la configuración"
        fi
    fi
    
    # Configurar DNS si se especificó
    if [[ -n "$DNS_SERVERS" ]]; then
        configure_dns
    fi
}

# Configurar DHCP
configure_dhcp() {
    log_message "INFO" "Configurando $INTERFACE para DHCP"
    
    # Verificar si dhclient está disponible
    if ! command -v dhclient &> /dev/null; then
        log_message "ERROR" "dhclient no está instalado"
        return 1
    fi
    
    # Liberar IP actual
    dhclient -r "$INTERFACE" 2>/dev/null
    
    # Obtener nueva IP vía DHCP
    if dhclient "$INTERFACE"; then
        log_message "SUCCESS" "DHCP configurado para $INTERFACE"
        
        # Mostrar IP obtenida
        local obtained_ip=$(ip addr show "$INTERFACE" | grep -oP 'inet \K[\d.]+')
        if [[ -n "$obtained_ip" ]]; then
            log_message "INFO" "IP obtenida vía DHCP: $obtained_ip"
        fi
    else
        log_message "ERROR" "Falló la configuración DHCP"
        return 1
    fi
}

# Configurar DNS
configure_dns() {
    log_message "INFO" "Configurando servidores DNS..."
    
    # Backup de resolv.conf
    cp /etc/resolv.conf /etc/resolv.conf.backup.$(date +%Y%m%d_%H%M%S)
    
    # Agregar servidores DNS
    IFS=',' read -ra DNS_ARRAY <<< "$DNS_SERVERS"
    for dns in "${DNS_ARRAY[@]}"; do
        dns=$(echo "$dns" | xargs)  # Trim whitespace
        echo "nameserver $dns" >> /etc/resolv.conf
        log_message "INFO" "DNS agregado: $dns"
    done
}

# Verificar configuración
verify_config() {
    log_message "INFO" "Verificando configuración..."
    
    # Mostrar configuración actual
    echo -e "\n${BLUE}=== Configuración de $INTERFACE ===${NC}"
    ip addr show "$INTERFACE"
    
    echo -e "\n${BLUE}=== Rutas ===${NC}"
    ip route show dev "$INTERFACE"
    
    # Test de conectividad
    if [[ -n "$GATEWAY" ]]; then
        echo -e "\n${BLUE}=== Test de conectividad al gateway ===${NC}"
        if ping -c 3 -W 5 "$GATEWAY" &>/dev/null; then
            log_message "SUCCESS" "Conectividad al gateway OK"
        else
            log_message "WARNING" "Sin conectividad al gateway"
        fi
    fi
}

# Procesar argumentos
while [[ $# -gt 0 ]]; do
    case $1 in
        -i|--interface)
            INTERFACE="$2"
            shift 2
            ;;
        -a|--address)
            IP_ADDRESS="$2"
            shift 2
            ;;
        -m|--mask)
            NETMASK="$2"
            shift 2
            ;;
        -g|--gateway)
            GATEWAY="$2"
            shift 2
            ;;
        -d|--dns)
            DNS_SERVERS="$2"
            shift 2
            ;;
        --dhcp)
            DHCP_MODE=true
            shift
            ;;
        -h|--help)
            show_help
            exit 0
            ;;
        *)
            log_message "ERROR" "Opción desconocida: $1"
            show_help
            exit 1
            ;;
    esac
done

# Función principal
main() {
    log_message "INFO" "Iniciando configuración de interfaz de red..."
    
    check_root
    validate_parameters
    backup_config
    
    if [[ "$DHCP_MODE" == true ]]; then
        configure_dhcp
    else
        configure_static
    fi
    
    verify_config
    log_message "SUCCESS" "Configuración completada exitosamente"
}

# Ejecutar si es llamado directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

Gestión Automática de Rutas

Script para Configuración de Rutas Estáticas

Automatización de la configuración de rutas estáticas con validación y persistencia.

manage_routes.sh Copiar
#!/bin/bash

# Script para Gestión Automatizada de Rutas
# Uso: ./manage_routes.sh [add|del|list|save|load] [opciones]

ROUTES_CONFIG_FILE="/etc/network/static-routes"
LOG_FILE="/var/log/route_management.log"

# Colores
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_message() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
    
    case $level in
        ERROR)   echo -e "${RED}[ERROR]${NC} $message" ;;
        SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
        WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
        INFO)    echo -e "${BLUE}[INFO]${NC} $message" ;;
    esac
}

# Verificar privilegios de root
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_message "ERROR" "Se requieren privilegios de root"
        exit 1
    fi
}

# Validar dirección de red
validate_network() {
    local network=$1
    if [[ ! $network =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$ ]]; then
        log_message "ERROR" "Formato de red inválido: $network"
        return 1
    fi
    return 0
}

# Validar gateway
validate_gateway() {
    local gateway=$1
    if [[ ! $gateway =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        log_message "ERROR" "Formato de gateway inválido: $gateway"
        return 1
    fi
    return 0
}

# Agregar ruta
add_route() {
    local network=$1
    local gateway=$2
    local interface=$3
    
    if ! validate_network "$network" || ! validate_gateway "$gateway"; then
        return 1
    fi
    
    # Verificar si la ruta ya existe
    if ip route show "$network" | grep -q "via $gateway"; then
        log_message "WARNING" "La ruta $network via $gateway ya existe"
        return 0
    fi
    
    # Agregar la ruta
    local route_cmd="ip route add $network via $gateway"
    if [[ -n "$interface" ]]; then
        route_cmd="$route_cmd dev $interface"
    fi
    
    if eval "$route_cmd"; then
        log_message "SUCCESS" "Ruta agregada: $network via $gateway"
        
        # Guardar en archivo de configuración para persistencia
        echo "$route_cmd" >> "$ROUTES_CONFIG_FILE"
        return 0
    else
        log_message "ERROR" "Falló al agregar ruta: $network via $gateway"
        return 1
    fi
}

# Eliminar ruta
delete_route() {
    local network=$1
    local gateway=$2
    
    if ! validate_network "$network" || ! validate_gateway "$gateway"; then
        return 1
    fi
    
    # Eliminar la ruta
    if ip route del "$network" via "$gateway"; then
        log_message "SUCCESS" "Ruta eliminada: $network via $gateway"
        
        # Remover del archivo de configuración
        if [[ -f "$ROUTES_CONFIG_FILE" ]]; then
            sed -i "\|$network via $gateway|d" "$ROUTES_CONFIG_FILE"
        fi
        return 0
    else
        log_message "ERROR" "Falló al eliminar ruta: $network via $gateway"
        return 1
    fi
}

# Listar rutas
list_routes() {
    echo -e "${BLUE}=== Rutas actuales del sistema ===${NC}"
    ip route show
    
    echo -e "\n${BLUE}=== Rutas estáticas configuradas ===${NC}"
    if [[ -f "$ROUTES_CONFIG_FILE" ]]; then
        cat "$ROUTES_CONFIG_FILE"
    else
        echo "No hay rutas estáticas guardadas"
    fi
}

# Guardar rutas actuales
save_routes() {
    local save_file=${1:-"$ROUTES_CONFIG_FILE"}
    
    log_message "INFO" "Guardando rutas actuales en $save_file"
    
    # Crear directorio si no existe
    mkdir -p "$(dirname "$save_file")"
    
    # Guardar todas las rutas no predeterminadas
    ip route show | grep -v '^default' | while read -r route; do
        echo "ip route add $route"
    done > "$save_file"
    
    log_message "SUCCESS" "Rutas guardadas en $save_file"
}

# Cargar rutas desde archivo
load_routes() {
    local load_file=${1:-"$ROUTES_CONFIG_FILE"}
    
    if [[ ! -f "$load_file" ]]; then
        log_message "ERROR" "Archivo de rutas no encontrado: $load_file"
        return 1
    fi
    
    log_message "INFO" "Cargando rutas desde $load_file"
    
    while IFS= read -r route_cmd; do
        if [[ -n "$route_cmd" && ! "$route_cmd" =~ ^# ]]; then
            if eval "$route_cmd"; then
                log_message "SUCCESS" "Ruta cargada: $route_cmd"
            else
                log_message "ERROR" "Falló al cargar: $route_cmd"
            fi
        fi
    done < "$load_file"
}

# Mostrar ayuda
show_help() {
    cat << EOF
Uso: $0 COMANDO [OPCIONES]

COMANDOS:
    add NETWORK GATEWAY [INTERFACE]  - Agregar ruta estática
    del NETWORK GATEWAY              - Eliminar ruta estática
    list                            - Listar todas las rutas
    save [ARCHIVO]                  - Guardar rutas actuales
    load [ARCHIVO]                  - Cargar rutas desde archivo

EJEMPLOS:
    $0 add 192.168.2.0/24 192.168.1.1 eth0
    $0 del 192.168.2.0/24 192.168.1.1
    $0 list
    $0 save /etc/network/my-routes
    $0 load /etc/network/my-routes
EOF
}

# Función principal
main() {
    check_root
    
    case "${1:-}" in
        add)
            if [[ $# -lt 3 ]]; then
                log_message "ERROR" "Uso: $0 add NETWORK GATEWAY [INTERFACE]"
                exit 1
            fi
            add_route "$2" "$3" "$4"
            ;;
        del|delete)
            if [[ $# -lt 3 ]]; then
                log_message "ERROR" "Uso: $0 del NETWORK GATEWAY"
                exit 1
            fi
            delete_route "$2" "$3"
            ;;
        list)
            list_routes
            ;;
        save)
            save_routes "$2"
            ;;
        load)
            load_routes "$2"
            ;;
        -h|--help|help)
            show_help
            exit 0
            ;;
        *)
            log_message "ERROR" "Comando desconocido: ${1:-}"
            show_help
            exit 1
            ;;
    esac
}

# Ejecutar función principal
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

Configuración de Firewall Automatizada

Script para iptables

Automatización de reglas de firewall con templates y validación.

firewall_manager.sh Copiar
#!/bin/bash

# Script para Gestión Automatizada de Firewall (iptables)
# Uso: ./firewall_manager.sh [start|stop|status|reset|add-rule|save|load]

FIREWALL_CONFIG="/etc/iptables/rules.v4"
BACKUP_DIR="/etc/iptables/backups"
LOG_FILE="/var/log/firewall.log"

# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_message() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
    
    case $level in
        ERROR)   echo -e "${RED}[ERROR]${NC} $message" ;;
        SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
        WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
        INFO)    echo -e "${BLUE}[INFO]${NC} $message" ;;
    esac
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_message "ERROR" "Se requieren privilegios de root"
        exit 1
    fi
}

# Crear backup de reglas actuales
backup_rules() {
    mkdir -p "$BACKUP_DIR"
    local backup_file="$BACKUP_DIR/iptables_$(date +%Y%m%d_%H%M%S).backup"
    
    iptables-save > "$backup_file"
    log_message "SUCCESS" "Backup creado: $backup_file"
}

# Configuración básica del firewall
setup_basic_firewall() {
    log_message "INFO" "Configurando reglas básicas del firewall..."
    
    # Limpiar reglas existentes
    iptables -F
    iptables -X
    iptables -t nat -F
    iptables -t nat -X
    iptables -t mangle -F
    iptables -t mangle -X
    
    # Políticas por defecto
    iptables -P INPUT DROP
    iptables -P FORWARD DROP
    iptables -P OUTPUT ACCEPT
    
    # Permitir loopback
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -o lo -j ACCEPT
    
    # Permitir conexiones establecidas y relacionadas
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # Permitir SSH (puerto 22) - IMPORTANTE para no perder acceso
    iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    
    # Permitir ping (ICMP)
    iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
    
    log_message "SUCCESS" "Reglas básicas configuradas"
}

# Agregar regla personalizada
add_custom_rule() {
    local protocol=$1
    local port=$2
    local action=${3:-ACCEPT}
    local source=${4:-"0.0.0.0/0"}
    
    if [[ -z "$protocol" || -z "$port" ]]; then
        log_message "ERROR" "Uso: add_rule PROTOCOL PORT [ACTION] [SOURCE]"
        return 1
    fi
    
    # Validar protocolo
    if [[ ! "$protocol" =~ ^(tcp|udp|icmp)$ ]]; then
        log_message "ERROR" "Protocolo inválido. Use: tcp, udp, icmp"
        return 1
    fi
    
    # Validar puerto
    if [[ ! "$port" =~ ^[0-9]+$ ]] || [[ $port -lt 1 || $port -gt 65535 ]]; then
        log_message "ERROR" "Puerto inválido: $port"
        return 1
    fi
    
    # Agregar regla
    local rule_cmd="iptables -A INPUT -p $protocol --dport $port -s $source -j $action"
    
    if eval "$rule_cmd"; then
        log_message "SUCCESS" "Regla agregada: $protocol/$port desde $source -> $action"
    else
        log_message "ERROR" "Falló al agregar regla"
        return 1
    fi
}

# Iniciar firewall
start_firewall() {
    log_message "INFO" "Iniciando firewall..."
    backup_rules
    
    # Si existe configuración guardada, cargarla
    if [[ -f "$FIREWALL_CONFIG" ]]; then
        log_message "INFO" "Cargando configuración desde $FIREWALL_CONFIG"
        if iptables-restore < "$FIREWALL_CONFIG"; then
            log_message "SUCCESS" "Configuración cargada exitosamente"
        else
            log_message "WARNING" "Falló al cargar configuración, usando básica"
            setup_basic_firewall
        fi
    else
        log_message "INFO" "No se encontró configuración guardada, usando básica"
        setup_basic_firewall
    fi
    
    # Habilitar firewall en systemd si está disponible
    if command -v systemctl &> /dev/null; then
        systemctl enable iptables 2>/dev/null || true
    fi
    
    log_message "SUCCESS" "Firewall iniciado"
}

# Detener firewall
stop_firewall() {
    log_message "INFO" "Deteniendo firewall..."
    
    # Cambiar políticas a ACCEPT
    iptables -P INPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
    
    # Limpiar todas las reglas
    iptables -F
    iptables -X
    iptables -t nat -F
    iptables -t nat -X
    iptables -t mangle -F
    iptables -t mangle -X
    
    log_message "SUCCESS" "Firewall detenido (todas las reglas eliminadas)"
}

# Mostrar estado
show_status() {
    echo -e "${BLUE}=== Estado del Firewall ===${NC}"
    
    # Mostrar políticas
    echo -e "\n${YELLOW}Políticas por defecto:${NC}"
    iptables -L -n | head -3
    
    # Mostrar reglas INPUT
    echo -e "\n${YELLOW}Reglas INPUT:${NC}"
    iptables -L INPUT -n --line-numbers
    
    # Mostrar estadísticas
    echo -e "\n${YELLOW}Estadísticas:${NC}"
    iptables -L -n -v | head -10
}

# Guardar configuración actual
save_config() {
    local save_file=${1:-"$FIREWALL_CONFIG"}
    
    mkdir -p "$(dirname "$save_file")"
    
    if iptables-save > "$save_file"; then
        log_message "SUCCESS" "Configuración guardada en $save_file"
    else
        log_message "ERROR" "Falló al guardar configuración"
        return 1
    fi
}

# Resetear a configuración básica
reset_firewall() {
    log_message "INFO" "Reseteando firewall a configuración básica..."
    backup_rules
    setup_basic_firewall
    save_config
    log_message "SUCCESS" "Firewall reseteado"
}

# Mostrar ayuda
show_help() {
    cat << EOF
Uso: $0 COMANDO [OPCIONES]

COMANDOS:
    start              - Iniciar firewall con configuración guardada
    stop               - Detener firewall (permitir todo)
    status             - Mostrar estado actual
    reset              - Resetear a configuración básica
    save [ARCHIVO]     - Guardar configuración actual
    add-rule PROTOCOL PORT [ACTION] [SOURCE]
                      - Agregar regla personalizada
    
EJEMPLOS:
    $0 start
    $0 add-rule tcp 80 ACCEPT
    $0 add-rule tcp 443 ACCEPT 192.168.1.0/24
    $0 save
    $0 status
EOF
}

# Función principal
main() {
    check_root
    
    case "${1:-}" in
        start)
            start_firewall
            ;;
        stop)
            stop_firewall
            ;;
        status)
            show_status
            ;;
        reset)
            reset_firewall
            ;;
        save)
            save_config "$2"
            ;;
        add-rule)
            if [[ $# -lt 3 ]]; then
                log_message "ERROR" "Uso: $0 add-rule PROTOCOL PORT [ACTION] [SOURCE]"
                exit 1
            fi
            add_custom_rule "$2" "$3" "$4" "$5"
            ;;
        -h|--help|help)
            show_help
            exit 0
            ;;
        *)
            log_message "ERROR" "Comando desconocido: ${1:-}"
            show_help
            exit 1
            ;;
    esac
}

# Ejecutar función principal
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

Gestión de Servicios de Red

Script para Gestión de Servicios

Automatización del control de servicios de red comunes.

network_services.sh Copiar
#!/bin/bash

# Script para Gestión de Servicios de Red
# Servicios: SSH, Apache, Nginx, NetworkManager, etc.

LOG_FILE="/var/log/network_services.log"

# Lista de servicios de red comunes
NETWORK_SERVICES=(
    "ssh"
    "apache2"
    "nginx"
    "NetworkManager"
    "systemd-networkd"
    "dnsmasq"
    "bind9"
    "openvpn"
)

# Colores
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_message() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
    
    case $level in
        ERROR)   echo -e "${RED}[ERROR]${NC} $message" ;;
        SUCCESS) echo -e "${GREEN}[SUCCESS]${NC} $message" ;;
        WARNING) echo -e "${YELLOW}[WARNING]${NC} $message" ;;
        INFO)    echo -e "${BLUE}[INFO]${NC} $message" ;;
    esac
}

# Verificar si systemctl está disponible
check_systemctl() {
    if ! command -v systemctl &> /dev/null; then
        log_message "ERROR" "systemctl no está disponible"
        exit 1
    fi
}

# Obtener estado de un servicio
get_service_status() {
    local service=$1
    
    if systemctl is-active "$service" &>/dev/null; then
        echo "running"
    elif systemctl is-enabled "$service" &>/dev/null; then
        echo "stopped"
    else
        echo "disabled"
    fi
}

# Mostrar estado de todos los servicios
show_all_status() {
    echo -e "${BLUE}=== Estado de Servicios de Red ===${NC}"
    printf "%-20s %-10s %-10s %s\n" "SERVICIO" "ESTADO" "ENABLED" "DESCRIPCIÓN"
    echo "────────────────────────────────────────────────────────────────"
    
    for service in "${NETWORK_SERVICES[@]}"; do
        # Verificar si el servicio existe
        if systemctl list-unit-files | grep -q "^$service.service"; then
            local status=$(get_service_status "$service")
            local enabled="No"
            
            if systemctl is-enabled "$service" &>/dev/null; then
                enabled="Sí"
            fi
            
            # Obtener descripción corta
            local description=$(systemctl show "$service" --property=Description --value 2>/dev/null | cut -c1-30)
            
            # Colorear según estado
            case $status in
                running)  printf "%-20s ${GREEN}%-10s${NC} %-10s %s\n" "$service" "$status" "$enabled" "$description" ;;
                stopped)  printf "%-20s ${YELLOW}%-10s${NC} %-10s %s\n" "$service" "$status" "$enabled" "$description" ;;
                disabled) printf "%-20s ${RED}%-10s${NC} %-10s %s\n" "$service" "$status" "$enabled" "$description" ;;
            esac
        fi
    done
}

# Controlar un servicio específico
control_service() {
    local action=$1
    local service=$2
    
    if [[ -z "$service" ]]; then
        log_message "ERROR" "Debe especificar un servicio"
        return 1
    fi
    
    # Verificar si el servicio existe
    if ! systemctl list-unit-files | grep -q "^$service.service"; then
        log_message "ERROR" "El servicio $service no existe"
        return 1
    fi
    
    case $action in
        start)
            if systemctl start "$service"; then
                log_message "SUCCESS" "Servicio $service iniciado"
            else
                log_message "ERROR" "Falló al iniciar $service"
                return 1
            fi
            ;;
        stop)
            if systemctl stop "$service"; then
                log_message "SUCCESS" "Servicio $service detenido"
            else
                log_message "ERROR" "Falló al detener $service"
                return 1
            fi
            ;;
        restart)
            if systemctl restart "$service"; then
                log_message "SUCCESS" "Servicio $service reiniciado"
            else
                log_message "ERROR" "Falló al reiniciar $service"
                return 1
            fi
            ;;
        enable)
            if systemctl enable "$service"; then
                log_message "SUCCESS" "Servicio $service habilitado al inicio"
            else
                log_message "ERROR" "Falló al habilitar $service"
                return 1
            fi
            ;;
        disable)
            if systemctl disable "$service"; then
                log_message "SUCCESS" "Servicio $service deshabilitado del inicio"
            else
                log_message "ERROR" "Falló al deshabilitar $service"
                return 1
            fi
            ;;
        status)
            systemctl status "$service" --no-pager
            ;;
        *)
            log_message "ERROR" "Acción desconocida: $action"
            return 1
            ;;
    esac
}

# Reiniciar servicios de red críticos
restart_critical_services() {
    local critical_services=("NetworkManager" "ssh" "systemd-networkd")
    
    log_message "INFO" "Reiniciando servicios críticos de red..."
    
    for service in "${critical_services[@]}"; do
        if systemctl is-active "$service" &>/dev/null; then
            log_message "INFO" "Reiniciando $service..."
            if systemctl restart "$service"; then
                log_message "SUCCESS" "$service reiniciado correctamente"
            else
                log_message "ERROR" "Falló al reiniciar $service"
            fi
        else
            log_message "WARNING" "$service no está ejecutándose"
        fi
    done
}

# Diagnosticar problemas de servicios
diagnose_services() {
    echo -e "${BLUE}=== Diagnóstico de Servicios de Red ===${NC}"
    
    for service in "${NETWORK_SERVICES[@]}"; do
        if systemctl list-unit-files | grep -q "^$service.service"; then
            local status=$(get_service_status "$service")
            
            if [[ "$status" == "disabled" ]] || ! systemctl is-active "$service" &>/dev/null; then
                echo -e "\n${YELLOW}Analizando $service...${NC}"
                
                # Mostrar últimos logs
                echo "Últimos logs:"
                journalctl -u "$service" --no-pager -n 5 --since "1 hour ago" 2>/dev/null || echo "  Sin logs recientes"
                
                # Verificar archivos de configuración principales
                case $service in
                    ssh)
                        [[ -f /etc/ssh/sshd_config ]] && echo "  Config: /etc/ssh/sshd_config existe" || echo "  Config: /etc/ssh/sshd_config FALTA"
                        ;;
                    apache2)
                        [[ -f /etc/apache2/apache2.conf ]] && echo "  Config: /etc/apache2/apache2.conf existe" || echo "  Config: /etc/apache2/apache2.conf FALTA"
                        ;;
                    nginx)
                        [[ -f /etc/nginx/nginx.conf ]] && echo "  Config: /etc/nginx/nginx.conf existe" || echo "  Config: /etc/nginx/nginx.conf FALTA"
                        ;;
                esac
            fi
        fi
    done
}

# Mostrar ayuda
show_help() {
    cat << EOF
Uso: $0 COMANDO [OPCIONES]

COMANDOS:
    status                              - Mostrar estado de todos los servicios
    start|stop|restart|enable|disable SERVICE
                                       - Controlar servicio específico
    restart-critical                   - Reiniciar servicios críticos
    diagnose                          - Diagnosticar problemas

EJEMPLOS:
    $0 status
    $0 start ssh
    $0 restart nginx
    $0 enable apache2
    $0 restart-critical
    $0 diagnose
EOF
}

# Función principal
main() {
    check_systemctl
    
    case "${1:-}" in
        status)
            show_all_status
            ;;
        start|stop|restart|enable|disable)
            control_service "$1" "$2"
            ;;
        restart-critical)
            restart_critical_services
            ;;
        diagnose)
            diagnose_services
            ;;
        -h|--help|help)
            show_help
            exit 0
            ;;
        *)
            log_message "ERROR" "Comando desconocido: ${1:-}"
            show_help
            exit 1
            ;;
    esac
}

# Ejecutar si es llamado directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi

Ejercicio Práctico Avanzado

Proyecto: Script de Configuración de Red Completa

Crea un script maestro que integre todas las funcionalidades:

  • Configuración de múltiples interfaces
  • Configuración de rutas estáticas
  • Configuración básica de firewall
  • Gestión de servicios de red
  • Validación y testing automático
  • Logging centralizado
Precauciones Importantes
  • Backup: Siempre hacer backup antes de cambios importantes
  • Testing: Probar scripts en entornos de desarrollo primero
  • SSH: Mantener acceso SSH activo durante cambios de red
  • Rollback: Implementar mecanismos de rollback automático
Ejercicios Adicionales
  1. Modifica los scripts para trabajar con IPv6
  2. Integra notificaciones por email en caso de fallos
  3. Añade soporte para configuración desde archivos YAML/JSON
  4. Implementa un modo "dry-run" para simular cambios
  5. Crea templates para diferentes tipos de servidores (web, DB, etc.)