Vici Pyton Modul: Unterschied zwischen den Versionen

Aus xinux.net
Zur Navigation springen Zur Suche springen
Zeile 41: Zeile 41:
 
=API documentation=
 
=API documentation=
 
For more details about the Python egg refer to the comments in the Python source code.
 
For more details about the Python egg refer to the comments in the Python source code.
 +
=Example=
 +
<pre>
 +
# This python script is *not* required to setup and run a tunnel,
 +
# rather it shows how an external python script can bring a tunnel up / down and monitor its status.
 +
 +
import vici
 +
import multiprocessing
 +
import collections
 +
import time
 +
# NOTE: unless you are root you will need to do the following: sudo chmod 777 /var/run/charon.vici
 +
 +
# Edit target_connections in the VState to include the VPN connections you would like to keep alive
 +
# if this connection is dropped for some reason it will be re-started automatically by the python script
 +
 +
class VState(object):
 +
    """holds the VPN state"""
 +
    def __init__(self):
 +
        self.alive = True
 +
        self.session = vici.Session()
 +
        self.possible_connections = []
 +
        self.target_connections = ['rw-2']
 +
        self.active_connections = []
 +
   
 +
class StrongSwan(object):
 +
    def __init__(self,  queue = None):
 +
        self.state = VState()
 +
        self.get_possible_connections()
 +
   
 +
    def process_control_connection_in(self):
 +
        '''handle incoming mavlink packets'''
 +
        pass
 +
   
 +
    def check_interfaces(self):
 +
        state = self.state
 +
        for vpn_conn in state.session.list_sas():
 +
            for key in state.active_connections:
 +
try:
 +
                  print 'key', key
 +
                  print vpn_conn[key]
 +
                  print vpn_conn[key]['established']
 +
                  print vpn_conn[key]['state']
 +
                  print vpn_conn[key]['local-host']
 +
                  print vpn_conn[key]['remote-host']
 +
except:
 +
  pass
 +
               
 +
                try:
 +
                    child = vpn_conn[key]['child-sas']
 +
                    if child == {}:
 +
                        child = None
 +
                except:
 +
                    print 'tunnel not connected at child level!'
 +
                    child = None
 +
               
 +
                if child is not None:
 +
                    for child_key in child:
 +
                       
 +
                        print 'time: ', time.time(), 'child key', child_key, child[child_key]['bytes-in'], child[child_key]['bytes-out']
 +
                   
 +
                        #print 'packets'
 +
                        #print 'in: ', child[child_key]['packets-in']
 +
                        #print 'out: ', child[child_key]['packets-out']
 +
                       
 +
                        #print 'bytes'
 +
                        #print 'in: ', child[child_key]['bytes-in']
 +
                        #print 'out: ', child[child_key]['bytes-out']
 +
                   
 +
                        #print child[child_key]['mode']
 +
                        #print 'ip: ', child[child_key]['local-ts']
 +
                        #print child[child_key]['remote-ts']
 +
                        #print 'key: ', child[child_key]['rekey-time']
 +
                        #print 'life: ', child[child_key]['life-time']
 +
                   
 +
               
 +
                if key in state.target_connections and child is None:
 +
                    self.connection_down(key)
 +
                    self.connection_up(key)
 +
       
 +
        for key in state.target_connections:
 +
            if key not in state.active_connections:
 +
                #the connection is inactive
 +
                self.connection_up(key)
 +
               
 +
       
 +
    def connection_up(self, key):
 +
        state = self.state
 +
        print 'up: ', key
 +
sa = collections.OrderedDict()
 +
sa['child'] = key
 +
sa['timeout'] = '2000'
 +
sa['loglevel'] = '0'
 +
rep =state.session.initiate(sa)
 +
rep.next()
 +
rep.close()
 +
 +
        #TODO: handle errors, log?
 +
       
 +
    def connection_down(self, key):
 +
        state = self.state
 +
        print 'down: ', key
 +
sa = collections.OrderedDict()
 +
sa['ike'] = key
 +
sa['timeout'] = '2000'
 +
sa['loglevel'] = '0'
 +
rep =state.session.terminate(sa)
 +
rep.next()
 +
rep.close()
 +
   
 +
#TODO: handle errors, log?
 +
 +
    def get_possible_connections(self):
 +
        '''reset and repopulate possible connections based on /etc/ipsec.conf'''
 +
        state = self.state
 +
        state.possible_connections = []
 +
        for conn in state.session.list_conns():
 +
            for key in conn:
 +
                state.possible_connections.append(key)
 +
       
 +
        print 'p',state.possible_connections
 +
               
 +
    def get_active_connections(self):
 +
        state = self.state
 +
        state.active_connections = []
 +
       
 +
        for conn in state.session.list_sas():
 +
            for key in conn:
 +
                state.active_connections.append(key)
 +
       
 +
        print 'a', state.active_connections
 +
               
 +
    def is_alive(self):
 +
        return self.state.alive
 +
 +
def main_loop():
 +
    '''main processing loop'''
 +
    #make a strongSwan control object
 +
    VPN = StrongSwan()
 +
    while VPN.is_alive():
 +
        VPN.process_control_connection_in()
 +
        VPN.get_possible_connections()
 +
        VPN.get_active_connections()
 +
        VPN.check_interfaces()
 +
        time.sleep(1.0)
 +
   
 +
 +
 +
if __name__ == '__main__':
 +
    #run main loop as a process
 +
    main = multiprocessing.Process(target=main_loop)
 +
    main.start()
 +
    main.join()
 +
</pre>
 +
 
=Sources=
 
=Sources=
 
*https://github.com/sbjorn/vici
 
*https://github.com/sbjorn/vici
 
*https://github.com/strongswan/strongswan/blob/master/src/libcharon/plugins/vici/python/vici/session.py
 
*https://github.com/strongswan/strongswan/blob/master/src/libcharon/plugins/vici/python/vici/session.py
 
*https://gist.githubusercontent.com/SamuelDudley/40ea891c7f1fd0221bc0b25e185fe8c6/raw/ad454506c56a87ad682a2c3027a55271df9ae6fc/vpn_control.py
 
*https://gist.githubusercontent.com/SamuelDudley/40ea891c7f1fd0221bc0b25e185fe8c6/raw/ad454506c56a87ad682a2c3027a55271df9ae6fc/vpn_control.py

Version vom 17. Dezember 2017, 17:29 Uhr

From the documentation

vici Python egg

The vici Python egg is a pure Python implementation of the VICI protocol to implement client applications. It is provided in the python subdirectory, and gets built and installed if strongSwan has been ./configure'd with --enable-vici and --enable-python-eggs.

The vici module provides a Session() constructor for a high level interface, the underlying classes are usually not required to build Python applications using VICI. The Session class provides methods for the supported VICI commands.

To represent the VICI message data tree, the library converts the binary encoding to Python data types. The Session class takes and returns Python objects for the exchanged message data:

Sections get encoded as OrderedDict, containing other sections, or Key/Values, where the values are strings as dictionary values Lists get encoded as Python Lists with string values Values that do not conform to Python dict or list get converted to strings using str(). Connecting to the daemon To create a connection to the daemon, a socket can be passed to the Session constructor. If none is passed, a default Unix socket at /var/run/charon.vici is used:

import vici
import socket

s = socket.socket(socket.AF_UNIX)
s.connect("/var/run/charon.vici")
v = vici.Session(s)
#A simple client request
#An example to print the daemon version information is as simple as:

ver = v.version()

print "{daemon} {version} ({sysname}, {release}, {machine})".format(**ver)
#A request with response iteration
#The Session class returns an iterable Python generator for streamed events to continuously stream objects to the caller. The following example lists all loaded connections using the list-conns command and implicitly the list-conn event:

for conn in v.list_conns():
	for key in conn:
		print key

Please note that if the returned generator is not iterated completely, it must be closed using close(). This is implicitly done when breaking from a loop, but an explicit call may be required when directly iterating the generator with next().

Sorting in dictionaries

In VICI, in some message trees the order of objects in dictionary matters. In contrast to ruby Hashes, Python dictionaries do not preserve order of added objects. It is therefore recommended to use OrderedDicts instead of the default dictionaries. Objects returned by the library use OrderedDicts.

API documentation

For more details about the Python egg refer to the comments in the Python source code.

Example

# This python script is *not* required to setup and run a tunnel,
# rather it shows how an external python script can bring a tunnel up / down and monitor its status.

import vici
import multiprocessing
import collections
import time
# NOTE: unless you are root you will need to do the following: sudo chmod 777 /var/run/charon.vici

# Edit target_connections in the VState to include the VPN connections you would like to keep alive
# if this connection is dropped for some reason it will be re-started automatically by the python script

class VState(object):
    """holds the VPN state"""
    def __init__(self):
        self.alive = True
        self.session = vici.Session()
        self.possible_connections = []
        self.target_connections = ['rw-2']
        self.active_connections = []
    
class StrongSwan(object):
    def __init__(self,  queue = None):
        self.state = VState()
        self.get_possible_connections()
    
    def process_control_connection_in(self):
        '''handle incoming mavlink packets'''
        pass
    
    def check_interfaces(self):
        state = self.state
        for vpn_conn in state.session.list_sas():
            for key in state.active_connections:
		try:
                   print 'key', key
                   print vpn_conn[key]
                   print vpn_conn[key]['established']
                   print vpn_conn[key]['state']
                   print vpn_conn[key]['local-host']
                   print vpn_conn[key]['remote-host']
		except:
		   pass
                
                try:
                    child = vpn_conn[key]['child-sas']
                    if child == {}:
                        child = None
                except:
                    print 'tunnel not connected at child level!'
                    child = None
                
                if child is not None:
                    for child_key in child:
                        
                        print 'time: ', time.time(), 'child key', child_key, child[child_key]['bytes-in'], child[child_key]['bytes-out']
                     
                        #print 'packets'
                        #print 'in: ', child[child_key]['packets-in']
                        #print 'out: ', child[child_key]['packets-out']
                         
                        #print 'bytes'
                        #print 'in: ', child[child_key]['bytes-in']
                        #print 'out: ', child[child_key]['bytes-out']
                     
                        #print child[child_key]['mode']
                        #print 'ip: ', child[child_key]['local-ts']
                        #print child[child_key]['remote-ts']
                        #print 'key: ', child[child_key]['rekey-time']
                        #print 'life: ', child[child_key]['life-time']
                    
                
                if key in state.target_connections and child is None:
                    self.connection_down(key)
                    self.connection_up(key)
        
        for key in state.target_connections:
            if key not in state.active_connections:
                #the connection is inactive
                self.connection_up(key)
                
        
    def connection_up(self, key):
        state = self.state
        print 'up: ', key
	sa = collections.OrderedDict()
	sa['child'] = key
	sa['timeout'] = '2000'
	sa['loglevel'] = '0'
	rep =state.session.initiate(sa)
	rep.next()
	rep.close()
	
        #TODO: handle errors, log?
        
    def connection_down(self, key):
        state = self.state
        print 'down: ', key
	sa = collections.OrderedDict()
	sa['ike'] = key
	sa['timeout'] = '2000'
	sa['loglevel'] = '0'
	rep =state.session.terminate(sa)
	rep.next()
	rep.close()
    
	#TODO: handle errors, log?

    def get_possible_connections(self):
        '''reset and repopulate possible connections based on /etc/ipsec.conf'''
        state = self.state
        state.possible_connections = []
        for conn in state.session.list_conns():
            for key in conn:
                state.possible_connections.append(key)
        
        print 'p',state.possible_connections
                
    def get_active_connections(self):
        state = self.state
        state.active_connections = []
        
        for conn in state.session.list_sas():
            for key in conn:
                state.active_connections.append(key)
        
        print 'a', state.active_connections
                
    def is_alive(self):
        return self.state.alive

def main_loop():
    '''main processing loop'''
    #make a strongSwan control object
    VPN = StrongSwan()
    while VPN.is_alive():
        VPN.process_control_connection_in()
        VPN.get_possible_connections()
        VPN.get_active_connections()
        VPN.check_interfaces()
        time.sleep(1.0)
    


if __name__ == '__main__':
    #run main loop as a process
    main = multiprocessing.Process(target=main_loop)
    main.start()
    main.join() 

Sources