lokinet/daemon/lokinet-vpn
2020-07-02 11:13:30 -04:00

103 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import sys
from socket import AF_INET
import zmq
from pyroute2 import IPRoute
class LokinetRPC:
def __init__(self, url):
self._rpc_context = zmq.Context()
self._rpc_socket = self._rpc_context.socket(zmq.DEALER)
self._rpc_socket.setsockopt(zmq.CONNECT_TIMEOUT, 5000)
self._rpc_socket.setsockopt(zmq.HANDSHAKE_IVL, 5000)
self._rpc_socket.connect(url)
self._url = url
def rpc(self, method):
self._rpc_socket.send_multipart([method.encode(), b'lokinet_vpn'+method.encode()])
if not self._rpc_socket.poll(timeout=50):
return
reply = self._rpc_socket.recv_multipart()
if len(reply) >= 3 and reply[0:2] == [b'REPLY', b'lokinet_vpn'+method.encode()]:
return reply[2].decode()
def get_first_hops(self):
data = self.rpc("llarp.status")
for link in data['result']['links']['outbound']:
for session in link["sessions"]['established']:
yield session['remoteAddr']
def close(self):
self._rpc_socket.close(linger=0)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--rpc", type=str, default='tcp://127.0.0.1:1190')
ap.add_argument("--ifname", type=str, default="lokitun0")
ap.add_argument("--up", action='store_const', dest='action', const='up')
ap.add_argument("--down", action='store_const', dest='action', const='down')
args = ap.parse_args()
rpc = LokinetRPC(args.rpc)
hops = dict()
for hop in rpc.get_first_hops():
ip = hop.split(':')[0]
hops[ip] = 0
rpc.close()
if len(hops) == 0:
print("lokinet is not connected yet")
return 1
with IPRoute() as ip:
ip.bind()
try:
idx = ip.link_lookup(ifname=args.ifname)[0]
except:
print("cannot find {}".format(args.ifname))
return 1
gateways = ip.get_default_routes(family=AF_INET)
gateway = None
for g in gateways:
useThisGateway = True
for name, val in g['attrs']:
if name == 'RTA_OIF' and val == idx:
useThisGateway = False
if not useThisGateway:
continue
for name, val in g['attrs']:
if name == 'RTA_GATEWAY':
gateway = val
if gateway:
for address in hops:
try:
if args.action == 'up':
ip.route("add", dst="{}/32".format(address), gateway=gateway)
elif args.action == 'down':
ip.route("del", dst="{}/32".format(address), gateway=gateway)
except:
pass
if args.action == 'up':
try:
ip.route('add', dst='0.0.0.0/0', oif=idx)
except:
print('failed to add default route')
return 1
elif args.action == 'down':
try:
ip.route('del', dst='0.0.0.0/0', oif=idx)
except:
print('failed to remove default route')
return 1
else:
print("could not find gateway")
return 1
return 0
if __name__ == '__main__':
sys.exit(main())