ROAMSWITCH SERVER 1.10.6 · Última actualización: 2026-09-26

Manual de operaciones de RoamSwitch Server Edition

Instalación oficial, implementación y referencia operativa para Cloud VPS (AWS, GCP, Azure, Linode, DigitalOcean), centros de datos básicos y hosts de contenedores.

1. Descripción general y requisitos

RoamSwitch Server Edition es una suite de monitoreo de integridad y defensa autónoma sin cabeza (cero dependencias de GUI) diseñada para servidores Linux expuestos a la Internet pública.

A diferencia de la edición de cliente que cambia dinámicamente los perfiles según el estado de Wi-Fi, la edición de servidor aplica Inbound Default Drop, monitoreo de integridad de archivos (FIM) de ruta crítica, mitigación preventiva de LPE del kernel (Frag Gap), detección de amenazas en tiempo de ejecución de eBPF, prevención de bloqueo SSH y alertas de emergencia multicanal automatizadas (Telegram/LINE/Webhook).

Principio Zero Telemetry (no se envía información sobre usted; la única comunicación externa por defecto es la recepción de datos firmados)
RoamSwitch no envía las direcciones IP de su servidor, la información de puertos, los hashes de archivos, los registros del sistema ni los resultados de diagnóstico al fabricante ni a ninguna nube. El propio binario del daemon no contiene ningún cliente TLS ni HTTP. Aparte de las actualizaciones del gestor de paquetes, el único tráfico que sale del host por defecto es la descarga anónima de datos firmados (cve_kernel_map_updates_enabled, activada de forma predeterminada). Son los datos de CVE del kernel, las reglas web y, en servidores Ubuntu, los datos de CVE de paquetes de Ubuntu que usa la comprobación de CVE de los paquetes del sistema. roamswitch-updater recibe, mediante HTTPS GET desde lafine.net, datos con firma Ed25519 (el manifiesto firmado se comprueba cada día, los datos de CVE en sí aproximadamente cada 30 días y las reglas web solo cuando el manifiesto tiene una versión más reciente), sin cadena de consulta ni cookies, con un User-Agent: RoamSwitch-Updater fijo como única cabecera que nombra el software, y no envía nada sobre este host. Se puede desactivar con roamswitch server config set cve_kernel_map_updates_enabled false (o con el asistente de configuración o la TUI del servidor), y la auditoría sigue funcionando con la línea base incorporada, aunque la comprobación de CVE de los paquetes del sistema en un servidor Ubuntu indicará entonces «sin datos de CVE locales». Todo el resto del tráfico que sale del host se limita a lo siguiente, que el operador ha habilitado explícitamente: notificaciones (Telegram / LINE / webhook), la verificación de firmas de npm (npm_audit_signatures_enabled, solo cuando se ejecuta el comando) y el reenvío de eventos (forward_enabled, desactivado de forma predeterminada; §16). El reenvío de eventos va únicamente a los destinos que usted mismo indique (un SIEM, syslog, un webhook); syslog sobre TLS se envía a través de openssl del sistema y el webhook estructurado mediante un subproceso curl. Además, el emparejamiento de Sensor (sensor_pairing_enabled, desactivado por defecto) y la integración con LLM de la herramienta independiente incluida accessscope (desactivada por defecto; en la línea de comandos, solo cuando se indica --llm) se conectan al exterior únicamente cuando el operador los activa. La lista de excepciones está en la sección Zero Telemetry del documento de diseño de seguridad de la Server Edition.

Requisitos del sistema

2. Procedimientos de instalación

El uso de repositorios oficiales firmados garantiza la resolución automática de dependencias y actualizaciones perfectas a través del administrador de paquetes del sistema estándar.

2.1 APT (sistema operativo Ubuntu/Debian/Raspberry Pi)

# 1. Registrar la clave de firma del repositorio
curl -fsSL https://lafine.net/apt/roamswitch-archive-keyring.asc \
  | sudo gpg --dearmor -o /usr/share/keyrings/roamswitch-archive-keyring.gpg

# 2. Añadir el repositorio
echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/roamswitch-archive-keyring.gpg] https://lafine.net/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/roamswitch.list

# 3. Instalar
sudo apt update && sudo apt install roamswitch-server

2.2 DNF/RPM (Fedora/RHEL/AlmaLinux/Rocky Linux)

# 1. Importar la clave GPG
sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch

# 2. Añadir el archivo de configuración del repositorio
sudo curl -fsSL -o /etc/yum.repos.d/roamswitch.repo https://lafine.net/rpm/fedora/roamswitch.repo

# 3. Instalar
sudo dnf install roamswitch-server

2.3 openSUSE (ziper)

sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch
sudo zypper addrepo https://lafine.net/rpm/opensuse/roamswitch.repo
sudo zypper refresh && sudo zypper install roamswitch-server
Paquete de exclusión mutua (conflictos)
La Edición Cliente (roamswitch) y la Edición Servidor (roamswitch-server) declaran conflictos de paquetes recíprocos. Seleccione siempre roamswitch-server en entornos de servidor sin cabeza.

3. Configuración inicial y verificación del servicio

3.1 Estado del servicio

Después de la instalación, roamswitch-server.service se inicia inmediatamente y se habilita en el inicio del sistema.

sudo systemctl status roamswitch-server.service

3.2 Asistente de configuración interactivo

Ejecute el asistente de configuración interactivo con el siguiente comando para configurar de forma interactiva los puertos, las IP de origen de mantenimiento, los canales de notificación y la acción de contención (pulse Intro para aceptar cada valor predeterminado).

sudo roamswitch server setup
  1. Puertos: introduzca los puertos de mantenimiento SSH (predeterminado 22) y los puertos de servicio públicos (predeterminado 80,443), separados por comas.
  2. IP de origen de mantenimiento: IP o CIDR de un bastión SSH o de la monitorización (p. ej. 203.0.113.50/32). El asistente exige una respuesta y no acepta un valor vacío. Para permitir SSH desde cualquier origen, escriba ANYWHERE (entonces la vía SSH de administración queda abierta al mundo entero, también durante el aislamiento).
  3. Canales de notificación: active el bot de Telegram, la API de mensajería de LINE y/o un webhook genérico (Slack / Discord / Teams).
  4. Respuesta ante un evento crítico de eBPF: elija isolate (aislar el host), freeze (congelar el proceso) o alert_only (solo notificar). Tras guardar, se le pedirá enviar una notificación de prueba y reiniciar el servicio.
  5. Actualización automática de los datos de CVE (predeterminado y): elija si la base de datos de CVE del kernel que usa la auditoría de aislamiento de contenedores, las reglas web y, en servidores Ubuntu, los datos de CVE de paquetes de Ubuntu que usa la comprobación de CVE de los paquetes del sistema se descargan de forma anónima de lafine.net (el manifiesto firmado se comprueba cada día, los datos de CVE en sí aproximadamente cada 30 días y las reglas web solo cuando el manifiesto tiene una versión más reciente; solo HTTPS GET, sin cadena de consulta ni cookies, con un User-Agent: RoamSwitch-Updater fijo como única cabecera que nombra el software, con la firma Ed25519 verificada). No se envía nada sobre este host. Es la única comunicación externa activada por defecto en la Server Edition; responder n la detiene (la propia auditoría sigue funcionando con la línea base incorporada, pero la comprobación de CVE de los paquetes del sistema en un servidor Ubuntu indicará entonces «sin datos de CVE locales»). Si ya está desactivada en un server.conf existente, la respuesta predeterminada sigue siendo n.
  6. Configuración de File Scan Guard: elija si desea habilitar el análisis antivirus para relés de correo, carpetas compartidas y destinos de carga (§13), y defina los directorios objetivo. Opcional, desactivado por defecto.
  7. Configuración de Resource Guard: active la protección de agotamiento de recursos que detecta un crecimiento sostenido de RSS (fugas de memoria/DoS) o bucles de fallos en servicios expuestos a la red.
  8. Resumen de las protecciones principales siempre activas: muestra las defensas principales que se ejecutan permanentemente al margen del asistente: rechazo entrante predeterminado, FIM, integración eBPF, etc. (no requiere entrada).
  9. Configuración de delegación al agente de investigación (investigation): elija si desea delegar automáticamente la investigación inicial — para eventos críticos de eBPF, o detecciones de manipulación de FIM de ruta crítica/archivos de bloqueo de dependencias, cuando se calificaron solo como notificación — a una CLI de agente de IA externo (Claude Code / agy / Codex CLI / OpenCode, o un comando personalizado) (§10.1). Desactivado por defecto.
Nota sobre el ID de chat de Telegram
El ID de chat de un supergrupo es un número negativo que comienza con -100 (p. ej. -1001234567890). Confirme el valor correcto en el campo "chat":{"id":...} de la respuesta de curl -s "https://api.telegram.org/bot<token>/getUpdates".

3.3 Auditoría de seguridad del servidor de 34 elementos

sudo roamswitch status --server

Realiza una auditoría instantánea de 34 comprobaciones de las reglas de firewall, la mitigación de Frag Gap, las restricciones y permisos de Yama LSM y la exposición del puerto Docker, lo que produce una puntuación y calificación de seguridad de 0 a 100 (S a C).

Cada elemento de comprobación ahora también se etiqueta, con fines de reporte de cumplimiento, con una función/categoría NIST CSF 2.0 (siempre presente cuando corresponde) y, solo cuando existe una correspondencia fiable, con un número de control de CIS Controls v8.

4. Reglas de puertos y firewall

El archivo de configuración /etc/roamswitch/server.conf exige permisos 0600 (lectura/escritura solo para root) para proteger la información sensible. El formato es clave=valor plano; las cabeceras de sección como [network] se ignoran.

