Files
microdao-daarion/security/hardening/cloud.md
Apple cba2ff47f3 📚 docs(security): Add comprehensive Security chapter
## New Security Documentation Structure

/security/
├── README.md                    # Security overview & contacts
├── forensics-checklist.md       # Incident investigation guide
├── persistence-scan.sh          # Quick persistence detector
├── runtime-detector.sh          # Mining/suspicious process detector
└── hardening/
    ├── docker.md                # Docker security baseline
    ├── kubernetes.md            # K8s policies (future reference)
    └── cloud.md                 # Hetzner-specific hardening

## Key Components

### Forensics Checklist
- Process analysis commands
- Persistence mechanism detection
- Network connection analysis
- File system inspection
- Authentication audit
- Decision matrix for threat response

### Scripts
- persistence-scan.sh: Cron, systemd, executables, SSH keys
- runtime-detector.sh: Mining process detection with --kill option

### Hardening Guides
- Docker: Secure compose template, Dockerfile best practices
- Kubernetes: NetworkPolicy, PodSecurityStandard, Falco rules
- Cloud: Egress firewall, SSH hardening, fail2ban, monitoring

## Post-Incident Documentation
Based on lessons learned from Incidents #1 and #2 (Jan 2026)

Co-authored-by: Cursor Agent <agent@cursor.sh>
2026-01-09 02:08:13 -08:00

6.9 KiB
Raw Blame History

☁️ Cloud Security Hardening — Hetzner

Версія: 1.0.0
Provider: Hetzner Dedicated (GEX44)
Server: NODE1 (144.76.224.179)


🎯 Критичні налаштування

1. Egress Firewall (№1 Priority)

Блокування внутрішніх мереж Hetzner:

#!/bin/bash
# /root/firewall-egress.sh

# Block Hetzner internal networks (prevent scanning)
iptables -I OUTPUT -d 10.0.0.0/8 -j DROP
iptables -I OUTPUT -d 172.16.0.0/12 -j DROP
iptables -I OUTPUT -d 192.168.0.0/16 -j DROP

# Allow necessary internal traffic
iptables -I OUTPUT -d 10.0.0.0/8 -p tcp --dport 443 -j ACCEPT
iptables -I OUTPUT -d 10.0.0.0/8 -p tcp --dport 80 -j ACCEPT

# Log blocked attempts
iptables -I OUTPUT -d 10.0.0.0/8 -j LOG --log-prefix "BLOCKED_INTERNAL: "

# Block known mining pool ports
MINING_PORTS="3333 5555 7777 14433 45700 45560 14444 9999"
for port in $MINING_PORTS; do
    iptables -A OUTPUT -p tcp --dport $port -j DROP
    iptables -A OUTPUT -p tcp --dport $port -j LOG --log-prefix "BLOCKED_MINING: "
done

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

2. SSH Hardening

# /etc/ssh/sshd_config

# Disable root login with password
PermitRootLogin prohibit-password

# Use only SSH keys
PasswordAuthentication no
PubkeyAuthentication yes

# Limit authentication attempts
MaxAuthTries 3
MaxSessions 5

# Idle timeout
ClientAliveInterval 300
ClientAliveCountMax 2

# Disable unused features
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no

# Allow only specific users
AllowUsers root

# Use strong ciphers
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

3. Fail2ban Configuration

# /etc/fail2ban/jail.local

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400

[docker-abuse]
enabled = true
filter = docker-abuse
logpath = /var/log/syslog
maxretry = 5
bantime = 3600

🔒 Network Security

UFW Configuration

#!/bin/bash
# /root/setup-ufw.sh

# Reset UFW
ufw --force reset

# Default policies
ufw default deny incoming
ufw default deny outgoing

# Allow SSH (from specific IPs if possible)
ufw allow in 22/tcp

# Allow HTTP/HTTPS
ufw allow in 80/tcp
ufw allow in 443/tcp

# Allow outbound DNS
ufw allow out 53/tcp
ufw allow out 53/udp

# Allow outbound HTTP/HTTPS
ufw allow out 80/tcp
ufw allow out 443/tcp

# Allow outbound to Docker registry
ufw allow out to any port 443 proto tcp

# Block mining pools (additional layer)
# Add rules from firewall-egress.sh

# Enable UFW
ufw --force enable

Port Exposure Rules

