From 32a83e64877e1572441fa15af995b58c7e982bf1 Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sun, 27 Aug 2023 18:57:48 +0200 Subject: [PATCH] VPN: WireGuard: Diagnostics - remove diagnostics tabs from "VPN: WireGuard: Settings" and replace it for a searchable grid containing the same information at "VPN: WireGuard: Diagnostics". Keep text mode endpoints for backwards compatibility in case someone queries them (to be removed in 24.1). --- net/wireguard/pkg-descr | 2 + .../Wireguard/Api/ServiceController.php | 36 ++++++++ .../Wireguard/DiagnosticsController.php | 37 ++++++++ .../models/OPNsense/Wireguard/Menu/Menu.xml | 3 +- .../views/OPNsense/Wireguard/diagnostics.volt | 89 +++++++++++++++++++ .../app/views/OPNsense/Wireguard/general.volt | 26 ------ .../src/opnsense/scripts/Wireguard/wg_show.py | 64 +++++++++++++ .../conf/actions.d/actions_wireguard.conf | 6 ++ 8 files changed, 236 insertions(+), 27 deletions(-) create mode 100644 net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/DiagnosticsController.php create mode 100644 net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/diagnostics.volt create mode 100755 net/wireguard/src/opnsense/scripts/Wireguard/wg_show.py diff --git a/net/wireguard/pkg-descr b/net/wireguard/pkg-descr index 8a590fa7e..77e00f49c 100644 --- a/net/wireguard/pkg-descr +++ b/net/wireguard/pkg-descr @@ -25,6 +25,8 @@ Changelog * Reimplement https://github.com/WireGuard/wireguard-tools/tree/master/contrib/reresolve-dns using Python in reresolve-dns.py * Enforce wireguard-tools rc script to be disabled when still installed, this should prevent bootup issues * Move 'interface' calculated field to model for easy reusability +* Move diagnostics to VPN: WireGuard: Diagnostics +* Change keypair generation to a separate API call and form button to ease copy/paste when adding new servers. * Change plugin maintainer 1.13 diff --git a/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ServiceController.php b/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ServiceController.php index f71b3d047..001c7890d 100644 --- a/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ServiceController.php +++ b/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ServiceController.php @@ -32,6 +32,8 @@ namespace OPNsense\Wireguard\Api; use OPNsense\Base\ApiMutableServiceControllerBase; use OPNsense\Core\Backend; use OPNsense\Wireguard\General; +use OPNsense\Wireguard\Client; +use OPNsense\Wireguard\Server; /** * Class ServiceController @@ -72,6 +74,7 @@ class ServiceController extends ApiMutableServiceControllerBase /** * show wireguard config + * XXX: remove in 24.1 * @return array */ public function showconfAction() @@ -82,6 +85,7 @@ class ServiceController extends ApiMutableServiceControllerBase /** * show wireguard handshakes + * XXX: remove in 24.1 * @return array */ public function showhandshakeAction() @@ -89,4 +93,36 @@ class ServiceController extends ApiMutableServiceControllerBase $response = (new Backend())->configdRun("wireguard showhandshake"); return array("response" => $response); } + + /** + * wg show all dump output + * @return array + */ + public function showAction() + { + $payload = json_decode((new Backend())->configdRun("wireguard show") ?? '', true); + $records = !empty($payload) && !empty($payload['records']) ? $payload['records'] : []; + $key_descriptions = []; + foreach ((new Client())->clients->client->iterateItems() as $key => $client) { + $key_descriptions[(string)$client->pubkey] = (string)$client->name; + } + foreach ((new Server())->servers->server->iterateItems() as $key => $server) { + $key_descriptions[(string)$server->pubkey] = (string)$server->name; + } + foreach ($records as &$record) { + if (!empty($record['public-key']) && !empty($key_descriptions[$record['public-key']])) { + $record['name'] = $key_descriptions[$record['public-key']]; + } else { + $record['name'] = ''; + } + } + $filter_funct = null; + $types = $this->request->get('type'); + if (!empty($types)) { + $filter_funct = function ($record) use ($types) { + return in_array($record['type'], $types); + }; + } + return $this->searchRecordsetBase($records, null, null, $filter_funct); + } } diff --git a/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/DiagnosticsController.php b/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/DiagnosticsController.php new file mode 100644 index 000000000..852ea92ac --- /dev/null +++ b/net/wireguard/src/opnsense/mvc/app/controllers/OPNsense/Wireguard/DiagnosticsController.php @@ -0,0 +1,37 @@ +view->pick('OPNsense/Wireguard/diagnostics'); + } +} diff --git a/net/wireguard/src/opnsense/mvc/app/models/OPNsense/Wireguard/Menu/Menu.xml b/net/wireguard/src/opnsense/mvc/app/models/OPNsense/Wireguard/Menu/Menu.xml index 8494a617f..f2c15f406 100644 --- a/net/wireguard/src/opnsense/mvc/app/models/OPNsense/Wireguard/Menu/Menu.xml +++ b/net/wireguard/src/opnsense/mvc/app/models/OPNsense/Wireguard/Menu/Menu.xml @@ -1,7 +1,8 @@ - + + diff --git a/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/diagnostics.volt b/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/diagnostics.volt new file mode 100644 index 000000000..ca0f8f9e8 --- /dev/null +++ b/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/diagnostics.volt @@ -0,0 +1,89 @@ +{# + # Copyright (c) 2023 Deciso B.V. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without modification, + # are permitted provided that the following conditions are met: + # + # 1. Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # + # 2. Redistributions in binary form must reproduce the above copyright notice, + # this list of conditions and the following disclaimer in the documentation + # and/or other materials provided with the distribution. + # + # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + # AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + # OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + # POSSIBILITY OF SUCH DAMAGE. + #} + + + +
+ + + + + + + + + + + + + + + + + +
{{ lang._('Interface') }}{{ lang._('Type') }}{{ lang._('Public key') }}{{ lang._('Name') }}{{ lang._('Port / Endpoint') }}{{ lang._('Handshake') }}{{ lang._('Send') }}{{ lang._('Received') }}
+
\ No newline at end of file diff --git a/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt b/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt index 84d598c6f..5960b3b2b 100644 --- a/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt +++ b/net/wireguard/src/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt @@ -78,24 +78,6 @@ } }); }) - - // Put API call into a function, needed for auto-refresh - function update_showconf() { - ajaxCall(url="/api/wireguard/service/showconf", sendData={}, callback=function(data,status) { - $("#listshowconf").text(data['response']); - setTimeout(update_showconf, 5000); - }); - } - - function update_showhandshake() { - ajaxCall(url="/api/wireguard/service/showhandshake", sendData={}, callback=function(data,status) { - $("#listshowhandshake").text(data['response']); - setTimeout(update_showhandshake, 5000); - }); - } - // Call update funcs once when page loaded - update_showconf(); - update_showhandshake(); }); @@ -103,8 +85,6 @@
  • {{ lang._('General') }}
  • {{ lang._('Local') }}
  • {{ lang._('Endpoints') }}
  • -
  • {{ lang._('Status') }}
  • -
  • {{ lang._('Handshakes') }}
  • @@ -169,12 +149,6 @@
    -
    -
    
    -    
    -
    -
    
    -    
    diff --git a/net/wireguard/src/opnsense/scripts/Wireguard/wg_show.py b/net/wireguard/src/opnsense/scripts/Wireguard/wg_show.py new file mode 100755 index 000000000..60973e10d --- /dev/null +++ b/net/wireguard/src/opnsense/scripts/Wireguard/wg_show.py @@ -0,0 +1,64 @@ +#!/usr/local/bin/python3 + +""" + Copyright (c) 2023 Ad Schellevis + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import subprocess +import ujson + +sp = subprocess.run(['/usr/bin/wg', 'show', 'all', 'dump'], capture_output=True, text=True) +result = {'records': []} +if sp.returncode == 0: + for line in sp.stdout.split("\n"): + record = {} + parts = line.split("\t") + # parse fields as explained in 'man wg' + record['if'] = parts[0] if len(parts) else None + if len(parts) == 5: + # intentially skip private key, should not expose it + record['type'] = 'interface' + record['public-key'] = parts[2] + record['listen-port'] = parts[3] + record['fwmark'] = parts[4] + # convenience, copy listen-port to endpoint + record['endpoint'] = parts[3] + elif len(parts) == 9: + record['type'] = 'peer' + record['public-key'] = parts[1] + # intentially skip preshared-key, should not expose it + record['endpoint'] = parts[3] + record['allowed-ips'] = parts[4] + record['latest-handshake'] = int(parts[5]) if parts[5].isdigit() else 0 + record['transfer-rx'] = int(parts[6]) if parts[6].isdigit() else 0 + record['transfer-tx'] = int(parts[7]) if parts[7].isdigit() else 0 + record['persistent-keepalive'] = parts[8] + else: + continue + result['records'].append(record) + result['status'] = 'ok' +else: + result['status'] = 'failed' + +print(ujson.dumps(result)) \ No newline at end of file diff --git a/net/wireguard/src/opnsense/service/conf/actions.d/actions_wireguard.conf b/net/wireguard/src/opnsense/service/conf/actions.d/actions_wireguard.conf index 397ded496..44c925e86 100644 --- a/net/wireguard/src/opnsense/service/conf/actions.d/actions_wireguard.conf +++ b/net/wireguard/src/opnsense/service/conf/actions.d/actions_wireguard.conf @@ -35,6 +35,12 @@ parameters: type:script_output message:Generating WireGuard keypair +[show] +command:/usr/local/opnsense/scripts/Wireguard/wg_show.py +parameters: +type:script_output +message:show WireGuard statistics [dump] + [showconf] command:/usr/bin/wg show all parameters: