66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
import argparse
|
|
import sys
|
|
import tomllib
|
|
import utils
|
|
import logging
|
|
|
|
|
|
class Config:
|
|
def __init__(self):
|
|
self.logger = logging.getLogger("sshd-bruteforce-detector")
|
|
parser = argparse.ArgumentParser(
|
|
prog="sshd-bruteforce-detector",
|
|
description="detects SSH bruteforce attacks by reading sshd's logs from systemd journal",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-c", "--config", nargs="?", help="provide a path for the config file"
|
|
)
|
|
parser.add_argument(
|
|
"-m",
|
|
"--max-attempts",
|
|
nargs="?",
|
|
help="Maximum number of failed login attempts allowed within the time window before triggering an alert. (default: 5)",
|
|
)
|
|
parser.add_argument(
|
|
"-w",
|
|
"--window",
|
|
nargs="?",
|
|
help="Time window used to group failed login attempts for detection (default: 5m)",
|
|
)
|
|
|
|
self.args = parser.parse_args()
|
|
self.config = {}
|
|
if getattr(self.args, "config", None):
|
|
self.__load_config(self.args.config)
|
|
|
|
def __load_config(self, path: str):
|
|
try:
|
|
with open(path, "rb") as f:
|
|
self.config = tomllib.load(f)
|
|
except FileNotFoundError:
|
|
self.logger.info("Config file not found. Stopping manually...")
|
|
sys.exit(1)
|
|
except tomllib.TOMLDecodeError:
|
|
self.logger.info(
|
|
"Config file not in valid TOML format. Stopping manually..."
|
|
)
|
|
sys.exit(1)
|
|
|
|
def __get_config_option(self, option):
|
|
opt = getattr(self.args, option, None)
|
|
opt_config = self.config.get(option, None)
|
|
if opt is not None:
|
|
return opt
|
|
elif opt_config is not None:
|
|
return opt_config
|
|
else:
|
|
return None
|
|
|
|
def get_window(self):
|
|
window = self.__get_config_option("window")
|
|
return utils.parse_window(window) if window is not None else 300
|
|
|
|
def get_max_attempts(self):
|
|
max_attempts = self.__get_config_option("max_attempts")
|
|
return int(max_attempts) if max_attempts is not None else 5
|