The Linux Audit Framework is the kernel-level system that records security-relevant events on your system. Unlike application-level logging, audit events are generated by the kernel itself, making them extremely difficult for an attacker to tamper with or bypass. If someone modifies a critical file, executes a suspicious binary, changes user permissions, or attempts to access a resource they should not, the audit system captures it.

This guide covers the complete audit stack: configuring the auditd daemon, writing audit rules for real-world security scenarios, analyzing events with ausearch and aureport, integrating with SIEM platforms, and applying audit rules specifically for Docker environments.

Installing and Configuring auditd

The audit daemon is included in most enterprise Linux distributions. On Debian/Ubuntu systems, you need to install it explicitly:

# Debian/Ubuntu
sudo apt install auditd audispd-plugins

# RHEL/CentOS/Fedora (usually pre-installed)
sudo dnf install audit audit-libs

# Enable and start the daemon
sudo systemctl enable --now auditd

# Check status
sudo auditctl -s
# enabled 1
# failure 1
# pid 1234
# rate_limit 0
# backlog_limit 8192
# lost 0
# backlog 0

Core Configuration: auditd.conf

The main configuration file controls how audit logs are stored and rotated:

# /etc/audit/auditd.conf
log_file = /var/log/audit/audit.log
log_format = ENRICHED
log_group = adm
priority_boost = 4
flush = INCREMENTAL_ASYNC
freq = 50
num_logs = 10
max_log_file = 50
max_log_file_action = ROTATE
space_left = 75
space_left_action = SYSLOG
admin_space_left = 50
admin_space_left_action = SUSPEND
disk_full_action = SUSPEND
disk_error_action = SUSPEND
tcp_listen_queue = 5
tcp_max_per_addr = 1
tcp_client_max_idle = 0
transport = TCP
krb5_principal = auditd
distribute_network = no
Setting Recommended Value Purpose
log_format ENRICHED Resolves UIDs/GIDs to names in log entries
flush INCREMENTAL_ASYNC Balance between performance and data safety
max_log_file 50 (MB) Rotate before files get unwieldy
num_logs 10 Keep 10 rotated log files
space_left_action SYSLOG Alert when disk space is low
disk_full_action SUSPEND Stop logging rather than crash the system
Warning: For compliance-sensitive environments (PCI DSS, HIPAA, SOC 2), set disk_full_action = HALT. This halts the system when audit logs can no longer be written, ensuring that no security events go unrecorded. This is extreme but may be required by your compliance framework.

Writing Audit Rules

Audit rules tell the kernel which events to record. There are three types: control rules (configure the audit system), file system rules (watch files/directories), and system call rules (monitor specific syscalls).

File and Directory Monitoring

# /etc/audit/rules.d/10-file-monitoring.rules

# Watch critical system files for any changes
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# Watch SSH configuration
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/ssh/ssh_config -p wa -k ssh_config
-w /root/.ssh/ -p wa -k root_ssh

# Watch cron configuration
-w /etc/crontab -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
-w /var/spool/cron/ -p wa -k cron

# Watch system binaries for tampering
-w /usr/bin/ -p wa -k system_binaries
-w /usr/sbin/ -p wa -k system_binaries
-w /usr/local/bin/ -p wa -k local_binaries
-w /usr/local/sbin/ -p wa -k local_binaries

# Watch kernel modules
-w /etc/modprobe.d/ -p wa -k kernel_modules
-w /lib/modules/ -p wa -k kernel_modules

The -p flag specifies which permissions to watch: r (read), w (write), x (execute), a (attribute change). The -k flag assigns a key for easier searching.

System Call Auditing

# /etc/audit/rules.d/20-syscall-monitoring.rules

# Monitor process execution
-a always,exit -F arch=b64 -S execve -k exec
-a always,exit -F arch=b32 -S execve -k exec

# Monitor file deletion
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -k file_deletion
-a always,exit -F arch=b32 -S unlink -S unlinkat -S rename -S renameat -k file_deletion

# Monitor mount operations
-a always,exit -F arch=b64 -S mount -S umount2 -k mounts
-a always,exit -F arch=b32 -S mount -S umount -S umount2 -k mounts

# Monitor changes to system time
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -S clock_settime -k time_change
-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -S clock_settime -k time_change
-w /etc/localtime -p wa -k time_change

# Monitor network configuration changes
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k network_config
-a always,exit -F arch=b32 -S sethostname -S setdomainname -k network_config
-w /etc/hosts -p wa -k network_config
-w /etc/hostname -p wa -k network_config
-w /etc/resolv.conf -p wa -k network_config

# Monitor kernel module loading
-a always,exit -F arch=b64 -S init_module -S finit_module -S delete_module -k kernel_modules
-a always,exit -F arch=b32 -S init_module -S finit_module -S delete_module -k kernel_modules

