5 Practical Bash Scripts for SSH Monitoring (No SIEM, No Agents)
Simple tools used correctly
5 Practical Bash Scripts for SSH Monitoring (No SIEM, No Agents)
Simple tools used correctly
SSH monitoring means tracking login attempts, authentication failures, and configuration changes to detect attacks and unauthorized access early.
You can monitor SSH activity using simple Bash scripts by parsing auth.log without deploying heavy security tools.
Important Scope (Read This First)
These scripts are not a replacement for:
- Fail2Ban
- central logging
- SIEMs
- configuration management
They are best used when:
- you run small fleets or VPSs
- you want visibility before adding heavy tools
- you need something auditable and transparent
- you want to understand what your SSH logs actually say
Log Location
Set this once and reuse it:
LOG_FILE="/var/log/auth.log" # /var/log/secure on RHEL/CentOS
Now let’s get into the meat of the article.
1. Detect SSH Brute Force Attempts (Time-Bounded & Stateful)
This solves the problem of random bots constantly hitting SSH. You only care when attempts are frequent and recent.
#!/bin/bash
LOG_FILE="/var/log/auth.log"
STATE_FILE="/var/tmp/ssh_failed.offset"
THRESHOLD=10
LAST_LINE=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
TOTAL_LINES=$(wc -l < "$LOG_FILE")
tail -n +"$((LAST_LINE + 1))" "$LOG_FILE" \
| grep "Failed password" \
| awk '{print $(NF-3)}' \
| sort | uniq -c \
| awk -v t="$THRESHOLD" '$1 >= t {print $2 " (" $1 " attempts)"}'
echo "$TOTAL_LINES" > "$STATE_FILE"
- Only scans new log lines since the last run
- Groups failed logins by IP
- Flags IPs that fail too many times in a short window
- Avoids re-alerting on old noise
This gives you signal, not background internet noise.
2. Alert on Root SSH Logins (Correctly)
Root SSH access should already be disabled. If it ever happens, you want to know once, not forever.
#!/bin/bash
LOG_FILE="/var/log/auth.log"
STATE_FILE="/var/tmp/ssh_root.offset"
LAST_LINE=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
TOTAL_LINES=$(wc -l < "$LOG_FILE")
tail -n +"$((LAST_LINE + 1))" "$LOG_FILE" \
| grep "Accepted" \
| grep "root" \
| while read -r line; do
echo " Root SSH login detected on $(hostname)"
echo "$line"
done
echo "$TOTAL_LINES" > "$STATE_FILE"
- Alerts only on new root logins
- Avoids alert spam
- Catches misconfiguration or policy violations fast
It’s best practice to disable root SSH entirely and keep this as a safety net.
3. Detect Successful SSH Logins From New IPs (Safely)
Instead of “any new IP ever”, this script tracks recent history.
#!/bin/bash
LOG_FILE="/var/log/auth.log"
KNOWN_IPS="/var/log/ssh_known_ips.txt"
grep "Accepted" "$LOG_FILE" \
| awk '{print $(NF-3)}' \
| sort -u > /tmp/current_ips
touch "$KNOWN_IPS"
NEW_IPS=$(comm -13 <(sort "$KNOWN_IPS") /tmp/current_ips)
if [[ -n "$NEW_IPS" ]]; then
echo "New SSH login IPs detected:"
echo "$NEW_IPS"
echo "$NEW_IPS" >> "$KNOWN_IPS"
fi
- Alerts only when a new source appears
- Simple and transparent
Helps catch stolen keys, leaked credentials and forgotten access paths.
It is noisy for:
- Mobile admins
- Dynamic IPs
- No bastion host
In those cases, use this for awareness, not blocking.
4. Detect SSH Configuration Changes
SSH config changes can silently weaken your security.
This script alerts you the moment it happens.
#!/bin/bash
CONFIG="/etc/ssh/sshd_config"
STATE="/var/log/sshd_config.sha256"
CURRENT=$(sha256sum "$CONFIG" | awk '{print $1}')
if [[ ! -f "$STATE" ]]; then
echo "$CURRENT" > "$STATE"
exit 0
fi
KNOWN=$(cat "$STATE")
if [[ "$CURRENT" != "$KNOWN" ]]; then
echo " SSH configuration changed on $(hostname)"
echo "$CURRENT" > "$STATE"
fi
- Detects unauthorized changes
- Catches config drift
- Works even without Git or Ansible
This is cheap integrity monitoring, and it’s effective.
5. Daily SSH Activity Summary (Readable & Actionable)
Instead of raw counts, this report gives context.
#!/bin/bash
LOG_FILE="/var/log/auth.log"
echo "===== SSH Daily Summary ====="
echo "Host: $(hostname)"
echo
echo "Successful logins by user:"
grep "Accepted" "$LOG_FILE" \
| awk '{print $(NF-5)}' \
| sort | uniq -c | sort -nr
echo
echo "Top source IPs:"
grep "Accepted" "$LOG_FILE" \
| awk '{print $(NF-3)}' \
| sort | uniq -c | sort -nr | head
echo
echo "Failed login attempts:"
grep "Failed password" "$LOG_FILE" \
| wc -l
- Shows who actually logged in
- Shows where access comes from
- Helps spot unusual patterns over time
Send this once per day, not every hour.
Go from a vanilla Ubuntu server to a production-ready baseline in under 10 minutes with the DevOps Starter Kit — a bundle of 20+ Bash scripts, cron jobs, and Docker templates to speed up your infrastructure setup.
메타데이터
- post_id
- a30d2d7f7e7d
- slug
- 5-practical-bash-scripts-for-ssh-monitoring-no-siem-no-agents-a30d2d7f7e7d
- url
- https://medium.com/@obaff/5-practical-bash-scripts-for-ssh-monitoring-no-siem-no-agents-a30d2d7f7e7d
- canonical_url
- https://medium.com/@obaff/5-practical-bash-scripts-for-ssh-monitoring-no-siem-no-agents-a30d2d7f7e7d
- author_url
- https://medium.com/@obaff
- status
- ok
- fetched_at
- 2026-07-14 07:12:13