net/wireguard: Reworked widget (#3117)

This commit is contained in:
Patrik Kernstock
2022-10-16 15:31:24 +02:00
committed by GitHub
parent f8aaa97b72
commit ea4fdeb57e
2 changed files with 165 additions and 30 deletions
@@ -2,6 +2,7 @@
/**
* Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
* Copyright (C) 2022 Patrik Kernstock <patrik@kernstock.net>
*
* All rights reserved.
*
@@ -31,9 +32,100 @@
namespace OPNsense\Wireguard\Api;
use OPNsense\Base\ApiMutableModelControllerBase;
use OPNsense\Core\Config;
use OPNsense\Core\Backend;
class GeneralController extends ApiMutableModelControllerBase
{
protected static $internalModelClass = '\OPNsense\Wireguard\General';
protected static $internalModelName = 'general';
public function getStatusAction()
{
// get wireguard configuration
$config = Config::getInstance()->object();
$config = $config->OPNsense->wireguard;
// craft peers array
$peers = [];
$peers_uuid_pubkey = [];
// enabled, name, pubkey
foreach ($config->client->clients->client as $client) {
$peerUuid = (string)$client->attributes()['uuid'];
$peers_uuid_pubkey[$peerUuid] = (string) $client->pubkey;
$peers[$peerUuid] = [
"name" => (string) $client->name,
"enabled" => (integer) $client->enabled,
"publicKey" => (string) $client->pubkey,
];
}
// prepare and initialize the server array
$status = [];
$peer_pubkey_reference = [];
foreach ($config->server->servers->server as $server) {
if ($server->enabled != "1") continue;
// build basic server array
$interface = "wg".$server->instance;
$status[$interface] = [
"instance" => (integer) $server->instance,
"interface" => (string) $interface,
"enabled" => (integer) $server->enabled,
"name" => (string) $server->name,
"peers" => [],
];
// parse and add peers with initial values to array
if (strlen($server->peers) > 0) {
// there is at least one peer defined
$serverPeers = explode(",", (string) $server->peers);
// iteriate over each peer uuid
foreach ($serverPeers as $peerUuid) {
// remember interface and pubkey <> peer-uuid reference for referencing handshake logic below
$peer_pubkey_reference[$interface][$peers_uuid_pubkey[$peerUuid]] = $peerUuid;
// merge peer info and initial values for handshake data
$status[$interface]["peers"][$peerUuid] = array_merge(
$peers[$peerUuid],
[
"lastHandshake" => "0000-00-00 00:00:00+00:00",
]);
}
}
}
// Get latest handshakes by running CLI command locally
$data = (new Backend())->configdRun("wireguard showhandshake");
// parse and set handshake to status datastructure
$data = trim($data);
if (strlen($data) !== 0) {
$wgHandshakes = explode("\n", $data);
foreach ($wgHandshakes as $handshake) {
$item = explode("\t", trim($handshake));
// set interface name and publickey
$interface = trim($item[0]);
$pubkey = trim($item[1]);
// calculate handshake time based on local timezone
$epoch = $item[2];
if ($epoch > 0) {
$dt = new \DateTime("@$epoch");
$dt->setTimezone(new \DateTimeZone(date_default_timezone_get()));
$latest = $dt->format("Y-m-d H:i:sP");
// set handshake
$peerUuid = $peer_pubkey_reference[$interface][$pubkey];
if (!empty($peerUuid)) {
$status[$interface]["peers"][$peerUuid]["lastHandshake"] = $latest;
}
}
}
}
return [
"items" => $status
];
}
}
@@ -3,6 +3,7 @@
/*
* Copyright (C) 2020 Deciso B.V.
* Copyright (C) 2020 D. Domig
* Copyright (C) 2022 Patrik Kernstock <patrik@kernstock.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,50 +31,92 @@
require_once("guiconfig.inc");
require_once("widgets/include/wireguard.inc");
$data = trim(configd_run('wireguard showhandshake'));
$enabled = ($config["OPNsense"]["wireguard"]["general"]["enabled"] === "1" ? true : false);
$empty = strlen($data) == 0;
?>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th><?= gettext("Name") ?></th>
<th><?= gettext("Interface") ?></th>
<th><?= gettext("Endpoint") ?></th>
<th><?= gettext("Public Key") ?></th>
<th><?= gettext("Latest Handshake") ?></th>
</tr>
</thead>
<tbody>
<?php if (!$empty):
$handshakes = explode("\n", $data);
foreach ($handshakes as $handshake):
$item = explode("\t", $handshake);
$epoch = $item[2];
$latest = "-";
if ($epoch > 0):
$dt = new DateTime("@$epoch");
$dt->setTimezone(new DateTimeZone(date_default_timezone_get()));
$latest = $dt->format(gettext("Y-m-d H:i:sP"));
endif; ?>
<tbody id="wg-table-tbody">
<?php if (!$enabled): ?>
<tr>
<td><?= $item[0] ?></td>
<td><?= gettext(substr($item[1], 0, 10)) ?>...</td>
<td><?= $latest ?></td>
<td colspan="5"><?= gettext("No WireGuard instance defined or enabled.") ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="3"><?= gettext("No WireGuard instance defined or enabled.") ?></td>
</tr>
<?php endif; ?>
<?php endif; ?>
</tbody>
</table>
<script>
$(window).on("load", function() {
function wgGenerateRow(name, interface, peerName, publicKey, latestHandshake, status)
{
publicKeyShort = publicKey.slice(0, 19) + '...';
var tr = ''
+'<tr>'
+' <td>' + name + '</td>'
+' <td>' + interface + '</td>'
+' <td>' + peerName + '</td>'
+' <td title="' + publicKey + '">' + publicKeyShort + '</td>'
+' <td>' + latestHandshake + '</td>'
+'</tr>';
return tr;
}
function wgUpdateStatusIf(obj)
{
// check if at least one peer is set. If not, ignore it.
if (Object.keys(obj.peers).length == 0) {
return '';
}
// generate row based on data
row = '';
for (var peerId in obj.peers) {
var peer = obj.peers[peerId];
// generate table row
row += wgGenerateRow(
obj.name,
obj.interface,
peer.name,
peer.publicKey,
peer.lastHandshake,
status
);
}
return row;
}
function wgUpdateStatus()
{
var table = '';
ajaxGet("/api/wireguard/general/getStatus", {}, function(data, status) {
if (status === 'success') {
for (var interface in data.items) {
table += wgUpdateStatusIf(data.items[interface]);
}
}
// update table accordingly
document.getElementById("wg-table-tbody").innerHTML = table;
setTimeout(wgUpdateStatus, 10000);
});
};
<?php if ($enabled): ?>
wgUpdateStatus();
<?php endif; ?>
});
</script>