# --- Firewall ---
ssh_ports=22                     # Puerto de administración SSH (se mantiene incluso durante el aislamiento de emergencia)
allowed_ports=80,443             # Puertos de servicio públicos
whitelist_ips=203.0.113.10/32    # IP/CIDR de origen de mantenimiento (vacío = permitir todo, antes admin_source_ips)
protect_docker_ports=true        # Protección DOCKER-USER (evita que los contenedores eludan el firewall)
preserve_ssh_on_isolation=true   # Conserva la vía de administración SSH incluso durante el aislamiento de emergencia (false = corte total)

# --- Guardia de tiempo de ejecución eBPF ---
action_on_critical=isolate       # isolate | freeze (SIGSTOP+corte de red) | alert_only
ebpf_socket_path=/run/roamswitch/events.sock

# --- Bloqueo de Egress/C2 y sumidero DNS ---
egress_ip_blocklist_enabled=true # Predeterminado true. La semilla incluida en el paquete solo contiene los tres servidores de ataque publicados por JPCERT/CC; no se bloquea nada más hasta que se instale un feed
metadata_watch_enabled=true      # Predeterminado true. Avisa cuando un programa que no es root/contenedor contacta con los metadatos de la nube (solo registro, no bloquea; detecta SSRF)
metadata_watch_allow_users=      # Cuentas que usan legítimamente el servicio de metadatos (nombres o ids numéricos, separados por comas; root siempre está exento)
dns_sinkhole_enabled=false       # Predeterminado false (para no romper el DNS interno/configuraciones split-horizon)
dns_sinkhole_provider=quad9      # quad9 | cloudflare | adguard | cleanbrowsing

# --- Datos CVE de aislamiento de contenedores (activados por defecto) ---
cve_kernel_map_updates_enabled=true # Predeterminado true. La única comunicación externa activada por defecto (datos de CVE del kernel firmados, reglas web y, en servidores Ubuntu, datos de CVE de paquetes de Ubuntu; manifiesto cada día, datos de CVE aproximadamente cada 30 días; anónima, solo recepción, firma verificada). false la detiene

# --- Notificaciones ---
telegram_enabled=false
telegram_bot_token=
telegram_chat_id=
line_enabled=false
webhook_enabled=false
webhook_url=
webhook_block_private_addresses=false   # opt-in SSRF guard
webhook_allow_addresses=

# --- Sistema ---
language=ja
fim_check_interval_secs=300      # Antes llamado scan_interval
isolation_hard_cap_secs=3600     # Segundos antes de que un aislamiento de alta confianza pase al modo DEGRADED (0 = mantener hasta que se libere)

Si edita el archivo directamente, reinicie el servicio para aplicar los cambios (roamswitch-server no admite recarga):

sudo roamswitch server restart

4.1 Política por nivel de gravedad (guard.yaml, opcional)

Si action_on_critical por sí solo no ofrece suficiente granularidad, cree /etc/roamswitch/guard.yaml (hay una plantilla en /etc/roamswitch/guard.yaml.example). Si no existe, se sintetiza automáticamente una política equivalente a partir de action_on_critical en server.conf, por lo que las instalaciones existentes no se ven afectadas.

policies:
  on_warning:
    action: log_and_notify
  on_critical:
    server_action: isolate_process
    kill_process: true
    fallback_to_host_isolation_after_retries: 3   # Escala automáticamente al aislamiento del host si el mismo proceso se repite
  on_emergency:
    action: isolate_host_all
    kill_process: true

server_safeguards:
  maintenance_ssh_ports: [22]
  safety_timer_secs: 300   # Segundos hasta que un aislamiento de baja confianza se restaura automáticamente (0 lo desactiva). No se aplica a los aislamientos de alta confianza (véase más abajo)

Liberación automática de un aislamiento (según la confianza): liberar solo con un temporizador fijo permite que un atacante paciente simplemente espere, por lo que el desencadenante de cada aislamiento se clasifica según su confianza. (1) Baja confianza (eBPF Error / Warning e inferiores, anomalías de puerto genéricas): se restaura por completo tras un temporizador corto (safety_timer_secs, 300 s de forma predeterminada). (2) Alta confianza (manipulación del canario, reescritura masiva al estilo ransomware, eBPF Critical / Emergency / Alert, escalada repetida de la misma regla): nunca se restaura en silencio. Tras el temporizador corto se sigue volviendo a comprobar la causa, y el aislamiento se libera con una notificación solo cuando se verifica que la causa ha desaparecido. Si no se puede confirmar, nadie lo ha reconocido (ack) y se alcanza el límite máximo (isolation_hard_cap_secs en server.conf, 3600 s de forma predeterminada, 0 = sin límite), pasa al modo DEGRADED. (3) El modo DEGRADED sigue bloqueando el tráfico nuevo distinto de las rutas de administración (los puertos SSH de mantenimiento y las IP de la lista blanca) y nunca se abre por temporizador. Solo se libera mediante una nueva comprobación que verifique que la causa ha desaparecido, un ack explícito (un ack durante DEGRADED significa liberar) o sudo roamswitch emergency-restore. En todo aislamiento se cortan las conexiones establecidas distintas de las rutas de administración (un canal C2 o una reverse shell que el atacante ya tenga abierta). Cada transición se registra en la línea de tiempo de incidentes y se notifica en 10 idiomas.

sudo roamswitch server ack

roamswitch server ack reconoce un aislamiento FULL manteniéndolo estricto (el operador se ha hecho cargo, por lo que no pasa a DEGRADED ni se libera automáticamente) y libera uno en DEGRADED.

4.2 Bloqueo de salida / C2 y sumidero DNS

Con egress_ip_blocklist_enabled=true (predeterminado), las conexiones salientes hacia IP maliciosas conocidas se bloquean con nftables. El feed es /var/lib/roamswitch/threatfeed/malicious_ips.txt (gestionado por el mecanismo de actualización) si existe; si no, la semilla incluida en el paquete (/usr/share/roamswitch/threatfeed/); se usa uno en lugar del otro, no se combinan. La semilla solo contiene las tres direcciones de servidores de ataque que JPCERT/CC publicó en su informe del 15/10/2026 sobre ataques a servicios web y API (210.149.87.120, 118.26.36.16, 69.10.51.162). Las direcciones de servidores alquilados pueden reasignarse a otras personas; si un destino legítimo deja de funcionar, revisa la línea correspondiente de ese archivo.

Establecer dns_sinkhole_enabled=true fuerza la resolución a través de un resolutor DNS de filtrado (Quad9 / Cloudflare / AdGuard / CleanBrowsing), bloqueando la resolución de dominios conocidos como maliciosos. Está desactivado (false) de forma predeterminada porque puede afectar al DNS interno o a configuraciones split-horizon.

Con metadata_watch_enabled activado (por defecto), la tabla nftables inet roamswitch_metadata_watch escribe una línea en el registro del kernel solo cuando un programa que no es root o un contenedor abre una nueva conexión a una dirección de metadatos de la nube (169.254.169.254, 169.254.170.2, 100.100.100.200, fd00:ec2::254); el demonio del servidor avisa una vez al día por cuenta (por dirección de origen en el caso de un contenedor). Solo registra y avisa, nunca bloquea. Cuando un atacante entrega a la aplicación la URL de su propio servidor, que redirige (302) a una dirección interna, el registro de acceso solo muestra la URL externa; únicamente este tráfico saliente deja ver el segundo salto. Una aplicación que usa legítimamente su rol en la nube también se notifica: añade su cuenta a metadata_watch_allow_users para exceptuarla (un contenedor no se puede exceptuar).

4.3 Protección de detección de escaneo de puertos entrantes

Detecta las IP de origen que se conectaron a numerosos puertos distintos en poco tiempo, correlacionando las reglas de registro de nftables con journald (activado por defecto). Las fuentes de escaneo de alta confianza pueden bloquearse automáticamente durante un periodo determinado. Cuando se usa junto con RoamSwitch Sensor (una función distinta del §10.1: las sondas de auditoría de todos los puertos de un Sensor emparejado se excluyen como mitigación de falsos positivos), la propia IP del Sensor queda excluida automáticamente.

# --- Detección de escaneo de puertos entrantes (activada por defecto) ---
port_scan_detect_enabled=true              # false para desactivar
port_scan_detect_min_distinct_ports=15     # Se considera un escaneo cuando las conexiones alcanzan esta cantidad de puertos distintos
port_scan_detect_window_secs=300           # Ventana de agregación para la detección (segundos)
port_scan_block_enabled=true               # Bloquea automáticamente la IP de origen del escaneo detectado
port_scan_block_duration_secs=600          # Duración del bloqueo automático (segundos)

Puede consultar el historial de detección con el comando roamswitch port-scan.

4.4 Protección de detección de túneles DNS

Inspecciona únicamente el tráfico DNS saliente propio de este host (puerto UDP/TCP 53) mediante un consumidor NFQUEUE dedicado. Una consulta se considera de forma sospechosa si la longitud de su etiqueta supera los 40 bytes Y su entropía de Shannon supera 3,8, o si su qtype es TXT/NULL; se emite una alerta en cuanto se detectan 10 o más consultas de este tipo en los últimos 60 segundos (un periodo de enfriamiento de 300 segundos evita alertas repetidas bajo la misma condición). Su objetivo es detectar los patrones de consulta característicos de herramientas de túneles DNS/exfiltración como iodine y dnscat2. La regla nftables subyacente lleva el mismo indicador bypass que el resto de protecciones DNS de este daemon, de modo que la resolución de nombres DNS nunca se ve interrumpida aunque esta protección esté detenida o no responda. Es una función exclusivamente de notificación: nunca bloquea automáticamente. Como con cualquier otro ajuste, un cambio en dns_tunnel_detect_enabled solo surte efecto tras reiniciar el servicio.

