Files
microdao-daarion/SECURITY-HARDENING-PLAN.md
Apple 1231647f94 🛡️ Add comprehensive Security Hardening Plan
- Created SECURITY-HARDENING-PLAN.md with 6 security levels
- Added setup-node1-security.sh for automated hardening
- Added scan-image.sh for pre-deployment image scanning
- Created docker-compose.secure.yml template
- Includes: Trivy, fail2ban, UFW, auditd, rkhunter, chkrootkit
- Network isolation, egress filtering, process monitoring
- Incident response procedures and recovery playbook
2026-01-10 05:05:21 -08:00

18 KiB
Raw Blame History

🛡️ Security Hardening Plan — DAARION & MicroDAO

Версія: 1.0.0
Дата: 2026-01-10
Статус: В процесі впровадження


📋 Зміст

  1. Аналіз інцидентів
  2. Рівень 1: Image Security
  3. Рівень 2: Container Runtime Security
  4. Рівень 3: Host Security
  5. Рівень 4: Network Security
  6. Рівень 5: Monitoring & Detection
  7. Рівень 6: Incident Response
  8. Чеклист впровадження

📊 Аналіз інцидентів

Що пішло не так:

Інцидент Вектор атаки Чому не виявили раніше
#1 Вразливий daarion-web образ Не сканували образи
#2 restart: unless-stopped Не видалили image, тільки container
#3 Compromised postgres image Довіряли Docker Hub без перевірки
#4 Host persistence (perfctl) Не перевіряли host на malware

Ключові уроки:

  1. 🔴 Не довіряти жодному образу — навіть official
  2. 🟡 Сканувати ВСЕ — images, containers, host
  3. 🟢 Моніторити в реальному часі — CPU, network, processes
  4. 🔵 Мати план відновлення — швидкий rebuild з нуля

🔒 Рівень 1: Image Security

1.1 Image Scanning (Trivy)

# Встановлення Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin

# Сканування перед pull
trivy image --severity HIGH,CRITICAL postgres:16-alpine

# Автоматичне сканування в CI/CD
trivy image --exit-code 1 --severity CRITICAL $IMAGE_NAME

1.2 Image Pinning by SHA256

НІКОЛИ:

image: postgres:16-alpine  # Тег може змінитись!

ЗАВЖДИ:

image: postgres@sha256:abc123...  # Фіксований digest

1.3 Allowlist Registry

# /etc/docker/daemon.json
{
  "allowed-registries": [
    "docker.io/library",
    "ghcr.io/daarion-dao"
  ]
}

1.4 Custom Base Images

Створити власні базові образи з мінімальним attack surface:

# Dockerfile.postgres-secure
FROM postgres:16-alpine@sha256:verified_digest

# Remove unnecessary packages
RUN apk del --purge wget curl busybox-extras

# Add security scanning
COPY --from=aquasec/trivy:latest /usr/local/bin/trivy /usr/local/bin/trivy

# Non-root user
USER postgres

# Read-only filesystem
# (set in docker-compose)

🐳 Рівень 2: Container Runtime Security

2.1 Security Options

# docker-compose.yml
services:
  postgres:
    image: postgres@sha256:verified_digest
    
    # ⚠️ НІКОЛИ auto-restart для нових сервісів
    restart: "no"  # Змінити на "unless-stopped" ТІЛЬКИ після верифікації
    
    # Security options
    security_opt:
      - no-new-privileges:true
      - seccomp:seccomp-profile.json
    
    # Read-only root filesystem
    read_only: true
    
    # Temporary directories
    tmpfs:
      - /tmp:noexec,nosuid,nodev,size=100m
      - /var/run/postgresql:noexec,nosuid,nodev
    
    # Resource limits
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M
    
    # Drop all capabilities, add only needed
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETUID
      - SETGID
    
    # No privileged mode
    privileged: false
    
    # User namespace
    userns_mode: "host"

2.2 Seccomp Profile

// seccomp-profile.json
{
  "defaultAction": "SCCOMP_ACT_ERRNO",
  "syscalls": [
    {
      "names": ["accept", "bind", "clone", "close", "connect", ...],
      "action": "SCCOMP_ACT_ALLOW"
    }
  ]
}

2.3 AppArmor Profile

