This commit is contained in:
jonas committed 2026-06-07 21:26:11 +02:00
commit 37fbf43322
3 files changed
+86

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
*.db
cursor.txt
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
import sqlite3, subprocess, re, os
DB = "sshd_failures.db"
STATE = "cursor.txt"
PATTERN = re.compile(r"PAM: Authentication failure for root from ([0-9a-fA-F:.]+)")
def get_cursor():
return open(STATE).read().strip() if os.path.exists(STATE) else None
def save_cursor(c):
open(STATE, "w").write(c)
def main():
db = sqlite3.connect(DB)
db.execute("CREATE TABLE IF NOT EXISTS failures(ts INTEGER, ip TEXT)")
cmd = ["journalctl", "-u", "sshd", "-o", "short-unix", "--no-pager"]
cur = get_cursor()
if cur:
cmd += ["--after-cursor", cur]
out = subprocess.check_output(cmd, text=True)
total = 0
parsed = 0
inserted = 0
for line in out.splitlines():
total += 1
if not line or not line[0].isdigit():
continue
parsed += 1
ts_str, msg = line.split(" ", 1)
try:
ts = int(float(ts_str))
except ValueError:
continue
m = PATTERN.search(msg)
if m:
db.execute("INSERT INTO failures VALUES (?, ?)", (ts, m.group(1)))
inserted += 1
db.commit()
db.close()
print(f"lines={total} parsed={parsed} inserted={inserted}")
# save cursor
out = subprocess.check_output(
["journalctl", "-u", "sshd", "-n", "1", "-o", "export"],
text=True
)
for l in out.splitlines():
if l.startswith("__CURSOR="):
save_cursor(l.split("=", 1)[1])
break
if __name__ == "__main__":
main()
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env python3
import sqlite3, datetime
DB = "sshd_failures.db"
db = sqlite3.connect(DB)
for ip, count, last_ts in db.execute("""
SELECT ip, COUNT(*), MAX(ts)
FROM failures
GROUP BY ip
ORDER BY COUNT(*) DESC
"""):
last = datetime.datetime.fromtimestamp(last_ts)
print(f"{ip:40} {count:5} last={last}")
db.close()