10. Checklist Final de Seguridad
TL;DR: Verificación consolidada de todos los controles de seguridad implementados. Usa este checklist para confirmar que tu instalación cumple con CIS Benchmark, Tailscale Hardening y OWASP Agentic Top 10.
Instrucciones de uso
- Ejecuta cada verificación en orden
- Marca cada control como ✅ (cumple) o ❌ (no cumple)
- No pongas OpenClaw en producción hasta que todos los controles críticos estén en ✅
- Guarda este checklist completado como evidencia de configuración
Script de verificación automática
Ejecuta este script para verificar automáticamente la mayoría de controles:
#!/bin/bash
# verificar_seguridad.sh - Verificación completa de seguridad
echo "========================================================"
echo " VERIFICACIÓN DE SEGURIDAD - OpenClaw VPS"
echo " Fecha: $(date '+%Y-%m-%d %H:%M:%S')"
echo " Hostname: $(hostname)"
echo "========================================================"
echo ""
PASS=0
FAIL=0
WARN=0
check() {
local name="$1"
local result="$2"
local critical="$3"
if [ "$result" = "pass" ]; then
echo "✅ $name"
((PASS++))
elif [ "$result" = "warn" ]; then
echo "⚠️ $name"
((WARN++))
else
if [ "$critical" = "critical" ]; then
echo "❌ [CRÍTICO] $name"
else
echo "❌ $name"
fi
((FAIL++))
fi
}
echo "=== 1. SISTEMA OPERATIVO ==="
# Usuario openclaw existe
if id openclaw &>/dev/null; then
check "Usuario openclaw existe" "pass"
else
check "Usuario openclaw existe" "fail" "critical"
fi
# Usuario openclaw no es root
if [ "$(id -u openclaw 2>/dev/null)" != "0" ]; then
check "Usuario openclaw no es root" "pass"
else
check "Usuario openclaw no es root" "fail" "critical"
fi
# UFW activo
if sudo ufw status | grep -q "Status: active"; then
check "Firewall UFW activo" "pass"
else
check "Firewall UFW activo" "fail" "critical"
fi
# Fail2ban activo
if systemctl is-active fail2ban &>/dev/null; then
check "Fail2ban activo" "pass"
else
check "Fail2ban activo" "fail"
fi
# Unattended upgrades
if systemctl is-active unattended-upgrades &>/dev/null; then
check "Actualizaciones automáticas" "pass"
else
check "Actualizaciones automáticas" "fail"
fi
# Auditd activo
if systemctl is-active auditd &>/dev/null; then
check "Auditd activo" "pass"
else
check "Auditd activo" "warn"
fi
# AIDE inicializado
if [ -f /var/lib/aide/aide.db ]; then
check "AIDE inicializado" "pass"
else
check "AIDE inicializado" "warn"
fi
echo ""
echo "=== 2. SSH HARDENING (CIS Benchmark) ==="
# PasswordAuthentication no
if sudo sshd -T 2>/dev/null | grep -qi "passwordauthentication no"; then
check "SSH: PasswordAuthentication no" "pass"
else
check "SSH: PasswordAuthentication no" "fail" "critical"
fi
# PermitRootLogin no
if sudo sshd -T 2>/dev/null | grep -qi "permitrootlogin no"; then
check "SSH: PermitRootLogin no" "pass"
else
check "SSH: PermitRootLogin no" "fail" "critical"
fi
# AllowUsers configurado
if sudo sshd -T 2>/dev/null | grep -qi "allowusers"; then
check "SSH: AllowUsers configurado" "pass"
else
check "SSH: AllowUsers configurado" "fail"
fi
# MaxAuthTries <= 4
MAX_AUTH=$(sudo sshd -T 2>/dev/null | grep -i maxauthtries | awk '{print $2}')
if [ -n "$MAX_AUTH" ] && [ "$MAX_AUTH" -le 4 ]; then
check "SSH: MaxAuthTries <= 4" "pass"
else
check "SSH: MaxAuthTries <= 4" "fail"
fi
# X11Forwarding no
if sudo sshd -T 2>/dev/null | grep -qi "x11forwarding no"; then
check "SSH: X11Forwarding no" "pass"
else
check "SSH: X11Forwarding no" "fail"
fi
# LogLevel VERBOSE
if sudo sshd -T 2>/dev/null | grep -qi "loglevel verbose"; then
check "SSH: LogLevel VERBOSE" "pass"
else
check "SSH: LogLevel VERBOSE" "warn"
fi
# Permisos sshd_config
SSHD_PERMS=$(stat -c "%a" /etc/ssh/sshd_config 2>/dev/null)
if [ "$SSHD_PERMS" = "600" ]; then
check "SSH: sshd_config permisos 600" "pass"
else
check "SSH: sshd_config permisos 600" "fail"
fi
echo ""
echo "=== 3. TAILSCALE ==="
# Tailscale instalado y activo
if systemctl is-active tailscaled &>/dev/null; then
check "Tailscale activo" "pass"
else
check "Tailscale activo" "fail" "critical"
fi
# SSH escuchando solo en Tailscale
SSH_LISTEN=$(sudo ss -tlnp | grep sshd | awk '{print $4}')
if echo "$SSH_LISTEN" | grep -q "100\."; then
check "SSH solo en interfaz Tailscale" "pass"
elif echo "$SSH_LISTEN" | grep -q "0\.0\.0\.0"; then
check "SSH solo en interfaz Tailscale" "fail" "critical"
else
check "SSH solo en interfaz Tailscale" "warn"
fi
# Puerto 22 cerrado en UFW (no debe haber regla para SSH)
if ! sudo ufw status | grep -E "22/tcp.*ALLOW.*Anywhere" | grep -v "100\." &>/dev/null; then
check "Puerto 22 público cerrado" "pass"
else
check "Puerto 22 público cerrado" "fail" "critical"
fi
# Tag vps configurado
if tailscale status 2>/dev/null | grep -q "tagged"; then
check "Tag 'vps' configurado" "pass"
else
check "Tag 'vps' configurado" "warn"
fi
echo ""
echo "=== 4. OPENCLAW ==="
# Servicio activo
if systemctl is-active openclaw &>/dev/null; then
check "Servicio OpenClaw activo" "pass"
else
check "Servicio OpenClaw activo" "warn"
fi
# Escuchando en localhost (no 0.0.0.0)
OPENCLAW_LISTEN=$(sudo ss -tlnp | grep 18789 | awk '{print $4}')
if echo "$OPENCLAW_LISTEN" | grep -q "127\.0\.0\.1"; then
check "OpenClaw en localhost (127.0.0.1:18789)" "pass"
elif echo "$OPENCLAW_LISTEN" | grep -q "0\.0\.0\.0"; then
check "OpenClaw en localhost (127.0.0.1:18789)" "fail" "critical"
else
check "OpenClaw en localhost (127.0.0.1:18789)" "warn"
fi
# /etc/openclaw/env con permisos 600 y propietario root
ENV_PERMS=$(stat -c "%a" /etc/openclaw/env 2>/dev/null)
ENV_OWNER=$(stat -c "%U" /etc/openclaw/env 2>/dev/null)
if [ "$ENV_PERMS" = "600" ] && [ "$ENV_OWNER" = "root" ]; then
check "/etc/openclaw/env permisos 600, propietario root" "pass"
elif [ "$ENV_PERMS" = "600" ]; then
check "/etc/openclaw/env propietario debe ser root (es $ENV_OWNER)" "fail" "critical"
else
check "/etc/openclaw/env permisos 600" "fail" "critical"
fi
# Puntuación systemd < 5
SECURITY_SCORE=$(systemd-analyze security openclaw.service 2>/dev/null | grep "Overall" | grep -oE "[0-9]+\.[0-9]+" | head -1)
if [ -n "$SECURITY_SCORE" ]; then
# Extraer parte entera para comparación (sin dependencia de bc)
SCORE_INT=${SECURITY_SCORE%%.*}
if [ -n "$SCORE_INT" ] && [ "$SCORE_INT" -lt 5 ]; then
check "Systemd hardening (score < 5.0): $SECURITY_SCORE" "pass"
elif [ -n "$SCORE_INT" ] && [ "$SCORE_INT" -ge 5 ]; then
check "Systemd hardening (score < 5.0): $SECURITY_SCORE" "fail"
else
check "Systemd hardening (score parse error)" "warn"
fi
else
check "Systemd hardening" "warn"
fi
echo ""
echo "=== 5. CONFIGURACIÓN DE OPENCLAW ==="
CONFIG_FILE="/home/openclaw/.openclaw/openclaw.json"
if [ ! -f "$CONFIG_FILE" ]; then
CONFIG_FILE="$HOME/.openclaw/openclaw.json"
fi
if [ -f "$CONFIG_FILE" ]; then
# Sandbox mode configurado (off = VPS dedicado con systemd hardening, all = Docker)
if grep -q '"sandbox"' "$CONFIG_FILE" && grep -A2 '"sandbox"' "$CONFIG_FILE" | grep -qE '"mode":\s*"(all|off)"'; then
SANDBOX_MODE=$(grep -A2 '"sandbox"' "$CONFIG_FILE" | grep -oE '"(all|off)"' | tr -d '"')
check "Sandbox mode configurado ($SANDBOX_MODE)" "pass"
else
check "Sandbox mode configurado" "fail" "critical"
fi
# dmPolicy configurado
if grep -q '"dmPolicy":\s*"pairing"' "$CONFIG_FILE" || grep -q '"dmPolicy":\s*"closed"' "$CONFIG_FILE"; then
check "dmPolicy configurado (pairing/closed)" "pass"
elif grep -q '"dmPolicy":\s*"open"' "$CONFIG_FILE"; then
check "dmPolicy configurado (pairing/closed)" "fail" "critical"
else
check "dmPolicy configurado (pairing/closed)" "warn"
fi
# Gateway en localhost
if grep -q '"host":\s*"127.0.0.1"' "$CONFIG_FILE"; then
check "Gateway host = 127.0.0.1" "pass"
else
check "Gateway host = 127.0.0.1" "fail" "critical"
fi
# Gateway TLS pairing
if grep -q '"pairing":\s*true' "$CONFIG_FILE"; then
check "Gateway TLS pairing habilitado" "pass"
else
check "Gateway TLS pairing habilitado" "warn"
fi
else
check "Archivo openclaw.json existe" "fail"
fi
# Verificar TOOLS.md (allowlist de herramientas)
TOOLS_FILE="/home/openclaw/.openclaw/workspace/TOOLS.md"
if [ ! -f "$TOOLS_FILE" ]; then
TOOLS_FILE="$HOME/.openclaw/workspace/TOOLS.md"
fi
if [ -f "$TOOLS_FILE" ]; then
check "TOOLS.md (allowlist) existe" "pass"
else
check "TOOLS.md (allowlist) existe" "warn"
fi
echo ""
echo "=== 6. MONITOREO Y AUDITORÍA ==="
# Reglas de audit para openclaw
if sudo auditctl -l 2>/dev/null | grep -q "openclaw"; then
check "Reglas de auditoría configuradas" "pass"
else
check "Reglas de auditoría configuradas" "warn"
fi
# Script de monitoreo existe
if [ -x /home/openclaw/openclaw/scripts/monitor_behavior.sh ] || [ -x ~/openclaw/scripts/monitor_behavior.sh ]; then
check "Script de monitoreo existe" "pass"
else
check "Script de monitoreo existe" "warn"
fi
# Backup script existe
if [ -x /home/openclaw/openclaw/scripts/backup.sh ] || [ -x ~/openclaw/scripts/backup.sh ]; then
check "Script de backup existe" "pass"
else
check "Script de backup existe" "warn"
fi
echo ""
echo "========================================================"
echo " RESUMEN"
echo "========================================================"
echo " ✅ Pasados: $PASS"
echo " ⚠️ Advertencias: $WARN"
echo " ❌ Fallidos: $FAIL"
echo ""
if [ $FAIL -eq 0 ]; then
echo " 🎉 Todos los controles críticos pasados"
exit 0
else
echo " ⚠️ Hay controles fallidos que deben corregirse"
exit 1
fi
Guarda y ejecuta:
nano ~/openclaw/scripts/verificar_seguridad.sh
chmod +x ~/openclaw/scripts/verificar_seguridad.sh
~/openclaw/scripts/verificar_seguridad.sh
Checklist manual detallado
1. Sistema Operativo
| # |
Control |
Verificación |
Estado |
| 1.1 |
Usuario openclaw creado |
id openclaw |
⬜ |
| 1.2 |
Usuario no es root |
id -u openclaw ≠ 0 |
⬜ |
| 1.3 |
Usuario tiene sudo |
groups openclaw incluye sudo |
⬜ |
| 1.4 |
UFW activo |
sudo ufw status = active |
⬜ |
| 1.5 |
UFW default deny incoming |
sudo ufw status verbose |
⬜ |
| 1.6 |
Fail2ban activo |
systemctl is-active fail2ban |
⬜ |
| 1.7 |
Fail2ban protegiendo SSH |
sudo fail2ban-client status sshd |
⬜ |
| 1.8 |
Actualizaciones automáticas |
systemctl is-active unattended-upgrades |
⬜ |
| 1.9 |
Auditd activo |
systemctl is-active auditd |
⬜ |
| 1.10 |
Reglas audit para OpenClaw |
sudo auditctl -l \| grep openclaw |
⬜ |
| 1.11 |
AIDE inicializado |
ls /var/lib/aide/aide.db |
⬜ |
2. SSH Hardening (CIS Benchmark 5.2)
| # |
Control |
Comando de verificación |
Valor esperado |
Estado |
| 2.1 |
PasswordAuthentication |
sudo sshd -T \| grep passwordauthentication |
no |
⬜ |
| 2.2 |
PermitRootLogin |
sudo sshd -T \| grep permitrootlogin |
no |
⬜ |
| 2.3 |
PermitEmptyPasswords |
sudo sshd -T \| grep permitemptypasswords |
no |
⬜ |
| 2.4 |
MaxAuthTries |
sudo sshd -T \| grep maxauthtries |
≤ 4 |
⬜ |
| 2.5 |
X11Forwarding |
sudo sshd -T \| grep x11forwarding |
no |
⬜ |
| 2.6 |
AllowTcpForwarding |
sudo sshd -T \| grep allowtcpforwarding |
local |
⬜ |
| 2.7 |
LogLevel |
sudo sshd -T \| grep loglevel |
VERBOSE |
⬜ |
| 2.8 |
ClientAliveInterval |
sudo sshd -T \| grep clientaliveinterval |
> 0 |
⬜ |
| 2.9 |
LoginGraceTime |
sudo sshd -T \| grep logingracetime |
≤ 60 |
⬜ |
| 2.10 |
AllowUsers |
sudo sshd -T \| grep allowusers |
openclaw |
⬜ |
| 2.11 |
Banner |
sudo sshd -T \| grep banner |
/etc/issue.net |
⬜ |
| 2.12 |
Ciphers seguros |
sudo sshd -T \| grep ciphers |
Sin arcfour, 3des |
⬜ |
| 2.13 |
KexAlgorithms post-cuántico |
sudo sshd -T \| grep kexalgorithms |
Incluye sntrup761 |
⬜ |
| 2.14 |
Permisos sshd_config |
stat -c %a /etc/ssh/sshd_config |
600 |
⬜ |
| 2.15 |
Propietario sshd_config |
stat -c %U:%G /etc/ssh/sshd_config |
root:root |
⬜ |
3. Tailscale
| # |
Control |
Verificación |
Estado |
| 3.1 |
Tailscale instalado |
tailscale version |
⬜ |
| 3.2 |
Tailscaled activo |
systemctl is-active tailscaled |
⬜ |
| 3.3 |
Conectado a Tailnet |
tailscale status muestra dispositivos |
⬜ |
| 3.4 |
Tag 'vps' asignado |
tailscale status muestra tagged |
⬜ |
| 3.5 |
ACLs configuradas (no permit-all) |
Verificar en panel Tailscale |
⬜ |
| 3.6 |
SSH escucha solo en IP Tailscale |
ss -tlnp \| grep sshd = |
⬜ |
| 3.7 |
Puerto 22 público cerrado |
ssh user@IP_PUBLICA falla |
⬜ |
| 3.8 |
Acceso por Tailscale funciona |
ssh user@IP_TAILSCALE funciona |
⬜ |
| 3.9 |
(Opcional) Tailnet Lock activo |
tailscale lock status |
⬜ |
| 3.10 |
(Opcional) Webhooks configurados |
Verificar en panel Tailscale |
⬜ |
4. OpenClaw
| # |
Control |
Verificación |
Estado |
| 4.1 |
Directorio estructura correcta |
ls ~/.openclaw/ |
⬜ |
| 4.2 |
openclaw.json existe |
ls ~/.openclaw/openclaw.json |
⬜ |
| 4.3 |
Archivo env existe y permisos 600 |
stat -c %a /etc/openclaw/env = 600 |
⬜ |
| 4.4 |
Archivo env propietario correcto |
stat -c %U /etc/openclaw/env = root |
⬜ |
| 4.5 |
Gateway host = 127.0.0.1 |
grep host ~/.openclaw/openclaw.json |
⬜ |
| 4.6 |
OpenClaw escucha localhost:18789 |
ss -tlnp \| grep 18789 = 127.0.0.1 |
⬜ |
| 4.7 |
No escucha en 0.0.0.0 |
ss -tlnp \| grep 18789 ≠ 0.0.0.0 |
⬜ |
| 4.8 |
Servicio systemd creado |
systemctl status openclaw |
⬜ |
| 4.9 |
Servicio habilitado |
systemctl is-enabled openclaw |
⬜ |
| 4.10 |
Hardening systemd aplicado |
Ver archivo service |
⬜ |
| 4.11 |
Puntuación systemd < 5 |
systemd-analyze security openclaw |
⬜ |
5. Seguridad OpenClaw (OWASP AA4/AA5)
| # |
Control |
Verificación |
Estado |
| 5.1 |
openclaw.json existe |
ls ~/.openclaw/openclaw.json |
⬜ |
| 5.2 |
Sandbox mode = all |
grep sandbox ~/.openclaw/openclaw.json |
⬜ |
| 5.3 |
dmPolicy = pairing o closed |
grep dmPolicy ~/.openclaw/openclaw.json |
⬜ |
| 5.4 |
Gateway TLS pairing activo |
grep tls ~/.openclaw/openclaw.json |
⬜ |
| 5.5 |
TOOLS.md (allowlist) existe |
ls ~/openclaw/workspace/TOOLS.md |
⬜ |
| 5.6 |
SOUL.md (límites) existe |
ls ~/openclaw/workspace/SOUL.md |
⬜ |
| 5.7 |
No hay herramientas peligrosas |
Revisar TOOLS.md manualmente |
⬜ |
| 5.8 |
openclaw security audit sin errores |
openclaw security audit |
⬜ |
| 5.9 |
SecretRef configurado (no .env plano) |
openclaw secrets list |
⬜ |
| 5.10 |
Canal de actualización = stable |
openclaw update --channel |
⬜ |
6. Seguridad del Agente (OWASP Agentic)
| # |
Control |
Referencia OWASP |
Estado |
| 6.1 |
Input validation configurado |
AA1 |
⬜ |
| 6.2 |
Output filtering activo |
AA2 |
⬜ |
| 6.3 |
Secrets redactados en outputs |
AA2 |
⬜ |
| 6.4 |
Principio mínimo privilegio |
AA4 |
⬜ |
| 6.5 |
Skills con allowlist |
AA5 |
⬜ |
| 6.6 |
Human-in-the-loop configurado |
AA8 |
⬜ |
| 6.7 |
Logging completo |
AA10 |
⬜ |
| 6.8 |
(Opcional) AppArmor perfil |
AA4 |
⬜ |
7. Monitoreo y Mantenimiento
| # |
Control |
Verificación |
Estado |
| 7.1 |
Script de monitoreo existe |
ls ~/openclaw/scripts/monitor_behavior.sh |
⬜ |
| 7.2 |
Script de backup existe |
ls ~/openclaw/scripts/backup.sh |
⬜ |
| 7.3 |
Cron jobs configurados |
crontab -l |
⬜ |
| 7.4 |
Logs rotatados |
ls /etc/logrotate.d/openclaw |
⬜ |
| 7.5 |
Fecha última rotación API keys |
cat ~/.openclaw/.last_key_rotation |
⬜ |
| 7.6 |
Backup descargado a local |
Verificar manualmente |
⬜ |
CIS Benchmark Ubuntu 24.04 L1
| Sección |
Descripción |
Cubierto |
| 5.2.1 |
Permisos sshd_config |
✅ |
| 5.2.2 |
Permisos claves SSH host |
✅ |
| 5.2.4 |
Ciphers SSH |
✅ |
| 5.2.5 |
MACs SSH |
✅ |
| 5.2.6 |
KEX SSH |
✅ |
| 5.2.7 |
Banner SSH |
✅ |
| 5.2.8 |
LogLevel SSH |
✅ |
| 5.2.9-23 |
Configuración SSH |
✅ |
Tailscale Security Hardening
| Control |
Descripción |
Cubierto |
| ACLs |
No usar permit-all |
✅ |
| Tags |
Usar tags para segmentación |
✅ |
| SSH sobre Tailscale |
Eliminar SSH público |
✅ |
| Tailnet Lock |
Firmas criptográficas |
⬜ Opcional |
| Webhooks |
Alertas de cambios |
⬜ Opcional |
OWASP Agentic Top 10 2026
| ID |
Riesgo |
Mitigación |
Cubierto |
| AA1 |
Agentic Injection |
Input validation |
✅ |
| AA2 |
Sensitive Data Exposure |
Output filtering |
✅ |
| AA3 |
Improper Output Handling |
Sanitización |
✅ |
| AA4 |
Excessive Agency |
Mínimo privilegio |
✅ |
| AA5 |
Tool Misuse |
Skills allowlist |
✅ |
| AA6 |
Insecure Memory |
Memoria cifrada y con retención |
✅ |
| AA7 |
Insufficient Identity |
ACLs Tailscale |
✅ |
| AA8 |
Unsafe Agentic Actions |
Human-in-the-loop |
✅ |
| AA9 |
Poor Multi-Agent Security |
N/A (single agent) |
➖ |
| AA10 |
Missing Audit Logs |
Auditd, logging |
✅ |
Instalación verificada por: _________________________
Fecha: _________________________
Puntuación de verificación automática:
- Pasados: ____
- Advertencias: ____
- Fallidos: ____
Notas:
_________________________________________________
_________________________________________________
_________________________________________________
Fin de la guía de instalación
Para mantenimiento continuo, consulta 9. Mantenimiento.