mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
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).
This commit is contained in:
@@ -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
|
||||
|
||||
+36
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Wireguard;
|
||||
|
||||
class DiagnosticsController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Wireguard/diagnostics');
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
<menu>
|
||||
<VPN>
|
||||
<WireGuard cssClass="fa fa-lock fa-fw" order="150">
|
||||
<Settings order="10" url="/ui/wireguard/general/index"/>
|
||||
<Settings order="10" url="/ui/wireguard/general/"/>
|
||||
<Diagnostics order="20" url="/ui/wireguard/diagnostics/"/>
|
||||
<LogFile order="70" VisibleName="Log File" url="/ui/diagnostics/log/core/wireguard"/>
|
||||
</WireGuard>
|
||||
</VPN>
|
||||
|
||||
@@ -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.
|
||||
#}
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
|
||||
let grid_phase1 = $("#grid-sessions").UIBootgrid({
|
||||
search:'/api/wireguard/service/show',
|
||||
options:{
|
||||
multiSelect: false,
|
||||
rowSelect: false,
|
||||
selection: false,
|
||||
formatters:{
|
||||
bytes: function(column, row) {
|
||||
if (row[column.id] && row[column.id] > 0) {
|
||||
return byteFormat(row[column.id], 2);
|
||||
}
|
||||
return row[column.id];
|
||||
}
|
||||
},
|
||||
requestHandler: function(request){
|
||||
if ( $('#type_filter').val().length > 0) {
|
||||
request['type'] = $('#type_filter').val();
|
||||
}
|
||||
return request;
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
$("#type_filter").change(function(){
|
||||
$('#grid-sessions').bootgrid('reload');
|
||||
});
|
||||
|
||||
$("#type_filter_container").detach().prependTo('#grid-sessions-header > .row > .actionBar > .actions');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="tab-content content-box">
|
||||
<div class="hidden">
|
||||
<!-- filter per type container -->
|
||||
<div id="type_filter_container" class="btn-group">
|
||||
<select id="type_filter" data-title="{{ lang._('Type') }}" class="selectpicker" multiple="multiple" data-width="200px">
|
||||
<option value="interface">{{ lang._('Interface') }}</option>
|
||||
<option value="peer">{{ lang._('Peer') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<table id="grid-sessions" class="table table-condensed table-hover table-striped table-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="if" data-type="string" data-width="8em">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="type" data-type="string" data-width="8em" data-visible="false">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="public-key" data-type="string" data-identifier="true">{{ lang._('Public key') }}</th>
|
||||
<th data-column-id="name" data-type="string">{{ lang._('Name') }}</th>
|
||||
<th data-column-id="endpoint" data-type="string">{{ lang._('Port / Endpoint') }}</th>
|
||||
<th data-column-id="latest-handshake" data-type="numeric">{{ lang._('Handshake') }}</th>
|
||||
|
||||
<th data-column-id="transfer-tx" data-formatter="bytes" data-type="numeric">{{ lang._('Send') }}</th>
|
||||
<th data-column-id="transfer-rx" data-formatter="bytes" data-type="numeric">{{ lang._('Received') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -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();
|
||||
});
|
||||
</script>
|
||||
<!-- Navigation bar -->
|
||||
@@ -103,8 +85,6 @@
|
||||
<li class="active"><a data-toggle="tab" href="#general">{{ lang._('General') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#servers">{{ lang._('Local') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#clients">{{ lang._('Endpoints') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#showconf">{{ lang._('Status') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#showhandshake">{{ lang._('Handshakes') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box tab-content">
|
||||
@@ -169,12 +149,6 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div id="showconf" class="tab-pane fade in">
|
||||
<pre id="listshowconf"></pre>
|
||||
</div>
|
||||
<div id="showhandshake" class="tab-pane fade in">
|
||||
<pre id="listshowhandshake"></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="page-content-main">
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/local/bin/python3
|
||||
|
||||
"""
|
||||
Copyright (c) 2023 Ad Schellevis <ad@opnsense.org>
|
||||
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))
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user