$linuxjunkies
>

Hands-on Linux Auditing with auditd

Learn to configure auditd rules, watch critical files and syscalls, and extract actionable security intelligence with ausearch and aureport on modern Linux.

AdvancedUbuntuDebianFedoraArch12 min readUpdated June 7, 2026

Before you start

  • Root or sudo access on the target system
  • Basic familiarity with systemd service management
  • Understanding of Linux file permissions and UIDs
  • A 64-bit Linux kernel (rules shown target x86-64)

The Linux Audit Framework, centred on auditd, gives you a tamper-evident, kernel-level record of who did what and when — before any userspace logging daemon even gets involved. It is the backbone of CIS, STIG, and PCI-DSS compliance on Linux, and once you understand how rules, events, and reports fit together it becomes an indispensable forensic tool. This guide covers practical usage: writing rules, watching files and syscalls, querying the log, and generating summary reports.

Install and Start auditd

Most enterprise distros ship auditd in the base install. If it is missing, install it:

# Debian / Ubuntu
sudo apt install auditd audispd-plugins

# Fedora / RHEL / Rocky
sudo dnf install audit audit-libs

# Arch
sudo pacman -S audit

Enable and start the service with systemd:

sudo systemctl enable --now auditd

Verify it is running and confirm the kernel module is active:

sudo systemctl status auditd
auditctl -s

auditctl -s prints the audit status block. Look for enabled 1 and pid pointing to the auditd process. Output will vary but a healthy system shows enabled 1.

Understanding the Rule Pipeline

Rules flow from three places, in priority order:

  • /etc/audit/audit.rules — compiled by augenrules or loaded directly; do not edit by hand.
  • /etc/audit/rules.d/*.rules — drop-in files merged at startup. This is where you write persistent rules.
  • auditctl -a/-w — runtime-only rules, lost on reboot. Useful for testing.

After editing any file under rules.d/, regenerate and reload:

sudo augenrules --load

Writing File-Watch Rules

File watches use the -w flag and are the easiest starting point. The -p flag sets the permission filter: read, write, execute, attribute-change. The -k flag attaches a searchable key.

Watch critical system files

Create /etc/audit/rules.d/40-watches.rules:

sudo tee /etc/audit/rules.d/40-watches.rules <<'EOF'
# Passwd and shadow changes
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group  -p wa -k identity
-w /etc/gshadow -p wa -k identity

# sudoers modifications
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# SSH server config
-w /etc/ssh/sshd_config -p wa -k sshd_config

# Audit config self-protection
-w /etc/audit/ -p wa -k audit_rules
-w /etc/audit/rules.d/ -p wa -k audit_rules
EOF
sudo augenrules --load
auditctl -l   # confirm rules are loaded

Writing Syscall Rules

Syscall rules are more powerful and more expensive. Use them for detecting privilege escalation, file deletion, and network socket creation by specific users or binaries.

Detect privilege escalation attempts

Watch for successful setuid/setgid calls by non-root users:

sudo tee /etc/audit/rules.d/50-privilege-escalation.rules <<'EOF'
# execve by any process that gained elevated privs
-a always,exit -F arch=b64 -S execve -C uid!=euid -F euid=0 -k setuid_exec
-a always,exit -F arch=b32 -S execve -C uid!=euid -F euid=0 -k setuid_exec
EOF

Detect file deletion

sudo tee /etc/audit/rules.d/55-delete.rules <<'EOF'
-a always,exit -F arch=b64 -S unlinkat,rename,renameat -F auid>=1000 -F auid!=4294967295 -k file_deletion
-a always,exit -F arch=b32 -S unlinkat,rename,renameat -F auid>=1000 -F auid!=4294967295 -k file_deletion
EOF

The magic value 4294967295 (-1 as unsigned 32-bit) means the kernel could not determine an audit UID — it filters out kernel threads and processes that ran before auditd started.

Watch outbound socket connections

sudo tee /etc/audit/rules.d/60-network.rules <<'EOF'
-a always,exit -F arch=b64 -S connect -F auid>=1000 -F auid!=4294967295 -k user_connect
EOF

Lock the ruleset

Place this as the last line in a file like 99-finalize.rules. It makes the ruleset immutable until reboot — even root cannot change it.

echo '-e 2' | sudo tee /etc/audit/rules.d/99-finalize.rules

Warning: With -e 2 active, augenrules --load will fail until reboot. Only add this line when your ruleset is stable.

sudo augenrules --load

Querying Events with ausearch

ausearch reads /var/log/audit/audit.log (and rotated logs) and outputs structured event records. Use -i to interpret UIDs and syscall names into human-readable strings.

Search by key

sudo ausearch -k identity -i

Search by user

sudo ausearch -ua 1001 -i   # by audit UID
sudo ausearch -ui bob -i    # by username (resolves via NSS)

Filter by time window

sudo ausearch -k sudoers -ts today -i
sudo ausearch -k file_deletion -ts '2024-05-01 08:00:00' -te '2024-05-01 18:00:00' -i

Filter by return code (failed events)

sudo ausearch -k user_connect -sv no -i   # only failed connects

Pipe to aureport for quick summaries

sudo ausearch -k setuid_exec -i | aureport -f -i --summary

Generating Reports with aureport

aureport produces tabular summaries directly from the audit log. No pipe required for the common reports.

Overall system summary

sudo aureport --summary

Authentication events

sudo aureport -au -i          # all auth attempts
sudo aureport -au --failed -i # only failures — spot brute-force fast

Executable and syscall reports

sudo aureport -x --summary -i   # top executed binaries
sudo aureport -s --summary -i   # top syscalls recorded

Key-tagged rule hits

sudo aureport -k --summary -i

Anomaly events

sudo aureport --anomaly -i

Verifying the Setup

Trigger a known event and confirm it is recorded end-to-end:

# Touch a watched file as a normal user
sudo -u nobody touch /etc/passwd 2>/dev/null || true

# Now look for it
sudo ausearch -k identity -ts recent -i

You should see an SYSCALL record with comm="touch", the UID of the calling process, and the identity key. If the record is absent, check auditctl -l to confirm the watch is loaded and journalctl -u auditd for errors.

Troubleshooting

  • No events recorded after rule load: Run auditctl -l — if the list is empty, augenrules --load may have encountered a syntax error. Check journalctl -u auditd -n 50.
  • High CPU / disk I/O: Syscall rules on common calls (read, write) without tight filters will flood the log. Always scope with -F auid>=1000 or a specific -F exe= path.
  • Arch mismatch — rules silently ignored: On 64-bit systems always add both arch=b64 and arch=b32 rule pairs; 32-bit binaries running under a 64-bit kernel use different syscall numbers.
  • augenrules exits non-zero after adding -e 2: Expected. The kernel rejected the reload because the ruleset is locked. Rules from before the lock are still active. Reboot to apply changes to a locked ruleset.
  • ausearch returns nothing for a key: Confirm the key spelling with auditctl -l | grep -k; keys are case-sensitive.
  • Fedora/RHEL SELinux AVC messages in audit.log: These are normal. Use ausearch -m AVC -i to separate them from your custom-keyed rules.
tested on:Ubuntu 24.04Fedora 40Rocky 9.3Arch rolling

Frequently asked questions

What is the difference between auditctl -w and a syscall rule?
A -w file-watch rule is syntactic sugar that internally translates to inode-based path watches using the 'path' filter. Syscall rules (-a always,exit -S) give you finer control: you can filter by architecture, UID, EUID, executable path, or return value, and capture events that have no direct file path association.
Why do I need both arch=b64 and arch=b32 syscall rules?
A 64-bit kernel can run 32-bit ELF binaries. These use a different syscall table (int 0x80 ABI vs. syscall), so a rule specifying only arch=b64 is invisible to 32-bit processes. Omitting the b32 variant is a common audit gap.
Will enabling heavy syscall rules noticeably slow down my system?
Broadly scoped rules on high-frequency syscalls like read or write will generate enormous log volume and measurable overhead. Always narrow rules with filters such as -F auid>=1000 or -F exe=/path/to/binary. File watches on infrequently written config files have negligible performance impact.
How do I rotate or archive audit logs without losing events?
auditd handles log rotation internally via the max_log_file_action and num_logs settings in /etc/audit/auditd.conf. Set max_log_file_action=ROTATE and num_logs to how many compressed logs to retain. For long-term archival, configure the audisp-remote plugin or pipe logs to a SIEM.
Can auditd rules survive a reboot?
Yes, but only rules written to /etc/audit/rules.d/ and compiled with augenrules. Rules added with auditctl at the command line are runtime-only and are lost when the service restarts or the system reboots.

Related guides