From 6e2bd1f5053f5244d1294ba5ae2c0ffc047743b6 Mon Sep 17 00:00:00 2001 From: hc Date: Sat, 1 Feb 2025 10:21:49 +0800 Subject: firstcommit --- client_ls.py | 21 ++++++++ client_manager.py | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ sys_init.py | 49 +++++++++++++++++++ 3 files changed, 210 insertions(+) create mode 100644 client_ls.py create mode 100644 client_manager.py create mode 100644 sys_init.py diff --git a/client_ls.py b/client_ls.py new file mode 100644 index 0000000..6aa3a7e --- /dev/null +++ b/client_ls.py @@ -0,0 +1,21 @@ + +#lists client information + +import fcntl +import json +import os + + +def read_data(): + try: + with open('/tmp/ssh_sessions.json', 'r') as f: + # Get shared lock for reading + fcntl.flock(f.fileno(), fcntl.LOCK_SH) + try: + return json.load(f) + finally: + fcntl.flock(f.fileno(), fcntl.LOCK_UN) + except (FileNotFoundError, ValueError): + return {} + +print(read_data()) diff --git a/client_manager.py b/client_manager.py new file mode 100644 index 0000000..84bf3df --- /dev/null +++ b/client_manager.py @@ -0,0 +1,140 @@ + +# main logic + +from sys_init import setup +setup() + +import pyinotify +import subprocess +import re +import pwd +import os +import json +import atexit +import fcntl + +def get_ssh_port(pid): + ''' + Jan 31 07:50:28 vultr sshd[43690]: Accepted publickey for root from 210.10.76.5 port 43730 ssh2: ED25519 SHA256:qz9ffMCb3vPlabn3ZHee00qIPBxkDiUiVSorcUkGdII + Jan 31 07:50:28 vultr sshd[43690]: pam_unix(sshd:session): session opened for user root(uid=0) by root(uid=0) + Jan 31 07:50:29 vultr sshd[43693]: Received disconnect from 210.10.76.5 port 43730:11: disconnected by user + Jan 31 07:50:29 vultr sshd[43693]: Disconnected from user root 210.10.76.5 port 43730 + Jan 31 07:50:29 vultr sshd[43690]: pam_unix(sshd:session): session closed for user root + ''' + ''' + # less efficient but readable + pid = '33216' + pids = [] + port = -1 + for l in lines: + l = l.split() + if pid == l[1]: + commonstring = l[8] + for l2 in lines: + if commonstring in l2.split(): + pids.append(l2.split()[1]) + for i in pids: + for l in lines: + l = l.split() + if i in l[1] and "*:" in l[8]: + port = l[8][2:] + ''' + try: + lines = subprocess.check_output("lsof -i -n | grep sshd", shell=True, text=True).splitlines() + pid = str(pid) + pids = {l.split()[1] for l in lines + if pid == l.split()[1] or + l.split()[8] in [x.split()[8] for x in lines if x.split()[1] == pid]} + + port = next(l.split()[8][2:] for l in lines if l.split()[1] in pids and "*:" in l.split()[8]) + return port + except: + return -1 + +def get_keyname(fingerprint): + auth_file = os.path.join(os.path.expanduser(f"~{user}"), ".ssh", "authorized_keys") + try: + result = subprocess.run(['ssh-keygen', '-lf', f'{auth_file}'], capture_output=True, text=True, shell=False, check=True) + # Raises CalledProcessError if command fails, for check = true + + #256 SHA256:d9CBxSLBLzLjYGZDCsO6V+lddlN/elK1hGDBS56cbTo user@host (ED25519) + for line in result.stdout.strip().split('\n'): + parts = line.split() + if fingerprint in parts[1]: + return parts[2] + return 'not found' + + except subprocess.CalledProcessError as e: + print(f"Error executing command: {e}") + return None + except Exception as e: + print(f"Error processing output: {e}") + return None + +def write_data(data): + with open('/tmp/ssh_sessions.json', 'w') as f: + # Get exclusive lock for writing + fcntl.flock(f.fileno(), fcntl.LOCK_EX) + try: + # Clear file and write new data + f.seek(0) + json.dump(data, f) + f.truncate() + finally: + fcntl.flock(f.fileno(), fcntl.LOCK_UN) + +def handle_log_change(event): + global last_position + with open(event.pathname, 'r') as f: + # Go to end and read new lines + f.seek(last_position) + new_lines = f.readlines() + last_position = f.tell() + + for line in new_lines: + #print(f"New log: {line.strip()}") + line = line.strip() + if f"Accepted publickey for {user}" in line: + pid = re.search(r'\[(\d+)\]', line.split()[4]).group(1) + port = get_ssh_port(pid) + keyname = get_keyname(line.split()[15]) + srcip = line.split()[10] + #print(pid, port, keyname, srcip) + ssh_sessions[pid] = [srcip, keyname, port] + ssh_sessions[pid] = { + 'srcip': srcip, + 'key': keyname, + 'pubport': port + } + write_data(ssh_sessions) + if "pam_unix(sshd:session): session closed" in line: + pid = re.search(r'\[(\d+)\]', line.split()[4]).group(1) + if pid in ssh_sessions: + del ssh_sessions[pid] + else: + print("WARNING! PID NOT FOUND IN SESSION CACHE!") + write_data(ssh_sessions) + + print("db: ",ssh_sessions) + + + +user = "root" + +# init last_position +global last_position +with open('/var/log/secure', 'r') as f: + f.seek(0, 2) + last_position = f.tell() + +global ssh_sessions +ssh_sessions = {} + +wm = pyinotify.WatchManager() +wm.add_watch('/var/log/secure', pyinotify.IN_MODIFY, handle_log_change) +notifier = pyinotify.Notifier(wm) + +print("Watching /var/log/secure...") +notifier.loop() + + diff --git a/sys_init.py b/sys_init.py new file mode 100644 index 0000000..5bcd618 --- /dev/null +++ b/sys_init.py @@ -0,0 +1,49 @@ + +#installs pip packages and lsof for debian + +import subprocess +import sys +import os +import importlib + +def check_os(): + if os.path.exists('/etc/os-release'): + with open('/etc/os-release', 'r') as f: + content = f.read().lower() + if 'debian' in content or 'ubuntu' in content: + return 'debian' + elif 'fedora' in content: + return 'fedora' + return None + +def install_package(package): + try: + importlib.import_module(package) + print(f"{package} is already installed") + except ImportError: + try: + subprocess.check_call([sys.executable, "-m", "pip", "install", package]) + print(f"Successfully installed {package}") + except subprocess.CalledProcessError: + print(f"Failed to install {package}") + +def install_lsof(): + os_type = check_os() + if os_type == 'debian': + try: + subprocess.check_call(['apt-get', 'update']) + subprocess.check_call(['apt-get', 'install', '-y', 'lsof']) + print("lsof installed successfully") + except subprocess.CalledProcessError: + print("Failed to install lsof") + else: + print("Not a Debian-based system, skipping lsof installation") + +def setup(): + # Install pyinotify + install_package('pyinotify') + # Install lsof if on Debian + install_lsof() + +if __name__ == "__main__": + setup() -- cgit v1.2.3-70-g09d2