diff --git a/examples/develop/wireguard/wireguard.vsh b/examples/develop/wireguard/wireguard.vsh new file mode 100755 index 00000000..dc2b236b --- /dev/null +++ b/examples/develop/wireguard/wireguard.vsh @@ -0,0 +1,34 @@ +#!/usr/bin/env -S v -n -w -gc none -no-retry-compilation -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.clients.wireguard +import time + +println('HIIII') + +// Create Wireguard client +mut wg := wireguard.get()! +println('Hello') +config_file_path := '~/wg1.conf' + +println('Before start') +wg.start(config_file_path: config_file_path)! +println('${config_file_path} is started') + +time.sleep(time.second * 2) + +info := wg.show()! +println('info: ${info}') + +config := wg.show_config(interface_name: 'wg1')! +println('config: ${config}') + +private_key := wg.generate_private_key()! +println('private_key: ${private_key}') + +public_key := wg.get_public_key(private_key: private_key)! +println('public_key: ${public_key}') + +time.sleep(time.second * 2) + +wg.down(config_file_path: config_file_path)! +println('${config_file_path} is down') diff --git a/lib/clients/wireguard/client.v b/lib/clients/wireguard/client.v index 16b8d737..f79628bc 100644 --- a/lib/clients/wireguard/client.v +++ b/lib/clients/wireguard/client.v @@ -1,16 +1,115 @@ module wireguard -fn (wg WireGuard) show() { +import os + +pub struct WGPeer { +pub mut: + endpoint string + allowed_ips string + latest_handshake string + transfer string + persistent_keepalive string } -fn (wg WireGuard) up() { +pub struct WGInterface { +pub mut: + name string + public_key string + listening_port int } -fn (wg WireGuard) down() { +pub struct WGInfo { +pub mut: + interface_ WGInterface + peers map[string]WGPeer } -fn (wg WireGuard) generate_key() !string { +pub struct WGShow { +pub mut: + configs map[string]WGInfo } -fn (wg WireGuard) get_public_key() { +pub fn (wg WireGuard) show() !WGShow { + cmd := 'wg show' + res := os.execute(cmd) + if res.exit_code != 0 { + return error('failed to execute show command due to: ${res.output}') + } + + return wg.parse_show_command_output(res.output) +} + +@[params] +pub struct ShowConfigArgs { +pub: + interface_name string @[required] +} + +pub fn (wg WireGuard) show_config(args ShowConfigArgs) !WGInfo { + configs := wg.show()!.configs + config := configs[args.interface_name] or { + return error('key ${args.interface_name} does not exists.') + } + return config +} + +@[params] +pub struct StartArgs { +pub: + config_file_path string @[required] +} + +pub fn (wg WireGuard) start(args StartArgs) ! { + if os.exists(args.config_file_path) { + return error('File ${args.config_file_path} does not exists.') + } + + cmd := 'sudo wg-quick up ${args.config_file_path}' + println('cmd: ${cmd}') + res := os.execute(cmd) + if res.exit_code != 0 { + return error('failed to execute start command due to: ${res.output}') + } +} + +@[params] +pub struct DownArgs { +pub: + config_file_path string @[required] +} + +pub fn (wg WireGuard) down(args DownArgs) ! { + if os.exists(args.config_file_path) { + return error('File ${args.config_file_path} does not exists.') + } + + cmd := 'sudo wg-quick down ${args.config_file_path}' + res := os.execute(cmd) + if res.exit_code != 0 { + return error('failed to execute down command due to: ${res.output}') + } +} + +pub fn (wg WireGuard) generate_private_key() !string { + cmd := 'wg genkey' + res := os.execute(cmd) + if res.exit_code != 0 { + return error('failed to execute genkey command due to: ${res.output}') + } + return res.output.trim_space() +} + +@[params] +pub struct GetPublicKeyArgs { +pub: + private_key string @[required] +} + +pub fn (wg WireGuard) get_public_key(args GetPublicKeyArgs) !string { + cmd := 'echo ${args.private_key} | wg pubkey' + res := os.execute(cmd) + if res.exit_code != 0 { + return error('failed to execute pubkey command due to: ${res.output}') + } + return res.output.trim_space() } diff --git a/lib/clients/wireguard/utils.v b/lib/clients/wireguard/utils.v new file mode 100644 index 00000000..968973e7 --- /dev/null +++ b/lib/clients/wireguard/utils.v @@ -0,0 +1,72 @@ +module wireguard + +fn (wg WireGuard) parse_show_command_output(res string) !WGShow { + mut configs := map[string]WGInfo{} + mut lines := res.split('\n') + mut current_interface := '' + mut current_peers := map[string]WGPeer{} + mut iface := WGInterface{} + mut peer_key := '' + + for line in lines { + mut parts := line.trim_space().split(': ') + if parts.len < 2 { + continue + } + + key := parts[0] + value := parts[1] + + if key.starts_with('interface') { + if current_interface != '' { + configs[current_interface] = WGInfo{ + interface_: iface + peers: current_peers.clone() + } + current_peers.clear() + } + + current_interface = value + iface = WGInterface{ + name: current_interface + public_key: '' + listening_port: 0 + } + } else if key == 'public key' { + iface.public_key = value + } else if key == 'listening port' { + iface.listening_port = value.int() + } else if key.starts_with('peer') { + peer_key = value + mut peer := WGPeer{ + endpoint: '' + allowed_ips: '' + latest_handshake: '' + transfer: '' + persistent_keepalive: '' + } + current_peers[peer_key] = peer + } else if key == 'endpoint' { + current_peers[peer_key].endpoint = value + } else if key == 'allowed ips' { + current_peers[peer_key].allowed_ips = value + } else if key == 'latest handshake' { + current_peers[peer_key].latest_handshake = value + } else if key == 'transfer' { + current_peers[peer_key].transfer = value + } else if key == 'persistent keepalive' { + current_peers[peer_key].persistent_keepalive = value + } + } + + if current_interface != '' { + configs[current_interface] = WGInfo{ + interface_: iface + peers: current_peers.clone() + } + } + + return WGShow{ + configs: configs + } +} diff --git a/lib/clients/wireguard/wireguard_factory_.v b/lib/clients/wireguard/wireguard_factory_.v index 3ab85106..05f75018 100644 --- a/lib/clients/wireguard/wireguard_factory_.v +++ b/lib/clients/wireguard/wireguard_factory_.v @@ -22,22 +22,29 @@ fn args_get(args_ ArgsGet) ArgsGet { args.name = wireguard_default } if args.name == '' { - args.name = 'default' + args.name = 'wireguard' } return args } pub fn get(args_ ArgsGet) !&WireGuard { + println('Before the args get') mut args := args_get(args_) + println('Before the bigger if') if args.name !in wireguard_global { - if args.name == 'default' { + println('Before the if connd') + if args.name == 'wireguard' { + println('Before saving') if !config_exists(args) { if default { + println('When saving') config_save(args)! } } + println('When loading') config_load(args)! } + println('After all') } return wireguard_global[args.name] or { println(wireguard_global) diff --git a/lib/clients/wireguard/wireguard_model.v b/lib/clients/wireguard/wireguard_model.v index ad058774..678a308b 100644 --- a/lib/clients/wireguard/wireguard_model.v +++ b/lib/clients/wireguard/wireguard_model.v @@ -20,13 +20,13 @@ pub fn heroscript_default() !string { @[heap] pub struct WireGuard { pub mut: - name string = 'default' + name string = 'wireguard' } fn cfg_play(p paramsparser.Params) ! { // THIS IS EXAMPLE CODE AND NEEDS TO BE CHANGED IN LINE WITH struct above mut mycfg := WireGuard{ - name: p.get_default('name', 'default')! + name: p.get_default('name', 'wireguard')! } set(mycfg)! }