Overview

3 AM, woken up by an alert. You log into the server and find a critical configuration file has been modified, but last shows no one logged in during that window, and bash_history has nothing. You know something happened, but you don’t know who did it or how.

This is when you need auditd—the audit system built into the Linux kernel. It’s like an airplane’s black box, recording every critical action on the system: who executed what command, which files were accessed, what configurations were changed, and when privilege escalation occurred. And these records are generated at the kernel level, independent of shell history or application logs—even if an attacker deletes ~/.bash_history, they can’t delete auditd’s logs.

This article covers everything from installation and deployment to rule writing, log analysis, and production tuning. It’s not a manual translation—it’s hands-on experience from the trenches.

What Is auditd and How Does It Differ from syslog

Let’s clear up a common confusion first. Many people think “I already have syslog/journald, why do I need auditd?”

These two record fundamentally different things:

Comparisonsyslog/journaldauditd
Recording LevelApplication layerKernel layer
Content RecordedService start/stop, application logs, login recordsSystem calls, file access, privilege changes
GranularityCoarse (per event)Fine (per system call)
Tamper ResistanceNone (root can freely modify)Yes (checksums before writing logs)
Performance ImpactMinimalDepends on rule count and complexity
Typical UseDaily operations loggingSecurity auditing, compliance checks, incident response

To use an analogy: syslog is like the visitor log at a building entrance—records who comes and goes. auditd is like per-apartment door access logs plus indoor cameras—when which door was opened, who opened it, and for how long, precise to the second.

auditd originated from Solaris’s audit subsystem, introduced in Linux kernel 2.6 (2004), developed primarily by Red Hat and IBM. It has since become a mandatory component for security compliance standards like CIS Benchmark, PCI-DSS, and HIPAA.

auditd has become an integral part of security standards like CIS benchmarks, PCI-DSS, and HIPAA. Source: Demystifying Auditd: A Complete Guide for Linux Security Monitoring

auditd Core Component Architecture

auditd is not a single program—it’s a toolchain:

┌─────────────────────────────────────────────────┐
                    Application Layer              
   auditctl (temp rules)  augenrules (perm rules) 
├─────────────────────────────────────────────────┤
                  Audit Daemon                     
                    auditd                         
   (receives kernel audit events, writes to        
    /var/log/audit/audit.log)                     
├─────────────────────────────────────────────────┤
                    Kernel Layer                   
              Linux Audit Subsystem               
   (hooks syscalls, generates audit events,        
    sends to auditd)                              
├─────────────────────────────────────────────────┤
                  Log Analysis Tools               
   ausearch (query)  aureport (reports)           
└─────────────────────────────────────────────────┘
ComponentPurposeUsage
auditdBackground daemon, receives kernel audit events and writes logsCore, always running
auditctlConfigure temporary audit rules (lost on reboot)Testing rules, ad-hoc investigation
augenrulesLoad permanent rules from /etc/audit/rules.d/Production rule management
ausearchQuery audit logs by conditionsDaily queries, incident response
aureportGenerate audit log summary reportsCompliance reports, periodic audits
audispdAudit event dispatcher (forward to external systems)SIEM/ELK integration

Installation and Basic Configuration

Installation

Most mainstream Linux distributions come with auditd pre-installed. If not:

# Ubuntu/Debian
sudo apt update && sudo apt install -y auditd audispd-plugins

# CentOS/RHEL 7
sudo yum install -y audit audit-libs

# CentOS/RHEL 8+/Fedora
sudo dnf install -y audit audit-libs

Start and enable on boot:

sudo systemctl enable --now auditd
sudo systemctl status auditd
# Confirm it shows active (running)

Note: In CentOS 7, auditd is marked as non-restartable (RefuseManualStop=yes), so systemctl restart auditd will fail. Use service auditd restart instead.

auditd.conf Main Configuration File

The main configuration file is at /etc/audit/auditd.conf, controlling log storage and behavior:

# /etc/audit/auditd.conf key parameters

# Log file path
log_file = /var/log/audit/audit.log

# Max single log file size (MB), default 8, production recommends at least 100
max_log_file = 100