# --- Detección de túneles DNS (activada por defecto) ---
dns_tunnel_detect_enabled=true              # false para desactivar

4.5 Guardia contra fuerza bruta SSH

La guardia lee los inicios de sesión fallidos de sshd en el momento en que se escriben en el registro y los cuenta por dirección de origen (activada por defecto). Para un origen que alcanza el número de fallos configurado (por defecto 6 en 600 segundos), la tabla nftables inet roamswitch_sshguard descarta solo las conexiones nuevas hacia los puertos SSH. El primer bloqueo dura 1 hora, se cuadruplica cada vez que el mismo origen reincide y tiene un tope de 7 días. En el momento del bloqueo también se cortan las conexiones que ese origen ya tenía abiertas hacia SSH (se eliminan sus entradas de conntrack y una regla descarta los paquetes del sentido de respuesta). Solo se bloquea un origen sin sesión autenticada, sin inicio de sesión con clave pública registrado y sin exención, y esto se comprueba otra vez justo antes de cortar, así que una sesión autenticada y un origen exento nunca se cortan. No se envía nada al exterior; solo se ejecutan localmente comandos como journalctl, nft y loginctl.

El registro se sigue con journalctl -f. journald anota qué proceso escribió cada línea, así que se ignoran las líneas escritas por algo que no sea sshd. Sin journald, la guardia sigue /var/log/auth.log o /var/log/secure, pero cualquier usuario local que pueda usar syslog puede falsificar líneas en esos archivos y lograr que se bloquee a un tercero; donde haya journald, deje ssh_guard_log_source en su valor predeterminado auto. Los fallos que se cuentan son contraseña incorrecta, usuario inexistente, desconexión antes de la autenticación tras indicar un nombre de usuario, exceso de intentos y fallos de autenticación PAM. Un fallo de clave pública (Failed publickey) no se cuenta, porque un cliente legítimo con varias claves lo genera en cada conexión. La dirección de origen se lee del final de la línea, en from <IP> port <N>. Un atacante puede poner cualquier texto en el nombre de usuario, pero una dirección de origen falsa escrita ahí no hace que se bloquee a un tercero. IPv6 se cuenta por /64 y el bloqueo también es por /64 (solo la dirección de origen si ese /64 contiene una dirección que debe seguir accesible, como la puerta de enlace).

Nunca se bloquean: la puerta de enlace, los resolutores DNS, el propio servidor, el bucle local, whitelist_ips, ssh_guard_allow, el origen de una sesión SSH abierta ya autenticada, cualquier dirección que haya iniciado sesión con clave pública en los últimos 30 días (ssh_guard_trust_key_days; un inicio de sesión correcto con contraseña no cuenta) y un Sensor emparejado. Si alguno de estos orígenes acumula fallos, la guardia solo lo registra. Las direcciones privadas no están exentas, porque un equipo comprometido dentro de la red también puede ser el origen de un ataque de fuerza bruta. Un origen que solo mantiene una conexión abierta antes de autenticarse tampoco está exento.

Cuando fail2ban (con una jail sshd activada) o CrowdSec (con un firewall bouncer en marcha) ya protege sshd, la guardia le cede el bloqueo para no bloquear dos veces la misma dirección, y solo detecta y notifica (ssh_guard_yield_to_fail2ban, true por defecto). Con ssh_guard_block_enabled=false también solo detecta y notifica. Notifica cuando bloquea (en modo solo detección, cuando se alcanza el umbral) y cuando un inicio de sesión tiene éxito desde un origen que había acumulado fallos (crítico: puede que un ataque de fuerza bruta haya tenido éxito; la sesión no se corta). No notifica cada fallo, y los orígenes que pasen de 10 por hora se agrupan en una sola notificación.

La lista de bloqueos se ve con roamswitch server bans (admite --json; la lista solo la puede leer root, así que con sudo) y se levanta con sudo roamswitch server unban <IP | /64 IPv6 | --all>; al levantar un bloqueo también se borra el contador de fallos de ese origen. Los bloqueos se restauran con el tiempo que les queda tras reiniciar el servidor. roamswitch emergency-restore no levanta los bloqueos SSH (restablecer la red no es motivo para dejar volver a quien estaba adivinando contraseñas); el menú de recuperación (roamswitch recover) y la desinstalación eliminan la tabla entera. La herramienta MCP get_ssh_guard_incidents es de solo lectura y no existe ninguna herramienta para levantar un bloqueo. En la TUI de Server, la sección «Fuerza bruta SSH» de la pantalla de incidentes lista los bloqueos y permite levantarlos (si se inicia como root; §17).

roamswitch server bans
sudo roamswitch server unban 203.0.113.9
sudo roamswitch server unban --all

Hay 10 ajustes, todos con el prefijo ssh_guard_ (§18.1). Se cambia uno, por ejemplo, con sudo roamswitch server config set ssh_guard_max_failures 10 y se aplica con sudo roamswitch server restart. Ponga ssh_guard_enabled=false para detener la guardia por completo, o ssh_guard_block_enabled=false para que solo detecte y notifique. El elemento «Protección de fuerza bruta SSH» del diagnóstico de 34 elementos también se supera mientras esta guardia esté en marcha y bloqueando.

Límites: los intentos que solo fallan con clave pública no se cuentan. Un ataque de fuerza bruta repartido entre muchos orígenes se cuenta por origen, por lo que no se detiene hasta que un origen alcanza el umbral. El remedio de fondo es desactivar la autenticación por contraseña y permitir solo claves públicas.

5. Prevención de bloqueo SSH a prueba de fallos

El bloqueo accidental debido a una mala configuración del firewall es un desastre operativo intolerable. RoamSwitch Server Edition incorpora protecciones de varios niveles:

6. Protección de contenedores (Docker/Podman)

El comportamiento predeterminado de Docker crea reglas de iptables personalizadas que evitan los firewalls de host estándar, exponiendo los puertos del contenedor (por ejemplo, -p 8080:8080) directamente a Internet.

Con protect_docker_ports=true (predeterminado), RoamSwitch se adapta al backend de firewall de Docker para que el tráfico hacia los contenedores tampoco sea accesible desde el exterior, salvo que se dirija a un puerto incluido en ssh_ports o allowed_ports. Con el backend iptables / iptables-nft inserta una regla de inspección al principio de la cadena DOCKER-USER (para IPv4, y también mediante ip6tables cuando IPv6 de Docker está habilitado). Con el backend nftables nativo de Docker (Docker 29 y posteriores, donde DOCKER-USER no existe) crea su propia tabla inet roamswitch_docker_guard en el hook forward, antes de las cadenas de Docker (una tabla inet cubre IPv4 e IPv6). La decisión usa el puerto de destino original previo al DNAT (ctorigdstport) y se aplica solo al tráfico que llega por la interfaz externa, de modo que el tráfico saliente de los contenedores y el tráfico entre contenedores no se ven afectados. Evita la exposición accidental de, por ejemplo, un contenedor de base de datos de desarrollo.

La protección es idempotente y se autorrepara cada minuto: si dockerd arranca después de RoamSwitch, si un reinicio o recarga de Docker reescribe las reglas, o tras un nft flush manual o la pérdida de la tabla nftables, se vuelve a aplicar, mientras que una protección que ya está al día se deja intacta.

Una protección en tiempo real que vigila docker events también detecta los contenedores iniciados con --privileged o con /var/run/docker.sock montado (riesgo de escape del contenedor) justo después de arrancar y le avisa. Además, la protección de ejecución en contenedores (container_exec_guard_enabled, activada de forma predeterminada) inspecciona con YARA los binarios ejecutados dentro de los contenedores (una evasión que elimina el archivo tras ejecutarlo también se inspecciona, porque el contenido se lee desde el descriptor de archivo ya abierto). La protección también marca los contenedores que ya están en ejecución al iniciar y sigue automáticamente los contenedores nuevos. Ambas son de solo notificación y nunca bloquean automáticamente. También funcionan con Docker 29 (desde la 1.11.1). Cuando la suscripción a los eventos sigue fallando, el intervalo de reconexión se amplía de 5 segundos hasta un máximo de 5 minutos.

7. Monitoreo de la integridad del archivo de ruta crítica (FIM)

Más de 150 archivos críticos (binarios críticos como /bin/login, /usr/bin/sudo y /usr/sbin/sshd, la configuración de autenticación como /etc/shadow y /etc/sudoers, y las unidades de systemd) se monitorizan mediante SHA-256.

El alcance no se limita a archivos individuales. En los directorios críticos (/etc/pam.d, /etc/sudoers.d, /etc/ssh/sshd_config.d, /etc/cron.*, /etc/systemd/system, /etc/ld.so.conf.d, /etc/profile.d y /root/.ssh (excepto known_hosts)) también se detecta la aparición de un archivo nuevo, y también se cubren el authorized_keys de todas las cuentas que pueden iniciar sesión, /etc/ld.so.preload (normalmente no existe; su aparición es indicio de un rootkit local) y los propios binarios de RoamSwitch. Se excluyen las unidades temporales que genera snapd (snap-*.mount y similares). La detección de archivos nuevos solo funciona frente a una línea base que incluya este alcance, así que ejecute sudo roamswitch fim update una vez tras actualizar. Los archivos que fim verify no puede leer cuando se ejecuta sin root se informan como «omitido, ilegible», no como manipulación.

7.1 Verificación manual de hash

sudo roamswitch fim verify

7.2 Detección basada en eventos (instantánea)

