From 8fb24b1db4ff30bbc6f00ea74018192bfba9472f Mon Sep 17 00:00:00 2001 From: carnivuth Date: Tue, 27 Jan 2026 17:41:41 +0100 Subject: [PATCH] added firewall strategy pattern --- src/firewall/fwtype.py | 40 +++++++++++++++++++++++++++++++++++++ src/firewall/iptables.py | 43 ++++++++++++++++++++++++++++++++++++++++ src/firewall/raw.py | 20 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 src/firewall/fwtype.py create mode 100644 src/firewall/iptables.py create mode 100644 src/firewall/raw.py diff --git a/src/firewall/fwtype.py b/src/firewall/fwtype.py new file mode 100644 index 0000000..2995489 --- /dev/null +++ b/src/firewall/fwtype.py @@ -0,0 +1,40 @@ +from abc import ABC, abstractmethod +from typing import Dict, Type + + +class FWType(ABC): + """Abstract base class for firewall types.""" + + # Registry to store child classes + _registry: Dict[str, Type['FWType']] = {} + + def __init_subclass__(cls, **kwargs): + """Automatically register subclasses with their class name.""" + super().__init_subclass__(**kwargs) + cls._registry[cls.__name__.lower()] = cls + + @classmethod + def create(cls, fw_type: str, **kwargs) -> 'FWType': + """ + Factory method to create instances of child classes. + + Args: + fw_type: String name of the firewall type class to instantiate + **kwargs: Arguments to pass to the child class constructor + + Returns: + Instance of the requested child class + + Raises: + ValueError: If fw_type is not registered + """ + fw_type = fw_type.lower() + if fw_type not in cls._registry: + available = ', '.join(cls._registry.keys()) + raise ValueError(f"Unknown firewall type: '{fw_type}'. Available: {available}") + + return cls._registry[fw_type](**kwargs) + + @abstractmethod + def getBanlist(self,ips): + """Return the ruleset for the specific server""" diff --git a/src/firewall/iptables.py b/src/firewall/iptables.py new file mode 100644 index 0000000..73ac623 --- /dev/null +++ b/src/firewall/iptables.py @@ -0,0 +1,43 @@ +from typing_extensions import override +from firewall.fwtype import FWType + +class Iptables(FWType): + + @override + def getBanlist(self,ips) -> str: + """ + Generate iptables ban rules from an array of IP addresses. + + Args: + ips: List of IP addresses to ban + + Returns: + String containing iptables commands, one per line + """ + if not ips: + return "" + + rules = [] + chain = "INPUT" + target = "DROP" + rules.append("#!/bin/bash") + rules.append("# iptables ban rules") + rules.append("") + + for ip in ips: + + ip = ip.strip() + + # Build the iptables command + rule_parts = [ + "iptables", + "-A", chain, + "-s", ip + ] + + # Add target + rule_parts.extend(["-j", target]) + + rules.append(" ".join(rule_parts)) + + return "\n".join(rules) diff --git a/src/firewall/raw.py b/src/firewall/raw.py new file mode 100644 index 0000000..1e29e75 --- /dev/null +++ b/src/firewall/raw.py @@ -0,0 +1,20 @@ +from typing_extensions import override +from firewall.fwtype import FWType + +class Raw(FWType): + + @override + def getBanlist(self,ips) -> str: + """ + Generate raw list of bad IP addresses. + + Args: + ips: List of IP addresses to ban + + Returns: + String containing raw ips, one per line + """ + if not ips: + return "" + + return "\n".join(ips)