From: Nicolas Emiliani Date: Sat, 10 Nov 2007 19:48:52 +0000 (-0300) Subject: VPN support added. X-Git-Url: https://git.llucax.com/software/pymin.git/commitdiff_plain/fa44834a03b01014380b5adf86f50398b5c5561e?ds=inline;hp=--cc VPN support added. --- fa44834a03b01014380b5adf86f50398b5c5561e diff --git a/pymin/services/vpn/__init__.py b/pymin/services/vpn/__init__.py new file mode 100644 index 0000000..789d137 --- /dev/null +++ b/pymin/services/vpn/__init__.py @@ -0,0 +1,171 @@ +# vim: set encoding=utf-8 et sw=4 sts=4 : + +import os +from os import path + +from pymin.seqtools import Sequence +from pymin.dispatcher import Handler, handler, HandlerError +from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ + TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError + + +class Host(Sequence): + def __init__(self, vpn_src, ip, vpn_src_net, key): + self.name = vpn_src + self.ip = ip + self.src_net = vpn_src_net + self.pub_key = key + self.dele = False + + def as_tuple(self): + return(self.name, self.ip, self.src_net, self.pub_key) + +class HostHandler(DictComposedSubHandler): + + handler_help = u"Manage hosts for a vpn" + _comp_subhandler_cont = 'vpns' + _comp_subhandler_attr = 'hosts' + _comp_subhandler_class = Host + + @handler('usage: add ') + def delete(self, vpn_src, host): + DictComposedSubHandler.delete(self, vpn_src, host) + if vpn_src in parent.vpns: + if host in parent.vpns[vpn_src].hosts: + parent.vpns[vpn_src].hosts[host].dele = True + + +class Vpn(Sequence): + def __init__(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, pub_key, priv_key): + self.vpn_src = vpn_src + self.vpn_dst = vpn_dst + self.vpn_src_ip = vpn_src_ip + self.vpn_src_mask = vpn_src_mask + self.pub_key = pub_key + self.priv_key = priv_key + self.hosts = dict() + self.dele = False + + def as_tuple(self): + return(self.vpn_src, self.vpn_dst, self.vpn_src_ip, self.vpn_src_mask, self.pub_key, self.priv_key) + + def update(self, vpn_dst=None, vpn_src_ip=None, vpn_src_mask=None): + if vpn_dst is not None: + self.vpn_dst = vpn_dst + if vpn_src_ip is not None: + self.vpn_src_ip = vpn_src_ip + if vpn_src_mask is not None: + self.vpn_src_mask = vpn_src_mask + + +class VpnHandler(Restorable, ConfigWriter, + TransactionalHandler, DictSubHandler): + + handler_help = u"Manage vpn service" + + _cont_subhandler_attr = 'vpns' + _cont_subhandler_class = Vpn + + _persistent_attrs = ('vpns','hosts') + + _restorable_defaults = dict( + vpns = dict(), + hosts = dict(), + ) + + _config_writer_files = ('tinc.conf','tinc-up','host') + _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates') + + def __init__(self, pickle_dir='.', config_dir='/etc/tinc'): + DictSubHandler.__init__(self,self) + self._config_writer_cfg_dir = config_dir + self._persistent_dir = pickle_dir + self._config_build_templates() + self._restore() + self.host = HostHandler(self) + + @handler('usage : add ') + def add(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask): + if not vpn_src in self.vpns: + DictSubHandler.add(self, vpn_src, vpn_dst, vpn_src_ip, vpn_src_mask, None, None) + elif vpn_src in self.vpns: + if self.vpns[vpn_src].dele : + self.vpns[vpn_src] = False + + @handler('usage : delete ') + def delete(self, vpn_src): + if vpn_src in self.vpns: + self.vpns[vpn_src].dele = True; + + + @handler('usage: start ') + def start(self, vpn_src): + if vpn_src in self.vpns: + call(('tincd','--net=',vpn_src)) + + @handler('usage: stop ') + def stop(self, vpn_src): + if vpn_src in self.vpns: + if path.exists('/var/lib/run/tincd.' + vpn_src + '.pid'): + pid = file('/var/lib/run/tincd.' + vpn_src + '.pid').readline() + try: + os.kill(int(pid.strip()), SIGTERM) + except OSError: + pass # XXX report error? + + def _write_config(self): + for v in self.vpns.values(): + #chek whether it's been created or not. + if not v.dele: + if v.pub_key is None : + try: + print 'douugh' + #first create the directory for the vpn + call(('mkdir','-p', path.join(self._config_writer_cfg_dir, v.vpn_src ,'hosts'))) + #this command should generate 2 files inside the vpn + #dir, one rsa_key.priv and one rsa_key.pub + #for some reason debian does not work like this + call(('tincd','-n', v.vpn_src,'-K','<','/dev/null')) + #open the created files and load the keys + f = file(path.join(self._config_writer_cfg_dir, v.vpn_src , 'rsa_key.priv'), 'r') + priv = f.read() + f.close() + f = file(path.join(self._config_writer_cfg_dir, v.vpn_src ,'rsa_key.pub'), 'r') + pub = f.read() + f.close() + v.pub_key = pub + v.priv_key = priv + except ExecutionError, e: + print e + + vars = dict( + vpn = v, + ) + self._write_single_config('tinc.conf',path.join(v.vpn_src,'tinc.conf'),vars) + self._write_single_config('tinc-up',path.join(v.vpn_src,'tinc-up'),vars) + for h in v.hosts.values(): + if not h.dele: + vars = dict( + host = h, + ) + self._write_single_config('host',path.join(v.vpn_src,'hosts',h.name),vars) + else: + try: + call(('rm','-f', path.join(v.vpn_src,'hosts',h.name))) + del v.hosts[h.name] + except ExecutionError, e: + print e + else: + #delete the vpn root at tinc dir + if path.exists('/etc/tinc/' + v.vpn_src): + self.stop(v.vpn_src) + call(('rm','-rf','/etc/tinc/' + v.vpn_src)) + del self.vpns[v.vpn_src] + + +if __name__ == '__main__': + v = VpnHandler() + v.add('test','127.0.0.1','192.168.0.1','255.255.255.0') + #v.host.add('test', 'sarasa' ,'127.0.0.1', '205.25.36.36','kjdhfkbdskljvkjblkbjeslkjbvkljbselvslberjhbvslbevlhb') + v.delete('test') + v.commit() diff --git a/pymin/services/vpn/templates/host b/pymin/services/vpn/templates/host new file mode 100644 index 0000000..c2a2acb --- /dev/null +++ b/pymin/services/vpn/templates/host @@ -0,0 +1,3 @@ +Address = ${host.ip} +Subnet = ${host.src_net} +${host.pub_key} diff --git a/pymin/services/vpn/templates/tinc-up b/pymin/services/vpn/templates/tinc-up new file mode 100644 index 0000000..fa9b987 --- /dev/null +++ b/pymin/services/vpn/templates/tinc-up @@ -0,0 +1 @@ +ifconfig $INTERFACE ${vpn.vpn_src_ip} netmask ${vpn.vpn_src_mask} diff --git a/pymin/services/vpn/templates/tinc.conf b/pymin/services/vpn/templates/tinc.conf new file mode 100644 index 0000000..a3e45ff --- /dev/null +++ b/pymin/services/vpn/templates/tinc.conf @@ -0,0 +1,4 @@ +Name = ${vpn.vpn_src} +Device = /dev/net/tun +PrivateKeyFile = /etc/tinc/${vpn.vpn_src}/rsa_key.priv +ConnectTo = ${vpn.vpn_dst}