🛡️ 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
This commit is contained in:
713
SECURITY-HARDENING-PLAN.md
Normal file
713
SECURITY-HARDENING-PLAN.md
Normal file
@@ -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
|
||||
195
docker-compose.secure.yml
Normal file
195
docker-compose.secure.yml
Normal file
@@ -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 налаштований
|
||||
# ============================================================
|
||||
120
scripts/security/scan-image.sh
Executable file
120
scripts/security/scan-image.sh
Executable file
@@ -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] <image_name>"
|
||||
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}"
|
||||
195
scripts/security/setup-node1-security.sh
Executable file
195
scripts/security/setup-node1-security.sh
Executable file
@@ -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"
|
||||
Reference in New Issue
Block a user