# /etc/apparmor.d/docker-postgres
profile docker-postgres flags=(attach_disconnected) {
  # Deny network raw access
  deny network raw,
  
  # Deny ptrace
  deny ptrace,
  
  # Allow only postgres paths
  /var/lib/postgresql/** rw,
  /var/run/postgresql/** rw,
  
  # Deny /tmp execution
  deny /tmp/** x,
}

🖥️ Рівень 3: Host Security

3.1 Hardening Script

#!/bin/bash
# /opt/scripts/harden-host.sh

set -e

echo "🔒 Hardening NODE1..."

# 1. Update system
apt update && apt upgrade -y

# 2. Install security tools
apt install -y \
    fail2ban \
    ufw \
    auditd \
    rkhunter \
    chkrootkit \
    lynis \
    aide

# 3. Configure fail2ban
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600

[docker-abuse]
enabled = true
filter = docker-abuse
logpath = /var/log/docker.log
maxretry = 5
bantime = 86400
EOF

# 4. Configure UFW
ufw default deny incoming
ufw default deny outgoing  # ⚠️ Strict egress!
ufw allow 22/tcp           # SSH
ufw allow 80/tcp           # HTTP
ufw allow 443/tcp          # HTTPS
ufw allow out 53/udp       # DNS
ufw allow out 443/tcp      # HTTPS out (for updates)
ufw allow out 80/tcp       # HTTP out (for updates)
# Block internal networks
ufw deny out to 10.0.0.0/8
ufw deny out to 172.16.0.0/12
ufw deny out to 192.168.0.0/16
ufw enable

# 5. Kernel hardening
cat >> /etc/sysctl.conf << 'EOF'
# Disable IP forwarding
net.ipv4.ip_forward = 0

# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# Enable SYN cookies
net.ipv4.tcp_syncookies = 1

# Disable source routing
net.ipv4.conf.all.accept_source_route = 0

# Log martians
net.ipv4.conf.all.log_martians = 1
EOF
sysctl -p

# 6. Audit rules
cat > /etc/audit/rules.d/docker.rules << 'EOF'
# Monitor Docker daemon
-w /usr/bin/docker -p rwxa -k docker
-w /var/lib/docker -p rwxa -k docker
-w /etc/docker -p rwxa -k docker

# Monitor /tmp for executables
-w /tmp -p x -k tmp_exec

# Monitor network connections
-a exit,always -F arch=b64 -S connect -k network
EOF
service auditd restart

# 7. Initialize AIDE (file integrity)
aideinit
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

echo "✅ Hardening complete!"

3.2 Automated Security Checks

#!/bin/bash
# /opt/scripts/security-check.sh
# Run via cron every hour

LOG="/var/log/security-check.log"
ALERT_EMAIL="admin@daarion.city"

echo "$(date) - Starting security check" >> $LOG

# 1. Check for suspicious processes
SUSPICIOUS=$(ps aux | grep -E "(xmrig|kdevtmp|kinsing|perfctl|httpd.*tmp)" | grep -v grep)
if [ -n "$SUSPICIOUS" ]; then
    echo "🚨 ALERT: Suspicious process found!" >> $LOG
    echo "$SUSPICIOUS" >> $LOG
    # Kill and alert
    pkill -9 -f "xmrig|kdevtmp|kinsing|perfctl"
    echo "$SUSPICIOUS" | mail -s "🚨 NODE1 ALERT: Suspicious process" $ALERT_EMAIL
fi

# 2. Check /tmp for executables
TMP_EXEC=$(find /tmp -type f -executable 2>/dev/null)
if [ -n "$TMP_EXEC" ]; then
    echo "🚨 ALERT: Executable in /tmp!" >> $LOG
    echo "$TMP_EXEC" >> $LOG
    rm -f $TMP_EXEC
    echo "$TMP_EXEC" | mail -s "🚨 NODE1 ALERT: Executable in /tmp" $ALERT_EMAIL
fi

# 3. Check CPU load
LOAD=$(uptime | awk -F'load average:' '{print $2}' | cut -d',' -f1 | tr -d ' ')
if (( $(echo "$LOAD > 5" | bc -l) )); then
    echo "⚠️ WARNING: High CPU load: $LOAD" >> $LOG
    TOP_PROCS=$(ps aux --sort=-%cpu | head -5)
    echo "$TOP_PROCS" | mail -s "⚠️ NODE1 WARNING: High CPU load" $ALERT_EMAIL
fi

# 4. Check for rootkits
rkhunter --check --skip-keypress --quiet
RKHUNTER_STATUS=$?
if [ $RKHUNTER_STATUS -ne 0 ]; then
    echo "🚨 ALERT: Rootkit detected!" >> $LOG
    rkhunter --check --skip-keypress | mail -s "🚨 NODE1 ALERT: Rootkit detected" $ALERT_EMAIL
fi

# 5. Check file integrity
aide --check > /tmp/aide_check.txt 2>&1
if grep -q "changed" /tmp/aide_check.txt; then
    echo "⚠️ WARNING: File integrity changed" >> $LOG
    cat /tmp/aide_check.txt | mail -s "⚠️ NODE1 WARNING: File integrity" $ALERT_EMAIL
fi

# 6. Check Docker containers
UNKNOWN_CONTAINERS=$(docker ps --format '{{.Names}}' | grep -v -E "(dagi-|postgres|redis|neo4j|qdrant|grafana|prometheus)")
if [ -n "$UNKNOWN_CONTAINERS" ]; then
    echo "🚨 ALERT: Unknown containers running!" >> $LOG
    echo "$UNKNOWN_CONTAINERS" >> $LOG
fi

echo "$(date) - Security check complete" >> $LOG

3.3 Cron Setup

# /etc/cron.d/security
# Security checks
0 * * * * root /opt/scripts/security-check.sh
*/15 * * * * root /opt/scripts/monitor-docker.sh

# Daily scans
0 3 * * * root rkhunter --update && rkhunter --check --skip-keypress
0 4 * * * root chkrootkit > /var/log/chkrootkit.log
0 5 * * * root lynis audit system --quiet

# Weekly
0 2 * * 0 root aide --check > /var/log/aide-weekly.log

🌐 Рівень 4: Network Security

4.1 Docker Network Isolation

# docker-compose.yml
networks:
  frontend:
    driver: bridge
    internal: false  # Can access internet
  backend:
    driver: bridge
    internal: true   # No internet access!
  database:
    driver: bridge
    internal: true   # No internet access!

services:
  nginx:
    networks:
      - frontend
  
  router:
    networks:
      - frontend
      - backend
  
  postgres:
    networks:
      - database  # Only database network!

4.2 Egress Filtering

#!/bin/bash
# /opt/scripts/setup-egress-firewall.sh

# Default deny outgoing
iptables -P OUTPUT DROP

# Allow established connections
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow loopback
iptables -A OUTPUT -o lo -j ACCEPT

# Allow DNS
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

# Allow HTTPS (for updates, API calls)
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT

# Allow HTTP (for Let's Encrypt)
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT

# Allow NTP
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

# Block internal networks (Hetzner)
iptables -A OUTPUT -d 10.0.0.0/8 -j DROP
iptables -A OUTPUT -d 172.16.0.0/12 -j DROP

# Log dropped packets
iptables -A OUTPUT -j LOG --log-prefix "DROPPED_EGRESS: "

# Save
iptables-save > /etc/iptables/rules.v4

4.3 Mining Pool Blocking

# /etc/hosts.deny additions
# Block known mining pools
0.0.0.0 pool.minexmr.com
0.0.0.0 xmr.pool.minergate.com
0.0.0.0 xmrpool.eu
0.0.0.0 pool.supportxmr.com
0.0.0.0 xmr-eu1.nanopool.org
0.0.0.0 xmr-eu2.nanopool.org
0.0.0.0 xmr.2miners.com
0.0.0.0 pool.hashvault.pro

📊 Рівень 5: Monitoring & Detection

5.1 Real-time Process Monitoring

#!/usr/bin/env python3
# /opt/scripts/process-monitor.py

import psutil
import time
import subprocess
import smtplib
from email.mime.text import MIMEText

SUSPICIOUS_NAMES = [
    'xmrig', 'kdevtmp', 'kinsing', 'perfctl', 'httpd',
    'softirq', 'vrarhpb', 'cpioshuf', 'ipcalc', 'mysql'
]

ALERT_EMAIL = "admin@daarion.city"
CPU_THRESHOLD = 80  # Alert if process uses >80% CPU

def send_alert(subject, body):
    """Send email alert"""
    # Implement email sending
    print(f"ALERT: {subject}\n{body}")

def check_processes():
    """Check for suspicious processes"""
    for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'cmdline']):
        try:
            name = proc.info['name'].lower()
            cmdline = ' '.join(proc.info['cmdline'] or []).lower()
            cpu = proc.info['cpu_percent']
            
            # Check suspicious names
            for suspicious in SUSPICIOUS_NAMES:
                if suspicious in name or suspicious in cmdline:
                    send_alert(
                        f"🚨 Suspicious process: {name}",
                        f"PID: {proc.info['pid']}\nCPU: {cpu}%\nCmd: {cmdline}"
                    )
                    # Kill it
                    proc.kill()
                    return
            
            # Check high CPU
            if cpu > CPU_THRESHOLD:
                send_alert(
                    f"⚠️ High CPU process: {name}",
                    f"PID: {proc.info['pid']}\nCPU: {cpu}%"
                )
                
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass

