Don't mess with the blacklist, it's handled elsewhere.
[nodemanager.git] / iptables.py
1 #!/usr/bin/python -tt
2
3 # Author: Daniel Hokka Zakrisson <daniel@hozac.com>
4 # $Id$
5
6 import os
7 import logger
8 import subprocess
9
10 class IPTables:
11     IPTABLES_RESTORE = "/sbin/iptables-restore"
12
13     def __init__(self):
14         self.extifs = []
15         self.intifs = []
16         self.pfs = []
17
18     def add(self, table, chain, rule):
19         self.rules[table][chain].append(rule)
20
21     def add_ext(self, interface):
22         self.extifs.append(interface)
23
24     def add_int(self, interface):
25         self.intifs.append(interface)
26
27     def add_pf(self, pf):
28         # XXX Should make sure the required fields are there
29         self.pfs.append(pf)
30
31     def commit(self):
32         # XXX This should check for errors
33         #     and make sure the new ruleset differs from the current one
34
35         if (len(self.extifs) + len(self.intifs) + len(self.pfs)) == 0:
36             return True
37
38         restore = subprocess.Popen([self.IPTABLES_RESTORE, "--noflush"], stdin=subprocess.PIPE)
39         restore.stdin.write("""*filter
40 :INPUT ACCEPT [0:0]
41 :FORWARD ACCEPT [0:0]
42 :OUTPUT ACCEPT [0:0]
43 :LOGDROP - [0:0]
44 :SLICESPRE - [0:0]
45 :SLICES - [0:0]
46 :PORTFW - [0:0]
47
48 -F INPUT
49 -F FORWARD
50 -F OUTPUT
51
52 -A LOGDROP -j LOG
53 -A LOGDROP -j DROP
54 -A OUTPUT -j BLACKLIST
55 -A OUTPUT -m mark ! --mark 0/65535 -j SLICESPRE
56 -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
57 """)
58
59         for int in self.intifs:
60             for ext in self.extifs:
61                 restore.stdin.write("-A FORWARD -i %s -o %s -j ACCEPT\n" % (int, ext))
62             restore.stdin.write("-A SLICESPRE -o %s -j SLICES\n" % int)
63
64         restore.stdin.write("-A FORWARD -m state --state NEW -j PORTFW\n")
65         for pf in self.pfs:
66             rule = "-A PORTFW -p %s -d %s " % (pf['protocol'], pf['destination'])
67             if 'interface' in pf:
68                 rule += "-i %s " % pf['interface']
69             if 'source' in pf:
70                 rule += "-s %s " % pf['source']
71             rule += "--dport %s" % pf['new_dport']
72             restore.stdin.write(rule + "\n")
73
74         restore.stdin.write("-A FORWARD -j LOGDROP\n")
75
76         # This should have a way to add rules
77         restore.stdin.write("-A SLICES -j LOGDROP\n")
78         restore.stdin.write("""COMMIT
79 *nat
80 :PREROUTING ACCEPT [0:0]
81 :POSTROUTING ACCEPT [0:0]
82 :OUTPUT ACCEPT [0:0]
83 :PORTFW - [0:0]
84 :MASQ - [0:0]
85
86 -F PREROUTING
87 -F POSTROUTING
88 -F OUTPUT
89 """)
90
91         for ext in self.extifs:
92             restore.stdin.write("-A MASQ -o %s -j MASQUERADE\n")
93
94         for pf in self.pfs:
95             rule = "-A PORTFW -p %s " % pf['protocol']
96             if 'interface' in pf:
97                 rule += "-i %s " % pf['interface']
98             if 'source' in pf:
99                 rule += "-s %s " % pf['source']
100             rule += "--dport %s -j DNAT --to %s:%s" % (pf['dport'], pf['destination'],
101                     pf['new_dport'])
102             restore.stdin.write(rule + "\n")
103
104         restore.stdin.write("COMMIT\n")
105         restore.stdin.close()
106         return restore.wait() == 0