Skip to content

pedrohaoa/icap-rhel

Repository files navigation

OPSWAT MetaDefender ICAP Server — Despliegue PoC

RHEL 9 OPSWAT VMware PostgreSQL SELinux F5

Contexto del Proyecto

PoC local (On-premises) de OPSWAT MetaDefender integrado con F5 BIG-IP vía protocolo ICAP, con foco en proteger un portal documental / NAS con latencia aceptable para el usuario final.

Caso de Uso

Ficheros de cliente final (Adobe, Imágenes, Office) que llegan desde el exterior al portal documental y se almacenan en el NAS. El objetivo es sanear (con Deep CDR) y validar el tipo real de fichero antes de persistirlo, manteniendo el flujo transparente al desarrollo y controlando la latencia de subida.


Arquitectura de la PoC

┌─────────────┐     HTTPS      ┌─────────────────┐
│   Cliente   │ ─────────────► │  Portal Web /   │
│  (usuario   │                │  App Backend    │
│   externo)  │                └────────┬────────┘
└─────────────┘                         │
                                        │ HTTP/HTTPS upload
                                        ▼
                               ┌─────────────────┐
                               │   F5        │
                               │                 │
                               │  iRule:         │
                               │  · Steering por │
                               │    URL/endpoint │
                               │  · Content-Len  │
                               │  · Tipo fichero │
                               └────────┬────────┘
                                        │ ICAP REQMOD
                                        │ TCP/1344
                                        ▼
                               ┌─────────────────┐
                               │  MetaDefender   │
                               │  ICAP Server    │
                               │  v5.13.0        │
                               │  :1344 (ICAP)   │
                               │  :8048 (UI)     │
                               └────────┬────────┘
                                        │ REST API
                                        │ HTTP/8008
                                        ▼
                               ┌─────────────────┐
                               │  MetaDefender   │
                               │  Core           │
                               │                 │
                               │  · Deep CDR     │
                               │  · Multi-AV     │
                               │  · True File    │
                               │    Type check   │
                               └────────┬────────┘
                                        │
                          ┌─────────────┴─────────────┐
                          ▼                           ▼
                   ✅ ALLOW                     ❌ BLOCK
              Fichero sanitizado           · True type mismatch
              (CDR aplicado)              · Malware detectado
              retorna a F5               · Tipo no permitido
              → NAS / flujo normal        → HTTP 403 al cliente

Prerrequisitos del Sistema

Componente Requisito mínimo Usado en PoC
CPU 4 cores 4 cores (VMware)
RAM 4 GB 8 GB
Disco / 20 GB libres 50 GB libres
SO RHEL 8/9 x86_64 RHEL 9.7 (Plow)
Virtualización Bare metal / VMware VMware STD8/Pro25
Kernel 4.x+ 5.14.0-611.42.1.el9_7
systemd 252+ 252
Suscripción RHEL Activa (BaseOS + AppStream) Simple Content Access

Puertos requeridos

Puerto Protocolo Uso
1344 TCP ICAP sin TLS (F5 → ICAP Server)
1345 TCP ICAP con TLS
8048 TCP Management UI (nginx)
5433 TCP PostgreSQL bundleado (solo localhost)

Tipos de fichero permitidos en la PoC

Tipo Extensiones CDR
Adobe PDF .pdf ✅ Deep CDR
Imágenes .jpg .jpeg .png ✅ CDR básico
Office .doc .docx .xls .xlsx .odt ✅ Deep CDR
Excluido .pptx .ppt ❌ Bloqueado en F5
Cualquier otro ❌ Bloqueado en F5

Dependencias del RPM

El paquete mdicapsrv bundlea internamente todas sus dependencias críticas en /usr/lib/mdicapsrv/:

  • Qt 6.9.3 (Core, Network, Sql, Xml, Qml, Concurrent)
  • libicudata/libicuuc 73.2
  • PostgreSQL propio en /usr/lib/mdicapsrv/postgres/
  • nginx propio
  • luajit 2.1
  • libcurl, libcrypto, libssl (versiones propias)

Dependencias que SÍ se instalan desde repos del sistema:

sudo dnf install -y openssl-libs libcurl libxcrypt-compat libnsl libpq libev luajit
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm

Instalación Paso a Paso

1. Verificar prerrequisitos

cat /etc/redhat-release
hostnamectl
ip addr show | grep "inet " | grep -v 127
nproc && free -h && df -h /
subscription-manager status
sudo dnf repolist

2. Instalar dependencias

sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install -y openssl-libs libcurl libxcrypt-compat libnsl libpq libev luajit

