Intrusion detection on Linux: auditd, AIDE, CrowdSec and Wazuh

Updated November 2026

Patching closes holes; intrusion detection tells you when someone got through anyway. On a Linux server the useful free tools fall into three groups: the kernel audit system (auditd) records who changed what, file integrity checkers such as AIDE spot altered files, and log-based tools such as CrowdSec, fail2ban and Wazuh react to attack patterns.

What each tool does

Free intrusion detection tools for Linux servers
ToolWhat it watchesWhat you get
auditd (Linux Audit)System calls in the kernel: file writes, program starts, permission changesA detailed record of who did what, searchable with ausearch and aureport. Records only; does not block.
AIDEChecksums and attributes of files, compared with a saved baselineA daily report of added, removed and changed files. See File integrity monitoring.
CrowdSecLogs (SSH, web servers, many others) matched against attack scenariosDecisions to block an IP, enforced by a separate "bouncer" (firewall, web server). Optional shared community blocklist.
fail2banLog lines matched by regular expressions per service ("jails")Temporary firewall bans after repeated failures.
WazuhLogs, file integrity, rootkit checks, configuration assessment, via an agent on each hostCentral server, alerts and a web dashboard for many servers.
OSSECLogs, file integrity, malware and rootkit checksThe original open-source host IDS, maintained by Atomicorp (release 4.4.1, October 2026); no bundled dashboard.

Two names you will meet in older guides: Tripwire open source is still packaged in Debian 13, but its last upstream tag (2.4.3.7) dates from March 2018; AIDE is the actively maintained choice. Lynis is an auditing tool that checks your configuration and suggests hardening; it is useful, but it does not watch for intrusions between runs.

auditd: record sensitive changes

The Linux audit system is built into the kernel. The auditd daemon writes its records to /var/log/audit/audit.log. RHEL installs it by default. On Debian and Ubuntu:

sudo apt install auditd
sudo auditctl -s     # status: "enabled 1" means auditing is on

Put permanent rules in a file in /etc/audit/rules.d/ (the name must end in .rules). The augenrules tool merges these files into /etc/audit/audit.rules and loads them. Older guides use -w /etc/passwd -p wa; the auditctl manual now calls that form deprecated for performance reasons and recommends the syscall form with -F path= (one file) or -F dir= (a directory tree), shown here.

Rules for accounts, sudo and SSH

Create /etc/audit/rules.d/50-local.rules:

## accounts and passwords
-a always,exit -F arch=b64 -F path=/etc/passwd -F perm=wa -F key=identity
-a always,exit -F arch=b32 -F path=/etc/passwd -F perm=wa -F key=identity
-a always,exit -F arch=b64 -F path=/etc/shadow -F perm=wa -F key=identity
-a always,exit -F arch=b32 -F path=/etc/shadow -F perm=wa -F key=identity
-a always,exit -F arch=b64 -F path=/etc/group -F perm=wa -F key=identity
-a always,exit -F arch=b32 -F path=/etc/group -F perm=wa -F key=identity

## sudo rights
-a always,exit -F arch=b64 -F path=/etc/sudoers -F perm=wa -F key=sudoers
-a always,exit -F arch=b64 -F dir=/etc/sudoers.d/ -F perm=wa -F key=sudoers

## SSH server config and root's keys
-a always,exit -F arch=b64 -F path=/etc/ssh/sshd_config -F perm=wa -F key=sshd
-a always,exit -F arch=b64 -F dir=/etc/ssh/sshd_config.d/ -F perm=wa -F key=sshd
-a always,exit -F arch=b64 -F dir=/root/.ssh/ -F perm=wa -F key=ssh_keys

perm=wa means "write or attribute change", so reads are not logged. The key is a label you search by later. On 64-bit x86 servers, the arch=b32 lines catch 32-bit programs too; copy that pattern for the other rules if you want the same coverage (the upstream example rules do). Add a dir= line for each .ssh directory of a real login user, and only for directories that exist.

Programs started by the web server user

A web server account should almost never start a shell, curl or wget. When it does, it is often a web shell or an exploited plugin. Log every program it runs:

# find the user's numeric ID: www-data is 33 on Debian/Ubuntu, apache is 48 on RHEL
id -u www-data

## add to 50-local.rules (replace 33 with your ID)
-a always,exit -F arch=b64 -S execve -F euid=33 -F key=webexec
-a always,exit -F arch=b32 -S execve -F euid=33 -F key=webexec

If PHP-FPM or another application server runs under its own user, add rules for that user too. Expect some noise at first if your application legitimately runs tools such as image converters; note what is normal.

Load and lock the rules

sudo augenrules --check    # do the merged rules differ from what is loaded?
sudo augenrules --load
sudo auditctl -l           # list active rules

Optionally, add a file named 99-finalize.rules containing -e 2. This locks the audit configuration: nobody, not even root, can change or delete rules until the next reboot. It makes it harder for an intruder to switch auditing off quietly, but every rule change then needs a reboot.

The upstream project ships ready-made rule sets (for example for STIG and PCI DSS) in /usr/share/doc/auditd/examples/audit-rules/ on Debian. Copy only the files you need; loading all of them together is not intended.

Reading audit logs: ausearch and aureport

# who touched account files today, with user names instead of numbers
sudo ausearch -k identity -ts today -i

# programs run by the web user in the last 10 minutes
sudo ausearch -k webexec -ts recent -i

# overview of everything recorded
sudo aureport --summary

# events per rule key, failed logins this week, account changes
sudo aureport -k --summary
sudo aureport -au --failed -ts this-week -i
sudo aureport -m -i

Each record shows the login user (auid), which stays the same after sudo or su. That is how you tell which person changed /etc/sudoers even if they did it as root. Remember that an attacker with root can delete audit.log: forward it off the server as described in Logging and monitoring.

CrowdSec and fail2ban: react to attacks

Both read your logs and block addresses that behave like attackers, for example dozens of failed SSH logins or scans for /wp-login.php.

Neither tool detects a successful intrusion. They reduce noise and slow down guessing. Brute-force attacks covers an active attack.

Wazuh: many servers, one dashboard

Wazuh installs a small agent on each server (its documentation gives about 35 MB of RAM on average). Agents send log events, file integrity results, rootkit checks and configuration assessments to a central Wazuh server, which stores them in the Wazuh indexer and shows them in a web dashboard. The central part is heavier: the quickstart asks for 4 vCPU, 8 GiB RAM and 50 GB of disk for up to 25 agents (90 days of alerts), and lists RHEL 7 to 10, Ubuntu up to 24.04, Amazon Linux and CentOS Stream 10 for it. The agent itself supports more systems.

Wazuh suits a team watching ten or more servers. For one or two servers, auditd plus AIDE plus central logging gives most of the value with far less to maintain.

Choosing and resource use

A practical starting point
SituationSuggested set
One or a few serversauditd with the rules above, AIDE daily, logs forwarded off-host, fail2ban or CrowdSec for SSH and web logins
A small fleet (10+)The same on each host, plus a central log server or Wazuh for alerts in one place
Compliance requirementsauditd with the matching upstream rule set, file integrity monitoring, central retention; check what your auditor expects

Whichever you choose, test it: add a line to a watched file, run a command as the web user, and confirm the event reaches you.

Sources