Zentrales Bash Backup-Skript für mehrere OPNsense Firewalls
Hier ist ein umfassendes Bash-Skript, das automatisierte Backups von mehreren OPNsense-Firewalls erstellt und verwaltet:
Hauptskript: opnsense-backup.sh
#!/bin/bash
################################################################################
# OPNsense Centralized Backup Script
# Erstellt automatisierte Backups von mehreren OPNsense Firewalls
# Anforderungen: curl, jq, ssh (optional für lokale Speicherung)
################################################################################
set -euo pipefail
# ============================================================================
# KONFIGURATION
# ============================================================================
# Backup-Verzeichnis
BACKUP_DIR="/var/backups/opnsense"
LOG_FILE="${BACKUP_DIR}/backup.log"
CONFIG_FILE="/etc/opnsense-backup/firewalls.conf"
# Aufbewahrungsdauer (Tage)
RETENTION_DAYS=30
# E-Mail-Benachrichtigungen (optional)
ENABLE_EMAIL=true
EMAIL_RECIPIENT="[email protected]"
EMAIL_FROM="[email protected]"
# Kompression
ENABLE_COMPRESSION=true
COMPRESSION_LEVEL=9
# Remote-Speicher (optional)
ENABLE_REMOTE_STORAGE=false
REMOTE_USER="backup"
REMOTE_HOST="backup.example.com"
REMOTE_PATH="/mnt/backups/opnsense"
# ============================================================================
# FUNKTIONEN
# ============================================================================
log() {
local level="$1"
shift
local message="$@"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[${timestamp}] [${level}] ${message}" | tee -a "${LOG_FILE}"
}
log_info() {
log "INFO" "$@"
}
log_error() {
log "ERROR" "$@"
}
log_success() {
log "SUCCESS" "$@"
}
# Verzeichnisse initialisieren
init_directories() {
mkdir -p "${BACKUP_DIR}"
mkdir -p "${BACKUP_DIR}/logs"
mkdir -p "${BACKUP_DIR}/configs"
chmod 700 "${BACKUP_DIR}"
}
# Konfigurationsdatei validieren
validate_config() {
if [[ ! -f "${CONFIG_FILE}" ]]; then
log_error "Konfigurationsdatei nicht gefunden: ${CONFIG_FILE}"
return 1
fi
log_info "Konfigurationsdatei validiert"
return 0
}
# Backup von einer OPNsense-Firewall erstellen
backup_firewall() {
local name="$1"
local host="$2"
local api_key="$3"
local api_secret="$4"
local backup_date=$(date '+%Y%m%d_%H%M%S')
local backup_file="${BACKUP_DIR}/configs/${name}_${backup_date}.xml"
local backup_file_compressed="${backup_file}.gz"
log_info "Starte Backup für Firewall: ${name} (${host})"
# API-Request zum Erstellen eines Backups
local response=$(curl -s -X POST \
-H "X-API-Key: ${api_key}" \
-H "X-API-Secret: ${api_secret}" \
"https://${host}/api/core/system/config/download" \
--insecure 2>&1)
if [[ $? -ne 0 ]]; then
log_error "Fehler beim Backup von ${name}: API-Anfrage fehlgeschlagen"
return 1
fi
# Backup speichern
echo "${response}" > "${backup_file}"
# Validierung: Prüfe ob XML-Datei gültig ist
if ! grep -q "<?xml" "${backup_file}"; then
log_error "Ungültige Backup-Datei für ${name}"
rm -f "${backup_file}"
return 1
fi
# Kompression (optional)
if [[ "${ENABLE_COMPRESSION}" == "true" ]]; then
gzip -${COMPRESSION_LEVEL} "${backup_file}"
backup_file="${backup_file_compressed}"
log_info "Backup komprimiert: $(ls -lh "${backup_file}" | awk '{print $5}')"
fi
# Dateigröße und Checksumme
local file_size=$(stat -f%z "${backup_file}" 2>/dev/null || stat -c%s "${backup_file}")
local checksum=$(sha256sum "${backup_file}" | awk '{print $1}')
log_success "Backup erstellt für ${name}: ${backup_file} (${file_size} bytes)"
# Metadaten speichern
echo "${backup_date}|${name}|${host}|${file_size}|${checksum}" >> "${BACKUP_DIR}/backup.index"
# Remote-Speicher (optional)
if [[ "${ENABLE_REMOTE_STORAGE}" == "true" ]]; then
backup_remote "${name}" "${backup_file}"
fi
return 0
}
# Backup zu Remote-Speicher übertragen
backup_remote() {
local name="$1"
local backup_file="$2"
log_info "Übertrage Backup für ${name} zu Remote-Speicher"
scp -q "${backup_file}" \
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/" 2>&1
if [[ $? -eq 0 ]]; then
log_success "Remote-Backup erfolgreich für ${name}"
else
log_error "Remote-Backup fehlgeschlagen für ${name}"
return 1
fi
}
# Alte Backups löschen (Retention Policy)
cleanup_old_backups() {
log_info "Bereinige alte Backups (älter als ${RETENTION_DAYS} Tage)"
find "${BACKUP_DIR}/configs" -name "*.xml*" -type f -mtime +${RETENTION_DAYS} -delete
log_success "Bereinigung abgeschlossen"
}
# E-Mail-Benachrichtigung senden
send_email_notification() {
local subject="$1"
local body="$2"
if [[ "${ENABLE_EMAIL}" != "true" ]]; then
return 0
fi
if ! command -v mail &> /dev/null; then
log_error "mail-Programm nicht installiert"
return 1
fi
echo -e "${body}" | mail -s "${subject}" \
-r "${EMAIL_FROM}" "${EMAIL_RECIPIENT}"
log_info "E-Mail-Benachrichtigung gesendet"
}
# Backup-Report generieren
generate_report() {
local report_file="${BACKUP_DIR}/logs/report_$(date '+%Y%m%d_%H%M%S').txt"
{
echo "======================================"
echo "OPNsense Backup Report"
echo "Datum: $(date)"
echo "======================================"
echo ""
echo "Backup-Verzeichnis: ${BACKUP_DIR}"
echo ""
echo "--- Backup-Übersicht ---"
ls -lh "${BACKUP_DIR}/configs" | tail -n +2 || echo "Keine Backups gefunden"
echo ""
echo "--- Disk-Nutzung ---"
du -sh "${BACKUP_DIR}"
echo ""
echo "--- Letzte 10 Log-Einträge ---"
tail -n 10 "${LOG_FILE}"
} > "${report_file}"
log_info "Report generiert: ${report_file}"
# Optional: Report per E-Mail versenden
if [[ "${ENABLE_EMAIL}" == "true" ]]; then
send_email_notification \
"OPNsense Backup Report - $(date '+%Y-%m-%d')" \
"$(cat "${report_file}")"
fi
}
# Hauptfunktion
main() {
log_info "=========================================="
log_info "OPNsense Backup-Prozess gestartet"
log_info "=========================================="
init_directories
validate_config || exit 1
# Backup-Index initialisieren
touch "${BACKUP_DIR}/backup.index"
local backup_count=0
local error_count=0
# Jede Firewall aus der Konfiguration sichern
while IFS='|' read -r name host api_key api_secret; do
# Kommentare und leere Zeilen ignorieren
[[ "$name" =~ ^#.*$ ]] && continue
[[ -z "$name" ]] && continue
if backup_firewall "$name" "$host" "$api_key" "$api_secret"; then
((backup_count++))
else
((error_count++))
fi
done < "${CONFIG_FILE}"
# Aufräumen
cleanup_old_backups
# Report generieren
generate_report
# Zusammenfassung
log_info "=========================================="
log_success "Backup-Prozess abgeschlossen"
log_info "Erfolgreiche Backups: ${backup_count}"
log_info "Fehler: ${error_count}"
log_info "=========================================="
# Exit-Code basierend auf Fehlern
[[ ${error_count} -eq 0 ]] && exit 0 || exit 1
}
# ============================================================================
# SCRIPT-AUSFÜHRUNG
# ============================================================================
main "$@"
Konfigurationsdatei: /etc/opnsense-backup/firewalls.conf
# OPNsense Firewall Backup-Konfiguration
# Format: name|host|api_key|api_secret
# Beispiel:
fw-prod|192.168.1.1|your-api-key-here|your-api-secret-here
fw-backup|192.168.1.2|your-api-key-here|your-api-secret-here
fw-branch|10.0.0.1|your-api-key-here|your-api-secret-here
Cron-Job Setup
# /etc/cron.d/opnsense-backup
# Täglich um 2:00 Uhr morgens ausführen
0 2 * * * root /usr/local/bin/opnsense-backup.sh >> /var/log/opnsense-backup.log 2>&1
# Wöchentliche Verifizierung (Sonntag um 3:00 Uhr)
0 3 * * 0 root /usr/local/bin/opnsense-backup-verify.sh >> /var/log/opnsense-backup-verify.log 2>&1
Verifikations-Skript: opnsense-backup-verify.sh
#!/bin/bash
# Verifiziert die Integrität von Backups
BACKUP_DIR="/var/backups/opnsense"
LOG_FILE="${BACKUP_DIR}/logs/verify.log"
verify_backups() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starte Backup-Verifikation" | tee -a "${LOG_FILE}"
local verified=0
local failed=0
while IFS='|' read -r backup_date name host file_size checksum; do
local backup_file=$(find "${BACKUP_DIR}/configs" -name "${name}_${backup_date}*" | head -1)
if [[ -f "${backup_file}" ]]; then
local actual_checksum=$(sha256sum "${backup_file}" | awk '{print $1}')
if [[ "${actual_checksum}" == "${checksum}" ]]; then
echo "[OK] ${name} - Checksumme stimmt überein" | tee -a "${LOG_FILE}"
((verified++))
else
echo "[FEHLER] ${name} - Checksumme stimmt nicht überein" | tee -a "${LOG_FILE}"
((failed++))
fi
fi
done < "${BACKUP_DIR}/backup.index"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Verifikation abgeschlossen - OK: ${verified}, Fehler: ${failed}" | tee -a "${LOG_FILE}"
}
verify_backups
Installation und Setup
# 1. Skripte installieren
sudo install -m 755 opnsense-backup.sh /usr/local/bin/
sudo install -m 755 opnsense-backup-verify.sh /usr/local/bin/
# 2. Konfiguration erstellen
sudo mkdir -p /etc/opnsense-backup
sudo install -m 600 firewalls.conf /etc/opnsense-backup/
# 3. Cron-Job aktivieren
sudo install -m 644 opnsense-backup.cron /etc/cron.d/opnsense-backup
# 4. Backups manuell testen
sudo /usr/local/bin/opnsense-backup.sh
Wichtige Hinweise
API-Credentials: Die API-Keys und Secrets müssen in OPNsense unter System → API erstellt werden. Der Benutzer benötigt Berechtigungen für core:system:config:download.
Sicherheit: Die Konfigurationsdatei sollte Permissions 600 haben und nur vom root-Benutzer lesbar sein.
HTTPS-Validierung: Das Skript nutzt --insecure für selbstsignierte Zertifikate. Für Produktionsumgebungen sollte dies durch ordnungsgemäße Zertifikat-Validierung ersetzt werden.
Remote-Speicher: SSH-Keys sollten für automatisierte Übertragungen konfiguriert sein.