# Action when log reaches max size:
# ROTATE  - rotate (keep old logs, create new file)
# KEEP_LOGS - don't overwrite, keep growing (will fill disk)
# IGNORE  - don't record, continue writing current file (may corrupt)
max_log_file_action = ROTATE

# Number of rotated log files to keep
# Total space = num_logs × max_log_file
num_logs = 10

# Trigger warning when disk free space falls below this (percentage or size)
space_left = 20%
space_left_action = SYSLOG

# Critical low space threshold
admin_space_left = 10%
# SUSPEND  - pause logging (default, prevents system crash)
# HALT     - shut down immediately (very high security, prevents log overwriting)
# SINGLE   - switch to single-user mode
admin_space_left_action = SUSPEND

# Data flush frequency to disk
# INCREMENTAL - with freq parameter, balances performance and safety
# DATA         - flush each record immediately (safest but slowest)
# SYNC         - synchronous writes (safest, worst performance)
flush = INCREMENTAL
freq = 50

# Log format: RAW or ENRICHED (enriched resolves UID/syscall names)
log_format = ENRICHED

# Whether to set immutability flag on audit log files
# Once set, even root cannot directly delete log files (must stop auditd first)
# Recommended for high-security environments, but adds operational complexity
# disk_full_action = HALT

These parameters need adjustment based on actual conditions. I’ve seen two common pitfalls: first, keeping max_log_file at the default 8MB, causing audit logs to rotate dozens of times per day, making it impossible to piece together complete event chains during investigation; second, setting admin_space_left_action to HALT, which shuts down the server when disk fills up, waking up ops at 3 AM to power it back on.

Verify Kernel Audit Functionality

# Check audit system status
sudo auditctl -s
# Example output:
# enabled 1
# flag -f 1
# rate_limit 0
# backlog_limit 8192
# lost 0
# backlog 0

# Check kernel audit backlog queue size
cat /proc/sys/kernel/audit_backlog_limit
# Default 64, production recommends at least 8192
# If 0, add audit=1 to /etc/default/grub and update grub

# Permanently set audit backlog queue size
echo "kernel.audit_backlog_limit=8192" | sudo tee -a /etc/sysctl.d/99-audit.conf
sudo sysctl -p /etc/sysctl.d/99-audit.conf

Writing Audit Rules

Rules are the soul of auditd. Without rules, auditd records nothing; with too many rules, CPU and disk suffer. The core principle is minimal necessity—only audit high-risk behaviors, avoid full monitoring.

Rule Storage Location

/etc/audit/audit.rules          # Old format, single file (deprecated)
/etc/audit/rules.d/             # New format, directory (recommended)
  ├── 10-base.rules             # Base rules
  ├── 20-user.rules             # User behavior rules
  ├── 30-services.rules         # Service-related rules
  ├── 40-custom.rules           # Custom rules
  └── 99-finalize.rules         # Finalization rules (lock config, etc.)

After writing rules, load with augenrules:

# Load all rules from /etc/audit/rules.d/
sudo augenrules --load

# Verify rules are loaded
sudo auditctl -l

# Restart auditd to apply configuration
sudo service auditd restart

Filesystem Rules: Monitoring File/Directory Access

Filesystem rules use the -w parameter to monitor access to specified paths:

# Basic syntax
# -w <path>     Path to monitor
# -p <perms>    Permissions to monitor: r=read, w=write, x=execute, a=attribute change
# -k <key>      Keyword tag (for log filtering)

Identity Layer: Monitor User Account Files

# /etc/audit/rules.d/10-identity.rules

# Monitor /etc/passwd write and attribute changes
-w /etc/passwd -p wa -k identity

# Monitor /etc/shadow (password hash file, high sensitivity)
-w /etc/shadow -p wa -k identity

# Monitor /etc/group
-w /etc/group -p wa -k identity

# Monitor /etc/gshadow
-w /etc/gshadow -p wa -k identity

# Monitor login history
-w /var/log/wtmp -p wa -k login_history
-w /var/log/btmp -p wa -k failed_login

Why use -p wa instead of -p rwxa? Because read operations (r) generate massive log volumes—every ls command reading /etc/passwd would trigger a record. What we care about is who modified these files, not who read them. Write (w) and attribute changes (a) are the high-risk behaviors.

Privilege Control Layer: Monitor sudo and Privilege Escalation

# /etc/audit/rules.d/20-privilege.rules

# Monitor sudoers config file modifications
-w /etc/sudoers -p wa -k sudoers_modify
-w /etc/sudoers.d/ -p wa -k sudoers_modify

# Monitor sudo command execution
-w /usr/bin/sudo -p x -k sudo_exec

# Monitor su command execution
-w /bin/su -p x -k su_exec

# Monitor pkexec (PolKit privileged execution)
-w /usr/bin/pkexec -p x -k pkexec_exec

# Monitor permission modification tools
-w /usr/bin/chmod -p x -k perm_change
-w /usr/bin/chown -p x -k perm_change
-w /usr/bin/chgrp -p x -k perm_change

Remote Access Layer: Monitor SSH Configuration

# /etc/audit/rules.d/30-remote.rules

# Monitor SSH service config file
-w /etc/ssh/sshd_config -p wa -k sshd_config

# Monitor authorized_keys file (for root and key users)
-w /root/.ssh/authorized_keys -p wa -k ssh_keys
-w /home/admin/.ssh/authorized_keys -p wa -k ssh_keys

# Monitor PAM configuration
-w /etc/pam.d/ -p wa -k pam_config

Sensitive Files: Monitor Configuration Change Pathways

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

# Monitor network configuration files
-w /etc/hosts -p wa -k network_config
-w /etc/resolv.conf -p wa -k network_config
-w /etc/sysconfig/network -p wa -k network_config

# Monitor environment configuration
-w /etc/profile -p wa -k profile_modify
-w /etc/bashrc -p wa -k bashrc_modify

# Monitor cron jobs (common backdoor vector)
-w /etc/crontab -p wa -k cron_modify
-w /etc/cron.d/ -p wa -k cron_modify
-w /var/spool/cron/ -p wa -k cron_modify

# Monitor systemd service files
-w /etc/systemd/system/ -p wa -k systemd_service
-w /usr/lib/systemd/system/ -p wa -k systemd_service

Syscall Rules: Monitoring Lower-Level Operations

Filesystem rules can only monitor file paths. Syscall rules capture lower-level behaviors:

# Basic syntax
# -a <action>,<filter>   Action and filter
#   action: always (always record) / never (never record)
#   filter: exit (on syscall exit) / entry (on entry) / task (on task creation)
# -F <field=value>        Filter conditions
#   arch: architecture (b64/b32)
#   -S: syscall name (execve/open/chmod etc.)
#   -F uid: user ID
#   -F auid: actual user ID (tracks original user even after privilege escalation)
# -k <key>                Keyword tag

# Monitor all command executions by non-root users
-a always,exit -F arch=b64 -S execve -F auid!=0 -k user_cmd

# Monitor setuid/setgid calls (privilege escalation)
-a always,exit -F arch=b64 -S setuid,setgid,setreuid,setregid -k privilege_change

# Monitor reads of /etc/shadow by non-root
-a always,exit -F arch=b64 -S open -F path=/etc/shadow -F uid!=0 -k shadow_read

# Monitor file deletion operations
-a always,exit -F arch=b64 -S unlink,unlinkat,rmdir -k file_delete

# Monitor network connection establishment
-a always,exit -F arch=b64 -S connect -k network_connect

The distinction between auid and uid is critical: uid is the current user ID (changes to 0 after privilege escalation), while auid is the original user ID at login time. Using auid, you can trace “which real user executed what operation through sudo privilege escalation,” even if the user has switched to root.

Finalization Rules: Tamper-Proof Configuration

# /etc/audit/rules.d/99-finalize.rules

# Set audit rules to immutable (-e 2)
# Once set, any modification to audit rules requires a system reboot
# This prevents attackers from temporarily disabling auditing
# But also increases operational complexity—changing rules requires reboot
-e 2

# Set behavior on audit buffer overflow
# -f 1: only log failures
# -f 2: log failures and trigger panic (kernel crash, only for extreme security)
-f 1

# Set rate limit (max audit events per second)
# 0 means unlimited; production recommends 100-500 to prevent event storms
-r 200