User Activity Tracking

# /etc/audit/rules.d/30-user-monitoring.rules

# Monitor login/logout events
-w /var/log/lastlog -p wa -k logins
-w /var/log/faillog -p wa -k logins
-w /var/log/wtmp -p wa -k logins
-w /var/log/btmp -p wa -k logins
-w /var/run/utmp -p wa -k session

# Monitor privilege escalation
-a always,exit -F arch=b64 -S setuid -S setgid -S setreuid -S setregid -k privilege_escalation
-a always,exit -F arch=b32 -S setuid -S setgid -S setreuid -S setregid -k privilege_escalation

# Monitor sudo usage
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k sudo_commands
-a always,exit -F arch=b32 -S execve -F euid=0 -F auid>=1000 -F auid!=4294967295 -k sudo_commands

# Monitor user/group management commands
-w /usr/sbin/useradd -p x -k user_management
-w /usr/sbin/userdel -p x -k user_management
-w /usr/sbin/usermod -p x -k user_management
-w /usr/sbin/groupadd -p x -k user_management
-w /usr/sbin/groupdel -p x -k user_management
-w /usr/sbin/groupmod -p x -k user_management

Loading and Managing Rules

# Load rules from files
sudo augenrules --load

# Or load a specific rule temporarily
sudo auditctl -w /etc/myapp.conf -p wa -k myapp_config

# List all active rules
sudo auditctl -l

# Delete all rules (for testing)
sudo auditctl -D

# Make rules immutable (cannot be changed without reboot)
# Add this as the LAST line in your rules
-e 2
Tip: The -e 2 rule makes the audit configuration immutable until the next reboot. This prevents an attacker who gains root access from disabling audit logging. Always add this as the very last rule after all other rules are configured and tested.

Analyzing Audit Logs with ausearch

ausearch is the primary tool for querying audit logs. It understands the audit log format and provides powerful filtering:

# Search by key
sudo ausearch -k identity --start today

# Search by event type
sudo ausearch -m USER_LOGIN --start recent

# Search for failed events
sudo ausearch --success no --start today

# Search by user
sudo ausearch -ua 1000 --start this-week

# Search by file
sudo ausearch -f /etc/passwd --start today

# Search by time range
sudo ausearch --start 04/25/2025 08:00:00 --end 04/25/2025 17:00:00

# Search for specific syscall
sudo ausearch -sc execve --start today

# Interpret results (resolve UIDs, syscall numbers)
sudo ausearch -k exec --start today --interpret

Generating Reports with aureport

aureport generates summary reports from audit logs:

# Summary report
sudo aureport --summary

# Authentication report
sudo aureport --auth --start today
# Auth Report
# ============================================
# date     time   acct   host  term  exe    success  event
# 04/25/25 08:12  root   ssh   pts/0 /usr/sbin/sshd  yes  125

# Failed authentication report
sudo aureport --auth --failed --start this-week

# File access report
sudo aureport --file --start today

# Executable report (what was executed)
sudo aureport -x --start today

# User report
sudo aureport -u --start today

# System event anomalies
sudo aureport --anomaly

# Generate a report for a specific key
sudo ausearch -k identity --raw | aureport --file

Docker Audit Rules

Docker introduces unique audit requirements. The Docker daemon runs as root and controls container lifecycles, making it a critical target for monitoring:

# /etc/audit/rules.d/40-docker.rules

# Monitor Docker daemon configuration
-w /etc/docker/ -p wa -k docker_config
-w /etc/docker/daemon.json -p wa -k docker_config
-w /etc/default/docker -p wa -k docker_config

# Monitor Docker service files
-w /usr/lib/systemd/system/docker.service -p wa -k docker_service
-w /usr/lib/systemd/system/docker.socket -p wa -k docker_service

# Monitor Docker socket access
-w /var/run/docker.sock -p wa -k docker_socket

# Monitor Docker binary
-w /usr/bin/docker -p x -k docker_commands
-w /usr/bin/dockerd -p x -k docker_daemon

# Monitor container runtime
-w /usr/bin/runc -p x -k container_runtime
-w /usr/bin/containerd -p x -k container_runtime
-w /usr/bin/containerd-shim -p x -k container_runtime

# Monitor Docker data directory
-w /var/lib/docker/ -p wa -k docker_data

# Monitor Docker Compose files in common locations
-w /opt/docker/ -p wa -k docker_compose
-w /home/ -p wa -k home_changes

Performance note: Monitoring broad directories like /var/lib/docker/ with write watches can generate significant audit volume on busy Docker hosts. For production, consider monitoring only the configuration directories and using container-level monitoring tools for runtime activity.

SIEM Integration

Audit logs need to be shipped to a centralized log management system for correlation, alerting, and long-term retention. There are several approaches:

Using audisp-remote

# /etc/audisp/plugins.d/au-remote.conf
active = yes
direction = out
path = /sbin/audisp-remote
type = always
format = string

# /etc/audisp/audisp-remote.conf
remote_server = siem.example.com
port = 60
transport = tcp
queue_file = /var/spool/audit/remote.log
mode = immediate

Using Filebeat

# /etc/filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/audit/audit.log
    tags: ["auditd"]
    fields:
      log_type: auditd

  - type: log
    enabled: true
    paths:
      - /var/log/audit/audit.log
    multiline:
      pattern: '^type='
      negate: true
      match: after

output.elasticsearch:
  hosts: ["https://elasticsearch.example.com:9200"]
  index: "auditd-%{+yyyy.MM.dd}"

# Or output to Logstash for processing
output.logstash:
  hosts: ["logstash.example.com:5044"]

Using rsyslog with the audit plugin

# /etc/rsyslog.d/audit.conf
module(load="imfile")

input(type="imfile"
      File="/var/log/audit/audit.log"
      Tag="auditd:"
      Facility="local6"
      Severity="info")

local6.* action(type="omfwd"
               target="siem.example.com"
               port="514"
               protocol="tcp"
               template="RSYSLOG_SyslogProtocol23Format")

Compliance Mappings

Different compliance frameworks require specific audit rules. Here are the key mappings:

Requirement PCI DSS HIPAA CIS Benchmark
Login/logout monitoring 10.2.1 164.312(b) 4.1.3
Failed authentication 10.2.4 164.312(b) 4.1.4
Privilege escalation 10.2.2 164.312(a)(1) 4.1.11
File integrity 10.5, 11.5 164.312(c)(2) 4.1.5
System time changes 10.4 164.312(b) 4.1.3
Log tampering detection 10.5.2 164.312(b) 4.1.18

Practical Alert Scenarios

Set up real-time alerting for high-priority events. Here is a script that watches the audit log and sends alerts:

#!/bin/bash
# audit-alerter.sh - Real-time audit event alerting
ALERT_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

tail -F /var/log/audit/audit.log | while read line; do
  # Alert on unauthorized access attempts
  if echo "$line" | grep -q 'type=AVC.*denied'; then
    MESSAGE="SELinux denial detected: $line"
    curl -s -X POST "$ALERT_WEBHOOK" \
      -H 'Content-type: application/json' \
      -d "{\"text\": \"$MESSAGE\"}"
  fi

  # Alert on new user creation
  if echo "$line" | grep -q 'type=ADD_USER'; then
    MESSAGE="New user created on $(hostname): $line"
    curl -s -X POST "$ALERT_WEBHOOK" \
      -H 'Content-type: application/json' \
      -d "{\"text\": \"$MESSAGE\"}"
  fi

  # Alert on Docker socket access by non-root
  if echo "$line" | grep -q 'key="docker_socket".*success=yes' && \
     echo "$line" | grep -qv 'uid=0'; then
    MESSAGE="Non-root Docker socket access on $(hostname): $line"
    curl -s -X POST "$ALERT_WEBHOOK" \
      -H 'Content-type: application/json' \
      -d "{\"text\": \"$MESSAGE\"}"
  fi
done
Tip: For production environments, use a proper log processing pipeline (Logstash, Fluentd, or Vector) rather than shell scripts. The script above is useful for testing alert logic but does not handle log rotation, error recovery, or high-volume events gracefully.

Performance Tuning

Audit logging has a measurable performance impact, especially with many syscall rules. Here are strategies for keeping the overhead acceptable:

  1. Be specific with rules. Monitoring -S all is catastrophically expensive. Target specific syscalls relevant to your security model.
  2. Use exit filters. Rules with -a always,exit only fire when the syscall completes, which is cheaper than entry-based rules.
  3. Exclude known-safe processes. Use -F exe!=/usr/bin/safe_daemon to exclude trusted high-volume processes from specific rules.
  4. Increase the backlog buffer. Set -b 8192 or higher if you see lost events under load.
  5. Use INCREMENTAL_ASYNC flush. This batches disk writes instead of flushing per-event.
# Set backlog buffer (place at top of rules)
-b 8192

# Exclude high-volume trusted processes from execve monitoring
-a always,exit -F arch=b64 -S execve -F exe!=/usr/lib/monitoring-agent -k exec

# Rate limit events from a noisy subsystem
-a always,exit -F arch=b64 -S open -F dir=/tmp -F success=0 -k tmp_access

The Linux audit system is one of the most powerful tools available for security monitoring and compliance. When properly configured and integrated with a SIEM, it provides a tamper-resistant record of every security-relevant event on your system. The investment in writing good audit rules pays dividends every time you need to investigate an incident or satisfy an auditor.