From 1231647f947c3f951f49fe2b4a8e901e5a42be5f Mon Sep 17 00:00:00 2001 From: Apple Date: Sat, 10 Jan 2026 05:05:21 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Add=20comprehensive=20S?= =?UTF-8?q?ecurity=20Hardening=20Plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- SECURITY-HARDENING-PLAN.md | 713 +++++++++++++++++++++++ docker-compose.secure.yml | 195 +++++++ scripts/security/scan-image.sh | 120 ++++ scripts/security/setup-node1-security.sh | 195 +++++++ 4 files changed, 1223 insertions(+) create mode 100644 SECURITY-HARDENING-PLAN.md create mode 100644 docker-compose.secure.yml create mode 100755 scripts/security/scan-image.sh create mode 100755 scripts/security/setup-node1-security.sh diff --git a/SECURITY-HARDENING-PLAN.md b/SECURITY-HARDENING-PLAN.md new file mode 100644 index 00000000..3c455018 --- /dev/null +++ b/SECURITY-HARDENING-PLAN.md @@ -0,0 +1,713 @@ +# 🛡️ Security Hardening Plan — DAARION & MicroDAO + +**Версія:** 1.0.0 +**Дата:** 2026-01-10 +**Статус:** В процесі впровадження + +--- + +## 📋 Зміст + +1. [Аналіз інцидентів](#аналіз-інцидентів) +2. [Рівень 1: Image Security](#рівень-1-image-security) +3. [Рівень 2: Container Runtime Security](#рівень-2-container-runtime-security) +4. [Рівень 3: Host Security](#рівень-3-host-security) +5. [Рівень 4: Network Security](#рівень-4-network-security) +6. [Рівень 5: Monitoring & Detection](#рівень-5-monitoring--detection) +7. [Рівень 6: Incident Response](#рівень-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) + +```bash +# Встановлення 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 + +**❌ НІКОЛИ:** +```yaml +image: postgres:16-alpine # Тег може змінитись! +``` + +**✅ ЗАВЖДИ:** +```yaml +image: postgres@sha256:abc123... # Фіксований digest +``` + +### 1.3 Allowlist Registry + +```yaml +# /etc/docker/daemon.json +{ + "allowed-registries": [ + "docker.io/library", + "ghcr.io/daarion-dao" + ] +} +``` + +### 1.4 Custom Base Images + +Створити власні базові образи з мінімальним attack surface: + +```dockerfile +# 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 + +```yaml +# 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 + +```json +// seccomp-profile.json +{ + "defaultAction": "SCCOMP_ACT_ERRNO", + "syscalls": [ + { + "names": ["accept", "bind", "clone", "close", "connect", ...], + "action": "SCCOMP_ACT_ALLOW" + } + ] +} +``` + +### 2.3 AppArmor Profile + +```bash +# /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 + +```bash +#!/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 + +```bash +#!/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 + +```bash +# /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 + +```yaml +# 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 + +```bash +#!/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 + +```bash +# /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 + +```python +#!/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 + +```bash +#!/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 + +```yaml +# /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 + +```bash +#!/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 + +```markdown +## 🔄 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 + +--- + +## 📚 Додаткові ресурси + +- [Docker Security Best Practices](https://docs.docker.com/engine/security/) +- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker) +- [Trivy Documentation](https://aquasecurity.github.io/trivy/) +- [Falco Runtime Security](https://falco.org/) +- [OWASP Container Security](https://owasp.org/www-project-container-security/) + +--- + +**Автор:** Ivan Tytar & AI Assistant +**Останнє оновлення:** 2026-01-10 diff --git a/docker-compose.secure.yml b/docker-compose.secure.yml new file mode 100644 index 00000000..a7a8404b --- /dev/null +++ b/docker-compose.secure.yml @@ -0,0 +1,195 @@ +# ============================================================ +# docker-compose.secure.yml — Secure Docker Compose Template +# ============================================================ +# Використовуйте цей шаблон як базу для всіх сервісів +# ============================================================ + +version: '3.8' + +# Ізольовані мережі +networks: + frontend: + driver: bridge + # Доступ до інтернету (для nginx, gateway) + backend: + driver: bridge + internal: true # БЕЗ доступу до інтернету! + database: + driver: bridge + internal: true # БЕЗ доступу до інтернету! + +services: + # ============================================================ + # ПРИКЛАД: Безпечний PostgreSQL + # ============================================================ + postgres: + # ✅ Завжди використовуйте digest, не тег! + image: postgres@sha256:ЗАМІНІТЬ_НА_ПЕРЕВІРЕНИЙ_DIGEST + container_name: dagi-postgres + + # ⚠️ НІКОЛИ auto-restart для нових сервісів! + # Змініть на "unless-stopped" ТІЛЬКИ після верифікації + restart: "no" + + # 🔒 Security options + security_opt: + - no-new-privileges:true + + # 📁 Read-only root filesystem + read_only: true + + # 📂 Тимчасові директорії (noexec!) + tmpfs: + - /tmp:noexec,nosuid,nodev,size=100m + - /var/run/postgresql:noexec,nosuid,nodev,size=10m + + # 💾 Volumes (тільки необхідні) + volumes: + - postgres_data:/var/lib/postgresql/data + + # 🔧 Resource limits + deploy: + resources: + limits: + cpus: '2' + memory: 2G + reservations: + cpus: '0.5' + memory: 512M + + # 🔓 Capabilities (мінімум!) + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + - DAC_OVERRIDE + + # ❌ No privileged mode! + privileged: false + + # 🌐 Network (тільки database!) + networks: + - database + + # 🔐 Environment + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: ${POSTGRES_DB} + + # 🏥 Healthcheck + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + + # ============================================================ + # ПРИКЛАД: Безпечний Redis + # ============================================================ + redis: + image: redis@sha256:ЗАМІНІТЬ_НА_ПЕРЕВІРЕНИЙ_DIGEST + container_name: dagi-redis + restart: "no" + + security_opt: + - no-new-privileges:true + + read_only: true + + tmpfs: + - /tmp:noexec,nosuid,nodev,size=50m + + volumes: + - redis_data:/data + + deploy: + resources: + limits: + cpus: '1' + memory: 512M + + cap_drop: + - ALL + + privileged: false + + networks: + - database + + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 30s + timeout: 10s + retries: 3 + + # ============================================================ + # ПРИКЛАД: Безпечний Router (з доступом до мережі) + # ============================================================ + router: + image: ghcr.io/daarion-dao/dagi-router@sha256:ЗАМІНІТЬ + container_name: dagi-router + restart: "no" + + security_opt: + - no-new-privileges:true + + # Router потребує запис для логів + read_only: false + + tmpfs: + - /tmp:noexec,nosuid,nodev,size=100m + + deploy: + resources: + limits: + cpus: '2' + memory: 1G + + cap_drop: + - ALL + cap_add: + - NET_BIND_SERVICE + + privileged: false + + # Router має доступ до frontend і backend + networks: + - frontend + - backend + + ports: + - "9102:9102" + + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9102/health"] + interval: 30s + timeout: 10s + retries: 3 + +# ============================================================ +# Volumes +# ============================================================ +volumes: + postgres_data: + driver: local + redis_data: + driver: local + +# ============================================================ +# SECURITY CHECKLIST: +# ============================================================ +# [ ] Всі images pinned by SHA256 digest +# [ ] restart: "no" для нових сервісів +# [ ] security_opt: no-new-privileges +# [ ] read_only: true де можливо +# [ ] tmpfs з noexec для /tmp +# [ ] Resource limits встановлені +# [ ] cap_drop: ALL + тільки необхідні cap_add +# [ ] privileged: false +# [ ] Мережі ізольовані (internal: true для backend/database) +# [ ] Healthcheck налаштований +# ============================================================ diff --git a/scripts/security/scan-image.sh b/scripts/security/scan-image.sh new file mode 100755 index 00000000..9f3129fd --- /dev/null +++ b/scripts/security/scan-image.sh @@ -0,0 +1,120 @@ +#!/bin/bash +# ============================================================ +# scan-image.sh — Сканування Docker образу перед використанням +# ============================================================ +# Використання: +# ./scan-image.sh postgres:16-alpine +# ./scan-image.sh --pull postgres:16-alpine +# ============================================================ + +set -e + +# Кольори +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +# Параметри +PULL=false +IMAGE="" + +# Парсинг аргументів +while [[ $# -gt 0 ]]; do + case $1 in + --pull|-p) + PULL=true + shift + ;; + *) + IMAGE="$1" + shift + ;; + esac +done + +if [ -z "$IMAGE" ]; then + echo "Usage: $0 [--pull] " + echo "Example: $0 postgres:16-alpine" + echo " $0 --pull postgres:16-alpine" + exit 1 +fi + +echo -e "${CYAN}🔍 Scanning Docker Image: $IMAGE${NC}" +echo "========================================" +date +echo "" + +# Перевірка Trivy +if ! command -v trivy &> /dev/null; then + echo -e "${RED}❌ Trivy not installed!${NC}" + echo "Install: curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin" + exit 1 +fi + +# Pull якщо потрібно +if [ "$PULL" = true ]; then + echo -e "${YELLOW}📥 Pulling image...${NC}" + docker pull "$IMAGE" + echo "" +fi + +# Отримати digest +echo -e "${YELLOW}📋 Image Info:${NC}" +DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE" 2>/dev/null || echo "N/A") +echo " Digest: $DIGEST" +echo "" + +# Сканування на вразливості +echo -e "${YELLOW}🔒 Scanning for vulnerabilities...${NC}" +echo "" + +# Запуск Trivy +trivy image --severity HIGH,CRITICAL "$IMAGE" +SCAN_EXIT=$? + +echo "" +echo "========================================" + +if [ $SCAN_EXIT -eq 0 ]; then + echo -e "${GREEN}✅ No HIGH/CRITICAL vulnerabilities found${NC}" + echo "" + echo -e "${GREEN}Safe to use:${NC}" + echo " image: $IMAGE" + if [ "$DIGEST" != "N/A" ]; then + echo "" + echo -e "${GREEN}Recommended (pinned by digest):${NC}" + echo " image: $DIGEST" + fi +else + echo -e "${RED}❌ Vulnerabilities found!${NC}" + echo "" + echo "Options:" + echo " 1. Use a different image version" + echo " 2. Build custom image with patches" + echo " 3. Accept risk (not recommended)" + exit 1 +fi + +# Додаткова перевірка на malware +echo "" +echo -e "${YELLOW}🦠 Checking for known malware patterns...${NC}" + +# Запустити контейнер і перевірити /tmp +MALWARE_CHECK=$(docker run --rm "$IMAGE" sh -c "ls -la /tmp 2>/dev/null | grep -E '(httpd|\.perf|mysql|xmrig|kdevtmp)' || echo 'clean'" 2>/dev/null || echo "check_failed") + +if [ "$MALWARE_CHECK" = "clean" ]; then + echo -e "${GREEN}✅ No known malware patterns in /tmp${NC}" +elif [ "$MALWARE_CHECK" = "check_failed" ]; then + echo -e "${YELLOW}⚠️ Could not check /tmp (image may not have shell)${NC}" +else + echo -e "${RED}❌ MALWARE DETECTED in /tmp!${NC}" + echo "$MALWARE_CHECK" + echo "" + echo -e "${RED}DO NOT USE THIS IMAGE!${NC}" + exit 1 +fi + +echo "" +echo -e "${GREEN}🎉 Image scan complete!${NC}" diff --git a/scripts/security/setup-node1-security.sh b/scripts/security/setup-node1-security.sh new file mode 100755 index 00000000..c6b2e417 --- /dev/null +++ b/scripts/security/setup-node1-security.sh @@ -0,0 +1,195 @@ +#!/bin/bash +# ============================================================ +# setup-node1-security.sh — Налаштування безпеки NODE1 +# ============================================================ +# Запускати на NODE1 після rebuild: +# ssh root@144.76.224.179 +# bash < <(curl -s https://raw.githubusercontent.com/.../setup-node1-security.sh) +# ============================================================ + +set -e + +echo "🛡️ NODE1 Security Setup" +echo "========================" +date +echo "" + +# Кольори +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# 1. Оновлення системи +echo -e "${YELLOW}[1/10] Оновлення системи...${NC}" +apt update && apt upgrade -y + +# 2. Встановлення security tools +echo -e "${YELLOW}[2/10] Встановлення security tools...${NC}" +apt install -y \ + fail2ban \ + ufw \ + auditd \ + rkhunter \ + chkrootkit \ + lynis \ + aide \ + unattended-upgrades \ + apt-listchanges + +# 3. Встановлення Trivy (image scanner) +echo -e "${YELLOW}[3/10] Встановлення Trivy...${NC}" +curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin +trivy --version + +# 4. Налаштування fail2ban +echo -e "${YELLOW}[4/10] Налаштування fail2ban...${NC}" +cat > /etc/fail2ban/jail.local << 'EOF' +[DEFAULT] +bantime = 3600 +findtime = 600 +maxretry = 3 + +[sshd] +enabled = true +port = ssh +filter = sshd +logpath = /var/log/auth.log +maxretry = 3 +bantime = 3600 +EOF +systemctl enable fail2ban +systemctl restart fail2ban + +# 5. Налаштування UFW (firewall) +echo -e "${YELLOW}[5/10] Налаштування UFW...${NC}" +ufw default deny incoming +ufw default deny outgoing +ufw allow 22/tcp comment 'SSH' +ufw allow 80/tcp comment 'HTTP' +ufw allow 443/tcp comment 'HTTPS' +ufw allow out 53/udp comment 'DNS' +ufw allow out 443/tcp comment 'HTTPS out' +ufw allow out 80/tcp comment 'HTTP out' +ufw allow out 123/udp comment 'NTP' +# Block internal networks +ufw deny out to 10.0.0.0/8 +ufw deny out to 172.16.0.0/12 +echo "y" | ufw enable + +# 6. Kernel hardening +echo -e "${YELLOW}[6/10] Kernel hardening...${NC}" +cat >> /etc/sysctl.conf << 'EOF' + +# Security hardening +net.ipv4.ip_forward = 0 +net.ipv4.conf.all.accept_redirects = 0 +net.ipv4.conf.default.accept_redirects = 0 +net.ipv4.tcp_syncookies = 1 +net.ipv4.conf.all.accept_source_route = 0 +net.ipv4.conf.all.log_martians = 1 +kernel.randomize_va_space = 2 +EOF +sysctl -p + +# 7. Налаштування auditd +echo -e "${YELLOW}[7/10] Налаштування auditd...${NC}" +cat > /etc/audit/rules.d/security.rules << 'EOF' +# Monitor Docker +-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 cron +-w /etc/crontab -p wa -k cron +-w /etc/cron.d -p wa -k cron + +# Monitor passwd/shadow +-w /etc/passwd -p wa -k passwd +-w /etc/shadow -p wa -k shadow + +# Monitor network config +-w /etc/hosts -p wa -k hosts +-w /etc/network -p wa -k network +EOF +systemctl enable auditd +systemctl restart auditd + +# 8. Створення директорій +echo -e "${YELLOW}[8/10] Створення директорій...${NC}" +mkdir -p /opt/scripts +mkdir -p /opt/config +mkdir -p /opt/backups +mkdir -p /var/log/security + +# 9. Створення security check script +echo -e "${YELLOW}[9/10] Створення security check script...${NC}" +cat > /opt/scripts/security-check.sh << 'SCRIPT' +#!/bin/bash +# Security check script - runs every hour + +LOG="/var/log/security/check-$(date +%Y%m%d).log" +echo "$(date) - Starting security check" >> $LOG + +# Check for suspicious processes +SUSPICIOUS=$(ps aux | grep -E "(xmrig|kdevtmp|kinsing|perfctl|httpd.*tmp|softirq|vrarhpb)" | grep -v grep) +if [ -n "$SUSPICIOUS" ]; then + echo "🚨 ALERT: Suspicious process found!" >> $LOG + echo "$SUSPICIOUS" >> $LOG + pkill -9 -f "xmrig|kdevtmp|kinsing|perfctl" +fi + +# 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 +fi + +# Check CPU load +LOAD=$(cat /proc/loadavg | cut -d' ' -f1) +if (( $(echo "$LOAD > 5" | bc -l) )); then + echo "⚠️ WARNING: High CPU load: $LOAD" >> $LOG + ps aux --sort=-%cpu | head -10 >> $LOG +fi + +# Check for unknown containers +UNKNOWN=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -v -E "^(dagi-|postgres|redis|neo4j|qdrant|grafana|prometheus)") +if [ -n "$UNKNOWN" ]; then + echo "⚠️ WARNING: Unknown containers: $UNKNOWN" >> $LOG +fi + +echo "$(date) - Security check complete" >> $LOG +SCRIPT +chmod +x /opt/scripts/security-check.sh + +# 10. Налаштування cron +echo -e "${YELLOW}[10/10] Налаштування cron...${NC}" +cat > /etc/cron.d/security << 'EOF' +# Security checks +0 * * * * root /opt/scripts/security-check.sh +0 3 * * * root rkhunter --update && rkhunter --check --skip-keypress > /var/log/security/rkhunter.log 2>&1 +0 4 * * * root chkrootkit > /var/log/security/chkrootkit.log 2>&1 +EOF + +# Фінальна перевірка +echo "" +echo -e "${GREEN}✅ Security setup complete!${NC}" +echo "" +echo "Встановлено:" +echo " ✓ fail2ban (SSH protection)" +echo " ✓ UFW (firewall with egress filtering)" +echo " ✓ Trivy (image scanner)" +echo " ✓ auditd (system auditing)" +echo " ✓ rkhunter + chkrootkit (rootkit detection)" +echo " ✓ Security check script (hourly)" +echo "" +echo "Перевірка:" +echo " ufw status" +echo " fail2ban-client status" +echo " trivy --version" +echo " /opt/scripts/security-check.sh"