From 7336f42b4b105fbd49af74328d1313e6d95a2095 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Fri, 25 Sep 2015 23:02:42 +0200 Subject: IPTipset: Add possibility to save ipset state between runs By setting the ipset-save Reporter option to point at a file name, the state will be automatically loaded upon start and saved before LogActio stops running. Signed-off-by: David Sommerseth --- LogActio/Reporters/IPTipset.py | 47 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/LogActio/Reporters/IPTipset.py b/LogActio/Reporters/IPTipset.py index baf4b68..164545c 100644 --- a/LogActio/Reporters/IPTipset.py +++ b/LogActio/Reporters/IPTipset.py @@ -40,6 +40,7 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): ipset-hashsize: 2048 ipset-timeout: 3600 ipset-counters: True + ipset-save: /var/lib/ipset/logactio-ipset.save iptables-chains: INPUT,OUTPUT,FORWARD iptables-insert-points: INPUT:2,FORWARD:4 iptables-jump: DROP @@ -61,6 +62,9 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): must be True, true or 1 to be considered set. Otherwise it is disabled. See the ipset(8) man page for more information about this feature too. + If ipset-save is set with a file name, ipset will preserve the ipset state when + shutting down. It will also reload the state upon start-up. + If iptables-chains is set, it will insert an iptables rule which checks the ipset set. If iptables-insert-point is set (optinal), the rule will be inserted at the given point, otherwise it will be inserted at the top. The iptables-jump @@ -114,12 +118,17 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): (chain, point) = inspoint.split(":") self.__iptchaininserts[chain.strip()] = str(point) + if config.has_key("ipset-save"): + self.__ipset_save = config["ipset-save"] + # Prepare this object, ipset and iptables self.__log = logger and logger or self.__logfnc if self.__create: self.__prepare_ipset() if self.__iptchains: self.__prepare_iptables() + if self.__ipset_save: + self.__load_ipset_state() # Register this module as a reporter module LogActio.ReporterQueue.ReporterQueue.__init__(self, @@ -127,6 +136,7 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): "IPTables IPset processor", self.__processqueue) + def __logfnc(self, lvl, msg): print "%s" % msg sys.stdout.flush() @@ -138,11 +148,16 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): self.__log(2, "[IPTipset] %s: %s" % (cmd, line)) - def __call_ipset(self, mode, args): + def __call_ipset(self, mode, args = None): if mode == "create": args = ["ipset", "--exist", "create", self.__ipsetname, "hash:ip"] + args else: - args = ["ipset", mode, self.__ipsetname, args] + if args is None: + args = ["ipset", mode, self.__ipsetname] + elif isinstance(args, list): + args = ["ipset", mode, self.__ipsetname] + args + else: + args = ["ipset", mode, self.__ipsetname, args] nullfp = os.open("/dev/null", os.O_RDWR) tmplog = tempfile.SpooledTemporaryFile(mode="rw+b") @@ -167,6 +182,30 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): self.__call_ipset("create", params) + def __load_ipset_state(self): + try: + f = open(self.__ipset_save, "r") + for line in f: + s = line.split() + # Only care about the add lines, we've already created the ipset list + if s[0] != 'add': + continue + self.__call_ipset(s[0], s[2:]) + except IOError, e: + # Ignore "No such file or directory", as the file may not exist + if e.errno != 2: + raise e + + + def __save_ipset_state(self): + args = ["ipset", "save", self.__ipsetname] + nullfp = os.open("/dev/null", os.O_RDWR) + f = open(self.__ipset_save, "w") + self.__log(4, "[IPTipset]: Saving state - Executing %s" % " ".join(args)) + subprocess.Popen(args, stdin=nullfp, stdout=f) + f.close() + + def __parse_already_registered(self): args = ["ipset", "save", self.__ipsetname] nullfp = os.open("/dev/null", os.O_RDWR) @@ -284,6 +323,10 @@ class IPTipset(LogActio.ReporterQueue.ReporterQueue): if self.__iptchains: self.__cleanup_iptables() + if self.__ipset_save: + self.__save_ipset_state() + if self.__iptchains and self.__ipset_save: + self.__call_ipset("destroy") self.__log(3, "[IPTipset] Module shut down") -- cgit