# What a server audit with server_audit_notify.sh checks

> The script runs Lynis, then checks failed SSH logins, listening ports, disk usage, large files and recent package installs. It saves each result to /var/log/server_audit and emails a summary.

Source: https://serverauditing.com/what-it-checks/

## Checks at a glance

All files go to `/var/log/server_audit` (or the `--report-dir` you set), and every file name ends with the start time of the run in the form `_YYYY-MM-DD_HH-MM-SS`.

| Check | Command | Output file | In the email |
| --- | --- | --- | --- |
| Security audit | `lynis audit system --no-colors --quiet` | `lynis_<time>.log`, `lynis-report_<time>.dat` | Up to 20 warnings |
| Failed SSH logins | `grep "Failed password"` on the SSH log | `ssh_failures_<time>.log` | Count and top 5 IPs |
| Large files | `find / -type f -size +100M` | `large_files_<time>.log` | At the thorough level |
| Disk usage | `df -h` | `disk_usage_<time>.log` | Yes, without tmpfs and udev |
| Listening ports | `ss -tuln` or `netstat -tuln` | `listening_ports_<time>.log` | Count and notable ports |
| Recent packages | `/var/log/dpkg.log` or `yum history` | `recent_packages_<time>.log` | At the thorough level |

## Lynis security audit

[Lynis](https://github.com/CISOfy/lynis) is an open-source security auditing tool for Linux, macOS and other Unix systems. The script runs `lynis audit system --no-colors --quiet` and saves the console output. It also passes `--report-file`, so Lynis writes its findings to `lynis-report_<time>.dat`. The script copies the last 20 `warning[]` entries from that file into the summary, each with its Lynis test ID.

If Lynis exits with an error, the script logs the exit status and carries on with the other checks.

The `--level` option changes what runs:

| Level | Lynis options | Other differences |
| --- | --- | --- |
| `basic` | `--tests-from-group "authentication ssh firewalls networking ports_packages"` | Skips the large file search |
| `standard` | none (all test groups) | The default |
| `thorough` | none (all test groups) | Adds Lynis suggestions, large files and recent packages to the email |

The standard and thorough levels run the same Lynis audit, as root, with every test group. The thorough level adds detail to the email. The script does not use the Lynis `--pentest` option, which the [Lynis documentation](https://cisofy.com/documentation/lynis/) describes as "Perform a penetration test scan (non-privileged)" and which skips tests that need root.

## Failed SSH logins

The script reads the last 50 lines that contain "Failed password" from the first source it finds:

1. `/var/log/auth.log` (Debian and Ubuntu with rsyslog)
2. `/var/log/secure` (Red Hat style systems)
3. The systemd journal, through `journalctl -u ssh -u sshd`

The summary names the source, shows how many lines it found (at most 50), and lists the five IP addresses that appear most often. If none of the sources exists, the section says "Source: none" and reports zero.

## Listening ports

The script saves the output of `ss -tuln`, or `netstat -tuln` when `ss` is not installed. Both list listening TCP and UDP sockets with numeric addresses. The summary counts lines in the `LISTEN` state, which covers TCP only, and prints any socket on ports 22 (SSH), 25 (SMTP), 80 (HTTP), 443 (HTTPS), 3306 (MySQL) or 5432 (PostgreSQL).

If neither tool is installed, the script skips this check and says so in the summary.

## Disk usage

The script saves `df -h` and copies it into the summary without `tmpfs` and `udev` lines. If any other file system shows 90% use or more, including 100%, the recommendations include "Free up disk space on partitions with 90% or more usage".

## Large files

The script lists up to 20 files larger than 100 MB, largest first. It searches from `/` and skips `/proc`, `/sys`, `/dev` and `/run`, so it can take a while on large disks. The basic level skips this search.

## Recent package installs

On systems with `apt`, the script saves the last 50 `install` lines from `/var/log/dpkg.log`. On systems with `yum`, it saves the first 20 lines of `yum history`.

## What the emailed summary looks like

The email body has a short header and then the summary file. The layout below comes from the script at the standard level; values in angle brackets are filled in at run time.

```text
Server Audit Notification
=========================

SERVER AUDIT SUMMARY
====================
Date: <date>
Hostname: <hostname>
IP Address: <first address from hostname -I>
Audit Level: standard
Issues Found: <yes or no>

SYSTEM INFORMATION
------------------
OS: <PRETTY_NAME from /etc/os-release>
Kernel: <uname -r>
Uptime: <uptime -p>

SECURITY WARNINGS
-----------------
- <Lynis warning text> [<Lynis test ID>]

FAILED SSH ATTEMPTS
-------------------
Source: <log file or journalctl>
<N> failed SSH login attempts found (last 50 at most)
Top IP addresses:
<count> <IP address>

DISK USAGE
----------
<df -h without tmpfs and udev>

LISTENING PORTS
---------------
Source: <ss -tuln or netstat -tuln>
<N> listening TCP sockets found
Notable ports:
<lines for ports 22, 25, 80, 443, 3306, 5432>

RECOMMENDATIONS
---------------
1. Review all security warnings
2. Investigate any suspicious failed login attempts
3. Check for unauthorized listening ports
4. Address Lynis security warnings
5. Free up disk space on partitions with 90% or more usage

For detailed information, see the full audit logs in /var/log/server_audit

Generated by server_audit_notify.sh
Powered by Forward Email - https://forwardemail.net
```

"Issues Found" is yes when there are Lynis warnings, failed SSH logins, or a file system at 90% or more. Recommendations 1 to 3 appear every time; number 4 appears when there are Lynis warnings, and number 5 when a file system is 90% full or more. The thorough level adds LYNIS SUGGESTIONS, LARGE FILES and RECENT PACKAGES sections.

The subject line is `Server Audit Report: <hostname> - <YYYY-MM-DD>`. By default the email goes out after every run; with `--only-on-issues` it goes out only when "Issues Found" is yes.

## Files written on each run

| File | Contents |
| --- | --- |
| `audit_<time>.log` | Progress messages of the script and any curl error, with timestamps |
| `summary_<time>.txt` | The summary shown above |
| `email_<time>.txt` | The email that was sent, with headers |
| `lynis-report_<time>.dat` | The Lynis report file with all warnings and suggestions |
| Six check files | One file per check, listed in the table at the top |

The script creates the report directory with mode 700. It does not write the SMTP password to any file.

## What the script does not check

The script reports. It does not change system settings or fix findings, apart from installing `lynis` and `curl` when they are missing. It also does not check:

- Pending security updates. Lynis may report some package findings, but the script itself only lists past installs.
- Firewall rules, user accounts or sudo rights, beyond what Lynis covers.
- File integrity. The script keeps no baseline and does not compare files between runs.
- Whether the server runs the code you expect. [Attestium](https://attestium.com) and [Audit Status](https://auditstatus.com) from the Forward Email team address that question with remote attestation.

The [Linux server audit checklist](https://serverauditing.com/linux-server-audit-checklist/) covers these areas with commands and sources.
