jueves, 17 de julio de 2025

🛡️ Cómo usar Wrappers en C para gestionar Asterisk, Servidores de Correo e Inteligencia Artificial desde la Web

🛡️ Cómo usar Wrappers en C para gestionar Asterisk, Servidores de Correo e Inteligencia Artificial desde la Web

Cuando desarrollamos sistemas que necesitan interactuar con Asterisk (PBX), servidores de correo como Postfix/Dovecot, o incluso ejecutar modelos de inteligencia artificial, muchas veces nos encontramos con una limitación importante:

🔒 PHP o tu app web no puede ejecutar comandos privilegiados directamente.

Por temas de seguridad, el usuario www-data de Apache/Nginx no tiene permisos para borrar correos, reiniciar servicios o ejecutar modelos de IA desde el sistema. ¿La solución? ➤ Un wrapper en C controlado con sudo.

🧩 ¿Qué es un wrapper en este contexto?

Un wrapper es un programa en C (o Bash/Python) que actúa como intermediario seguro entre tu aplicación web y el sistema operativo. Lo usas para:

  • Borrar buzones de forma segura
  • Ejecutar comandos como postmap, dovecot reload, etc.
  • Recargar configuraciones de Asterisk (module reload, dialplan reload)
  • Ejecutar modelos de IA (como un clasificador en Python o C++)

🛠️ Proyecto completo: sistema_wrapper.c

Este wrapper más avanzado permite ejecutar diferentes operaciones del sistema de forma controlada:

📦 Funcionalidades del wrapper:

  • ✅ Eliminar un buzón de correo
  • ✅ Recargar Asterisk
  • ✅ Ejecutar un modelo IA
  • ✅ Registrar todo en un log seguro
  • ✅ Validar argumentos
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

const char *LOG_PATH = "/var/log/sistema_wrapper.log";

void registrar_log(const char *operacion, const char *detalle) {
    FILE *log = fopen(LOG_PATH, "a");
    if (log) {
        time_t ahora = time(NULL);
        char *tiempo = ctime(&ahora);
        tiempo[strcspn(tiempo, "\n")] = 0;
        fprintf(log, "[%s] [%s] %s\n", tiempo, operacion, detalle);
        fclose(log);
    }
}

void eliminar_buzon(const char *email) {
    if (strstr(email, "..") || strchr(email, ';')) {
        registrar_log("ERROR", "Entrada maliciosa en email");
        printf("Entrada inválida.\n");
        return;
    }

    char comando[512];
    snprintf(comando, sizeof(comando), "rm -rf /var/mail/vhosts/%s", email);

    int r = system(comando);
    if (r == 0) {
        registrar_log("BUZON", email);
        printf("Buzón %s eliminado.\n", email);
    } else {
        registrar_log("ERROR", "Fallo al eliminar buzón.");
        printf("Error al eliminar buzón.\n");
    }
}

void recargar_asterisk() {
    int r = system("asterisk -rx 'module reload'");
    if (r == 0) {
        registrar_log("ASTERISK", "Recarga de módulos completada");
        printf("Asterisk recargado.\n");
    } else {
        registrar_log("ERROR", "Fallo al recargar Asterisk");
        printf("Error recargando Asterisk.\n");
    }
}

void ejecutar_modelo_ia() {
    int r = system("python3 /opt/ia/clasificador.py /tmp/mensaje.txt >> /tmp/resultado.txt");
    if (r == 0) {
        registrar_log("IA", "Modelo ejecutado con éxito");
        printf("Modelo IA ejecutado.\n");
    } else {
        registrar_log("ERROR", "Fallo al ejecutar IA");
        printf("Error en ejecución de IA.\n");
    }
}

void mostrar_uso() {
    printf("Uso: sistema_wrapper [comando] [argumento]\n");
    printf("Comandos:\n");
    printf("  eliminar-buzon email@dominio.com\n");
    printf("  recargar-asterisk\n");
    printf("  ejecutar-ia\n");
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        mostrar_uso();
        return 1;
    }

    if (strcmp(argv[1], "eliminar-buzon") == 0 && argc == 3) {
        eliminar_buzon(argv[2]);
    } else if (strcmp(argv[1], "recargar-asterisk") == 0) {
        recargar_asterisk();
    } else if (strcmp(argv[1], "ejecutar-ia") == 0) {
        ejecutar_modelo_ia();
    } else {
        mostrar_uso();
        return 1;
    }

    return 0;
}

⚙️ Compilación y permisos

gcc -o /usr/local/bin/sistema_wrapper sistema_wrapper.c
chmod +x /usr/local/bin/sistema_wrapper

🔐 Seguridad vía sudoers

sudo visudo

Agrega esta línea:

www-data ALL=(ALL) NOPASSWD: /usr/local/bin/sistema_wrapper

🌐 Llamada desde Laravel o PHP

// Eliminar buzón
shell_exec("sudo /usr/local/bin/sistema_wrapper eliminar-buzon jose@midominio.com");

// Recargar Asterisk
shell_exec("sudo /usr/local/bin/sistema_wrapper recargar-asterisk");

// Ejecutar modelo IA
shell_exec("sudo /usr/local/bin/sistema_wrapper ejecutar-ia");

📊 Log generado

Contenido típico en /var/log/sistema_wrapper.log:

[2025-07-17 10:23:44] [BUZON] jose@midominio.com
[2025-07-17 10:24:01] [ASTERISK] Recarga de módulos completada
[2025-07-17 10:25:05] [IA] Modelo ejecutado con éxito

🚀 Conclusión

Los wrappers en C son herramientas extremadamente útiles para permitir que tu sistema web realice tareas privilegiadas de forma controlada, segura y auditada. Ya sea para administrar Asterisk, Postfix o ejecutar modelos IA, puedes confiar en este enfoque cuando los permisos o la seguridad del sistema sean una prioridad.

No hay comentarios: