#!/bin/ucode import * as uloop from 'uloop'; import { readfile, popen, pipe } from 'fs'; //import { event_fns } from './set_endpoint_events.uc' // Aggregate all Endpoints // Start pipe and loop and listen for set_endpoint commands // set_endpoint command structure: userId,endpoint // // The User fetches vendor endpoints over the vendors backend directly from the provider, if not possible if will be fetchable over our service // If the User has a matching plan, the user can provide thier wireguard backend / socks proxy function log(msg,code) { let prefix = "[+] "; if(code == 1) { prefix = "[!W] "; } if(code == 2) { prefix = "[!!!Err] "; } print(prefix + msg + "\n"); } function endpoint_format(ip,port) { return { endpoint: { ip: ip, port: port } }; } function tunnel_ip_format(v4_addr, v6_addr, v4_endpoint, v6_endpoint) { return { tunnel: { ipv4: { if_addr: v4_addr, endpoint: v4_endpoint }, ipv6: { if_addr: v6_addr, endpoint: v6_endpoint } } }; } function wireguard_format(name, pubkey, private_key_path, tunnel_props) { return { wireguard: { name: name, tunnel: tunnel_props, public_key: pubkey, private_key: private_key_path } }; } function socks5_format() {} function nm_unified_format(provider, data) { return { nm_unified: { provider: provider, data: data // Should be array of wireguard or openvpn or socks format } }; } function wireguard_connect(ctx,args) { } // Converts mullvad endpoints respecting its config to nm wireguard endpoint obj function mullvad_parse() { const conf = json(readfile("/etc/providers/config_"+provider_name+".json")); let raw_apiresp = readfile('/tmp/mullvad_endpoints'); let wg_part = {}; log(raw_apiresp); if(raw_apiresp == null) { status = system('uclient-fetch -q -O /tmp/mullvad_endpoints https://api.mullvad.net/app/v1/relays'); log("uclient-fetch error",2); raw_apiresp = readfile('/tmp/mullvad_endpoints'); } const parsed_resp = json(raw_apiresp); log("Loading... mullvad"); log(parsed_resp); wg_part = parsed_resp['wireguard']; const port = 51820; let data = []; let i = 0; MAX_ENDPOINT_COUNT = 5; OFFSET = 0; for (relay in wg_part['relays']) { if(i > MAX_ENDPOINT_COUNT || i < OFFSET) { break; } log("Creating endpoint obj for " + relay); e_v4 = endpoint_format(relay['ipv4_addr_in'],port); e_v6 = endpoint_format(relay['ipv6_addr_in'],port); // Create Mullvad tunnel, getting its internal ip address from the config files (should be set to a database later) tunnel = tunnel_ip_format(conf.ipv4, conf.ipv6, e_v4, e_v6); log("Created Endpoint -> "+ e_v4 + "\n" + e_v6 + "\n"+ tunnel); print(tunnel); push(data, wireguard_format(relay['hostname'], relay['public_key'], config.private_key_path, tunnel)); i += 1; } return nm_unified_format('mullvad',content); } // An array first containing the mullvad_endpoints and then a timestamp of the current time // Used to calculate if the endpoints are old mullvad_endpoints = [mullvad_parse(),time()]; const mainPipeHandle = pipe(); let uloop = uloop.init(); if(!uloop) { log("Error initiating uloop, exiting ...", 2); exit(1); } let p = pipe(); // 1. Read sessionID,CommandID. After reading the initation state is started. CommandID can be resolved to its CommandObject and the pre function can be executed // 2. Read sessionID,commaseperatedvalues after the initation state and the pre function got executed the objects parameters can be populated for the after function // 3. Read sessionID,OpendedCommandID. If the Command initation state was opened for that sessionID execute the apply function using the parameters from step 2 as parameters and then execute the post function let i = 0; log("+++ Creating uloop handle using fd: "); const handle = uloop.handle(p[1],(e) => { if(e & uloop.ULOOP_WRITE) log("Write event " + p[0].read(1024)); },uloop.ULOOP_READ); log("Created Handle for Event Messages - Event Handle:\n" + handle.fileno()); uloop.run();