1 # vim: set encoding=utf-8 et sw=4 sts=4 :
3 # TODO See if it's better (more secure) to execute commands via python instead
4 # of using script templates.
8 from pymin.seqtools import Sequence
9 from pymin.dispatcher import Handler, handler, HandlerError
10 from pymin.services.util import Restorable, ConfigWriter, ServiceHandler, \
11 TransactionalHandler, ListSubHandler
13 __ALL__ = ('FirewallHandler', 'Error')
15 class Error(HandlerError):
17 Error(command) -> Error instance :: Base FirewallHandler exception class.
19 All exceptions raised by the FirewallHandler inherits from this one, so you can
20 easily catch any FirewallHandler exception.
22 message - A descriptive error message.
27 r"""Rule(chain, target[, src[, dst[, ...]]]) -> Rule instance.
29 chain - INPUT, OUTPUT or FORWARD.
30 target - ACCEPT, REJECT or DROP.
31 src - Source subnet as IP/mask.
32 dst - Destination subnet as IP/mask.
33 protocol - ICMP, UDP, TCP or ALL.
34 src_port - Source port (only for UDP or TCP protocols).
35 dst_port - Destination port (only for UDP or TCP protocols).
38 def __init__(self, chain, target, src=None, dst=None, protocol=None,
39 src_port=None, dst_port=None):
40 r"Initialize object, see class documentation for details."
45 self.protocol = protocol
46 # TODO Validate that src_port and dst_port could be not None only
47 # if the protocol is UDP or TCP
48 self.src_port = src_port
49 self.dst_port = dst_port
51 def update(self, chain=None, target=None, src=None, dst=None, protocol=None,
52 src_port=None, dst_port=None):
53 r"update([chain[, ...]]) -> Update the values of a rule (see Rule doc)."
54 if chain is not None: self.chain = chain
55 if target is not None: self.target = target
56 if src is not None: self.src = src
57 if dst is not None: self.dst = dst
58 if protocol is not None: self.protocol = protocol
59 # TODO Validate that src_port and dst_port could be not None only
60 # if the protocol is UDP or TCP
61 if src_port is not None: self.src_port = src_port
62 if dst_port is not None: self.dst_port = dst_port
64 def __cmp__(self, other):
65 r"Compares two Rule objects."
66 return cmp(self.as_tuple(), other.as_tuple())
69 r"Return a tuple representing the rule."
70 return (self.chain, self.target, self.src, self.dst, self.protocol,
71 self.src_port, self.dst_port)
73 class RuleHandler(ListSubHandler):
74 r"""RuleHandler(parent) -> RuleHandler instance :: Handle a list of rules.
76 This class is a helper for FirewallHandler to do all the work related to rules
79 parent - The parent service handler.
82 handler_help = u"Manage firewall rules"
84 _cont_subhandler_attr = 'rules'
85 _cont_subhandler_class = Rule
87 class FirewallHandler(Restorable, ConfigWriter, ServiceHandler,
88 TransactionalHandler):
89 r"""FirewallHandler([pickle_dir[, config_dir]]) -> FirewallHandler instance.
91 Handles firewall commands using iptables.
93 pickle_dir - Directory where to write the persistent configuration data.
95 config_dir - Directory where to store de generated configuration files.
97 Both defaults to the current working directory.
100 handler_help = u"Manage firewall service"
102 _persistent_attrs = 'rules'
104 _restorable_defaults = dict(rules=list())
106 _config_writer_files = 'iptables.sh'
107 _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
109 def __init__(self, pickle_dir='.', config_dir='.'):
110 r"Initialize the object, see class documentation for details."
111 self._persistent_dir = pickle_dir
112 self._config_writer_cfg_dir = config_dir
113 self._service_start = ('sh', path.join(self._config_writer_cfg_dir,
114 self._config_writer_files))
115 self._service_stop = ('iptables', '-t', 'filter', '-F')
116 self._service_restart = self._service_start
117 self._service_reload = self._service_start
118 self._config_build_templates()
120 self.rule = RuleHandler(self)
122 def _get_config_vars(self, config_file):
123 return dict(rules=self.rules)
126 if __name__ == '__main__':
130 fw_handler = FirewallHandler()
135 print fw_handler.rule.show()
140 fw_handler.rule.add('input','drop','icmp')
142 fw_handler.rule.update(0, dst='192.168.0.188/32')
144 fw_handler.rule.add('output','accept', '192.168.1.0/24')
152 os.system('rm -f *.pkl iptables.sh')