reguire gnupg1 on f>=31; sense the system to use gpg1 when installed
[nodemanager.git] / iptables.py
index fa83ee6..2842a9d 100644 (file)
@@ -1,13 +1,12 @@
-#!/usr/bin/python -tt
-
+#!/usr/bin/python3 -tt
+#
 # Author: Daniel Hokka Zakrisson <daniel@hozac.com>
-# $Id$
 
 import os
-import logger
 import subprocess
 
 class IPTables:
+    """A class to encapsulate iptables operations"""
     IPTABLES_RESTORE = "/sbin/iptables-restore"
 
     def __init__(self):
@@ -15,37 +14,54 @@ class IPTables:
         self.intifs = []
         self.pfs = []
 
-    def add(self, table, chain, rule):
-        self.rules[table][chain].append(rule)
-
     def add_ext(self, interface):
+        """Adds an external interface. An external interface is one where
+           outgoing traffic will be NATed, and incoming traffic will go to
+           the port forward chain."""
         self.extifs.append(interface)
 
     def add_int(self, interface):
+        """Adds an internal interface. An internal interface is trusted,
+           and traffic coming in on it is allowed through."""
         self.intifs.append(interface)
 
     def add_pf(self, pf):
+        """Adds a port forward. The argument is a dict consisting of:
+           'protocol'       tcp/udp
+           'destination'    the new destination IP
+           'dport'          the destination port
+           'new_dport'      the new destination port
+           and optionally:
+           'interface'      the incoming interface
+           'source'         limit the redirect to these IPs"""
         # XXX Should make sure the required fields are there
         self.pfs.append(pf)
 
     def commit(self):
+        """Call commit when all the rules are ready to be applied.
+           This is a no-op if no port forwards, external or internal
+           interfaces have been declared."""
+
         # XXX This should check for errors
         #     and make sure the new ruleset differs from the current one
 
         if (len(self.extifs) + len(self.intifs) + len(self.pfs)) == 0:
             return True
 
-        restore = subprocess.Popen([self.IPTABLES_RESTORE], stdin=subprocess.PIPE)
+        restore = subprocess.Popen([self.IPTABLES_RESTORE, "--noflush"], stdin=subprocess.PIPE)
         restore.stdin.write("""*filter
 :INPUT ACCEPT [0:0]
 :FORWARD ACCEPT [0:0]
 :OUTPUT ACCEPT [0:0]
-:BLACKLIST - [0:0]
 :LOGDROP - [0:0]
 :SLICESPRE - [0:0]
 :SLICES - [0:0]
 :PORTFW - [0:0]
 
+-F INPUT
+-F FORWARD
+-F OUTPUT
+
 -A LOGDROP -j LOG
 -A LOGDROP -j DROP
 -A OUTPUT -j BLACKLIST
@@ -54,12 +70,15 @@ class IPTables:
 """)
 
         for int in self.intifs:
+            # Allow all traffic from internal to external
             for ext in self.extifs:
                 restore.stdin.write("-A FORWARD -i %s -o %s -j ACCEPT\n" % (int, ext))
+            # Traffic from slices to internal networks is scrutinized
             restore.stdin.write("-A SLICESPRE -o %s -j SLICES\n" % int)
 
         restore.stdin.write("-A FORWARD -m state --state NEW -j PORTFW\n")
         for pf in self.pfs:
+            # Port forwards, redirect incoming external traffic to some internal address
             rule = "-A PORTFW -p %s -d %s " % (pf['protocol'], pf['destination'])
             if 'interface' in pf:
                 rule += "-i %s " % pf['interface']
@@ -79,11 +98,17 @@ class IPTables:
 :OUTPUT ACCEPT [0:0]
 :PORTFW - [0:0]
 :MASQ - [0:0]
+
+-F PREROUTING
+-F POSTROUTING
+-F OUTPUT
 """)
 
+        # Outgoing traffic on external interfaces needs to be NATed
         for ext in self.extifs:
             restore.stdin.write("-A MASQ -o %s -j MASQUERADE\n")
 
+        # Redirect port forwards to their real destination
         for pf in self.pfs:
             rule = "-A PORTFW -p %s " % pf['protocol']
             if 'interface' in pf: