Linux auditd: Complete Guide to Kernel Audit Logging, Rules, and SIEM Integration
π― Key Takeaways
- Table of Contents
- Why Kernel Auditing Matters
- Installing and Starting auditd
- How the Linux Audit System Works
- Writing Audit Rules with auditctl
π Table of Contents
- Table of Contents
- Why Kernel Auditing Matters
- Installing and Starting auditd
- How the Linux Audit System Works
- Writing Audit Rules with auditctl
- Persistent Rules: audit.rules and auditd.conf
- CIS Benchmark Audit Rules
- Searching Audit Logs with ausearch
- Generating Reports with aureport
- Monitoring Critical Files and Directories
- Auditing System Calls
- Tracking User Logins and Privilege Escalation
- Forwarding Audit Events to a SIEM
- Performance Tuning
- Troubleshooting
- Conclusion
Linux’s audit subsystem β managed by auditd β gives you a tamper-evident, kernel-level record of every file access, system call, user login, privilege escalation, and configuration change on your server. Unlike application-level logging, audit records are generated by the kernel before any process can suppress or alter them. This guide covers installing and configuring auditd, writing effective audit rules, querying logs with ausearch and aureport, and integrating audit events with centralized log management.
π Table of Contents
- Table of Contents
- Why Kernel Auditing Matters
- Installing and Starting auditd
- How the Linux Audit System Works
- Writing Audit Rules with auditctl
- Rule Syntax
- Understanding audit UIDs (auid)
- Persistent Rules: audit.rules and auditd.conf
- Key auditd.conf Settings
- CIS Benchmark Audit Rules
- Searching Audit Logs with ausearch
- Generating Reports with aureport
- Monitoring Critical Files and Directories
- Auditing System Calls
- Tracking User Logins and Privilege Escalation
- Forwarding Audit Events to a SIEM
- Forward to syslog (via audisp-syslog plugin)
- Forward to a Remote auditd Server (audisp-remote)
- Forward with Filebeat/Elastic Agent
- Performance Tuning
- Troubleshooting
- Conclusion
Table of Contents
- Why Kernel Auditing Matters
- Installing and Starting auditd
- How the Linux Audit System Works
- Writing Audit Rules with auditctl
- Persistent Rules: audit.rules and auditd.conf
- CIS Benchmark Audit Rules
- Searching Audit Logs with ausearch
- Generating Reports with aureport
- Monitoring Critical Files and Directories
- Auditing System Calls
- Tracking User Logins and Privilege Escalation
- Forwarding Audit Events to a SIEM
- Performance Tuning
- Troubleshooting
Why Kernel Auditing Matters
Standard logging (syslog, journald) captures what applications choose to record. Auditd captures what actually happened at the kernel syscall level β including by root, by setuid binaries, and by attackers who have disabled application logging. Compliance frameworks including PCI-DSS, HIPAA, SOC 2, and CIS Linux Benchmarks all require kernel audit logging. Auditd provides the raw material for:
- Incident response: reconstruct exactly what files were accessed or modified during a breach
- Privilege tracking: every
sudo,su, andsetuidexecution recorded - Change detection: unauthorized edits to
/etc/passwd, SSH keys, cron jobs, and sudoers - Compliance evidence: exportable records satisfying audit requirements
Installing and Starting auditd
# RHEL / Rocky Linux / AlmaLinux / Fedora
dnf install -y audit audit-libs
# Ubuntu / Debian
apt install -y auditd audispd-plugins
# Enable and start the service
systemctl enable --now auditd
# Verify it is running and collecting events
systemctl status auditd
auditctl -s # Show kernel audit status (enabled, backlog, etc.)
On RHEL-family systems, auditd is typically installed by default. Check its status before installing to avoid reinstallation.
How the Linux Audit System Works
The audit subsystem has three layers:
- Kernel audit module: intercepts system calls, file accesses, and user-space events. Rules loaded here determine what generates a record.
- auditd daemon: reads events from the kernel netlink socket and writes them to
/var/log/audit/audit.log. It is the only process allowed to consume this socket. - audisp (audit dispatcher): a plugin subsystem that can forward audit events in real time to syslog, remote systems, or custom processors.
Key configuration files:
/etc/audit/auditd.confβ daemon behavior (log size, rotation, what to do when disk is full)/etc/audit/rules.d/*.rulesβ persistent rule files loaded at boot/var/log/audit/audit.logβ the audit event log
Writing Audit Rules with auditctl
Rules loaded with auditctl are active immediately but lost on reboot. Use them to test rules before making them persistent.
Rule Syntax
# -w: watch a file or directory
# -p: permissions to monitor (r=read, w=write, x=execute, a=attribute change)
# -k: tag for searching (key)
# Watch /etc/passwd for any writes or attribute changes
auditctl -w /etc/passwd -p wa -k identity
# Watch the entire /etc directory recursively (expensive β see performance section)
auditctl -w /etc -p wa -k etc-changes
# -a: append a syscall rule
# -S: system call name or number
# -F: filter field (auid=audit UID, uid=process UID, etc.)
# -k: key tag
# Audit all commands run by root (uid=0)
auditctl -a always,exit -F arch=b64 -S execve -F uid=0 -k root-commands
# Audit failed file access attempts (permission denied events)
auditctl -a always,exit -F arch=b64 -S open,openat -F exit=-EACCES -k access-denied
auditctl -a always,exit -F arch=b64 -S open,openat -F exit=-EPERM -k access-denied
# List active rules
auditctl -l
# Delete all active rules
auditctl -D
Understanding audit UIDs (auid)
# auid is the "login UID" β the original user who authenticated, preserved across su/sudo
# This is more reliable than uid (which changes with privilege escalation)
# Audit all sudo activity by non-root users
auditctl -a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=-1 -k user-commands
# auid=-1 (or 4294967295) means the process has no login session (system daemons)
# Exclude these from user tracking to reduce noise
Persistent Rules: audit.rules and auditd.conf
# Persistent rules go in /etc/audit/rules.d/
# Files are processed in alphabetical order
# Convention: 10-base.rules, 20-file-watches.rules, 99-finalize.rules
# Create a base rules file
cat > /etc/audit/rules.d/10-base.rules << 'RULES'
## Remove all existing rules
-D
## Set buffer size (increase if you see backlog errors)
-b 8192
## Set failure mode: 0=silent, 1=printk, 2=panic
## Mode 1 (printk) logs to kernel ring buffer if auditd dies
-f 1
## Ignore auditd itself to prevent log flooding
-a never,exclude -F msgtype=CWD
RULES
# Make the ruleset immutable until reboot (optional β prevents runtime rule changes)
# Add this as the LAST rule:
echo "-e 2" >> /etc/audit/rules.d/99-finalize.rules
# Apply all rules from /etc/audit/rules.d/ without rebooting
augenrules --load
# Or reload manually
service auditd reload # RHEL/Rocky (systemctl reload does NOT reload rules)
# Ubuntu:
auditctl -R /etc/audit/audit.rules
Key auditd.conf Settings
# /etc/audit/auditd.conf β important production settings
# Log file location and rotation
log_file = /var/log/audit/audit.log
max_log_file = 100 # Max size in MB per log file
num_logs = 10 # Number of rotated logs to keep
max_log_file_action = ROTATE
# What to do when disk space runs out
space_left = 500 # MB: trigger action when less than 500MB free
space_left_action = EMAIL # Options: IGNORE, SYSLOG, EMAIL, EXEC, SUSPEND, SINGLE, HALT
action_mail_acct = root
admin_space_left = 100 # MB: final warning threshold
admin_space_left_action = SUSPEND # Stop writing to allow manual intervention
disk_full_action = SUSPEND
disk_error_action = SUSPEND
# For high-security (compliance) environments, use HALT instead of SUSPEND
# HALT causes an emergency shutdown if disk is full β prevents unlogged events
CIS Benchmark Audit Rules
The CIS Linux Benchmark specifies a comprehensive set of audit rules for compliance. Below is the core set covering the most critical events.
cat > /etc/audit/rules.d/50-cis.rules << 'RULES'
## CIS Linux Benchmark Audit Rules
## Time changes
-a always,exit -F arch=b64 -S adjtimex,settimeofday -k time-change
-a always,exit -F arch=b32 -S adjtimex,settimeofday -k time-change
-a always,exit -F arch=b64 -S clock_settime -k time-change
-w /etc/localtime -p wa -k time-change
## User and group modifications
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity
## Network environment modifications
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale
-w /etc/issue -p wa -k system-locale
-w /etc/issue.net -p wa -k system-locale
-w /etc/hosts -p wa -k system-locale
-w /etc/networks -p wa -k system-locale
-w /etc/sysconfig/network -p wa -k system-locale
## Login and logout events
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins
-w /var/log/tallylog -p wa -k logins
## Session initiation
-w /var/run/utmp -p wa -k session
-w /var/log/wtmp -p wa -k logins
-w /var/log/btmp -p wa -k logins
## Discretionary access control (DAC) permission changes
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=-1 -k perm-mod
-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>=1000 -F auid!=-1 -k perm-mod
-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr \
-F auid>=1000 -F auid!=-1 -k perm-mod
## Unsuccessful file access attempts
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate \
-F exit=-EACCES -F auid>=1000 -F auid!=-1 -k access
-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate \
-F exit=-EPERM -F auid>=1000 -F auid!=-1 -k access
## Mount operations
-a always,exit -F arch=b64 -S mount -F auid>=1000 -F auid!=-1 -k mounts
## File deletions
-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat \
-F auid>=1000 -F auid!=-1 -k delete
## Privileged command execution (setuid/setgid binaries)
-a always,exit -F path=/usr/bin/passwd -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/chsh -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
-a always,exit -F path=/usr/bin/newgrp -F perm=x -F auid>=1000 -F auid!=-1 -k privileged
## Sudo log
-w /var/log/sudo.log -p wa -k actions
## Kernel module loading
-w /sbin/insmod -p x -k modules
-w /sbin/rmmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module,delete_module -k modules
## Sudoers modifications
-w /etc/sudoers -p wa -k scope
-w /etc/sudoers.d/ -p wa -k scope
## SSH configuration
-w /etc/ssh/sshd_config -p wa -k sshd
## systemd
-w /usr/lib/systemd/ -p wa -k systemd
-w /etc/systemd/ -p wa -k systemd
RULES
augenrules --load
Searching Audit Logs with ausearch
# Search by key tag
ausearch -k identity # All identity-related events
ausearch -k privileged # All privileged command executions
# Search by time range
ausearch -k logins --start today
ausearch -k logins --start "03/01/2026 00:00:00" --end "03/31/2026 23:59:59"
# Search by user
ausearch -ua alice # Events for user 'alice'
ausearch -auid 1001 # Events by audit UID 1001
# Search by event type
ausearch -m USER_LOGIN # Login events
ausearch -m USER_AUTH # Authentication events
ausearch -m USER_CMD # Commands run via sudo
ausearch -m SYSCALL # System call events
ausearch -m AVC # SELinux denials
# Search for failed events
ausearch --success no -k access
# Raw output for piping to other tools
ausearch -k identity -i # -i = interpret UIDs/GIDs to names
ausearch -k privileged --format text # Human-readable text output
ausearch -k modules --format csv # CSV for spreadsheet import
# Combine search terms
ausearch -k perm-mod -ua root --start yesterday -i
Generating Reports with aureport
# Summary report of all audit activity
aureport
# Login report β who logged in and from where
aureport --login -i
# Authentication failures
aureport --auth --failed -i
# Failed file access attempts
aureport --file --failed -i
# Executable/command report
aureport --exe -i
# System call report
aureport --syscall -i
# Anomaly report (unusual events)
aureport --anomaly
# Report for a specific time range
aureport --start "04/01/2026 00:00:00" --end "04/30/2026 23:59:59" --login -i
# Summary of events by type (useful for dashboards)
aureport --summary
# Events by user
aureport --user -i
Monitoring Critical Files and Directories
# High-value file watches for security monitoring
cat > /etc/audit/rules.d/30-file-watches.rules << 'RULES'
## SSH authorized keys β flag any changes
-w /root/.ssh/ -p wa -k ssh-keys
-w /home/ -p wa -k ssh-keys
## Cron jobs β persistence mechanism
-w /etc/cron.allow -p wa -k cron
-w /etc/cron.deny -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
-w /etc/cron.daily/ -p wa -k cron
-w /etc/cron.hourly/ -p wa -k cron
-w /etc/cron.weekly/ -p wa -k cron
-w /var/spool/cron/ -p wa -k cron
## Package management (detect unauthorized software installs)
-w /usr/bin/apt -p x -k package-management
-w /usr/bin/apt-get -p x -k package-management
-w /usr/bin/dpkg -p x -k package-management
-w /usr/bin/dnf -p x -k package-management
-w /usr/bin/rpm -p x -k package-management
-w /usr/bin/yum -p x -k package-management
## Startup scripts
-w /etc/init.d/ -p wa -k init
-w /etc/rc.d/ -p wa -k init
-w /etc/rc.local -p wa -k init
## PAM configuration (authentication changes)
-w /etc/pam.d/ -p wa -k pam
-w /etc/security/ -p wa -k pam
## ld.so (library loading β LD_PRELOAD attacks)
-w /etc/ld.so.conf -p wa -k libpath
-w /etc/ld.so.conf.d/ -p wa -k libpath
RULES
augenrules --load
Auditing System Calls
# Monitor process execution (all commands run on the system)
# This is high volume β filter by auid to limit noise
auditctl -a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=-1 -k user-exec
# Monitor network connections (detect beaconing, lateral movement)
auditctl -a always,exit -F arch=b64 -S connect -k network-connect
auditctl -a always,exit -F arch=b64 -S accept -k network-accept
# Monitor socket creation
auditctl -a always,exit -F arch=b64 -S socket -k socket-create
# ptrace (process injection β used by debuggers and some rootkits)
auditctl -a always,exit -F arch=b64 -S ptrace -k ptrace
# Monitor ioctl on block devices (disk wiping detection)
auditctl -a always,exit -F arch=b64 -S ioctl -F a1=BLKDISCARD -k disk-discard
# Check what architecture your kernel uses
uname -m
# x86_64 β use arch=b64 for 64-bit calls, also add -F arch=b32 for 32-bit compat layer
Tracking User Logins and Privilege Escalation
# View recent login events from audit log
ausearch -m USER_LOGIN -i --start today
# View sudo usage
ausearch -m USER_CMD -i --start today
# View su usage
ausearch -m USER_AUTH -i | grep su
# View all authentication failures today
ausearch -m USER_AUTH --success no -i --start today
# Correlate user activity: find everything alice did in the last hour
ausearch -ua alice --start "1 hour ago" -i
# Find who modified /etc/sudoers
ausearch -k scope -i | grep "type=PATH" | grep sudoers
# Find all commands run as root via sudo
ausearch -m USER_CMD -i | grep "terminal=sudo"
# Generate a full login history report
aureport --login --start "04/01/2026" -i
Forwarding Audit Events to a SIEM
Forward to syslog (via audisp-syslog plugin)
# On RHEL/Rocky β enable the syslog forwarding plugin
cat > /etc/audisp/plugins.d/syslog.conf << 'CONF'
active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_INFO LOG_LOCAL6
format = string
CONF
service auditd restart
# Audit events now appear in syslog as LOCAL6.INFO
# Configure rsyslog or syslog-ng to forward LOCAL6 to your SIEM
Forward to a Remote auditd Server (audisp-remote)
# Install audisp-remote plugin
dnf install -y audispd-plugins # RHEL/Rocky
apt install -y audispd-plugins # Ubuntu
# Configure the remote plugin
cat > /etc/audisp/audisp-remote.conf << 'CONF'
remote_server = siem.example.com
port = 60
transport = tcp
mode = immediate
queue_depth = 2048
fail_action = SYSLOG
network_failure_action = SYSLOG
CONF
# Enable the plugin
sed -i 's/^active = no/active = yes/' /etc/audisp/plugins.d/au-remote.conf
service auditd restart
Forward with Filebeat/Elastic Agent
# Configure Filebeat to ship /var/log/audit/audit.log to Elasticsearch
cat > /etc/filebeat/inputs.d/audit.yml << 'CONF'
- type: log
enabled: true
paths:
- /var/log/audit/audit.log
tags: ["auditd"]
processors:
- decode_json_fields:
fields: ["message"]
target: "auditd"
CONF
# The Elastic Auditbeat module provides richer parsing of native audit records
# Auditbeat reads directly from the kernel netlink socket β no file parsing delay
Performance Tuning
# Check for audit backlog (lost events due to buffer overflow)
auditctl -s | grep backlog
# If backlog > 0, increase -b value in rules
# Increase buffer size in /etc/audit/rules.d/10-base.rules
# Change: -b 8192
# To: -b 16384
# Check for dropped events
cat /proc/audit_stats # Or: ausearch -m DAEMON_ROTATE
# Exclude high-volume, low-value events to reduce log noise
cat > /etc/audit/rules.d/05-exclude.rules << 'RULES'
## Exclude cron noise
-a never,user -F subj_type=crond_t
## Exclude kernel thread events
-a never,exit -F arch=b64 -F auid=-1 -F uid=0 \
-S execve -F path=/usr/lib/systemd/systemd
## Exclude specific high-frequency commands (tune for your environment)
-a never,exit -F arch=b64 -S open -F path=/proc/self/status
RULES
# Wide directory watches (/home, /etc recursively) generate many events
# Be selective: watch specific high-value files rather than entire trees
# Example: Instead of -w /etc -p wa, watch specific config files
# Measure audit log growth rate
watch -n 30 'ls -lh /var/log/audit/audit.log'
Troubleshooting
# auditd not starting
journalctl -u auditd --no-pager
# Common cause: immutable ruleset (-e 2) requires reboot to change rules
# Rules not loading after reboot
augenrules --check # Verify rule syntax without loading
augenrules --load # Manually load rules from /etc/audit/rules.d/
# On RHEL/Rocky, reload rules without restart:
service auditd reload # NOT systemctl reload (systemctl skips rule reloading)
# Rule conflicts β duplicate or contradictory rules
auditctl -l | sort | uniq -d # Find duplicate rules
# Check if a file watch is active
auditctl -l | grep passwd
# Test that a watch fires correctly
touch /etc/passwd # Should generate an event with key=identity
ausearch -k identity --start recent -i
# SELinux denials blocking auditd
ausearch -m AVC | grep auditd
# If present, use audit2allow to generate a policy module
# Disk filling from audit logs
# Immediate: rotate logs manually
pkill -HUP auditd # Signals auditd to rotate log now
# Long-term: reduce rule verbosity or increase max_log_file/num_logs in auditd.conf
Conclusion
Auditd is the most reliable source of truth about what happened on a Linux system β it operates below the application layer, records events before any process can suppress them, and maintains chain of custody for compliance purposes. The key to a useful audit configuration is selectivity: broad rules like watching all of /proc or logging every open syscall generate hundreds of thousands of events per day and make meaningful analysis impossible. Start with the CIS Benchmark rule set, tune out noise from known-good processes, and direct your rules toward the events that matter β file writes to authentication configuration, privilege escalation, kernel module loading, and unauthorized file access. Combined with ausearch for targeted investigation and aureport for compliance reporting, auditd gives sysadmins a complete, tamper-resistant view of system activity.
Was this article helpful?
About Ramesh Sundararamaiah
Red Hat Certified Architect
Expert in Linux system administration, DevOps automation, and cloud infrastructure. Specializing in Red Hat Enterprise Linux, CentOS, Ubuntu, Docker, Ansible, and enterprise IT solutions.