Los archivos supervisados se vigilan individualmente mediante fanotify (FAN_CLASS_NOTIF, eventos de finalización de escritura), por lo que una manipulación se vuelve a verificar y se detecta en el instante en que ocurre, sin esperar al siguiente análisis periódico. El análisis periódico (predeterminado fim_check_interval_secs=300 segundos) sigue actuando como respaldo ante eventos no capturados. También se detectan las ediciones que colocan un archivo nuevo bajo el mismo nombre (install, sed -i y similares), y la notificación indica el proceso que hizo el cambio y su inicio de sesión SSH (§7.5).

7.3 Sincronización automática de referencia en actualizaciones del sistema operativo

En Debian/Ubuntu, la instalación de paquetes configura automáticamente el gancho DPkg::Post-Invoke en /etc/apt/apt.conf.d/99roamswitch-fim. En Fedora/RHEL/Rocky/AlmaLinux/openSUSE, una unidad systemd.path (roamswitch-fim-update.path) que vigila /var/lib/rpm cumple la misma función.

En Debian/Ubuntu, /etc/apt/apt.conf.d/99roamswitch-fim adjunta un gancho DPkg::Post-Invoke. Las actualizaciones legítimas de paquetes a través de sudo apt upgrade actualizan automáticamente la línea base FIM, eliminando alertas de falsos positivos.

sudo roamswitch fim update

Cuando el demonio arranca por primera vez y construye la línea base, si un gestor de paquetes (apt/dpkg, dnf/rpm, zypper o pacman) está trabajando, espera hasta 120 segundos a que termine antes de construirla. Aunque se instale en el mismo apt install que Apache u otro paquete, los archivos temporales con los que trabaja dpkg (como *.dpkg-new) ya no entran en la línea base ni parecen una manipulación en la verificación siguiente (desde la 1.11.18). Si pasados 120 segundos sigue ocupado, se registra una advertencia y la línea base se construye igualmente.

7.4 Honeytokens (señuelos de credenciales)

Al iniciarse, aprovechando que se ejecuta como root, el daemon despliega de forma idempotente tres archivos de credenciales señuelo bajo /root: .aws/credentials, .ssh/id_rsa y .docker/config.json (en conjunto, honeytokens). Nunca sobrescribe un archivo real ya existente en esas rutas. Un proceso de vigilancia en segundo plano usa inotify para detectar cualquier acceso de lectura a estos archivos y lo interpreta como reconocimiento de credenciales tras un compromiso (MITRE ATT&CK T1552: Unsecured Credentials), enviando de inmediato una notificación de severidad Critical y registrándolo en la línea temporal de incidentes. La función está activada por defecto y se ajusta con las claves honeytokens_enabled (false detiene la colocación y la vigilancia; los señuelos ya colocados permanecen) y honeytokens_home (dónde se colocan los señuelos; por defecto /root). Los paquetes hasta la 1.10.4 no incluían roamswitch-honeytokens, necesario para esta función, por lo que no se ejecutaba en las instalaciones desde los paquetes. Se incluye desde la 1.10.5, y el problema de que el sandbox de systemd bloqueara las escrituras en /root en la edición de servidor se corrigió en la 1.10.10. Desde la 1.11.1, cada comando docker que ejecuta el propio RoamSwitch se inicia con un directorio privado vacío (/run/roamswitch/docker-config como root) como DOCKER_CONFIG, por lo que no activa el señuelo .docker/config.json (antes, la vigilancia del daemon y roamswitch status --server podían leer el señuelo y generar una detección falsa). La lectura por cualquier otro programa se sigue detectando como antes.

Si se detecta un acceso real a alguno de los honeytokens, previendo que el atacante seguirá explorando, RoamSwitch despliega hasta dos señuelos adicionales relacionados temáticamente por cada disparador (por ejemplo, al alcanzar .aws/credentials también se despliega .aws/config; al alcanzar .ssh/id_rsa, .ssh/config; al alcanzar .docker/config.json, .kube/config), con un máximo total de seis entre todos los disparadores. Si observa que estos archivos desconocidos se acumulan bajo /root durante una investigación de un incidente, es un comportamiento esperado.

7.5 Vía de intrusión (quién hizo el cambio y mediante qué inicio de sesión SSH)

Las notificaciones sobre un archivo modificado (FIM de rutas críticas y FIM de archivos de bloqueo) incluyen ahora el proceso que hizo el cambio (cuenta, ejecutable, comando) y el inicio de sesión SSH al que pertenece (IP y puerto de origen, hora de inicio de sesión, método de autenticación y huella de la clave pública). Está activado por defecto (fim_intrusion_context_enabled). En el momento en que se lee un evento, el demonio toma una instantánea de /proc/<pid> del proceso que escribe (ejecutable, usuario, loginuid, sessionid, cgroup, cadena de padres), porque un proceso como tee o sed desaparece un milisegundo después. Un proceso que ya había terminado se completa con el registrador de ejecuciones (si está activado). La asociación con un inicio de sesión usa primero la tabla de sesiones de la guardia SSH y, si no, las líneas Accepted de logind y journald. Funciona aunque la guardia SSH esté desactivada. No se envía nada al exterior.

Solo se confía en los valores que informa el kernel: el ejecutable sale de /proc/<pid>/exe (no de argv[0]), el inicio de sesión de loginuid (se fija una sola vez al iniciar sesión y se hereda a través de sudo y su) y del session-N.scope del cgroup, y el resto de la cadena de padres. Los valores que un proceso puede cambiar por sí mismo, como comm, la línea de comandos y el entorno, se muestran pero nunca se usan para decidir; un proceso que solo se llama sshd no se toma por un inicio de sesión SSH. Una notificación distingue tres respuestas: encontrado (origen, hora, método, clave); «No se encontró ningún inicio de sesión SSH» (la comprobación mostró un servicio de systemd, un contenedor, una sesión de inicio local o un proceso sin sesión de inicio); y «No se pudo determinar la vía de acceso» (el proceso ya no existía y no está en el registrador de ejecuciones, logind no respondió, el cambio lo halló el escaneo periódico y el proceso se desconoce, etc.). Lo que no se pudo comprobar nunca se presenta como «no es un inicio de sesión». La notificación sale aunque falle la consulta.

/etc/ssh/sshd_config: modified
  Proceso: root (inició sesión como admin) / /usr/bin/tee / comando: tee /etc/ssh/sshd_config (pid 4121)
  Inicio de sesión SSH: la sesión que admin abrió desde 203.0.113.25:51544 a las 2026-10-17 03:12:08 (autenticación: publickey, clave SHA256:AbCdEf0123456789)

/etc/sudoers: modified
  No se pudo determinar la vía de acceso (el cambio lo encontró el análisis periódico, así que no se sabe qué proceso lo hizo)

Ahora también se detectan las ediciones que colocan un archivo nuevo bajo el mismo nombre: install, sed -i y cp seguido de mv en el mismo directorio. La marca por archivo se asocia al inodo, por lo que antes este tipo de edición no generaba ningún evento. Ahora el demonio marca también los directorios que contienen archivos vigilados y, cuando se cierra un archivo con otro nombre en el mismo directorio, vuelve a consultar el nombre unos milisegundos después. Límite: un archivo escrito en otro directorio y movido con mv solo lo encuentra el escaneo periódico (fim_check_interval_secs). Entonces no se conoce el proceso que escribió, y la notificación lo indica.

Además de la notificación, el hallazgo se conserva en la cronología de incidentes (tipo fim) y en /var/lib/roamswitch/fim_intrusions.json (solo root, los últimos 100). La herramienta MCP verify_fim lo devuelve en un campo añadido, recentIntrusionContext (solo si se ejecuta como root). El veredicto sobre si un archivo fue manipulado no cambia. Límites: con el registrador de ejecuciones desactivado y un proceso escritor que vive solo un instante, se desconoce el ejecutable y se muestran el ejecutable y la línea de comandos del proceso padre. Las notificaciones de la vigilancia de persistencia (persistence_watch) no llevan información de proceso, por lo que no reciben vía de intrusión. La vía muestra el proceso que hizo el cambio y su inicio de sesión, y nada más: la puerta de entrada en sí (la vulnerabilidad explotada o cómo se robó una clave) no se muestra. Para desactivarlo, pon fim_intrusion_context_enabled=false.

8. Integración de Falco y Runtime Guard de eBPF

Se conecta a eventos eBPF del espacio del kernel (Falco/Tetragon) para detectar la escalada de privilegios del kernel de Frag Gap, escapes de contenedores y shells inversos no autorizados.

8.1 Arquitectura anti-inflación

Para evitar la «explosión de syslog» y la presión sobre el disco que afectan a las herramientas de seguridad convencionales, RoamSwitch se conecta a Falco directamente a través del socket de dominio UNIX /run/roamswitch/events.sock. El socket se crea accesible solo para root (0600), de modo que solo Falco ejecutándose como root puede escribir en él (no se necesita ninguna configuración de permisos adicional).

8.2 Contención autónoma

Al detectar un ataque crítico, RoamSwitch emite inmediatamente SIGSTOP para congelar el PID del proceso infractor y aplica el aislamiento Air-Gap de nftables.

8.3 Preservación automática de evidencias forenses (Forensic Evidence Capture)

