# DAARION Network - Security Hardening Playbook # Comprehensive security setup for all nodes --- - name: Security Hardening hosts: all become: yes vars: allowed_ssh_port: "{{ ansible_port | default(22) }}" tasks: # ========================================================================= # SECURITY PACKAGES # ========================================================================= - name: Install security packages apt: name: "{{ security_packages }}" state: present when: ansible_os_family == "Debian" - name: Install Trivy (vulnerability scanner) shell: | curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin args: creates: /usr/local/bin/trivy # ========================================================================= # UFW FIREWALL # ========================================================================= - name: UFW - Reset to defaults ufw: state: reset - name: UFW - Default deny incoming ufw: direction: incoming policy: deny - name: UFW - Default deny outgoing ufw: direction: outgoing policy: deny - name: UFW - Allow SSH ufw: rule: allow port: "{{ allowed_ssh_port }}" proto: tcp - name: UFW - Allow necessary TCP ports ufw: rule: allow port: "{{ item }}" proto: tcp loop: "{{ firewall_allowed_tcp_ports }}" when: firewall_allowed_tcp_ports is defined - name: UFW - Allow necessary outgoing ufw: rule: allow direction: out port: "{{ item.port }}" proto: "{{ item.proto }}" loop: "{{ firewall_allowed_outgoing }}" - name: UFW - Block internal networks ufw: rule: deny direction: out to_ip: "{{ item }}" loop: "{{ firewall_blocked_networks }}" when: firewall_blocked_networks is defined - name: UFW - Enable ufw: state: enabled # ========================================================================= # FAIL2BAN # ========================================================================= - name: Configure fail2ban copy: dest: /etc/fail2ban/jail.local content: | [DEFAULT] bantime = 3600 findtime = 600 maxretry = 3 [sshd] enabled = true port = {{ allowed_ssh_port }} filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 86400 notify: restart fail2ban - name: Enable fail2ban service: name: fail2ban enabled: yes state: started # ========================================================================= # AUDITD # ========================================================================= - name: Configure auditd rules copy: dest: /etc/audit/rules.d/daarion.rules content: | # Monitor file changes in critical directories -w /etc/passwd -p wa -k passwd_changes -w /etc/shadow -p wa -k shadow_changes -w /etc/ssh/sshd_config -p wa -k sshd_config # Monitor Docker -w /var/lib/docker -p wa -k docker -w /etc/docker -p wa -k docker_config # Monitor cron -w /etc/crontab -p wa -k cron -w /etc/cron.d -p wa -k cron # Monitor tmp (malware indicator) -w /tmp -p x -k tmp_exec -w /var/tmp -p x -k var_tmp_exec notify: restart auditd - name: Enable auditd service: name: auditd enabled: yes state: started # ========================================================================= # KERNEL HARDENING # ========================================================================= - name: Kernel security parameters sysctl: name: "{{ item.name }}" value: "{{ item.value }}" state: present reload: yes loop: - { name: 'net.ipv4.conf.all.accept_redirects', value: '0' } - { name: 'net.ipv4.conf.default.accept_redirects', value: '0' } - { name: 'net.ipv4.conf.all.send_redirects', value: '0' } - { name: 'net.ipv4.conf.default.send_redirects', value: '0' } - { name: 'net.ipv4.tcp_syncookies', value: '1' } - { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: '1' } - { name: 'kernel.randomize_va_space', value: '2' } - { name: 'kernel.kptr_restrict', value: '2' } - { name: 'kernel.dmesg_restrict', value: '1' } # ========================================================================= # SECURITY CHECK SCRIPT # ========================================================================= - name: Deploy security check script copy: dest: "{{ scripts_dir }}/security-check.sh" mode: '0755' content: | #!/bin/bash # DAARION Security Check Script # Runs hourly via cron LOG="{{ logs_dir }}/security-$(date +%Y%m%d).log" ALERT_FILE="/tmp/security_alert" log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG" } log "=== Security Check Started ===" # Check for suspicious processes SUSPICIOUS=$(ps aux | grep -E "(xmrig|kdevtmp|kinsing|perfctl|httpd.*tmp|mysql.*tmp)" | grep -v grep) if [ -n "$SUSPICIOUS" ]; then log "CRITICAL: Suspicious process detected!" log "$SUSPICIOUS" pkill -9 -f "xmrig|kdevtmp|kinsing|perfctl" touch "$ALERT_FILE" fi # Check for executables in /tmp TMP_EXEC=$(find /tmp /var/tmp /dev/shm -type f -executable 2>/dev/null) if [ -n "$TMP_EXEC" ]; then log "WARNING: Executable files in tmp directories!" log "$TMP_EXEC" rm -f $TMP_EXEC 2>/dev/null fi # Check CPU usage (potential mining) LOAD=$(cat /proc/loadavg | cut -d' ' -f1) CPU_COUNT=$(nproc) THRESHOLD=$(echo "$CPU_COUNT * 2" | bc) if (( $(echo "$LOAD > $THRESHOLD" | bc -l) )); then log "WARNING: High CPU load: $LOAD (threshold: $THRESHOLD)" fi # Check for unauthorized SSH keys for user_home in /root /home/*; do if [ -f "$user_home/.ssh/authorized_keys" ]; then KEY_COUNT=$(wc -l < "$user_home/.ssh/authorized_keys") log "INFO: $user_home has $KEY_COUNT SSH keys" fi done # Check failed SSH attempts FAILED_SSH=$(grep "Failed password" /var/log/auth.log 2>/dev/null | wc -l) log "INFO: Failed SSH attempts today: $FAILED_SSH" # Check Docker containers if command -v docker &> /dev/null; then CONTAINER_COUNT=$(docker ps -q | wc -l) log "INFO: Running Docker containers: $CONTAINER_COUNT" # Check for containers running as root docker ps -q | while read cid; do USER=$(docker inspect --format '{{.Config.User}}' $cid) NAME=$(docker inspect --format '{{.Name}}' $cid) if [ -z "$USER" ] || [ "$USER" = "root" ] || [ "$USER" = "0" ]; then log "WARNING: Container $NAME running as root" fi done fi log "=== Security Check Completed ===" - name: Setup security cron cron: name: "Hourly security check" minute: "0" job: "{{ scripts_dir }}/security-check.sh" - name: Setup daily rkhunter scan cron: name: "Daily rkhunter scan" hour: "3" minute: "0" job: "rkhunter --update && rkhunter --check --skip-keypress > {{ logs_dir }}/rkhunter.log 2>&1" # ========================================================================= # AUTO UPDATES # ========================================================================= - name: Configure unattended-upgrades copy: dest: /etc/apt/apt.conf.d/50unattended-upgrades content: | Unattended-Upgrade::Allowed-Origins { "${distro_id}:${distro_codename}"; "${distro_id}:${distro_codename}-security"; "${distro_id}ESMApps:${distro_codename}-apps-security"; "${distro_id}ESM:${distro_codename}-infra-security"; }; Unattended-Upgrade::AutoFixInterruptedDpkg "true"; Unattended-Upgrade::Remove-Unused-Dependencies "true"; Unattended-Upgrade::Automatic-Reboot "false"; when: ansible_os_family == "Debian" # ========================================================================= # VERIFICATION # ========================================================================= - name: Verify security setup shell: | echo "=== Security Status ===" echo "UFW: $(ufw status | head -1)" echo "Fail2ban: $(systemctl is-active fail2ban)" echo "Auditd: $(systemctl is-active auditd)" echo "Trivy: $(trivy --version 2>/dev/null | head -1 || echo 'not installed')" register: security_status changed_when: false - name: Show security status debug: var: security_status.stdout_lines handlers: - name: restart fail2ban service: name: fail2ban state: restarted - name: restart auditd service: name: auditd state: restarted