#!/usr/bin/env bash
#=============================================================================
# Sentinela ? Intelligent Linux Security Framework
# CLI principal
#=============================================================================
#
# Uso: sentinela <comando> [opciones]
#
# Comandos:
# install Instalar Sentinela en el sistema
# uninstall Desinstalar Sentinela
# update Actualizar Sentinela
#
# apply Aplicar reglas de firewall
# stop Detener firewall (remover cadenas Sentinela)
# restart Reiniciar firewall (stop + apply)
# status Mostrar estado del firewall
#
# ban <IP> Bloquear una IP manualmente
# unban <IP> Desbloquear una IP
# block <IP> Sinónimo de ban
# flush Limpiar todas las IPs bloqueadas
#
# scan Ejecutar escaneo IDS
# reputation Actualizar listas de reputación
# cleanup Limpiar cachés y logs antiguos
# health Verificar estado del sistema
#
# whitelist Listar IPs en whitelist
# trust <IP> Agregar IP a whitelist
# untrust <IP> Quitar IP de whitelist
#
# logs Mostrar logs de Sentinela
# attacks Mostrar logs de ataques
# banned Mostrar IPs bloqueadas
#
# backup Crear backup completo
# restore Restaurar desde backup
#
# dashboard Abrir dashboard web (si está configurado)
# geoip Información GeoIP de una IP
#
# telegram-test Probar conexión con Telegram
#
# version Mostrar versión
# help Mostrar esta ayuda
#=============================================================================
set -Eeuo pipefail
#=============================================================================
# Configuración de rutas
#=============================================================================
SENTINELA_DIR="${SENTINELA_DIR:-/usr/local/sentinela}"
SENTINELA_SRC="${SENTINELA_SRC:-/root/sentinela}"
# Si no existe en /usr/local, usar /root/sentinela directamente
if [[ ! -d "${SENTINELA_DIR}" ]]; then
SENTINELA_DIR="${SENTINELA_SRC}"
fi
CONFIG_DIR="${CONFIG_DIR:-/etc/sentinela}"
SENTINELA_CONFIG="${CONFIG_DIR}/config.conf"
# Si no existe config en /etc, usar la del source
if [[ ! -f "${SENTINELA_CONFIG}" ]]; then
SENTINELA_CONFIG="${SENTINELA_DIR}/config.conf"
fi
export SENTINELA_DIR
export SENTINELA_CONFIG
#=============================================================================
# Cargar configuración y librerías
#=============================================================================
load_libs() {
local lib_dir="${SENTINELA_DIR}/lib"
if [[ -d "${lib_dir}" ]]; then
# shellcheck source=lib/common.sh
source "${lib_dir}/common.sh"
init
else
echo "[ERROR] Librerías no encontradas en ${lib_dir}"
exit 1
fi
}
#=============================================================================
# Mostrar banner
#=============================================================================
show_banner_mini() {
echo "Sentinela v1.0.0 ? Intelligent Linux Security Framework"
echo
}
#=============================================================================
# Mostrar ayuda
#=============================================================================
show_help() {
show_banner_mini
cat << 'HELPEOF'
USO:
sentinela <comando> [opciones]
COMANDOS PRINCIPALES:
install Instalar Sentinela en el sistema
uninstall Desinstalar Sentinela del sistema
update Actualizar Sentinela
FIREWALL:
apply Aplicar reglas de firewall
stop Detener firewall (remover cadenas Sentinela)
restart Reiniciar firewall
status Mostrar estado del firewall y ipsets
BLOQUEO:
ban <IP> Bloquear una IP manualmente
unban <IP> Desbloquear una IP
block <IP> Sinónimo de ban
flush Limpiar todas las IPs bloqueadas
IDS:
scan Ejecutar escaneo de logs (Apache, SSH)
reputation Actualizar listas de reputación (Spamhaus, etc.)
cleanup Limpiar cachés y logs antiguos
health Verificar estado de todos los componentes
WHITELIST:
whitelist Listar IPs en lista blanca
trust <IP> Agregar IP a lista blanca
untrust <IP> Quitar IP de lista blanca
LOGS:
logs Mostrar logs generales (últimas 50 líneas)
attacks Mostrar logs de ataques detectados
banned Mostrar IPs actualmente bloqueadas
BACKUP:
backup Crear backup completo del sistema
restore Restaurar sistema desde un backup
UTILERÍAS:
dashboard Abrir dashboard web en el navegador
geoip <IP> Mostrar información GeoIP de una dirección
telegram-test Enviar mensaje de prueba a Telegram
INFORMACIÓN:
version Mostrar versión de Sentinela
help Mostrar esta ayuda
EJEMPLOS:
sentinela apply Aplicar firewall
sentinela status Ver estado
sentinela scan Escanear logs
sentinela ban 192.168.1.100 Bloquear IP
sentinela unban 192.168.1.100 Desbloquear IP
sentinela trust 192.168.1.1 Agregar IP a whitelist
sentinela logs --tail 100 Ver últimas 100 líneas de log
sentinela backup Crear backup
HELPEOF
}
#=============================================================================
# Comando: apply
#=============================================================================
cmd_apply() {
load_libs
require_root
# Iniciar transacción de rollback
source "${SENTINELA_DIR}/lib/rollback.sh"
rollback_start
# Crear snapshot adicional
source "${SENTINELA_DIR}/lib/snapshot.sh"
snapshot_create "pre-apply"
# Aplicar firewall
source "${SENTINELA_DIR}/firewall/firewall.sh"
firewall_apply
# Verificar conectividad (con timeout para confirmación)
echo
echo "???????????????????????????????????????????????????????"
echo " Firewall aplicado. Verificando conectividad..."
echo "???????????????????????????????????????????????????????"
echo
echo "Si pierde acceso SSH, el sistema hará rollback automático"
echo "en ${ROLLBACK_TIMEOUT} segundos."
echo
rollback_verify
}
#=============================================================================
# Comando: stop
#=============================================================================
cmd_stop() {
load_libs
require_root
source "${SENTINELA_DIR}/firewall/firewall.sh"
firewall_stop
}
#=============================================================================
# Comando: restart
#=============================================================================
cmd_restart() {
cmd_stop
echo
cmd_apply
}
#=============================================================================
# Comando: status
#=============================================================================
cmd_status() {
load_libs
require_root
show_banner_mini
source "${SENTINELA_DIR}/firewall/firewall.sh"
firewall_status
}
#=============================================================================
# Comando: ban / block
#=============================================================================
cmd_ban() {
local ip="$1"
local reason="${2:-manual}"
if [[ -z "${ip}" ]]; then
echo "[ERROR] Debe especificar una IP"
echo "Uso: sentinela ban <IP> [razón]"
exit 1
fi
load_libs
require_root
source "${SENTINELA_DIR}/firewall/blacklist.sh"
blacklist_add "${ip}" "${reason}"
if [[ "${TELEGRAM_ENABLE}" == "yes" ]]; then
source "${SENTINELA_DIR}/telegram/telegram.sh"
telegram_send_alert "${ip}" "manual" "Bloqueo manual: ${reason}" "" "" "" "CLI"
fi
echo "IP ${ip} bloqueada (${reason})"
}
#=============================================================================
# Comando: unban
#=============================================================================
cmd_unban() {
local ip="$1"
if [[ -z "${ip}" ]]; then
echo "[ERROR] Debe especificar una IP"
echo "Uso: sentinela unban <IP>"
exit 1
fi
load_libs
require_root
source "${SENTINELA_DIR}/firewall/blacklist.sh"
blacklist_remove "${ip}"
echo "IP ${ip} desbloqueada"
}
#=============================================================================
# Comando: flush
#=============================================================================
cmd_flush() {
load_libs
require_root
echo "¿Está seguro de limpiar TODAS las IPs bloqueadas?"
read -r -p "Confirmar (s/N): " confirm
if [[ "${confirm,,}" == "s" ]]; then
source "${SENTINELA_DIR}/firewall/blacklist.sh"
blacklist_flush
echo "Todas las IPs bloqueadas han sido liberadas"
fi
}
#=============================================================================
# Comando: scan
#=============================================================================
cmd_scan() {
load_libs
require_root
source "${SENTINELA_DIR}/cron/cron.sh"
# Apache scan
if log_check_exists "apache_access"; then
echo "Escaneando logs de Apache (${LOG_SYSTEM})..."
source "${SENTINELA_IDS}/apache.sh"
apache_scan
else
echo "Log de Apache no disponible (sistema: ${LOG_SYSTEM})"
fi
# SSH scan
if log_check_exists "ssh_auth"; then
echo "Escaneando logs de SSH (${LOG_SYSTEM})..."
source "${SENTINELA_IDS}/ssh.sh"
ssh_brute_force_detect
else
echo "Log de SSH no disponible (sistema: ${LOG_SYSTEM})"
fi
# Limpiar cache
source "${SENTINELA_IDS}/scanners.sh"
scanner_cleanup_cache
echo "Escaneo completado"
}
#=============================================================================
# Comando: reputation
#=============================================================================
cmd_reputation() {
load_libs
require_root
source "${SENTINELA_DIR}/cron/cron.sh"
cron_reputation
}
#=============================================================================
# Comando: cleanup
#=============================================================================
cmd_cleanup() {
load_libs
source "${SENTINELA_DIR}/cron/cron.sh"
cron_cleanup
echo "Limpieza completada"
}
#=============================================================================
# Comando: health
#=============================================================================
cmd_health() {
load_libs
require_root
show_banner_mini
echo "??? Health Check ???"
echo
source "${SENTINELA_DIR}/cron/cron.sh"
cron_health
}
#=============================================================================
# Comando: whitelist
#=============================================================================
cmd_whitelist() {
load_libs
require_root
source "${SENTINELA_DIR}/firewall/whitelist.sh"
whitelist_list
}
#=============================================================================
# Comando: trust
#=============================================================================
cmd_trust() {
local ip="$1"
if [[ -z "${ip}" ]]; then
echo "[ERROR] Debe especificar una IP"
echo "Uso: sentinela trust <IP>"
exit 1
fi
load_libs
require_root
source "${SENTINELA_DIR}/firewall/whitelist.sh"
whitelist_add "${ip}"
}
#=============================================================================
# Comando: untrust
#=============================================================================
cmd_untrust() {
local ip="$1"
if [[ -z "${ip}" ]]; then
echo "[ERROR] Debe especificar una IP"
echo "Uso: sentinela untrust <IP>"
exit 1
fi
load_libs
require_root
source "${SENTINELA_DIR}/firewall/whitelist.sh"
whitelist_remove "${ip}"
}
#=============================================================================
# Comando: logs
#=============================================================================
cmd_logs() {
local tail_lines="${1:-50}"
local logfile="${LOG_DIR:-/var/log/sentinela}/sentinela.log"
if [[ ! -f "${logfile}" ]]; then
logfile="${SENTINELA_DIR}/logs/sentinela.log"
fi
if [[ ! -f "${logfile}" ]]; then
echo "No se encontró el archivo de log"
exit 1
fi
tail -n "${tail_lines}" "${logfile}"
}
#=============================================================================
# Comando: attacks
#=============================================================================
cmd_attacks() {
local tail_lines="${1:-50}"
local logfile="${LOG_DIR:-/var/log/sentinela}/attacks.log"
if [[ ! -f "${logfile}" ]]; then
logfile="${SENTINELA_DIR}/logs/attacks.log"
fi
if [[ ! -f "${logfile}" ]]; then
echo "No se encontró el archivo de ataques"
exit 1
fi
tail -n "${tail_lines}" "${logfile}"
}
#=============================================================================
# Comando: banned
#=============================================================================
cmd_banned() {
load_libs
require_root
source "${SENTINELA_DIR}/firewall/blacklist.sh"
blacklist_list
}
#=============================================================================
# Comando: backup
#=============================================================================
cmd_backup() {
load_libs
require_root
source "${SENTINELA_DIR}/backup/restore.sh"
backup_create "$@"
}
#=============================================================================
# Comando: restore
#=============================================================================
cmd_restore() {
load_libs
require_root
source "${SENTINELA_DIR}/backup/restore.sh"
backup_restore "$@"
}
#=============================================================================
# Comando: dashboard
#=============================================================================
cmd_dashboard() {
local port="${DASHBOARD_PORT:-8080}"
local url="http://localhost:${port}"
echo "Abriendo dashboard en: ${url}"
if command -v xdg-open &>/dev/null; then
xdg-open "${url}" 2>/dev/null || true
elif command -v sensible-browser &>/dev/null; then
sensible-browser "${url}" 2>/dev/null || true
fi
echo "Si no se abre el navegador, visite: ${url}"
}
#=============================================================================
# Comando: geoip
#=============================================================================
cmd_geoip() {
local ip="$1"
if [[ -z "${ip}" ]]; then
echo "[ERROR] Debe especificar una IP"
echo "Uso: sentinela geoip <IP>"
exit 1
fi
load_libs
echo "??? GeoIP: ${ip} ???"
echo
if command -v geoiplookup &>/dev/null; then
geoiplookup "${ip}" 2>/dev/null || echo "GeoIP no disponible"
elif command -v mmdblookup &>/dev/null; then
if [[ -f "${GEOIP_DB}" ]]; then
echo "País:"
mmdblookup --file "${GEOIP_DB}" --ip "${ip}" country names en 2>/dev/null | \
grep -oP '"[^"]+"' | head -1 | tr -d '"' || echo " Desconocido"
fi
if [[ -f "${GEOIP_ASN_DB}" ]]; then
echo "ASN:"
mmdblookup --file "${GEOIP_ASN_DB}" --ip "${ip}" autonomous_system_number 2>/dev/null | \
grep -oP '\d+' | head -1 || echo " No disponible"
echo "Organización:"
mmdblookup --file "${GEOIP_ASN_DB}" --ip "${ip}" autonomous_system_organization 2>/dev/null | \
grep -oP '"[^"]+"' | head -1 | tr -d '"' || echo " No disponible"
fi
else
echo "GeoIP no está instalado. Ejecute: sentinela install"
fi
# API externa como respaldo
local ipinfo
ipinfo=$(curl -s "http://ip-api.com/json/${ip}" --max-time 3 2>/dev/null || echo "")
if [[ -n "${ipinfo}" ]]; then
echo
echo "Información adicional (ip-api.com):"
echo "$(echo "${ipinfo}" | python3 -m json.tool 2>/dev/null || echo "${ipinfo}")"
fi
}
#=============================================================================
# Comando: telegram-test
#=============================================================================
cmd_telegram_test() {
load_libs
source "${SENTINELA_DIR}/telegram/telegram.sh"
telegram_test
}
#=============================================================================
# Comando: version
#=============================================================================
cmd_version() {
load_libs
echo "Sentinela v${SENTINELA_VERSION} ? ${SENTINELA_DESC}"
}
#=============================================================================
# Main
#=============================================================================
main() {
if [[ $# -eq 0 ]]; then
show_help
exit 0
fi
local cmd="$1"
shift
case "${cmd}" in
# Instalación
install)
if [[ -f "${SENTINELA_SRC}/install.sh" ]]; then
exec bash "${SENTINELA_SRC}/install.sh" "$@"
else
echo "[ERROR] Script de instalación no encontrado en ${SENTINELA_SRC}/install.sh"
exit 1
fi
;;
uninstall)
if [[ -f "${SENTINELA_SRC}/uninstall.sh" ]]; then
exec bash "${SENTINELA_SRC}/uninstall.sh" "$@"
else
echo "[ERROR] Script de desinstalación no encontrado"
exit 1
fi
;;
update)
if [[ -f "${SENTINELA_SRC}/update.sh" ]]; then
exec bash "${SENTINELA_SRC}/update.sh" "$@"
else
echo "[ERROR] Script de actualización no encontrado"
exit 1
fi
;;
# Firewall
apply) cmd_apply "$@" ;;
stop) cmd_stop "$@" ;;
restart) cmd_restart "$@" ;;
status) cmd_status "$@" ;;
# Bloqueo
ban|block) cmd_ban "$@" ;;
unban) cmd_unban "$@" ;;
flush) cmd_flush "$@" ;;
# IDS
scan) cmd_scan "$@" ;;
reputation) cmd_reputation "$@" ;;
cleanup) cmd_cleanup "$@" ;;
health) cmd_health "$@" ;;
# Whitelist
whitelist) cmd_whitelist "$@" ;;
trust) cmd_trust "$@" ;;
untrust) cmd_untrust "$@" ;;
# Logs
logs) cmd_logs "$@" ;;
attacks) cmd_attacks "$@" ;;
banned) cmd_banned "$@" ;;
# Backup
backup) cmd_backup "$@" ;;
restore) cmd_restore "$@" ;;
# Utilidades
dashboard) cmd_dashboard "$@" ;;
geoip) cmd_geoip "$@" ;;
telegram-test) cmd_telegram_test "$@" ;;
# Información
version) cmd_version "$@" ;;
help|--help|-h) show_help "$@" ;;
start) cmd_apply "$@" ;;
*)
echo "[ERROR] Comando desconocido: ${cmd}"
echo "Ejecute 'sentinela help' para ver los comandos disponibles"
exit 1
;;
esac
}
main "$@"
|