-e 2 is a critical security setting—it puts audit rules into immutable mode. Even if an attacker gains root access, they can’t clear rules with auditctl -D to hide their tracks. The trade-off is that changing rules requires a system reboot. For high-security environments (finance, government), this trade-off is worth it.

Rule Writing Best Practices

PrincipleDescriptionAnti-Pattern
Only audit high-risk behaviorsFocus on writes, executions, privilege escalationMonitoring reads of /var/log, causing log explosion
Every rule must have -k tagEnables easy filtering and queryingNo -k tag, requiring full log scan during investigation
Avoid high-traffic paths/tmp, /proc, /var/log read operations are too frequent-w /tmp -p rwx generates massive log volume
Use -F for precise filteringSpecify specific users, paths to reduce match scopeNo filtering, recording all execve calls
Test before persistingUse auditctl for temporary rules, confirm no issues before writing filesWriting directly to rules.d, causing auditd startup failure from bad rules

Log Analysis in Practice

Rules are configured, logs are being generated. But audit.log’s format is not human-friendly—each record is a line of key=value text with abbreviated field names. Reading it manually is painful.

Audit Log Format Parsing

A typical audit log entry looks like this:

type=SYSCALL msg=audit(1721000000.123:456): arch=c000003e syscall=2 success=yes exit=3 a0=7fff5a3b2c10 a1=0 a2=1b6 a3=0 items=1 ppid=1234 pid=5678 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="cat" exe="/usr/bin/cat" key="shadow_read"

Field meanings:

FieldMeaningExample
typeEvent typeSYSCALL, PATH, USER_LOGIN
msgtimestamp:sequence1721000000.123:456
archArchitecturec000003e (x86_64)
syscallSyscall number2 (open)
successWhether successfulyes/no
auidOriginal user ID1000 (stays 1000 even after privilege escalation)
uidCurrent user ID0 (escalated to root)
commProcess command namecat
exeExecutable file path/usr/bin/cat
keyRule tagshadow_read

ausearch: Conditional Query

ausearch is the most commonly used query tool, supporting filtering by time, keyword, user, etc.:

# Query by keyword (most common)
sudo ausearch -k identity
# Query all audit events with the identity tag

# Query by time range
sudo ausearch -ts today -k sudo_exec
sudo ausearch -ts "07/15/2026" "02:00" -te "07/15/2026" "06:00"
sudo ausearch -ts yesterday -te today

# Query by user
sudo ausearch -ua 1000       # Query all events with auid=1000
sudo ausearch -ui 0          # Query all events with uid=0 (root)

# Query by event type
sudo ausearch -m USER_LOGIN  # Query login events
sudo ausearch -m USER_AUTH   # Query authentication events
sudo ausearch -m SYSCALL     # Query syscall events

# Combined query: commands executed by non-root users today
sudo ausearch -ts today -k user_cmd -m SYSCALL

# Only failed authentications
sudo ausearch -m USER_AUTH -sv no

# Check modifications to a specific file
sudo ausearch -f /etc/passwd

# Output in more readable format (-i resolves UID/syscall names)
sudo ausearch -k identity -i

The -i parameter is important—it resolves numeric UID, GID, and syscall numbers into readable names.

aureport: Summary Reports

aureport generates statistical reports, ideal for periodic audit reporting:

# Generate today's summary report
sudo aureport -ts today

# Summarize command execution count by user
sudo aureport -x --summary -ts today

# Summarize file access count
sudo aureport -f -ts today

# Summarize by event type
sudo aureport -e -ts today

# Summarize failed events
sudo aureport --failed -ts today

# Generate readable login report
sudo aureport -l -i -ts today

Example output:

Summary Report
======================
Range of time in log: 07/15/2026 02:00:00 - 07/15/2026 06:00:00
Number of changes in configuration: 0
Number of changes to user, group, role, or SElinux user: 2
Number of logins: 3
Number of failed logins: 17
Number of authentications: 12
Number of failed authentications: 17
Number of users: 3
Number of terminals: 5
Number of host names: 4
Number of executables: 23
Number of commands: 156
Number of files: 89
Number of AVC's: 0
Number of events: 1245

Incident Response: Tracing Attack Paths

Suppose you discover /etc/passwd has been modified. Here’s how to reconstruct the attack chain with auditd:

# Step 1: Find who modified /etc/passwd
sudo ausearch -k identity -i -ts today
# Find the auid and pid

# Step 2: Check what commands this user executed before the modification
sudo ausearch -ua <auid> -i -ts today | grep execve

# Step 3: Check if this user escalated privileges
sudo ausearch -k privilege_change -ua <auid> -i

# Step 4: Check if a backdoor user was created
sudo ausearch -k user_cmd -m SYSCALL -i -ts today | grep -E "useradd|usermod"

# Step 5: Check if SSH config was modified to inject public keys
sudo ausearch -k sshd_config -i
sudo ausearch -k ssh_keys -i

# Step 6: Check if cron jobs were modified
sudo ausearch -k cron_modify -i

# Step 7: Export complete audit logs for forensics
sudo ausearch --start today --end now -i > /tmp/incident-$(date +%Y%m%d).log

In one incident response, auditd successfully reconstructed the complete attack chain from vulnerability exploitation to privilege escalation—ten times more efficient than reviewing regular system logs. Source: Linux Security Auditing in Practice: auditd Rule Configuration and Log Analysis

Integrating auditd with SIEM Systems

The limitation of single-machine audit logs is that once an attacker gains root, they can attempt to tamper with local logs. Production environments should forward audit logs in real-time to a centralized log platform (SIEM).

Forwarding via audispd to Remote Log Server

audispd (audit dispatcher daemon) is auditd’s event dispatch plugin, capable of forwarding audit events to syslog, remote log servers, or custom programs:

# Install audispd plugins
sudo apt install -y audispd-plugins    # Ubuntu/Debian
sudo yum install -y audispd-plugins     # CentOS/RHEL

# Configure remote forwarding
sudo vi /etc/audisp/audisp-remote.conf

## remote_ending = single
## remote_server = 10.0.1.100        # Remote log server IP
## remote_port = 60                  # Port
## local_port = any
## transport = tcp
## queue_file = /var/spool/audit/remote.log
## mode = forward
## network_retry_time = 1
## initial_tries = 3
## enable_krb5 = no

# Enable remote plugin
sudo vi /etc/audisp/plugins.d/au-remote.conf

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

# Restart auditd
sudo service auditd restart

Integrating with ELK/Loki

A more common approach is to relay through rsyslog to ELK or Loki:

# Configure rsyslog to receive auditd logs
# /etc/rsyslog.d/audit.conf

# Receive logs from auditd (via syslog method)
$ModLoad imfile

$InputFileName /var/log/audit/audit.log
$InputFileTag auditd
$InputFileStateFile audit-state
$InputFileSeverity info
$InputRunFileMonitor

# Forward to remote ELK/Loki
*.* @@10.0.1.100:514    # Forward via TCP to remote syslog server

Using auditbeat for Collection (ELK Ecosystem)

If your log platform is ELK, Elastic’s official auditbeat is more convenient:

# auditbeat.yml
auditd.audit_rules: |
  -w /etc/passwd -p wa -k identity
  -w /etc/shadow -p wa -k identity
  -w /etc/sudoers -p wa -k sudoers_modify
  -a always,exit -F arch=b64 -S execve -F auid!=0 -k user_cmd  

# Output to Elasticsearch
output.elasticsearch:
  hosts: ["es-node:9200"]
  index: "auditd-logs-%{+yyyy.MM.dd}"

# Or output to Logstash
output.logstash:
  hosts: ["logstash:5044"]

Performance Tuning

auditd’s performance impact is real. Poorly written rules can spike CPU from 2% to 30% and double disk I/O.

Performance Impact Testing

Run baseline tests before adding rules:

# Baseline test: record current CPU and disk I/O
mpstat 1 60        # 60 seconds CPU usage
iostat -x 1 60     # 60 seconds disk I/O

# Add test rule
sudo auditctl -a always,exit -F arch=b64 -S open -k test_open

# Test again
mpstat 1 60
iostat -x 1 60

# Remove test rule
sudo auditctl -d always,exit -F arch=b64 -S open -k test_open

Performance Optimization Tips

