init
This commit is contained in:
commit
37fbf43322
3 files changed
+86
No files matched your search
@@ -0,0 +1,2 @@
|
|||||||
|
*.db
|
||||||
|
cursor.txt
|
||||||
@@ -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()
|
||||||
@@ -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()
|
||||||
Reference in new issue
Block a user