Se crea automáticamente un paquete de evidencias cada vez que la protección de tiempo de ejecución eBPF aplica una acción de contención por proceso (congelación mediante SIGSTOP más corte de red). Según la política predeterminada del §4.1, los eventos de severidad Critical siguen esta ruta; los eventos de severidad Emergency, que aíslan todo el host, actualmente no generan un paquete. Un paquete contiene una captura de paquetes acotada, de mejor esfuerzo, de unos 30 segundos en la interfaz de enrutamiento predeterminada (se omite silenciosamente, dejando constancia de ello, si tshark no está instalado), y, cuando se conoce el PID responsable, una instantánea de /proc/<pid>: status, cmdline, maps, environ (los valores cuyo nombre contiene KEY/TOKEN/SECRET/PASSWORD se sustituyen por [REDACTED]), una lista de los destinos de los descriptores de archivo abiertos y la cadena de procesos ancestros hasta el PID 1. Se incluye un manifest.json con el hash SHA-256 de cada archivo capturado para una verificación de manipulación posterior.

Los paquetes se almacenan en /var/lib/roamswitch/incident-evidence/<marca de tiempo>-<ID>/. Nunca se purgan automáticamente. Para liberar espacio en disco, elimine explícitamente los paquetes más antiguos que el periodo de retención (30 días por defecto) con:

sudo roamswitch-incident-capture prune [--keep-days N]

También puede capturar una instantánea manual en cualquier momento, sin esperar a una acción de contención, con:

sudo roamswitch-incident-capture snapshot [--pid PID] [--reason TEXT] [--json]

8.4 Medición de la rapidez del aislamiento y latido (heartbeat) de la vía de alertas

La precisión y la rapidez del aislamiento eBPF dependen de las reglas del sensor (Falco o Tetragon). De hecho, las reglas estándar de Falco 0.45.0 (29 en total) no incluyen ninguna que detecte un reverse shell en el host: las reglas de reverse shell son solo para contenedores, y algunas se descartan por la condición priority: warning de RoamSwitch. RoamSwitch no da por buenas las reglas; lo compensa de tres maneras: mide cuánto tarda el aislamiento, comprueba con regularidad que la vía de alertas está viva y detecta por sí mismo los reverse shells.

Medición de la latencia del aislamiento: por cada incidente eBPF el demonio registra el tiempo desde la detección de Falco hasta que lee la alerta (detect_to_receive_ms), desde que la lee hasta que termina la respuesta (receive_to_action_ms, medido cuando vuelve la llamada de aislamiento; en el Air-Gap del host, hasta que se carga el conjunto de reglas) y la suma de ambos (detect_to_action_ms). Los valores aparecen como campos añadidos en ebpf_incidents.json y en la herramienta MCP get_ebpf_incidents. La notificación de un proceso aislado incluye una línea «de la detección a la respuesta: N ms». Medido en una VM con Ubuntu 24.04 (Falco 0.45.0, modern eBPF): de 1 a 2 ms de la detección a la recepción, de 41 a 62 ms de la recepción al aislamiento del proceso más SIGKILL (42 a 64 ms en total) y 109 ms en total para el Air-Gap del host (dentro del objetivo de 150 ms). Las cifras son de esa VM. Tetragon pone la marca de tiempo al recibir, por lo que no tiene detect_to_receive_ms.

Heartbeat (ebpf_heartbeat_interval_secs; 600 segundos por defecto, 0 lo desactiva, en otro caso de 60 a 86400): el paquete incluye una regla de Falco propia de RoamSwitch, 96-roamswitch-heartbeat.yaml. En cada intervalo el demonio abre una ruta desechable que solo root puede usar (un nombre aleatorio bajo /run/roamswitch/heartbeat/) y mide cuánto tarda la alerta de esa regla en volver por la salida de Falco. Un solo viaje de ida y vuelta muestra a la vez que la regla está cargada, que Falco funciona y que la vía de salida está viva. Solo cuando dos comprobaciones seguidas no vuelven (la segunda un minuto después de la primera) avisa: «las reglas no están cargadas o la salida no llega», como máximo una vez cada 24 horas. Una línea de heartbeat se descarta sin llegar al aislamiento, la notificación, la lista de permitidos ni el registro de incidentes. No se envía nada al exterior. Los viajes de ida y vuelta medidos fueron de 2 a 6 ms; al quitar la regla el aviso llegó tras unos 164 segundos, y al restaurarla el estado volvió a la normalidad en unos 75 segundos.

El estado se guarda en /var/lib/roamswitch/ebpf_heartbeat.json y lo leen el campo heartbeat de la herramienta MCP get_ebpf_incidents y el diagnóstico K-04 (agente de ejecución eBPF; el número de puntos de diagnóstico sigue siendo 34). Aunque Falco esté funcionando, K-04 falla si el heartbeat no vuelve. Límites: se comprueba un viaje de ida y vuelta de una sola regla (las llamadas al sistema de la familia open); no se puede saber si otra regla está rota por su cuenta. Lo que se rompe entre dos comprobaciones (10 minutos por defecto) no se ve hasta la siguiente. No se hace para Tetragon. En un host donde Falco no está en marcha o falta el archivo de la regla, no se comprueba nada ni se avisa de nada (de eso se encarga la notificación existente de «guardia detenida»). Falco escribe una línea de aviso en syslog por cada comprobación (144 líneas al día con el valor por defecto).

8.5 Detección de reverse shell (propia de RoamSwitch)

Sin apoyarse en las reglas de Falco, RoamSwitch lee por sí mismo /proc cada 2 segundos y busca una shell o un intérprete (sh, bash, python, perl, ruby, php, node y similares) cuya entrada y salida estándar sean una única conexión TCP que este host abrió hacia una dirección externa. Se cubren bash -i >& /dev/tcp/…, python, perl, nc -e y socat exec:. Solo se informa de lo que se ve dos veces seguidas, una vez por proceso. Por defecto solo cuentan las direcciones externas públicas; las privadas (RFC 1918, CGNAT, enlace local) cuentan solo con reverse_shell_watch_include_private=true, porque el ProxyCommand de ssh, los contenedores y el desarrollo local las hacen frecuentes y legítimas. El loopback nunca se vigila. Las conexiones que el host aceptó (por inetd o socat TCP-LISTEN) tampoco se cubren. Medido en una VM con Ubuntu 24.04, bash /dev/tcp, python, perl, nc -e y socat exec: se detectaron cada uno unos 2,4 segundos después de la conexión. No se detectan ssh, ssh con ProxyCommand, git sobre ssh ni un cliente nc.

Una detección entra por la misma vía que una alerta de Falco (lista de permitidos, enfriamiento de notificaciones, acciones por gravedad de guard.yaml, registro de incidentes) como un evento eBPF Critical llamado RoamSwitch Reverse Shell. Por defecto aísla el proceso y lo mata (kill). Un reverse shell propiedad de root no se puede aislar por proceso, así que, como cualquier evento Critical, pasa al Air-Gap de todo el host. Hay dos salidas si preocupa que se marque por error un programa legítimo: reverse_shell_watch_notify_only=true (un Warning con solo notificación; no se aísla ni se mata nada; false por defecto) y una entrada en la lista de permitidos, sudo roamswitch server allowlist add "RoamSwitch Reverse Shell" <nombre del proceso>. Las tres claves de ajuste son reverse_shell_watch_enabled (true por defecto), reverse_shell_watch_include_private (false) y reverse_shell_watch_notify_only (false).

Límites: se filtra por nombre (nombre del proceso y del ejecutable), así que un binario casero con un nombre distinto del de una shell o un intérprete que ate su entrada y salida estándar a un socket no se encuentra. Las conexiones por loopback (como el retorno de ssh -R) y las de menos de 2 segundos no se ven, ni tampoco los procesos que no son visibles desde el espacio de procesos del host. Esta detección existe solo en la Server Edition; el Mac y el cliente Linux no la tienen.

9. Alertas de emergencia (Telegram / LINE / Webhook)

Envía alertas inmediatas a canales de notificación externos cuando ocurren anomalías en los puertos, manipulación de FIM o eventos de contención de eBPF:

[notifications]
language = ja
# Telegram: token del bot e ID de chat
telegram_bot_token = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ"
telegram_chat_id = "-1001234567890"

# LINE: token de acceso al canal de Messaging API e ID de usuario
line_channel_access_token = "YOUR_LINE_ACCESS_TOKEN"
line_user_id = "U1234567890abcdef1234567890abcdef"

# Webhook genérico (Slack, Discord, Teams, su propia plataforma de monitorización)
webhook_url = "https://hooks.slack.com/services/T00/B00/XXXXX"

Incluso sin configurar estos canales externos, cada alerta enviada también se conserva localmente durante los últimos 7 días. Consúltela con roamswitch notifications.

Rechazar destinos de webhook internos (opt-in): con webhook_block_private_addresses=true (por defecto false = sin cambios), un webhook de notificación se rechaza si su destino —en un nombre de host basta con una sola dirección resuelta— es loopback, privado (10/8, 172.16/12, 192.168/16), enlace local (169.254/16, incluido el endpoint de metadatos cloud 169.254.169.254), ULA (fc00::/7) o CGNAT (100.64/10). El motivo se registra en el log y en el error de roamswitch notify-test. También se clasifican grafías alternativas como 2130706433 o 0x7f.1 y el IPv6 IPv4-mapped, y las direcciones verificadas se fijan en curl, de modo que el DNS rebinding no pueda cambiar el destino. Los destinos internos legítimos, como un SIEM propio, se permiten con webhook_allow_addresses=10.20.0.0/16,fd00::/8 (CIDR separados por comas). Los webhooks de reenvío de eventos tienen el mismo par: forward_webhook_block_private_addresses y forward_webhook_allow_addresses. Incluso con la opción en false, si el destino es una dirección de metadatos cloud se registra una advertencia (el envío no se detiene). Si hay una variable de entorno de proxy HTTP, la resolución y la conexión las hace el proxy y quedan fuera de esta comprobación.

10. Integración de agente AI/MCP (protocolo de contexto modelo)