3. Configurar firewalld

sudo firewall-cmd --permanent --add-port=1344/tcp
sudo firewall-cmd --permanent --add-port=1345/tcp
sudo firewall-cmd --permanent --add-port=8048/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

4. Modo SELinux temporal durante instalación

sudo setenforce 0
getenforce   # debe mostrar Permissive

5. Crear el ignition file ANTES de instalar el RPM

sudo mkdir -p /etc/mdicapsrv
sudo tee /etc/mdicapsrv/mdicapsrv.ignition > /dev/null << 'EOF'
[dbserver]
type=local
host=localhost
port=5432
user=postgres
password=<CONTRASEÑA_SEGURA_ASCII_SIN_UNICODE>
EOF
sudo chmod 640 /etc/mdicapsrv/mdicapsrv.ignition
sudo chown root:root /etc/mdicapsrv/mdicapsrv.ignition

⚠️ El fichero debe existir ANTES de ejecutar el RPM. Solo caracteres ASCII en user y password. Sin Unicode.

6. Descargar y verificar el RPM

wget https://metascanbucket.s3.amazonaws.com/Metadefender/ICAP_Server/5.13.0-1/mdicapsrv-5.13.0-2.x86_64.rpm \
  --no-check-certificate \
  -O mdicapsrv-5.13.0-2.x86_64.rpm

# Verificar checksum (obtener SHA256 del portal OPSWAT)
echo "<SHA256_DEL_PORTAL>  mdicapsrv-5.13.0-2.x86_64.rpm" | sha256sum --check

7. Instalar el RPM

sudo dnf localinstall -y mdicapsrv-5.13.0-2.x86_64.rpm 2>&1 | tee /tmp/mdicapsrv-install.log

El instalador leerá el ignition file y configurará PostgreSQL automáticamente.

8. Verificar servicios

sudo systemctl status mdicapsrv mdicapsrv-pg --no-pager
sudo ss -tlnp | grep -E "1344|8048|5433"

9. Activar licencia

Acceder a http://<IP>:8048 y completar el wizard de setup inicial.

10. Hardening post-instalación

# Eliminar password del ignition file
sudo sed -i '/^password=/d' /etc/mdicapsrv/mdicapsrv.ignition

# Restaurar SELinux Enforcing
sudo setenforce 1
getenforce

Configuración del Workflow cdr_wf

Tab Parámetro Valor configurado
Request Filters HTTP Body Size < 10 MB
File Type Engine timeout 5 min
File Type Engine failure Block
Scan Allow Scan ON
Scan Scan Target MDCore_cdr_profile
Scan Scan Timeout 30 seg
Data Trickling Enable OFF (incompatible con CDR)
Content Encoded Scan Content Scan all content
Content Encoded Base64 failure Block
Content Encoded Limit File Size 10 MB
Advanced Override Processing History
Advanced Override Client IP by Header X-Client-IP / ICAP Header

Perfil de servidor MDCore_cdr_profile

Parámetro Valor
Type MetaDefender Core
Core URL http://<CORE_IP>:8008/
Workflow ICAP Deep CDR
Local Scan Deshabilitado
Webhook Callbacks Deshabilitado
Preference order Failover

Resultados de Validación Funcional

Test EICAR (fichero infectado)

Resultado:     BLOCKED ✅
HTTP response: 403 Forbidden
X-Infection-Found: Virus/EICAR_Test_File
X-Violations-Found: 1
Motores AV:    15/21 detecciones
Processing Time Core: 36 ms

Test PDF limpio (CDR)

Resultado:     Allowed ✅
X-Response-Info: Allowed
CDR aplicado:  documento_sanitized_by_OPSWAT_MetaDefender_<hash>.pdf
Latencia total: 332 ms

Métricas de latencia

Escenario Latencia Umbral PoC Estado
Fichero infectado (bloqueo) ~36 ms 2.000 ms
PDF limpio + CDR (<1KB) 332 ms 2.000 ms
PDF real estimado (<10MB) 500–1.200 ms 2.000 ms ✅ Proyección

Integración F5 — iRule ICAP

La iRule de steering selectivo debe implementarse en el F5 con la siguiente lógica:

when HTTP_REQUEST {
    # Steering selectivo: solo endpoints de subida de ficheros
    if { [HTTP::uri] starts_with "/upload" or
         [HTTP::uri] starts_with "/api/documents" } {

        # Solo ficheros dentro del límite de tamaño PoC
        if { [HTTP::header "Content-Length"] < 10485760 } {

            # Activar inspección ICAP REQMOD
            ICAP::enable reqmod

            # Propagar IP real del cliente al ICAP Server
            ICAP::header insert "X-Client-IP" [IP::client_addr]
        }
    }
}

