LinuxXXXI · Audit and Security LoggingAudit rules
audit rules and watch points - what to record
What you'll learn
- Write audit rules for common scenarios
- Choose watch points by impact
- Tune audit for performance
- Document the rule set
Prerequisites
Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09
Audit rules define what the kernel records. Too few rules miss incidents; too many overwhelm the system. This lesson covers the right rules for production.
Rule categories
- File watch: changes to specific files (config, binaries, sensitive data).
- Syscall watch: specific syscalls (execve, setuid, bind).
- User watch: actions by specific users.
- System watch: kernel module loads, time changes, etc.
CIS Benchmark rules
The CIS Benchmarks include audit rules. Common ones:
# /etc/audit/rules.d/10-base-config.rules
# Identity files
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/security/opasswd -p wa -k identity
# sudoers
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
# SSH
-w /etc/ssh/sshd_config -p wa -k sshd
# Login/logout
-w /var/log/lastlog -p wa -k logins
-w /var/log/faillog -p wa -k logins
-w /var/log/wtmp -p wa -k logins
# Privileged commands
-a always,exit -F path=/usr/bin/sudo -F perm=x -k privileged
-a always,exit -F path=/usr/bin/su -F perm=x -k privileged
-a always,exit -F path=/usr/bin/passwd -F perm=x -k privileged
-a always,exit -F path=/usr/bin/chsh -F perm=x -k privileged
-a always,exit -F path=/usr/bin/chfn -F perm=x -k privileged
-a always,exit -F path=/usr/bin/newgrp -F perm=x -k privileged
-a always,exit -F path=/usr/bin/gpasswd -F perm=x -k privileged
-a always,exit -F path=/usr/bin/mount -F perm=x -k privileged
-a always,exit -F path=/usr/bin/umount -F perm=x -k privileged
-a always,exit -F path=/usr/bin/ssh-agent -F perm=x -k privileged
# Kernel module loads
-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 -k modules
-a always,exit -F arch=b64 -S finit_module -k modules
-a always,exit -F arch=b64 -S delete_module -k modules
Load with:
sudo augenrules --load
sudo auditctl -l
Freeze the rule set: -e 2
Everything above is undone by one command:
sudo auditctl -D # delete all rules
An attacker who reaches root does this before doing anything
else, and the audit trail of what they did next does not
exist. The control that prevents it is the enabled flag.
auditctl(8):
To lock the audit configuration so that it can’t be changed, pass a 2 as the argument. Locking the configuration is intended to be the last command in audit.rules […] Any attempt to change the configuration in this mode will be audited and denied. The configuration can only be changed by rebooting the machine.
Put these in the highest-numbered rules file so they sort last:
# /etc/audit/rules.d/99-finalize.rules
# Make loginuid unchangeable once set, so auid cannot be
# rewritten to disown an action
--loginuid-immutable
# MUST BE THE LAST LINE: freeze the rule set until reboot
-e 2
Confirm it took:
sudo auditctl -s | grep -w enabled # expect: enabled 2
Capacity behaviour: the settings that can halt the host
auditd.conf decides what happens as /var/log/audit fills.
Several of the actions are not logging actions at all — they
take the machine down, by design, on the reasoning that a
system that cannot record is a system that must not run.
# /etc/audit/auditd.conf
max_log_file = 50
num_logs = 10
max_log_file_action = ROTATE
space_left = 20%
space_left_action = SYSLOG
admin_space_left = 10%
admin_space_left_action = SYSLOG
disk_full_action = ROTATE
The values that bite, per auditd.conf(5):
| Setting | Dangerous values | Effect |
|---|---|---|
space_left_action | single, suspend | single drops to single-user mode |
admin_space_left_action | single, halt | halt shuts the system down |
disk_full_action | single, halt | same, when the partition is full |
max_log_file_action | suspend | daemon stops recording but stays alive |
Tuning for performance
Audit generates events. On busy hosts, too many rules slow the system.
# Exclude noisy processes
-a never,exclude -F exe=/usr/sbin/chronyd
-a never,exclude -F exe=/usr/sbin/rsyslogd
# Use a larger buffer
-b 8192
# Increase the failure mode (1 = printk instead of panic)
-f 1
Exclude processes that legitimately do many syscalls (log daemons, monitoring agents).
Reducing noise without losing coverage
There is no time-of-day filter. auditctl -F accepts a fixed
field list — arch, auid, uid, exe, path, perm,
success, msgtype and the rest — and none of them is a clock.
Any rule you see written with -F 'msg<=08:00' is invented: there
is no msg field either (the record-type field is msgtype, one
word), and auditctl rejects the rule rather than silently
ignoring it.
That is the right outcome. “Stop auditing outside office hours” would blind the audit trail during precisely the window an intruder would choose.
Reduce volume by excluding known-noisy actors, not time
ranges. Suppression rules must come before the recording rules
in /etc/audit/rules.d/, because the kernel stops at the first
matching rule:
# /etc/audit/rules.d/10-exclusions.rules - loaded first
-a never,exit -F arch=b64 -F exe=/usr/sbin/chronyd
-a never,exit -F arch=b64 -F exe=/usr/lib/systemd/systemd-journald
-a never,exit -F arch=b64 -F auid=unset -F uid=prometheus
# Drop a whole record type that is pure volume for your estate
-a never,exclude -F msgtype=CWD
Then the recording rules in a later-numbered file. Verify what the kernel actually loaded, since a malformed rule is refused individually while the rest of the file loads:
sudo augenrules --load
sudo auditctl -l # the rules in force, in order
sudo auditctl -s | grep -E 'lost|backlog' # non-zero lost = the real volume problem
If lost is climbing, the answer is a bigger -b backlog and
tighter exclusions — not less auditing during the night.
What to record vs skip
| Record | Skip |
|---|---|
| Identity file changes | Routine log writes |
| Sudo / su usage | User shell startup (noisy) |
| SSH login events | Routine cron output |
| PAM events | Time sync events |
| SELinux denials | Routine service restarts |
| Kernel module loads | High-frequency reads |
| Privilege escalation | Routine package updates |
The rule: record what is needed to investigate an incident. Routine activity can be inferred from what is not recorded.
Document and version
Place audit rules in /etc/audit/rules.d/ with version
control:
/etc/audit/rules.d/
├── 10-base-config.rules # CIS baseline
├── 20-custom.rules # site-specific
└── 99-debug.rules # temporary debugging (off by default)
Configuration management owns these files. Drift detection catches ad-hoc changes.
Knowledge check
Knowledge check · 3 questions
Q1. Which command loads persistent audit rules?
Q2. Excluding events during off-hours is a safe performance tuning.
Q3. Which of the following are valid audit watch points? Select all that apply.
Passing score: 75%. Answers are checked in this browser.