Added logic to create all necessary firewall rules

TODO:  Auto add chains
TODO:  Delete rules that should not be there
TODO: Deal with precidence
This commit is contained in:
Ian Southam 2014-08-15 15:20:07 +02:00 committed by wilderrodrigues
parent cd0ad69281
commit 19fd0b4b57
2 changed files with 87 additions and 21 deletions

View File

@ -1,20 +1,26 @@
import CsHelper
from pprint import pprint
import logging
class CsChain(object):
def __init__(self):
self.chain = {}
self.last_added = ''
def add(self, table, chain):
if not table in self.chain.keys():
self.chain.setdefault(table, []).append( chain )
else:
self.chain[table].append(chain)
self.last_added = chain
def get(self, table):
return self.chain[table]
def last(self):
return self.last_added
class CsTable(object):
def __init__(self):
@ -49,6 +55,7 @@ class CsNetfilters(object):
if i.startswith('-A'): # Rule
rule = CsNetfilter()
rule.parse(i)
rule.set_table(self.table.last())
self.save(rule)
def save(self,rule):
@ -63,15 +70,75 @@ class CsNetfilters(object):
def hasChain(self, table, chain):
return chain in self.chain.get(table)
def has_rule(self, new_rule):
for r in self.get():
if new_rule.equals(r):
return True
return False
def compare(self, list):
""" Compare reality with what is needed """
for fw in list:
new_rule = CsNetfilter()
new_rule.parse(fw[2])
new_rule.set_table(fw[0])
if self.has_rule(new_rule):
logging.debug("rule %s exists in table %s", fw[2], new_rule.get_table())
else:
logging.info("Add rule %s in table %s", fw[2], new_rule.get_table())
print "Add rule %s in table %s" % (fw[2], new_rule.get_table())
CsHelper.execute("iptables -t %s %s" % (new_rule.get_table(), fw[2]))
class CsNetfilter(object):
def __intt(self):
self.rule = {}
self.table = ''
self.chain = ''
def parse(self, rule):
rule.replace('! -', '!_-')
self.rule = self.__convert_to_dict(rule)
def __convert_to_dict(self, rule):
rule = rule.replace('! -', '!_-')
# -m can appear twice in a string
rule = rule.replace('-m state', '-m2 state')
bits = rule.split(' ')
self.rule = dict(zip(bits[0::2], bits[1::2])).iteritems()
rule = dict(zip(bits[0::2], bits[1::2]))
if "-A" in rule.keys():
self.chain = rule["-A"]
return rule
if __name__ == "__main__":
def set_table(self, table):
if table == '':
table = "filter"
self.table = table
def get_table(self):
return self.table
def set_chain(self, chain):
self.chain = chain
def get_chain(self):
return self.chain
def get_rule(self):
return self.rule
def to_str(self):
return ', '.join("%s=%r" % (key,val) for (key,val) in self.rule.iteritems())
def equals(self, rule):
if rule.get_table() != self.get_table():
return False
if rule.get_chain() != self.get_chain():
return False
for r in rule.get_rule():
if not r in self.get_rule().keys():
return False
if rule.get_rule()[r] != self.get_rule()[r]:
return False
return True
t = CsNetfilters()
print t.hasTable('mangle');
print t.hasChain('mangle', 'PREROUTING');

View File

@ -27,7 +27,7 @@ import shutil
import os.path
from cs_ip import merge
import CsHelper
import CsNetfilter
from CsNetfilter import CsNetfilters
fw = []
@ -219,7 +219,7 @@ class CsPasswdSvc(CsApp):
def setup(self):
fw.append(["", "front",
"-A INPUT -i %s -d %s -p tcp -m tcp --state NEW --dport 8080 -j ACCEPT" % (self.dev, self.ip)
"-A INPUT -i %s -d %s/32 -p tcp -m tcp -m state --state NEW --dport 8080 -j ACCEPT" % (self.dev, self.ip)
])
proc = CsProcess(['/opt/cloud/bin/vpc_passwd_server', self.ip])
@ -252,7 +252,7 @@ class CsApache(CsApp):
CsHelper.service("apache2", "restart")
fw.append(["", "front",
"-A INPUT -i %s -d %s -p tcp -m state --state NEW --dport 80 -j ACCEPT" % (self.dev, self.ip)
"-A INPUT -i %s -d %s/32 -p tcp -m state -m tcp --state NEW --dport 80 -j ACCEPT" % (self.dev, self.ip)
])
class CsDnsmasq(CsApp):
@ -261,16 +261,16 @@ class CsDnsmasq(CsApp):
def add_firewall_rules(self):
""" Add the necessary firewall rules
"""
fw.append(["", "front"
fw.append(["", "front",
"-A INPUT -i %s -p udp -m udp --dport 67 -j ACCEPT" % self.dev
])
fw.append(["", "front"
"-A INPUT -i %s -d %s -p udp -m udp --dport 53 -j ACCEPT" % (self.dev, self.ip)
fw.append(["", "front",
"-A INPUT -i %s -d %s/32 -p udp -m udp --dport 53 -j ACCEPT" % (self.dev, self.ip)
])
fw.append(["", "front"
"-A INPUT -i %s -d %s -p tcp -m tcp --dport 53 -j ACCEPT" % ( self.dev, self.ip )
fw.append(["", "front",
"-A INPUT -i %s -d %s/32 -p tcp -m tcp --dport 53 -j ACCEPT" % ( self.dev, self.ip )
])
def configure_server(self, method = "add"):
@ -360,8 +360,8 @@ class CsDevice:
if " DOWN " in i:
cmd2 = "ip link set %s up" % self.dev
CsHelper.execute(cmd2)
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-mark 0x%s" % \
(self.dev, "Table_%s" % self.tableNo)
cmd = "-A PREROUTING -i %s -m state --state NEW -j CONNMARK --set-xmark 0x%s/0xffffffff" % \
(self.dev, self.dev[3])
fw.append(["mangle", "", cmd])
@ -428,16 +428,14 @@ class CsIP:
"-A POSTROUTING -s %s -o %s -j SNAT --to-source %s" % \
(self.address['network'], self.dev, self.address['public_ip'])
])
fw.append(["", "", "-N %s" % devChain ])
fw.append(["mangle", "", "-N %s" % devChain ])
fw.append(["mangle", "", "-A %s -j ACCEPT" % devChain])
fw.append(["", "",
"-A FORWARD -o %s -d %s -j %s" % (self.dev, self.address['network'], devChain)
])
fw.append(["", "", "-A DROP -j %s" % devChain])
fw.append(["", "", "-A %s -j DROP" % devChain])
fw.append(["mangle", "",
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s -j %s" % \
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j %s" % \
(self.dev, self.address['network'], self.address['public_ip'], devChain)
])
dns = CsDnsmasq(self)
@ -752,7 +750,8 @@ def main(argv):
acls = CsAcl('networkacl')
acls.process()
pprint(fw)
nf = CsNetfilters()
nf.compare(fw)
if __name__ == "__main__":
main(sys.argv)