def check_network():
    """Check for suspicious network connections"""
    connections = psutil.net_connections()
    for conn in connections:
        if conn.status == 'ESTABLISHED':
            # Check for mining pool ports
            if conn.raddr and conn.raddr.port in [3333, 4444, 5555, 8080, 8888]:
                send_alert(
                    f"🚨 Suspicious connection to port {conn.raddr.port}",
                    f"Remote: {conn.raddr}\nPID: {conn.pid}"
                )

if __name__ == "__main__":
    while True:
        check_processes()
        check_network()
        time.sleep(10)  # Check every 10 seconds

5.2 Docker Event Monitoring

#!/bin/bash
# /opt/scripts/monitor-docker.sh

# Monitor Docker events in real-time
docker events --filter 'type=container' --format '{{.Time}} {{.Action}} {{.Actor.Attributes.name}}' | while read event; do
    echo "$event" >> /var/log/docker-events.log
    
    # Alert on suspicious events
    if echo "$event" | grep -qE "(start|create)"; then
        CONTAINER=$(echo "$event" | awk '{print $3}')
        # Check if container is in allowlist
        if ! grep -q "$CONTAINER" /opt/config/allowed-containers.txt; then
            echo "🚨 Unknown container started: $CONTAINER" | mail -s "NODE1 ALERT" admin@daarion.city
        fi
    fi
done

5.3 Prometheus Alerts

# /opt/prometheus/alerts.yml
groups:
  - name: security
    rules:
      - alert: HighCPUUsage
        expr: node_cpu_seconds_total{mode="idle"} < 20
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High CPU usage detected"
          
      - alert: SuspiciousProcess
        expr: process_cpu_seconds_total{process=~"xmrig|kdevtmp|perfctl"} > 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Suspicious process detected"
          
      - alert: UnauthorizedContainer
        expr: container_last_seen{name!~"dagi-.*|postgres|redis|neo4j"} > 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Unauthorized container running"

🚨 Рівень 6: Incident Response

6.1 Automated Response Script

#!/bin/bash
# /opt/scripts/incident-response.sh
# Автоматична реакція на інцидент

set -e

LOG="/var/log/incident-response.log"
BACKUP_DIR="/opt/backups/incident-$(date +%Y%m%d_%H%M%S)"

echo "$(date) - INCIDENT RESPONSE STARTED" >> $LOG

# 1. Зберегти стан для форензики
mkdir -p $BACKUP_DIR
ps aux > $BACKUP_DIR/processes.txt
netstat -tulpn > $BACKUP_DIR/network.txt
docker ps -a > $BACKUP_DIR/containers.txt
docker images > $BACKUP_DIR/images.txt
iptables -L -n > $BACKUP_DIR/iptables.txt
cat /etc/crontab > $BACKUP_DIR/crontab.txt
ls -la /tmp > $BACKUP_DIR/tmp.txt

# 2. Kill suspicious processes
pkill -9 -f "xmrig|kdevtmp|kinsing|perfctl|httpd.*tmp"

# 3. Stop all non-essential containers
docker stop $(docker ps -q --filter "name!=dagi-router" --filter "name!=dagi-gateway")

# 4. Block all outgoing traffic except SSH
iptables -P OUTPUT DROP
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT

# 5. Clean /tmp
find /tmp -type f -executable -delete
rm -rf /tmp/.perf.c /tmp/httpd /tmp/mysql

# 6. Alert
echo "INCIDENT RESPONSE COMPLETED at $(date)" | mail -s "🚨 NODE1 INCIDENT" admin@daarion.city

echo "$(date) - INCIDENT RESPONSE COMPLETED" >> $LOG
echo "Backup saved to: $BACKUP_DIR" >> $LOG

6.2 Recovery Playbook

## 🔄 Recovery Playbook

### Крок 1: Ізоляція (0-5 хвилин)
1. Запустити incident-response.sh
2. Відключити від мережі (якщо критично)
3. Зберегти докази

### Крок 2: Аналіз (5-30 хвилин)
1. Переглянути логи: /var/log/security-check.log
2. Перевірити processes.txt
3. Ідентифікувати вектор атаки

### Крок 3: Очищення (30-60 хвилин)
1. Видалити compromised containers + images
2. Очистити persistence mechanisms
3. Перевірити cron, systemd, /etc/ld.so.preload

### Крок 4: Відновлення (1-2 години)
1. Rebuild з чистих images
2. Restore з backup (якщо потрібно)
3. Перевірити функціональність

### Крок 5: Post-mortem (24 години)
1. Документувати інцидент
2. Оновити захист
3. Ротувати секрети

Чеклист впровадження

Негайно (сьогодні):

  • Встановити Trivy на NODE1
  • Створити security-check.sh
  • Налаштувати cron для перевірок
  • Оновити docker-compose.yml з security options
  • Налаштувати egress firewall

Цього тижня:

  • Впровадити image pinning by SHA
  • Налаштувати fail2ban
  • Встановити rkhunter, chkrootkit
  • Налаштувати auditd
  • Створити process-monitor.py

Цього місяця:

  • Впровадити network isolation
  • Налаштувати Prometheus alerts
  • Створити custom secure base images
  • Документувати всі процедури
  • Провести security audit

📚 Додаткові ресурси


Автор: Ivan Tytar & AI Assistant
Останнє оновлення: 2026-01-10