OptimizationApproachEffect
Reduce syscall rulesPrefer filesystem rules (-w), minimize syscall rules (-a -S)Syscall rules have far greater performance impact than file rules
Avoid high-traffic pathsDon’t monitor reads of /tmp, /proc, /var/logPrevents log explosion and CPU spikes
Use -F for precise filteringSpecify specific users, paths to reduce match scopeReduces kernel-space filtering overhead
Set rate limit-r 200 limits max events per secondPrevents event storms from overwhelming the system
Increase backlog queueaudit_backlog_limit=8192Prevents event loss
Reasonable log rotationmax_log_file=100 + num_logs=10Prevents disk from filling up
Use ENRICHED formatlog_format=ENRICHEDResolves UID/syscall at log generation time, reducing post-processing overhead

Microsoft Defender for Endpoint from version 101.2408.0000 no longer uses auditd as an event provider, switching to eBPF sensors. Main reasons include reducing audit log noise, reducing application rule conflicts, lowering file event monitoring overhead, and improving event throughput with reduced memory usage. This demonstrates that auditd’s performance has real bottlenecks under high load, and eBPF is a direction worth watching. Source: Using eBPF sensors for Microsoft Defender for Endpoint on Linux

auditd’s core limitation is that its syscall hooking approach is relatively “heavy”—each rule must be matched in kernel space, and overhead grows linearly with rule count. eBPF offers a lighter-weight alternative:

ComparisonauditdeBPF
ImplementationKernel audit subsystem hooks syscallsBPF programs attached to kernel hook points
Performance ImpactSignificant (noticeable with many rules)Minimal (JIT compiled, kernel-space execution)
FlexibilityFixed rule syntaxProgrammable, supports complex logic
Ecosystem MaturityMature, widely used for complianceRapidly developing, used in Falco, Tracee
Compliance RecognitionExplicitly required by CIS/PCI-DSS/HIPAANot yet widely recognized by compliance standards

In the short term, auditd remains the standard for compliance auditing. eBPF is better suited for runtime security monitoring (HIDS scenarios). The two are complementary, not replacement.

Compliance Requirements

MLPS 2.0 (China’s Multi-Level Protection Scheme) Audit Requirements

MLPS Level 3 and above requires “logging of network device operations, network traffic, and user behavior in network systems.” For host-level:

MLPS RequirementCorresponding auditd Rules
Record user login and logoutMonitor /var/log/wtmp, /var/log/btmp
Record system administrator operationsMonitor sudo, su execution, record execve syscalls
Record access and modification of important filesMonitor /etc/passwd, /etc/shadow, /etc/sudoers
Record audit logs of security eventsAll rules + -k tag classification
Log retention period no less than 6 monthsConfigure num_logs and max_log_file for sufficient retention
Log integrity protection-e 2 immutable mode + remote forwarding

CIS Benchmark Reference

CIS Red Hat Enterprise Linux 8 Benchmark recommended auditd rules (excerpt):

# CIS 4.1.3 - Ensure auditd service is enabled
systemctl is-enabled auditd

# CIS 4.1.4 - Ensure audit log file permissions are correct
# audit.log permissions should be 600
ls -l /var/log/audit/audit.log

# CIS 4.1.9 - Ensure audit system behavior on insufficient disk space
# Set in /etc/audit/auditd.conf
space_left_action = email
admin_space_left_action = halt

# CIS 4.1.10 - Ensure audit configuration is immutable
auditctl -e 2

# CIS 4.1.11 - Ensure login and logout events are recorded
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins

# CIS 4.1.13 - Ensure session start information is recorded
-w /var/run/utmp -p wa -k session
-w /var/log/wtmp -p wa -k session
-w /var/log/btmp -p wa -k session

# CIS 4.1.14 - Ensure permission modification events are recorded
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=-1 -F key=perm_mod
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=-1 -F key=perm_mod

# CIS 4.1.15 - Ensure unauthorized access events are recorded
-a always,exit -F arch=b64 -S open,openat,creat,truncate,ftruncate -F auid>=1000 -F auid!=-1 -F exit=-EACCES -F key=access
-a always,exit -F arch=b64 -S open,openat,creat,truncate,ftruncate -F auid>=1000 -F auid!=-1 -F exit=-EPERM -F key=access

Refer to the complete CIS Benchmark rule set—auditd is a mandatory component for CIS, PCI-DSS, HIPAA, and other security compliance standards. Source: Linux Audit System Configuration Introduction

Automation Scripts

Batch Deploy auditd Rules to Multiple Servers

#!/bin/bash
# deploy-auditd-rules.sh
# Batch deploy auditd rules across multiple servers

SERVERS=("web01.prod" "web02.prod" "db01.prod" "cache01.prod")
RULES_DIR="./audit-rules"

for server in "${SERVERS[@]}"; do
    echo ">>> Deploying auditd rules to $server"
    
    # Create rules directory
    ssh "$server" "sudo mkdir -p /etc/audit/rules.d"
    
    # Transfer rule files
    scp -r "$RULES_DIR"/* "$server:/tmp/audit-rules/"
    
    # Install auditd (if not installed)
    ssh "$server" "sudo apt install -y auditd audispd-plugins 2>/dev/null || sudo yum install -y audit audit-libs"
    
    # Backup existing rules
    ssh "$server" "sudo cp -r /etc/audit/rules.d /etc/audit/rules.d.bak.$(date +%Y%m%d)"
    
    # Deploy new rules
    ssh "$server" "sudo cp /tmp/audit-rules/*.rules /etc/audit/rules.d/"
    
    # Load rules
    ssh "$server" "sudo augenrules --load && sudo service auditd restart"
    
    # Verify rules
    echo ">>> Rules loaded on $server:"
    ssh "$server" "sudo auditctl -l"
    
    echo ">>> Done: $server"
done

echo ">>> All servers deployed."

Audit Log Periodic Cleanup Script

#!/bin/bash
# audit-log-cleanup.sh
# Periodically clean old audit logs to free disk space

# Keep logs from the last 180 days (compliance requirement)
RETENTION_DAYS=180
AUDIT_LOG_DIR="/var/log/audit"

# Clean old rotated log files
find "$AUDIT_LOG_DIR" -name "audit.log.*" -mtime +$RETENTION_DAYS -delete

# Compress logs older than 30 days
find "$AUDIT_LOG_DIR" -name "audit.log.*" -mtime +30 ! -name "*.gz" -exec gzip {} \;

# Output current disk usage
echo "=== Audit log disk usage ==="
du -sh "$AUDIT_LOG_DIR"
ls -lh "$AUDIT_LOG_DIR" | head -20
echo "=== Total files: $(find $AUDIT_LOG_DIR -type f | wc -l) ==="

Audit Anomaly Detection Script

#!/bin/bash
# audit-anomaly-check.sh
# Periodically check audit logs for anomalous behavior

REPORT_FILE="/var/log/audit-anomaly-$(date +%Y%m%d).log"

echo "=== Audit Anomaly Report - $(date) ===" > "$REPORT_FILE"

# Check 1: After-hours (22:00-06:00) sudo executions
echo "--- After-hours sudo executions ---" >> "$REPORT_FILE"
sudo ausearch -k sudo_exec -ts today | \
  awk -F"audit\(" '{print $2}' | \
  awk -F":" '{print $1}' | \
  while read ts; do
    hour=$(date -d @${ts%.*} +%H 2>/dev/null)
    if [ "$hour" -ge "22" ] || [ "$hour" -lt "06" ]; then
      echo "  Suspicious: sudo at $hour:00 (timestamp: $ts)"
    fi
  done >> "$REPORT_FILE" 2>/dev/null

# Check 2: Failed authentication count exceeding threshold
echo "--- Failed authentications (>5 times) ---" >> "$REPORT_FILE"
sudo ausearch -m USER_AUTH -sv no -ts today -i 2>/dev/null | \
  grep "uid=" | \
  awk -F'uid="' '{print $2}' | \
  awk -F'"' '{print $1}' | \
  sort | uniq -c | sort -rn | \
  awk '$1 > 5 {print "  User "$2": "$1" failed attempts"}' >> "$REPORT_FILE"

# Check 3: New user creation
echo "--- New user creation ---" >> "$REPORT_FILE"
sudo ausearch -k identity -ts today -i 2>/dev/null | \
  grep -E "useradd|adduser" >> "$REPORT_FILE"

# Check 4: SSH configuration file modifications
echo "--- SSH config changes ---" >> "$REPORT_FILE"
sudo ausearch -k sshd_config -ts today -i >> "$REPORT_FILE"

# Check 5: Cron job modifications (possible backdoor)
echo "--- Cron modifications ---" >> "$REPORT_FILE"
sudo ausearch -k cron_modify -ts today -i >> "$REPORT_FILE"

# Check 6: Whether audit rules were cleared (attacker may try to disable auditing)
echo "--- Audit rule count check ---" >> "$REPORT_FILE"
RULE_COUNT=$(sudo auditctl -l 2>/dev/null | wc -l)
if [ "$RULE_COUNT" -lt 5 ]; then
  echo "  WARNING: Only $RULE_COUNT audit rules active! Possible tampering." >> "$REPORT_FILE"
else
  echo "  OK: $RULE_COUNT audit rules active." >> "$REPORT_FILE"
fi

echo "" >> "$REPORT_FILE"
echo "=== End of report ===" >> "$REPORT_FILE"

cat "$REPORT_FILE"

Add this script to crontab for daily execution:

# Check yesterday's audit anomalies every day at 8 AM
0 8 * * * /usr/local/bin/audit-anomaly-check.sh

Summary

auditd is the infrastructure for Linux system auditing. It costs nothing and comes pre-installed, but using it well requires effort. Key takeaways from practice:

  1. Audit first, lock later. In the first phase, configure rules and run for a week to check if log volume is reasonable and if there are false positives. Once confirmed, add -e 2 to lock. If you lock immediately and something goes wrong, you can’t change rules without a reboot—shooting yourself in the foot.
  2. Filesystem rules over syscall rules. -w has far less performance impact than -a -S. Use file rules whenever a scenario can be covered by them.
  3. Logs must be forwarded. Local logs become untrustworthy once an attacker gains root. At minimum, configure audispd to forward to a remote syslog server, or use auditbeat to send to ELK. Ideally, logs should be append-only and stored on a separate server.
  4. Audit regularly, not just when something happens. Run that anomaly detection script and review the report weekly. If you wait until an incident to check logs, they may have already been rotated and overwritten.
  5. -k tags are your best friend. Every rule should have a -k tag. During investigation, ausearch -k xxx filters relevant events in one command. Rules without tags have no classification, making investigation much less efficient.
  6. Watch the eBPF trend. auditd has clear performance bottlenecks under high load. Falco, Tracee, and other eBPF security tools are maturing rapidly and may become a complement or even replacement for auditd in the future. But for now, compliance auditing still relies on auditd.

One final point: security auditing isn’t “install a tool and forget.” It’s a continuous process—regularly check whether rules cover newly emerging attack techniques, regularly review anomalous patterns in logs, and regularly update anomaly detection script rules. An audit system that’s been running for a year is more valuable than one just deployed, because you already know what’s normal and what warrants vigilance.

References & Acknowledgments

The following resources were referenced during the writing of this article. We thank the original authors for their contributions:

  1. Linux auditd Command — Runoob, auditd core component introduction and basic command usage
  2. Demystifying Auditd: A Complete Guide for Linux Security Monitoring — CSDN, complete auditd guide covering security compliance standards and best practices
  3. Linux Security Auditing in Practice: auditd Rule Configuration and Log Analysis — CSDN, auditd rule configuration and incident response cases
  4. Linux Audit System Configuration Introduction — CSDN, auditd configuration parameter details and CIS Benchmark rule references
  5. Linux User Behavior Audit System: auditd Configuration and Operations Practice — php.cn, user behavior audit layered monitoring strategy and rule configuration
  6. Linux Security Auditing in Practice: auditd Rule Templates and Log Analysis — CSDN, scenario-based auditd rule templates and monitoring strategies
  7. Linux Audit in Practice: From Rule Configuration to Log Analysis, Comparing syslog and Security Monitoring — CSDN, auditd vs syslog comparison and SIEM integration
  8. Using eBPF Sensors for Microsoft Defender for Endpoint on Linux — Microsoft Learn, eBPF replacing auditd performance advantages analysis
  9. Linux Security Auditing Tutorial: auditd Log Monitoring and Anomaly Detection — Jianshu, auditd anomaly detection and ELK integration practices