|
# 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() |
@SamuelDudley, seems like your python script gets terminated with the exception when:
I took your script as the basis and trying to adopt it in order to be able to restart the VPN connections on our remote peers,