RoamSwitch Server Edition incluye roamswitch-mcp, lo que permite a los agentes de IA (Claude, Gemini, Cursor) monitorear el estado y la postura de la infraestructura.

Garantía de seguridad de sólo lectura
Para evitar que los ataques de inyección rápida comprometan la infraestructura, la interfaz MCP es estrictamente de solo lectura. Los agentes de IA no pueden abrir puertos, eliminar el aislamiento ni alterar las configuraciones de seguridad a través de MCP. La corrección requiere acceso al shell TTY local autenticado.

Ejemplo de configuración (`claude_desktop_config.json`)

{
  "mcpServers": {
    "roamswitch": {
      "command": "/usr/bin/roamswitch-mcp",
      "args": []
    }
  }
}

10.1 Delegación al agente de investigación (investigation: delegación de la investigación automatizada inicial a un agente de IA)

Mientras que el roamswitch-mcp del §10 atiende consultas del cliente de IA de una persona, la delegación investigation es un mecanismo independiente en el que el propio demonio lanza de forma autónoma una CLI de agente de IA externo, activada por un evento de detección. Se dirige a eventos críticos de eBPF calificados como solo notificación (que no desencadenaron aislamiento automático ni congelación de procesos), además de detecciones de manipulación de FIM de ruta crítica y archivos de bloqueo de dependencias. Al activarse, el demonio primero genera un informe de triaje inicial heurístico local (probabilidad de falso positivo, razonamiento, próximos pasos sugeridos) y luego lanza la CLI de agente de IA configurada como subproceso con ese informe adjunto, delegando la investigación adicional y el resumen. Desactivado por defecto.

# Añadir a /etc/roamswitch/guard.yaml (un archivo distinto de server.conf)
investigation:
  enabled: true
  command: "claude"                 # "claude" | "agy" | "codex" | "opencode" | cualquier comando personalizado
  args: ["-p"]                      # El prompt se añade automáticamente como el último argumento
  timeout_secs: 180

Los mismos ajustes también pueden configurarse desde el asistente interactivo de sudo roamswitch server setup (§3.2, último paso). Elija entre los preajustes de Claude Code (claude -p), agy (agy -p --dangerously-skip-permissions), Codex CLI (codex exec), OpenCode (opencode run), o un comando personalizado. Al volver a ejecutarlo, se selecciona automáticamente el preajuste correspondiente según la configuración guardada.

Nota sobre la inyección de prompts
La integración investigation pasa los detalles del incidente (nombres de proceso, rutas de archivos y cadenas similares que un atacante puede controlar en parte) al prompt del agente de IA como cadenas JSON truncadas. Como cadenas JSON, los saltos de línea y las comillas no sirven para simular una línea separadora ni una sección de instrucciones falsa. Eso no impide que el contenido de una cadena se lea como una instrucción, por lo que el agente no puede ejecutarse como root: una configuración sin un usuario sin privilegios en run_as no la guarda el asistente (CLI y TUI) y el demonio no la inicia. Lanzar la herramienta en un modo que omite las confirmaciones de permisos, como --dangerously-skip-permissions, aumenta el riesgo de que una entrada maliciosa haga que el agente realice acciones no previstas. El asistente muestra este aviso al elegir agy. Donde existan rutas de entrada de registros no confiables, se recomienda una configuración de herramienta que no omita las confirmaciones de permisos.

La delegación investigation nunca se invoca mientras la red está desconectada (por ejemplo, durante un Air-Gap activo, o cualquier estado equivalente a isolate_host_all).

11. Hoja de referencia de comandos CLI

Comando Privilegios Descripción
sudo roamswitch status --server root Muestra la puntuación de seguridad del servidor de 34 elementos y su estado (--json imprime el mismo informe como JSON)
sudo roamswitch ports root Audite los puertos de escucha abiertos y los procesos vinculados
sudo roamswitch fim verify root Verifique la integridad SHA-256 de los archivos del sistema de ruta crítica
roamswitch notifications Usuario Muestra el historial de notificaciones de la última semana (todas las alertas enviadas); se admiten --json y --export FILE
sudo roamswitch server setup root Iniciar el asistente de configuración inicial interactivo
sudo roamswitch fim update root Actualizar la base de datos de referencia FIM SHA-256
sudo roamswitch server config set <key> <value> root Cambia y guarda una sola clave de configuración (lista en el §18)
sudo roamswitch emergency-restore raíz Desactiva todo el aislamiento de eBPF/firewall y restaura la línea base inicial
roamswitch port-scan Usuario Muestra el historial de detección de la protección de detección de escaneo de puertos entrantes (§4.3) (IP de origen, si se bloqueó automáticamente y duración del bloqueo)
roamswitch sensor [key|list|pair|unpair|request-audit|results] Usuario/root Confianza mutua con un RoamSwitch Sensor mediante códigos de emparejamiento. pair --addr <IP> --code <code> --fingerprint <SHA-256> empareja (la huella digital es el valor que se muestra en la pantalla del Sensor), repin actualiza el pin después de que el Sensor regenere su certificado, y request-audit solicita una auditoría activa de vulnerabilidades (obtenga el resultado con results). Requiere sensor_pairing_enabled: true (desactivado de forma predeterminada). Consulte el Manual de operaciones del Sensor para más detalles
roamswitch server tui Usuario/root Inicia la TUI que cubre todas las funciones (solo lectura para usuarios normales, control total como root; §17)
sudo roamswitch server ack root Reconoce el aislamiento de emergencia actual (mantiene estricto un aislamiento FULL y libera uno en DEGRADED; §4.1)
roamswitch server ebpf Usuario Muestra el estado de contención actual de la protección de ejecución eBPF y el historial de incidentes detectados
roamswitch server bans [--json] Usuario/root Muestra la guardia contra fuerza bruta SSH (§4.5): su estado y los orígenes bloqueados en este momento con el tiempo restante. Admite --json. La lista de bloqueos solo la puede leer root
sudo roamswitch server unban <IP | IPv6 /64 | --all> root Levanta un bloqueo de la guardia SSH y borra el contador de fallos de ese origen (indique un origen IPv6 por su /64; --all levanta todos los bloqueos)
sudo roamswitch server allowlist [list|add <rule> <process> [--exe <path>]|remove <rule> <process>] root Administra la lista de permitidos permanente de falsos positivos. Con --exe la entrada se vincula a la ruta real del ejecutable para que un proceso renombrado no pueda usarla (una entrada solo por nombre puede suplantarse, y se imprime una advertencia)
roamswitch frozen [list|resume <PID>|resume all] Usuario/root Lista los procesos que las protecciones mantienen en SIGSTOP y libera uno que fue un falso positivo (SIGCONT); resume all libera todos
sudo roamswitch events search|tree|export|verify|status root Busca en el grabador de ejecuciones (--since 2h --pid --exe --user --parent --text --json), imprime un árbol de procesos, exporta, verifica la cadena de hashes y muestra el estado (§15)
sudo roamswitch forward status|test|queue root Muestra el estado del reenvío de eventos, envía un evento de prueba y lista la cola de reintentos (§16)
roamswitch timeline / notifications [--json] [--export FILE] Usuario Muestra la línea de tiempo unificada de incidentes (experimental) o el historial de notificaciones; --json imprime un array JSON y --export FILE escribe JSON Lines
roamswitch audit-agent-setup [--json] Usuario Comprobación de solo lectura de los archivos de instrucciones, skills y ajustes de OpenClaw dados a agentes de IA en busca de contenido de riesgo (solo la carpeta personal, sin red; --json imprime JSON). También disponible en «Herramientas» del Server TUI

12. Solución de problemas y preguntas frecuentes

P1. ¿RoamSwitch desconectará inesperadamente mi sesión SSH?

No. En el funcionamiento normal, RoamSwitch permite incondicionalmente los estados de conexión established/related y ssh_ports (22 de forma predeterminada). Incluso cuando un ataque grave desencadena un aislamiento de emergencia Air-Gap, preserve_ssh_on_isolation=true (el valor predeterminado) mantiene las sesiones de administración en los puertos SSH de mantenimiento y las IP de administración (se cortan todas las demás conexiones establecidas). La edición de servidor hasta la 1.10.4 tenía un defecto. Las reglas de aislamiento descartaban las respuestas SSH, por lo que el SSH del operador no funcionaba durante el aislamiento. Se corrigió en la 1.10.5.

P2. ¿Cómo recupero el acceso si me quedo bloqueado accidentalmente?

Inicie sesión a través de la consola web de su proveedor de nube (VNC / consola serie) y ejecute sudo roamswitch emergency-restore para desactivar el aislamiento, o sudo systemctl stop roamswitch-server para detener el servicio.

P3. ¿Cómo expongo puertos para servicios web recién agregados (por ejemplo, Nginx)?

Ejecute sudo roamswitch server config set allowed_ports 80,443,3000 (o edite directamente /etc/roamswitch/server.conf) y después sudo roamswitch server restart.

13. File Scan Guard (protección de relés de correo, carpetas compartidas y puntos de subida)

Función opcional relevante solo si este host tiene un directorio que almacena archivos para otros: un relé de correo, un recurso compartido Samba/NFS, un punto de subida de archivos. El motor YARA integrado siempre analiza clamav_scan_dirs sin dependencias externas; al activar clamav_enabled=true se añade ClamAV como segunda opinión. Las amenazas confirmadas se ponen en cuarentena automáticamente en /var/lib/roamswitch/quarantine y se notifica al operador.

# --- File Scan Guard (ClamAV, opt-in) ---
# El motor YARA integrado siempre analiza clamav_scan_dirs de forma incondicional.
clamav_enabled=false             # true habilita la inspección adicional mediante clamdscan
clamav_scan_dirs=                # Rutas absolutas a analizar (separadas por comas)
clamav_scan_interval_secs=86400  # Intervalo de análisis (segundos, mínimo 3600)
clamav_freshclam_interval_secs=7200  # Intervalo de actualización automática de la base de firmas (segundos, mínimo 1800)

También configurable desde el asistente interactivo sudo roamswitch server setup; puede comprobar su configuración y el estado de la cuarentena con la herramienta MCP get_file_scan_guard_status.

14. Log Audit (detección y notificación de anomalías de patrones de registro)

Un análisis periódico de journalctl convierte los mensajes de registro en plantillas para detectar patrones nuevos (formas de registro nunca vistas) y anomalías de frecuencia (un pico estadístico, Z-score > 3.0). Es un mecanismo ligero que no requiere ningún demonio adicional ni dependencia externa, por lo que está habilitado de forma predeterminada. Las detecciones se envían a través de los mismos canales de notificación que File Scan Guard y FIM (Telegram / LINE / Webhook). Cualquier clave API o token que pueda aparecer en una línea de registro se enmascara automáticamente antes de incluirse en la notificación.

# --- Log Audit (habilitado de forma predeterminada) ---
log_audit_enabled=true           # false para deshabilitar
log_audit_interval_secs=1800     # Intervalo de exploración en segundos (mínimo 300)

También se puede configurar desde el asistente interactivo sudo roamswitch server setup, y los últimos resultados de detección se pueden consultar mediante el comando CLI roamswitch audit-logs o la herramienta MCP audit_security_logs.

AccessScope, una herramienta de diagnóstico de registros de acceso (herramienta independiente): el deb / rpm de la Server Edition incluye el comando accessscope de una herramienta independiente que diagnostica los registros de acceso de servidores web y de SSH (la app con ventana no se incluye). Es de solo lectura, y su análisis no usa ni un LLM ni la red. El análisis con un LLM es opcional y está desactivado por defecto (cuando se activa, también puede ejecutarse como root, pero el LLM se ejecuta entonces con los derechos de root; se recomienda un usuario sin privilegios). accessscope scan --auto diagnostica los registros de este host y accessscope discover lista dónde están los registros. Consulte la página de AccessScope para más detalles. Los deb / rpm de la Server Edition incluyen también los comandos personalsoc y pathscope de otras dos herramientas independientes, PersonalSOC (revisa los registros y las defensas de este host) y PathScope (analiza rutas de escalada de privilegios); las apps con ventana no se incluyen. Los propios comandos no realizan comunicación de red. El análisis con LLM de PersonalSOC solo se ejecuta si se indica --llm.

15. Grabador de ejecuciones y reglas de correlación (local, solo notificación)

Las ejecuciones de procesos (exec) se registran a través del proc connector de netlink: ejecutable, argumentos, linaje de procesos padre, UID, cwd, ID de contenedor y SHA-256. Está activado de forma predeterminada, y los registros se almacenan en el directorio de este host accesible solo para root /var/lib/roamswitch/exec_log como JSON Lines segmentados y encadenados por hash (0600, 200 MB / 14 días de forma predeterminada) y nunca se envían a ninguna parte. El registro es evidente ante manipulaciones (tamper-evident; events verify), no a prueba de manipulaciones. Si no se puede abrir el proc connector, se degrada a un escaneo de /proc de baja frecuencia. El registro se ejecuta en sus propios hilos, separados del bucle de eventos de permisos de fanotify, y mantiene su propio uso de CPU dentro de un presupuesto (3 % de forma predeterminada).

Busque y exporte en local (el registro es accesible solo para root, por lo que normalmente se requiere sudo).

sudo roamswitch events status
sudo roamswitch events search --since 2h --exe curl
sudo roamswitch events tree 4242
sudo roamswitch events export --since 1d > exec-events.jsonl
sudo roamswitch events verify

Reglas de correlación EXR-001 a EXR-007 (solo notificación, cada una con un ID de técnica de MITRE ATT&CK): EXR-001 una shell generada por un servicio web / EXR-002 ejecución desde /tmp, un archivo eliminado o memfd / EXR-003 ejecución justo después de una descarga / EXR-004 una línea de intérprete que usa base64 o eval / EXR-005 obtención de uid 0 sin setuid / EXR-006 ejecución de un binario recién colocado por cron o systemd / EXR-007 ejecución tras cambiar ld.so.preload. Cada regla tiene un valor predeterminado deliberadamente silencioso y nunca aísla por sí misma. Silencie reglas individuales con exec_rules_disabled (por ejemplo EXR-003,EXR-004) y ajuste los usuarios que vigila EXR-001 con exec_rule_service_users.

Solo si establece explícitamente exec_rules_isolation_optin (predeterminado false) en true, las reglas de gravedad alta se tratan como desencadenante de aislamiento de alta confianza (§4.1). De forma predeterminada las reglas solo notifican. Los registros también pueden leerse mediante las herramientas MCP de solo lectura search_exec_events y get_process_tree.

16. Reenvío de eventos (SIEM / syslog / webhook, opt-in)

Los eventos de detección pueden reenviarse a los destinos que especifique en su propia organización. Está desactivado de forma predeterminada: no se envía nada hasta que establezca forward_enabled=true y configure al menos un destino, y no hay ningún destino del fabricante incorporado. Lo que se reenvía es la línea de tiempo de incidentes, el historial de notificaciones, la protección eBPF, las transiciones de estado de aislamiento y las alertas de FIM, canario y reglas de ejecución; el propio registro de ejecuciones sin procesar no se reenvía. Hay tres tipos de destino.

Los eventos que no pudieron entregarse (TCP / TLS / webhook) se colocan en una cola de reintentos en disco (0600, limitada por forward_queue_max_mb, 20 de forma predeterminada, y forward_queue_max_age_hours, 72 de forma predeterminada) y se reintentan con retroceso exponencial, también tras un reinicio. forward_min_severity (predeterminado low) establece la gravedad mínima que se envía. La entrega se ejecuta en un hilo dedicado para que no se bloquee ninguna ruta crítica, y cuando la cola se desborda se descartan primero los elementos más antiguos.

Compruebe el estado, pruebe la conectividad e inspeccione la cola de reintentos con los siguientes comandos (reinicie el servicio tras cambiar la configuración).

# /etc/roamswitch/server.conf
forward_enabled=true
forward_syslog_url=tls://siem.example.org:6514
forward_syslog_format=rfc5424
forward_tls_ca_file=/etc/ssl/certs/corp-ca.pem
forward_min_severity=medium

sudo roamswitch server restart
sudo roamswitch forward status
sudo roamswitch forward test
sudo roamswitch forward queue

17. TUI del servidor (una interfaz de terminal para todas las funciones)

roamswitch-server-tui (que también se inicia con roamswitch server tui) es una TUI que da acceso a todas las funciones de Server Edition, repartidas entre los verbos de la CLI y los dos archivos de configuración (server.conf y guard.yaml), únicamente con el teclado y por SSH (funciona en 80x24, en 10 idiomas). Las pruebas de desarrollo fallan siempre que un verbo de la CLI o una clave de configuración carezca de su equivalente en la TUI.

Inícielo con:

sudo roamswitch-server-tui    # full control
roamswitch-server-tui         # read-only
roamswitch server tui         # same as roamswitch-server-tui

18. Referencia de claves de configuración (server.conf / guard.yaml)

roamswitch-server no admite recargar su configuración: todas las claves necesitan reiniciar el servicio para surtir efecto (sudo roamswitch server restart). Cambie las claves de server.conf con roamswitch server config set <key> <value> o con el editor del §17; cambie guard.yaml con el editor o editándolo a mano.

18.1 server.conf (109 claves)

Clave Tipo / valores Predeterminado Reinicio
languagesystem | ja | en | zh-hans | zh-hant | ko | de | fr | es | it | ptjaSí
ssh_portsport list22Sí
allowed_portsport list80,443Sí
whitelist_ipslist—Sí
preserve_ssh_on_isolationbooltrueSí
telegram_enabledboolfalseSí
telegram_bot_tokenstring—Sí
telegram_chat_idstring—Sí
line_enabledboolfalseSí
line_channel_access_tokenstring—Sí
line_user_idstring—Sí
webhook_enabledboolfalseSí
webhook_urlURL—Sí
webhook_block_private_addressesboolfalseSí
webhook_allow_addressesCIDR list—Sí
action_on_criticalisolate | freeze | alert_onlyisolateSí
ebpf_socket_pathabs path/run/roamswitch/events.sockSí
ebpf_heartbeat_interval_secs0 (off) | int 60–86400600Sí
isolation_hard_cap_secsint ≥ 03600Sí
fim_check_interval_secsint ≥ 10300Sí
fim_intrusion_context_enabledbooltrueSí
protect_docker_portsbooltrueSí
dns_sinkhole_enabledboolfalseSí
dns_sinkhole_providerquad9 | cloudflare | adguard | cleanbrowsingquad9Sí
egress_ip_blocklist_enabledbooltrueSí
metadata_watch_enabledbooltrueSí
metadata_watch_allow_userslist—Sí
cve_kernel_map_updates_enabledbooltrueSí
clamav_enabledboolfalseSí
clamav_scan_dirsabs path list—Sí
clamav_scan_interval_secsint ≥ 360086400Sí
clamav_freshclam_interval_secsint ≥ 18007200Sí
lockfile_watch_dirsabs path list—Sí
npm_audit_signatures_enabledboolfalseSí
log_audit_enabledbooltrueSí
log_audit_interval_secsint ≥ 3001800Sí
resource_guard_enabledbooltrueSí
resource_guard_rss_sample_interval_secsint ≥ 1060Sí
resource_guard_rss_window_secsint ≥ 3001800Sí
resource_guard_rss_min_samplesint ≥ 310Sí
resource_guard_rss_min_growth_pctint ≥ 1050Sí
resource_guard_rss_recovery_drop_pctint ≥ 110Sí
resource_guard_rss_min_kbint ≥ 020000Sí
resource_guard_crash_loop_window_secsint ≥ 60300Sí
resource_guard_crash_loop_min_restartsint ≥ 23Sí
resource_guard_correlation_window_secsint ≥ 60600Sí
resource_guard_zombie_min_countint ≥ 020Sí
resource_guard_load_min_normalizedfloat ≥ 0.00.5Sí
resource_guard_load_enabledbooltrueSí
resource_guard_cpu_enabledbooltrueSí
resource_guard_cpu_sample_interval_secsint ≥ 060Sí
resource_guard_cpu_window_secsint ≥ 0600Sí
resource_guard_cpu_min_samplesint ≥ 08Sí
resource_guard_cpu_pct_thresholdfloat 0.0–1000.080.0Sí
container_exec_guard_enabledbooltrueSí
port_scan_detect_enabledbooltrueSí
port_scan_detect_min_distinct_portsint ≥ 015Sí
port_scan_detect_window_secsint ≥ 0300Sí
port_scan_block_enabledbooltrueSí
port_scan_block_duration_secsint ≥ 0600Sí
ssh_guard_enabledbooltrueSí
ssh_guard_block_enabledbooltrueSí
ssh_guard_max_failuresint 2–10006Sí
ssh_guard_window_secsint 10–86400600Sí
ssh_guard_ban_secsint 60–25920003600Sí
ssh_guard_ban_max_secsint 60–31536000604800Sí
ssh_guard_allowIP/CIDR list—Sí
ssh_guard_log_sourceauto | journal | abs pathautoSí
ssh_guard_yield_to_fail2banbooltrueSí
ssh_guard_trust_key_daysint 0–365030Sí
dns_tunnel_detect_enabledbooltrueSí
reverse_shell_watch_enabledbooltrueSí
reverse_shell_watch_include_privateboolfalseSí
reverse_shell_watch_notify_onlyboolfalseSí
sensor_pairing_enabledboolfalseSí
sensor_colocatedboolfalseSí
forward_enabledboolfalseSí
forward_syslog_urlURL—Sí
forward_syslog_formatrfc5424 | cefrfc5424Sí
forward_syslog_framingoctet | lfoctetSí
forward_tls_ca_fileabs path—Sí
forward_file_pathabs path—Sí
forward_file_max_mbint 1–1000050Sí
forward_file_keepint 1–1005Sí
forward_webhook_urlURL—Sí
forward_webhook_secretstring—Sí
forward_webhook_secret_fileabs path—Sí
forward_webhook_block_private_addressesboolfalseSí
forward_webhook_allow_addressesCIDR list—Sí
forward_min_severityinfo | low | medium | high | criticallowSí
forward_queue_max_mbint 1–1000020Sí
forward_queue_max_age_hoursint 1–876072Sí
exec_recorder_enabledbooltrueSí
exec_recorder_retention_mbint 1–100000200Sí
exec_recorder_retention_daysint 1–365014Sí
exec_recorder_hash_chainbooltrueSí
exec_recorder_hash_exebooltrueSí
exec_recorder_cpu_budget_pctint 1–503Sí
exec_rules_enabledbooltrueSí
exec_rules_disabledstring—Sí
exec_rule_service_usersstring—Sí
exec_rule_window_secsint 5–3600120Sí
exec_rules_isolation_optinboolfalseSí
honeytokens_enabledbooltrueSí
honeytokens_homeabs path/rootSí
harden_userns_enabledbooltrueSí
dns_tunnel_entropy_allowlistlist—Sí
fleet_forwarding_allowed_hostslist—Sí
fleet_forwarding_allow_plaintextboolfalseSí

18.2 guard.yaml (37 claves)

Clave Tipo / valores Predeterminado Reinicio
sensor.typefalco | tetragonfalcoSí
sensor.transportstringunix_socketSí
sensor.socket_pathabs path/run/roamswitch/events.sockSí
sensor.reconnect_interval_msint 100–36000001000Sí
policies.on_warning.actionlog_and_notify | isolate_process | isolate_host_alllog_and_notifySí
policies.on_warning.server_actionlog_and_notify | isolate_process | isolate_host_all—Sí
policies.on_warning.kill_processboolfalseSí
policies.on_warning.freeze_processboolfalseSí
policies.on_warning.fallback_to_host_isolation_after_retriesint 0–1000—Sí
policies.on_error.actionlog_and_notify | isolate_process | isolate_host_allisolate_processSí
policies.on_error.server_actionlog_and_notify | isolate_process | isolate_host_all—Sí
policies.on_error.kill_processboolfalseSí
policies.on_error.freeze_processboolfalseSí
policies.on_error.fallback_to_host_isolation_after_retriesint 0–1000—Sí
policies.on_critical.actionlog_and_notify | isolate_process | isolate_host_allisolate_processSí
policies.on_critical.server_actionlog_and_notify | isolate_process | isolate_host_all—Sí
policies.on_critical.kill_processbooltrueSí
policies.on_critical.freeze_processboolfalseSí
policies.on_critical.fallback_to_host_isolation_after_retriesint 0–10003Sí
policies.on_emergency.actionlog_and_notify | isolate_process | isolate_host_allisolate_host_allSí
policies.on_emergency.server_actionlog_and_notify | isolate_process | isolate_host_all—Sí
policies.on_emergency.kill_processbooltrueSí
policies.on_emergency.freeze_processboolfalseSí
policies.on_emergency.fallback_to_host_isolation_after_retriesint 0–1000—Sí
server_safeguards.allow_established_connectionsbooltrueSí
server_safeguards.maintenance_ssh_portsport list22Sí
server_safeguards.whitelist_cidrslist—Sí
server_safeguards.whitelist_dns_serverslist—Sí
server_safeguards.safety_timer_secsint ≥ 0300Sí
adaptive_security.enabledbooltrueSí
adaptive_security.untrusted_network_actions.elevate_falco_profilestring—Sí
adaptive_security.untrusted_network_actions.auto_enable_userns_restrictionboolfalseSí
investigation.enabledboolfalseSí
investigation.commandabs path—Sí
investigation.argslist—Sí
investigation.run_asstring—Sí
investigation.timeout_secsint 1–86400180Sí

19. Detección de web shells y código inyectado (Web Rules)

Esta función detecta web shells PHP, JavaScript, JSP y ASP y código inyectado que se ejecutan en su servidor web, PHP oculto en imágenes y abusos de .htaccess (a partir de Linux 1.11.23). No hace falta configurar nada: encuentra las raíces de documentos en la configuración de Apache, nginx y Caddy y comprueba un archivo justo después de escribirse y cerrarse (con fanotify solo de notificación, que nunca puede detener a otro proceso). Un análisis periódico cada 6 horas cubre los eventos perdidos y los archivos anteriores al inicio. No se requiere ClamAV.

El comportamiento se fija en /etc/roamswitch/web_rules.conf (propietario root, modo 0644; un archivo que otros puedan escribir se ignora). Aplique un cambio con sudo roamswitch server restart. Una plantilla se imprime con roamswitch web-rules example conf.

ClaveSignificado (valor por defecto)
quarantineNivel de cuarentena automática. off nunca pone en cuarentena, critical solo critical, high critical y high (por defecto: critical). Un resultado high con el nivel critical solo notifica y dispara el hook; el archivo no se toca.
account_actionIndica si se revoca el shell de inicio de sesión del propietario de un archivo detectado. off / revoke_shell (por defecto: off). Solo cuentan los resultados critical o high puestos en cuarentena. Nunca se toca a root, a los UID por debajo de account_min_uid, a los usuarios con sesión iniciada ni al usuario del demonio. El shell anterior se registra y sudo roamswitch web-rules unlock-account <usuario> lo restablece.
account_min_uidaccount_min_uid: el UID más bajo sobre el que puede actuar la respuesta sobre cuentas (1000 por defecto; no puede bajar de 100).
scan_dirs, auto_docroots, watch, scan_interval_secsscan_dirs (rutas absolutas separadas por comas), auto_docroots (por defecto true; false detiene el descubrimiento automático desde la configuración del servidor web), watch (por defecto true; false desactiva la vigilancia de escrituras y deja solo el análisis periódico) y scan_interval_secs (por defecto 21600, mínimo 3600).
# /etc/roamswitch/web_rules.conf
quarantine=critical
account_action=off
account_min_uid=1000
#scan_dirs=/srv/sites/a,/srv/sites/b
auto_docroots=true
watch=true
scan_interval_secs=21600

Una detección envía una notificación (Telegram, LINE, webhook) que nombra la regla e indica si el archivo se puso en cuarentena o se dejó. Para mirar sin mover nada, use sudo roamswitch web-scan <carpeta> (solo consulta; --quarantine para poner en cuarentena) o la pantalla Herramientas de la TUI del servidor. Sus reglas van en /etc/roamswitch/rules.d/*.json. Para llamar a su script tras una detección, colóquelo en /etc/roamswitch/hooks/post-detection (el resultado llega como JSON por la entrada estándar; solo se ejecuta un archivo propiedad de root, no escribible por otros y en un directorio seguro; sin shell y con parada a los 30 segundos). Las actualizaciones de reglas van en la actualización diaria de solo recepción. Con cve_kernel_map_updates_enabled desactivado no hay ningún contacto de red y se usan las reglas integradas.

← Informe técnico de Server Edition A la página de instalación de Linux →