when ICAP_REQUEST {
    # Configurar el servidor ICAP
    ICAP::server "icap://<ICAP_IP>:1344/mdicapsrv"
}

⚠️ Adaptar los endpoints /upload y /api/documents a los paths reales del portal documental.


Troubleshooting

Problema: mdicapsrv.ignition no leído durante instalación

Síntoma: El instalador pregunta interactivamente por los datos de BD. Causa: El archivo no existía antes de lanzar el RPM, o el directorio /etc/mdicapsrv/ no existía. Solución: Crear el directorio y el archivo ANTES del dnf localinstall.

Problema: libicu.so.73 no encontrada

Síntoma: Dependencias no resueltas en rpm -qRp. Causa: RHEL 9.7 tiene libicu-67. El RPM requiere .so.73. Solución: No instalar libicu73 externa. OPSWAT bundlea libicudata.so.73 y libicuuc.so.73 en /usr/lib/mdicapsrv/. El dry-run --setopt=tsflags=test pasa correctamente.

Problema: UI muestra "404 - page doesn't exist"

Síntoma: http://<IP>:8048/ muestra error 404. Causa: Es una SPA con hash routing. curl no ejecuta JavaScript. Solución: Usar http://<IP>:8048 en un navegador real. La SPA carga index.html y el router maneja /#/.

Problema: SELinux bloquea el servicio tras instalación

Síntoma: mdicapsrv en estado failed con SELinux Enforcing. Solución:

sudo setenforce 0
sudo systemctl restart mdicapsrv
sudo ausearch -m avc -ts today | grep mdicapsrv | audit2allow -M mdicapsrv_poc
sudo semodule -i mdicapsrv_poc.pp
sudo setenforce 1

Problema: postgresql-libs no encontrado en RHEL 9

Síntoma: rpm -q postgresql-libs devuelve not installed. Causa: En RHEL 9 el paquete se llama libpq, no postgresql-libs. Solución: Instalar libpq — es el equivalente correcto.

Problema: Header X-Client-IP no aparece en logs

Síntoma: Los logs del ICAP muestran la IP del F5, no la del cliente real. Causa: El campo Name en Advanced → Override Client IP no está configurado, o la iRule del F5 usa un nombre de header diferente. Solución: Verificar que la iRule inserta X-Client-IP y que en el workflow Advanced está marcado Override Client IP by Header con Name = X-Client-IP.


Logs y Monitorización

Log Ruta Contenido
ICAP Server /var/log/mdicapsrv/mdicapsrv.log Requests, respuestas, errores
nginx (UI) /var/log/mdicapsrv/nginx-mdicapsrv.log Acceso UI de gestión
PostgreSQL /var/lib/mdicapsrv/pg_data/log/ BD interna
Upgrade/Install /var/log/mdicapsrv/mdicap-upgrade-db_*.log Migraciones BD
Core (escaneos) http://<CORE_IP>:8008 → Processing History Resultados AV + CDR

Rotación de logs: Preconfigurada por OPSWAT — daily, 30 días, comprimido.


Criterios de Bloqueo de la PoC

Criterio Origen detección Acción
Malware detectado por multi-AV MetaDefender Core BLOCK → HTTP 403
True File Type mismatch ICAP Server (FileType engine) BLOCK → HTTP 403
Fichero fuera de tipo permitido F5 (primario) BLOCK en F5
Fichero fuera de tipo permitido MetaDefender Core (secundario) BLOCK → HTTP 403
Core inalcanzable (timeout 30s) ICAP Server BLOCK (fail-secure)
FileType engine failure ICAP Server BLOCK (fail-secure)
Base64 decoding error ICAP Server BLOCK
Encoding no soportado ICAP Server BLOCK
Fichero > 10 MB F5 / ICAP Server BLOCK / Skip ICAP

Información del Entorno PoC

⚠️ IPs y credenciales sanitizadas. Sustituir por valores reales en cada despliegue.

Componente Valor (sanitizado)
ICAP Server IP <ICAP_SERVER_IP>
ICAP Server hostname icap5
MetaDefender Core IP <CORE_IP>
ICAP Server versión mdicapsrv-5.13.0-2.x86_64
Management UI http://<ICAP_SERVER_IP>:8048
ICAP endpoint icap://<ICAP_SERVER_IP>:1344/mdicapsrv

Referencias

About

Guía completa para desplegar OPSWAT MetaDefender ICAP Server en RHEL. Paso a paso, probado en entorno real.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages