I got tired of grepping auth.log by hand every time a box looked noisy. This is a tiny pipeline that pulls failed SSH attempts out of a log dump and tells me which IPs are actually spraying credentials vs someone who fat-fingered a password twice.
Stack: Bash for collection, Python for parsing and scoring.
- Shell script grabs lines that look like auth events (or keeps the sample file if you don't have root on the box).
- Python turns each line into a structured event: time, host, user, IP, fail/ok.
- Failures get grouped by source IP.
- If an IP crosses a threshold, it becomes an alert with a severity.
That's it. No agents, no fancy models — just counts and a few thresholds I can defend.
I kept this boring on purpose.
| Signal | Why I care |
|---|---|
| Fail count for one IP | Brute force / bot |
| Distinct usernames tried | Credential spray (admin, root, ubuntu, oracle…) |
| Mix of both | Usually worse than a single repeated user |
Defaults:
- under 3 fails → ignore
- 3–7-ish with few users → low/medium
- lots of fails or many different usernames → high
One wrong password is human. Six usernames from the same IP is not.
flowchart TD
A[auth.log or sample dump] --> B[collect_auth.sh]
B --> C{Readable system log?}
C -->|yes| D[grep fail/accept lines]
C -->|no| E[keep sample_data]
D --> F[auth_events.log]
E --> F
F --> G[parser.py]
G --> H[AuthEvent list]
H --> I[detector.py]
I --> J{fails per IP >= min?}
J -->|no| K[quiet]
J -->|yes| L[severity + reason]
L --> M[CLI text or JSON]
log-pulse/
scripts/collect_auth.sh
src/
parser.py
detector.py
main.py
sample_data/auth_events.log
tests/
- Wrote a few regexes against real-looking sshd lines until parse didn't break.
- Dumped events into a list and counted fails by IP in a notebook-style script, then moved that into
detector.py. - Added severity after I saw that “5 fails on one user” and “5 fails across 7 users” are not the same story.
- Wrapped it in a CLI with
--jsonso I can pipe it later if I want. - Bash collector last — once the Python side worked on a static file.
git clone https://github.com/Nabil201-ctrl/log-pulse.git
cd log-pulse
# optional: try live logs (needs read on /var/log/auth.log or secure)
chmod +x scripts/collect_auth.sh
./scripts/collect_auth.sh sample_data
python3 src/main.py
python3 src/main.py -i sample_data/auth_events.log --jsonQuick sanity check:
python3 -c "
import sys
from pathlib import Path
sys.path.insert(0, str(Path('src').resolve()))
sys.path.insert(0, str(Path('tests').resolve()))
from test_detector import test_parse_fail, test_spike_flags_noisy_ip
test_parse_fail(); test_spike_flags_noisy_ip()
print('ok')
"parsed 22 auth events from sample_data/auth_events.log
2 alert(s):
[HIGH ] 45.33.32.156
fails=9 users=admin, ftp, guest, mysql, pi, root, user
9 failed attempts across 7 username(s) — looks like credential spray or a noisy bot
- Sliding time windows instead of whole-file counts
- GeoIP on the source
- Webhook / write hits to sqlite
If you're just learning log analysis, start here before the bigger tools.