Port Service Binding Notes
22 SSH 0.0.0.0 With fail2ban
80 Nginx 0.0.0.0 Redirect to 443
443 Nginx 0.0.0.0 HTTPS only
3000 daarion-web 127.0.0.1 Via Nginx
9102 Router 127.0.0.1 Internal
9300 Gateway 127.0.0.1 Via Nginx
* Other services 127.0.0.1 Never public

📊 Monitoring

System Monitoring Script

#!/bin/bash
# /root/security-monitor.sh
# Run via cron every 5 minutes

LOG_FILE="/var/log/security-monitor.log"
ALERT_THRESHOLD_CPU=80
ALERT_THRESHOLD_LOAD=10

timestamp() {
    date '+%Y-%m-%d %H:%M:%S'
}

# Check load average
LOAD=$(cat /proc/loadavg | awk '{print $1}')
LOAD_INT=${LOAD%.*}

if [ "$LOAD_INT" -gt "$ALERT_THRESHOLD_LOAD" ]; then
    echo "[$(timestamp)] ALERT: High load average: $LOAD" >> $LOG_FILE
    # Send alert (implement your notification)
fi

# Check for mining processes
MINING=$(ps aux | grep -iE "xmrig|catcal|softirq|vrarhpb|miner" | grep -v grep)
if [ -n "$MINING" ]; then
    echo "[$(timestamp)] CRITICAL: Mining process detected!" >> $LOG_FILE
    echo "$MINING" >> $LOG_FILE
    # Kill the process
    echo "$MINING" | awk '{print $2}' | xargs -r kill -9
fi

# Check outbound connections to mining ports
MINING_CONN=$(ss -antp | grep -E ":(3333|5555|7777|14433)")
if [ -n "$MINING_CONN" ]; then
    echo "[$(timestamp)] CRITICAL: Mining pool connection!" >> $LOG_FILE
    echo "$MINING_CONN" >> $LOG_FILE
fi

# Check Docker containers CPU
docker stats --no-stream --format "{{.Name}}: {{.CPUPerc}}" | while read line; do
    CPU=$(echo "$line" | grep -oE '[0-9]+' | head -1)
    if [ -n "$CPU" ] && [ "$CPU" -gt "$ALERT_THRESHOLD_CPU" ]; then
        echo "[$(timestamp)] WARNING: High CPU container: $line" >> $LOG_FILE
    fi
done

Cron Setup

# /etc/cron.d/security-monitor

# Run security monitor every 5 minutes
*/5 * * * * root /root/security-monitor.sh

# Run persistence scan daily
0 3 * * * root /opt/microdao-daarion/security/persistence-scan.sh >> /var/log/persistence-scan.log 2>&1

# Log rotation
0 0 * * * root find /var/log -name "*.log" -mtime +30 -delete

🚨 Incident Response (Hetzner)

При отриманні Abuse Report:

  1. Негайно:

    # Заблокувати весь вихідний трафік
    iptables -I OUTPUT -j DROP
    
    # Зберегти стан для аналізу
    ps auxf > /root/incident/ps_$(date +%s).txt
    ss -antp > /root/incident/ss_$(date +%s).txt
    docker ps -a > /root/incident/docker_$(date +%s).txt
    
  2. Знайти джерело:

    # Запустити forensics
    /opt/microdao-daarion/security/persistence-scan.sh
    /opt/microdao-daarion/security/runtime-detector.sh
    
  3. Усунути загрозу:

    # Kill процеси
    killall -9 <process_name>
    
    # Видалити контейнер ТА образ
    docker stop <container>
    docker rm <container>
    docker rmi <image>  # КРИТИЧНО!
    
  4. Відповісти Hetzner:

  5. Задокументувати:

    • Оновити INFRASTRUCTURE.md
    • Створити incident report

🔐 Secrets Management

Environment Variables

# /opt/microdao-daarion/.env

# NEVER commit to git!
# Use .env.example as template

# Generate secure passwords
openssl rand -base64 32

# Store secrets securely
chmod 600 .env
chown root:root .env

SSH Keys

# Generate strong SSH key
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519

# Rotate keys periodically
# Keep backup of old keys until rotation complete

Hetzner Security Checklist

  • Egress firewall blocking internal networks
  • Mining pool ports blocked
  • SSH hardened (key-only, fail2ban)
  • UFW configured (deny by default)
  • All services bound to 127.0.0.1 except Nginx
  • Security monitoring cron active
  • Log rotation configured
  • .env file secured (chmod 600)
  • Rescue mode access documented
  • Hetzner Robot access secured