mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 00:07:26 +00:00
wireguard: merge net/wireguard as of version 2.2 #6827
Omit the dependency on wireguard-kmod as we will be targeting the kernel module with 24.1. Some people may run into this but it's safer than trying to rely on a package that won't be available going from 23.7 to 24.1.
This commit is contained in:
parent
a91bc81aaf
commit
871182c4f2
4
LICENSE
4
LICENSE
@ -6,6 +6,7 @@ Copyright (c) 2005-2008 Bill Marquette <bill.marquette@gmail.com>
|
||||
Copyright (c) 2003-2005 Bob Zoller <bob@kludgebox.com>
|
||||
Copyright (c) 2012 Carlos Cesario <carloscesario@gmail.com>
|
||||
Copyright (c) 2005-2006 Colin Smith <ethethlay@gmail.com>
|
||||
Copyright (c) 2020 D. Domig
|
||||
Copyright (c) 2013 Dagorlad
|
||||
Copyright (c) 2006 Daniel S. Haischt
|
||||
Copyright (c) 2012 Darren Embry <dse@webonastick.com>
|
||||
@ -37,8 +38,9 @@ Copyright (c) 2012 Marcello Coutinho
|
||||
Copyright (c) 2018 Martin Wasley <martin@team-rebellion.net>
|
||||
Copyright (c) 2022 Maurice Walker <maurice@walker.earth>
|
||||
Copyright (c) 2010-2015 Michael Bostock
|
||||
Copyright (c) 2019-2021 Michael Muenz <m.muenz@gmail.com>
|
||||
Copyright (c) 2018-2021 Michael Muenz <m.muenz@gmail.com>
|
||||
Copyright (c) 2019 Pascal Mathis <mail@pascalmathis.com>
|
||||
Copyright (c) 2022 Patrik Kernstock <patrik@kernstock.net>
|
||||
Copyright (c) 2005-2006 Paul Taylor <paultaylor@winn-dixie.com>
|
||||
Copyright (c) 2005-2006 Peter Allgeyer <allgeyer@web.de>
|
||||
Copyright (c) 2004 Peter Curran <peter@closeconsultants.com>
|
||||
|
||||
33
plist
33
plist
@ -43,6 +43,7 @@
|
||||
/usr/local/etc/inc/plugins.inc.d/unbound.inc
|
||||
/usr/local/etc/inc/plugins.inc.d/vxlan.inc
|
||||
/usr/local/etc/inc/plugins.inc.d/webgui.inc
|
||||
/usr/local/etc/inc/plugins.inc.d/wireguard.inc
|
||||
/usr/local/etc/inc/rrd.inc
|
||||
/usr/local/etc/inc/system.inc
|
||||
/usr/local/etc/inc/util.inc
|
||||
@ -127,6 +128,7 @@
|
||||
/usr/local/etc/rc.syshook.d/carp/20-openvpn
|
||||
/usr/local/etc/rc.syshook.d/carp/20-openvpn-instances
|
||||
/usr/local/etc/rc.syshook.d/carp/20-ppp
|
||||
/usr/local/etc/rc.syshook.d/carp/20-wireguard
|
||||
/usr/local/etc/rc.syshook.d/early/05-upgrade
|
||||
/usr/local/etc/rc.syshook.d/early/10-configd
|
||||
/usr/local/etc/rc.syshook.d/early/15-templates
|
||||
@ -464,6 +466,15 @@
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dnsbl.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/forwarding.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/general.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ClientController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/GeneralController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ServerController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/Api/ServiceController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/DiagnosticsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/GeneralController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/forms/dialogEditWireguardClient.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/forms/dialogEditWireguardServer.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Wireguard/forms/general.xml
|
||||
/usr/local/opnsense/mvc/app/library/Google/API/Drive.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/API.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/AuthenticationFactory.php
|
||||
@ -728,6 +739,15 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Migrations/M1_0_8.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Unbound.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Unbound.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/ACL/ACL.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/Client.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/Client.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/FieldTypes/ServerField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/General.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/General.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/Menu/Menu.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/Server.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Wireguard/Server.xml
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/clients.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/index.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/vouchers.volt
|
||||
@ -800,6 +820,8 @@
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/overrides.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/overview.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/stats.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Wireguard/diagnostics.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt
|
||||
/usr/local/opnsense/mvc/app/views/layout_partials/base_dialog.volt
|
||||
/usr/local/opnsense/mvc/app/views/layout_partials/base_dialog_processing.volt
|
||||
/usr/local/opnsense/mvc/app/views/layout_partials/base_form.volt
|
||||
@ -879,6 +901,10 @@
|
||||
/usr/local/opnsense/scripts/OPNsense/Monit/carp_status
|
||||
/usr/local/opnsense/scripts/OPNsense/Monit/gateway_alert
|
||||
/usr/local/opnsense/scripts/OPNsense/Monit/setup.sh
|
||||
/usr/local/opnsense/scripts/Wireguard/gen_keypair.py
|
||||
/usr/local/opnsense/scripts/Wireguard/reresolve-dns.py
|
||||
/usr/local/opnsense/scripts/Wireguard/wg-service-control.php
|
||||
/usr/local/opnsense/scripts/Wireguard/wg_show.py
|
||||
/usr/local/opnsense/scripts/auth/add_user.php
|
||||
/usr/local/opnsense/scripts/auth/list_group_members.php
|
||||
/usr/local/opnsense/scripts/dhcp/cleanup_leases4.php
|
||||
@ -1110,6 +1136,7 @@
|
||||
/usr/local/opnsense/service/conf/actions.d/actions_template.conf
|
||||
/usr/local/opnsense/service/conf/actions.d/actions_unbound.conf
|
||||
/usr/local/opnsense/service/conf/actions.d/actions_webgui.conf
|
||||
/usr/local/opnsense/service/conf/actions.d/actions_wireguard.conf
|
||||
/usr/local/opnsense/service/conf/actions.d/actions_zfs.conf
|
||||
/usr/local/opnsense/service/conf/actions_service.conf
|
||||
/usr/local/opnsense/service/conf/configd.conf
|
||||
@ -1222,6 +1249,7 @@
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/local/squid_access.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/local/suricata.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/local/vpn.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/local/wireguard.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/local/wireless.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/newsyslog.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/rc.conf.d
|
||||
@ -1246,6 +1274,9 @@
|
||||
/usr/local/opnsense/service/templates/OPNsense/WebGui/etc.php.ini
|
||||
/usr/local/opnsense/service/templates/OPNsense/WebGui/lib.php.ini
|
||||
/usr/local/opnsense/service/templates/OPNsense/WebGui/php.ini
|
||||
/usr/local/opnsense/service/templates/OPNsense/Wireguard/+TARGETS
|
||||
/usr/local/opnsense/service/templates/OPNsense/Wireguard/wireguard
|
||||
/usr/local/opnsense/service/templates/OPNsense/Wireguard/wireguard-server.conf
|
||||
/usr/local/opnsense/service/tests/__init__.py
|
||||
/usr/local/opnsense/service/tests/config/config.xml
|
||||
/usr/local/opnsense/service/tests/core.py
|
||||
@ -2090,6 +2121,7 @@
|
||||
/usr/local/www/widgets/include/system_log.inc
|
||||
/usr/local/www/widgets/include/thermal_sensors.inc
|
||||
/usr/local/www/widgets/include/traffic_graph.inc
|
||||
/usr/local/www/widgets/include/wireguard.inc
|
||||
/usr/local/www/widgets/widgets/carp_status.widget.php
|
||||
/usr/local/www/widgets/widgets/cpu_usage.widget.php
|
||||
/usr/local/www/widgets/widgets/gateways.widget.php
|
||||
@ -2107,6 +2139,7 @@
|
||||
/usr/local/www/widgets/widgets/system_log.widget.php
|
||||
/usr/local/www/widgets/widgets/thermal_sensors.widget.php
|
||||
/usr/local/www/widgets/widgets/traffic_graphs.widget.php
|
||||
/usr/local/www/widgets/widgets/wireguard.widget.php
|
||||
/usr/local/www/wizard.php
|
||||
/usr/local/www/xmlrpc.php
|
||||
@sample /usr/local/etc/bogons.sample
|
||||
|
||||
138
src/etc/inc/plugins.inc.d/wireguard.inc
Normal file
138
src/etc/inc/plugins.inc.d/wireguard.inc
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
function wireguard_enabled()
|
||||
{
|
||||
return (string)(new \OPNsense\Wireguard\General())->enabled == '1';
|
||||
}
|
||||
|
||||
function wireguard_services()
|
||||
{
|
||||
$services = [];
|
||||
|
||||
if (!wireguard_enabled()) {
|
||||
return $services;
|
||||
}
|
||||
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $key => $node) {
|
||||
if (!empty((string)$node->enabled)) {
|
||||
$services[] = [
|
||||
'description' => "Wireguard " . htmlspecialchars($node->name),
|
||||
'configd' => [
|
||||
'start' => ["wireguard start {$key}"],
|
||||
'restart' => ["wireguard restart {$key}"],
|
||||
'stop' => ["wireguard stop {$key}"],
|
||||
],
|
||||
'nocheck' => true, /* no daemon to check */
|
||||
'id' => $key,
|
||||
'name' => "wireguard"
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $services;
|
||||
}
|
||||
|
||||
function wireguard_syslog()
|
||||
{
|
||||
return [
|
||||
'wireguard' => ['facility' => ['wireguard']]
|
||||
];
|
||||
}
|
||||
|
||||
function wireguard_interfaces()
|
||||
{
|
||||
$interfaces = [];
|
||||
|
||||
if (!wireguard_enabled()) {
|
||||
return $interfaces;
|
||||
}
|
||||
|
||||
$interfaces['wireguard'] = [
|
||||
'descr' => gettext('WireGuard (Group)'),
|
||||
'if' => 'wireguard',
|
||||
'virtual' => true,
|
||||
'enable' => true,
|
||||
'type' => 'group',
|
||||
'networks' => [],
|
||||
];
|
||||
|
||||
return $interfaces;
|
||||
}
|
||||
|
||||
function wireguard_xmlrpc_sync()
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$result['id'] = 'wireguard';
|
||||
$result['section'] = 'OPNsense.wireguard';
|
||||
$result['description'] = gettext('WireGuard');
|
||||
$result['services'] = ['wireguard'];
|
||||
|
||||
return [$result];
|
||||
}
|
||||
|
||||
function wireguard_devices()
|
||||
{
|
||||
return [['pattern' => '^wg', 'volatile' => true]];
|
||||
}
|
||||
|
||||
function wireguard_configure()
|
||||
{
|
||||
return [
|
||||
'newwanip' => ['wireguard_renew:2'],
|
||||
'vpn' => ['wireguard_configure_do:2'],
|
||||
];
|
||||
}
|
||||
|
||||
function wireguard_configure_do($verbose = false, $unused = '')
|
||||
{
|
||||
if (!wireguard_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
service_log('Configuring WireGuard VPN...', $verbose);
|
||||
|
||||
configd_run('wireguard configure');
|
||||
|
||||
service_log("done.\n", $verbose);
|
||||
}
|
||||
|
||||
function wireguard_renew($verbose = false, $unused = '')
|
||||
{
|
||||
if (!wireguard_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
service_log('Renewing WireGuard VPN...', $verbose);
|
||||
|
||||
configd_run('wireguard renew');
|
||||
|
||||
service_log("done.\n", $verbose);
|
||||
}
|
||||
3
src/etc/rc.syshook.d/carp/20-wireguard
Executable file
3
src/etc/rc.syshook.d/carp/20-wireguard
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
configctl -dq wireguard configure
|
||||
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
*
|
||||
* 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\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
|
||||
class ClientController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'client';
|
||||
protected static $internalModelClass = '\OPNsense\Wireguard\Client';
|
||||
|
||||
public function searchClientAction()
|
||||
{
|
||||
return $this->searchBase(
|
||||
'clients.client',
|
||||
["enabled", "name", "pubkey", "tunneladdress", "serveraddress", "serverport"]
|
||||
);
|
||||
}
|
||||
|
||||
public function getClientAction($uuid = null)
|
||||
{
|
||||
return $this->getBase('client', 'clients.client', $uuid);
|
||||
}
|
||||
|
||||
public function addClientAction()
|
||||
{
|
||||
return $this->addBase('client', 'clients.client');
|
||||
}
|
||||
|
||||
public function delClientAction($uuid)
|
||||
{
|
||||
return $this->delBase('clients.client', $uuid);
|
||||
}
|
||||
|
||||
public function setClientAction($uuid)
|
||||
{
|
||||
return $this->setBase('client', 'clients.client', $uuid);
|
||||
}
|
||||
|
||||
public function toggleClientAction($uuid)
|
||||
{
|
||||
return $this->toggleBase('clients.client', $uuid);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
* Copyright (C) 2022 Patrik Kernstock <patrik@kernstock.net>
|
||||
*
|
||||
* 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\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';
|
||||
|
||||
/**
|
||||
* XXX: remove in 24.1 unused
|
||||
*/
|
||||
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" => (int) $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" => (int) $server->instance,
|
||||
"interface" => (string) $interface,
|
||||
"enabled" => (int) $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) {
|
||||
// skipping removed peer that is still referenced in server
|
||||
if (!isset($peers[$peerUuid])) {
|
||||
continue;
|
||||
}
|
||||
// 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
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
* 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\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
|
||||
class ServerController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'server';
|
||||
protected static $internalModelClass = '\OPNsense\Wireguard\Server';
|
||||
|
||||
public function keyPairAction()
|
||||
{
|
||||
return json_decode((new Backend())->configdRun('wireguard gen_keypair'), true);
|
||||
}
|
||||
|
||||
public function searchServerAction()
|
||||
{
|
||||
$search = $this->searchBase(
|
||||
'servers.server',
|
||||
["enabled", "instance", "peers", "name", "networks", "pubkey", "port", "tunneladdress", 'interface']
|
||||
);
|
||||
return $search;
|
||||
}
|
||||
|
||||
public function getServerAction($uuid = null)
|
||||
{
|
||||
return $this->getBase('server', 'servers.server', $uuid);
|
||||
}
|
||||
|
||||
public function addServerAction($uuid = null)
|
||||
{
|
||||
return $this->addBase('server', 'servers.server', $uuid);
|
||||
}
|
||||
|
||||
public function delServerAction($uuid)
|
||||
{
|
||||
return $this->delBase('servers.server', $uuid);
|
||||
}
|
||||
|
||||
public function setServerAction($uuid = null)
|
||||
{
|
||||
return $this->setBase('server', 'servers.server', $uuid);
|
||||
}
|
||||
|
||||
public function toggleServerAction($uuid)
|
||||
{
|
||||
return $this->toggleBase('servers.server', $uuid);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
* 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\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableServiceControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Wireguard\General;
|
||||
use OPNsense\Wireguard\Client;
|
||||
use OPNsense\Wireguard\Server;
|
||||
|
||||
/**
|
||||
* Class ServiceController
|
||||
* @package OPNsense\Wireguard
|
||||
*/
|
||||
class ServiceController extends ApiMutableServiceControllerBase
|
||||
{
|
||||
protected static $internalServiceClass = '\OPNsense\Wireguard\General';
|
||||
protected static $internalServiceTemplate = 'OPNsense/Wireguard';
|
||||
protected static $internalServiceEnabled = 'enabled';
|
||||
protected static $internalServiceName = 'wireguard';
|
||||
|
||||
/**
|
||||
* hook group interface registration on reconfigure
|
||||
* @return bool
|
||||
*/
|
||||
protected function invokeInterfaceRegistration()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function reconfigureAction()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return ['result' => 'failed'];
|
||||
}
|
||||
|
||||
$this->sessionClose();
|
||||
$backend = new Backend();
|
||||
$backend->configdRun('template reload ' . escapeshellarg(static::$internalServiceTemplate));
|
||||
$backend->configdpRun('wireguard configure');
|
||||
|
||||
return ['result' => 'ok'];
|
||||
}
|
||||
|
||||
/**
|
||||
* show wireguard config
|
||||
* XXX: remove in 24.1
|
||||
* @return array
|
||||
*/
|
||||
public function showconfAction()
|
||||
{
|
||||
$response = (new Backend())->configdRun("wireguard showconf");
|
||||
return array("response" => $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* show wireguard handshakes
|
||||
* XXX: remove in 24.1
|
||||
* @return array
|
||||
*/
|
||||
public function showhandshakeAction()
|
||||
{
|
||||
$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 = [];
|
||||
$ifnames = [];
|
||||
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;
|
||||
$ifnames[(string)$server->interface] = (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'] = '';
|
||||
}
|
||||
$record['ifname'] = $ifnames[$record['if']];
|
||||
}
|
||||
$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);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<?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
|
||||
{
|
||||
protected function templateJSIncludes()
|
||||
{
|
||||
$result = parent::templateJSIncludes();
|
||||
$result[] = '/ui/js/moment-with-locales.min.js';
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Wireguard/diagnostics');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
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 GeneralController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->generalForm = $this->getForm("general");
|
||||
$this->view->formDialogEditWireguardClient = $this->getForm("dialogEditWireguardClient");
|
||||
$this->view->formDialogEditWireguardServer = $this->getForm("dialogEditWireguardServer");
|
||||
$this->view->pick('OPNsense/Wireguard/general');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>client.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will enable or disable the client config.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.name</id>
|
||||
<label>Name</label>
|
||||
<type>text</type>
|
||||
<help>Set the name for this instance.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.pubkey</id>
|
||||
<label>Public Key</label>
|
||||
<type>text</type>
|
||||
<help>Public key of this instance.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.psk</id>
|
||||
<label>Shared Secret</label>
|
||||
<type>text</type>
|
||||
<help>Shared secret (PSK) for this peer. You can generate a key using "wg genpsk" on a client with WireGuard installed.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.tunneladdress</id>
|
||||
<label>Allowed IPs</label>
|
||||
<style>tokenize</style>
|
||||
<type>select_multiple</type>
|
||||
<allownew>true</allownew>
|
||||
<help>List of addresses allowed to pass trough the tunnel adapter. Please use CIDR notation like 10.0.0.1/24.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.serveraddress</id>
|
||||
<label>Endpoint Address</label>
|
||||
<type>text</type>
|
||||
<help>Set public IP address the endpoint listens to.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.serverport</id>
|
||||
<label>Endpoint Port</label>
|
||||
<type>text</type>
|
||||
<help>Set port the endpoint listens to.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.keepalive</id>
|
||||
<label>Keepalive Interval</label>
|
||||
<type>text</type>
|
||||
<help>Set persistent keepalive interval in seconds.</help>
|
||||
</field>
|
||||
</form>
|
||||
@ -0,0 +1,88 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>server.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will enable or disable the server config.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.name</id>
|
||||
<label>Name</label>
|
||||
<type>text</type>
|
||||
<help>Set the name for this instance.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.instance</id>
|
||||
<label>Instance</label>
|
||||
<type>info</type>
|
||||
<help>This is the instance number to give the wg interface a unique name (wgX).</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.pubkey</id>
|
||||
<label>Public Key</label>
|
||||
<type>text</type>
|
||||
<help>Public key of this instance. You can specify your own one, or a key will be generated after saving.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.privkey</id>
|
||||
<label>Private Key</label>
|
||||
<type>text</type>
|
||||
<help>Private key of this instance. You can specify your own one, or a key will be generated after saving. Please keep this key safe.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.port</id>
|
||||
<label>Listen Port</label>
|
||||
<type>text</type>
|
||||
<help>Optionally set a fixed port for this instance to listen on. The standard port range starts at 51820.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.mtu</id>
|
||||
<label>MTU</label>
|
||||
<type>text</type>
|
||||
<advanced>true</advanced>
|
||||
<help>Set the interface MTU for this interface. Leaving empty uses the MTU from main interface which is fine for most setups.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.dns</id>
|
||||
<label>DNS Server</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<allownew>true</allownew>
|
||||
<advanced>true</advanced>
|
||||
<help>Set the interface specific DNS server.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.tunneladdress</id>
|
||||
<label>Tunnel Address</label>
|
||||
<style>tokenize</style>
|
||||
<type>select_multiple</type>
|
||||
<allownew>true</allownew>
|
||||
<help>List of addresses to configure on the tunnel adapter. Please use CIDR notation like 10.0.0.1/24.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.carp_depend_on</id>
|
||||
<label>Depend on (CARP)</label>
|
||||
<type>dropdown</type>
|
||||
<help>The CARP VHID to depend on. When this virtual address is not in master state, then the instance will be shutdown.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.peers</id>
|
||||
<label>Peers</label>
|
||||
<type>select_multiple</type>
|
||||
<allownew>true</allownew>
|
||||
<help>List of peers for this server.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.disableroutes</id>
|
||||
<label>Disable Routes</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will prevent installing routes. Usually you only enable this to do own routing decisions via a local gateway and gateway rules.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.gateway</id>
|
||||
<label>Gateway</label>
|
||||
<type>text</type>
|
||||
<advanced>true</advanced>
|
||||
<help>Set the gateway IP here when using Disable Routes feature. You also have to add this as a gateway in OPNsense.</help>
|
||||
</field>
|
||||
</form>
|
||||
@ -0,0 +1,8 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>general.enabled</id>
|
||||
<label>Enable WireGuard</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will activate WireGuard and start all enabled instances.</help>
|
||||
</field>
|
||||
</form>
|
||||
@ -0,0 +1,9 @@
|
||||
<acl>
|
||||
<page-wireguard-config>
|
||||
<name>VPN: Wireguard</name>
|
||||
<patterns>
|
||||
<pattern>ui/wireguard/*</pattern>
|
||||
<pattern>api/wireguard/*</pattern>
|
||||
</patterns>
|
||||
</page-wireguard-config>
|
||||
</acl>
|
||||
31
src/opnsense/mvc/app/models/OPNsense/Wireguard/Client.php
Normal file
31
src/opnsense/mvc/app/models/OPNsense/Wireguard/Client.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
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;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class Client extends BaseModel
|
||||
{
|
||||
}
|
||||
45
src/opnsense/mvc/app/models/OPNsense/Wireguard/Client.xml
Normal file
45
src/opnsense/mvc/app/models/OPNsense/Wireguard/Client.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<model>
|
||||
<mount>//OPNsense/wireguard/client</mount>
|
||||
<description>Wireguard Client configuration</description>
|
||||
<version>0.0.7</version>
|
||||
<items>
|
||||
<clients>
|
||||
<client type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<name type="TextField">
|
||||
<Required>Y</Required>
|
||||
<mask>/^([0-9a-zA-Z._\-]){1,64}$/u</mask>
|
||||
<ValidationMessage>Should be a string between 1 and 64 characters. Allowed characters are alphanumeric characters, dash and underscores.</ValidationMessage>
|
||||
</name>
|
||||
<pubkey type="Base64Field">
|
||||
<Required>Y</Required>
|
||||
<ValidationMessage>Should be a base64-encoded 32 byte string.</ValidationMessage>
|
||||
</pubkey>
|
||||
<psk type="Base64Field">
|
||||
<Required>N</Required>
|
||||
<ValidationMessage>Should be a base64-encoded 32 byte string.</ValidationMessage>
|
||||
</psk>
|
||||
<tunneladdress type="NetworkField">
|
||||
<FieldSeparator>,</FieldSeparator>
|
||||
<Required>Y</Required>
|
||||
<asList>Y</asList>
|
||||
</tunneladdress>
|
||||
<serveraddress type="HostnameField">
|
||||
<Required>N</Required>
|
||||
</serveraddress>
|
||||
<serverport type="PortField">
|
||||
<Required>N</Required>
|
||||
</serverport>
|
||||
<keepalive type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>86400</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 1 and 86400.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</keepalive>
|
||||
</client>
|
||||
</clients>
|
||||
</items>
|
||||
</model>
|
||||
@ -0,0 +1,58 @@
|
||||
<?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\FieldTypes;
|
||||
|
||||
use OPNsense\Base\FieldTypes\ArrayField;
|
||||
use OPNsense\Base\FieldTypes\TextField;
|
||||
|
||||
class ServerField extends ArrayField
|
||||
{
|
||||
/**
|
||||
* push internal reusable properties as virtuals
|
||||
*/
|
||||
protected function actionPostLoadingEvent()
|
||||
{
|
||||
foreach ($this->internalChildnodes as $node) {
|
||||
if (!$node->getInternalIsVirtual()) {
|
||||
$files = [
|
||||
'cnfFilename' => "/usr/local/etc/wireguard/wg{$node->instance}.conf",
|
||||
'statFilename' => "/usr/local/etc/wireguard/wg{$node->instance}.stat",
|
||||
'interface' => "wg{$node->instance}",
|
||||
];
|
||||
foreach ($files as $name => $payload) {
|
||||
$new_item = new TextField();
|
||||
$new_item->setInternalIsVirtual();
|
||||
$new_item->setValue($payload);
|
||||
$node->addChildNode($name, $new_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent::actionPostLoadingEvent();
|
||||
}
|
||||
}
|
||||
35
src/opnsense/mvc/app/models/OPNsense/Wireguard/General.php
Normal file
35
src/opnsense/mvc/app/models/OPNsense/Wireguard/General.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
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;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class General extends BaseModel
|
||||
{
|
||||
}
|
||||
11
src/opnsense/mvc/app/models/OPNsense/Wireguard/General.xml
Normal file
11
src/opnsense/mvc/app/models/OPNsense/Wireguard/General.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<model>
|
||||
<mount>//OPNsense/wireguard/general</mount>
|
||||
<description>WireGuard configuration</description>
|
||||
<version>0.0.1</version>
|
||||
<items>
|
||||
<enabled type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
</items>
|
||||
</model>
|
||||
@ -0,0 +1,9 @@
|
||||
<menu>
|
||||
<VPN>
|
||||
<WireGuard cssClass="fa fa-lock fa-fw" order="150">
|
||||
<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>
|
||||
</menu>
|
||||
31
src/opnsense/mvc/app/models/OPNsense/Wireguard/Server.php
Normal file
31
src/opnsense/mvc/app/models/OPNsense/Wireguard/Server.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Copyright (C) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
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;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class Server extends BaseModel
|
||||
{
|
||||
}
|
||||
82
src/opnsense/mvc/app/models/OPNsense/Wireguard/Server.xml
Normal file
82
src/opnsense/mvc/app/models/OPNsense/Wireguard/Server.xml
Normal file
@ -0,0 +1,82 @@
|
||||
<model>
|
||||
<mount>//OPNsense/wireguard/server</mount>
|
||||
<description>Wireguard Server configuration</description>
|
||||
<version>0.0.4</version>
|
||||
<items>
|
||||
<servers>
|
||||
<server type=".\ServerField">
|
||||
<enabled type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<name type="TextField">
|
||||
<Required>Y</Required>
|
||||
<mask>/^([0-9a-zA-Z._\-]){1,64}$/u</mask>
|
||||
<ValidationMessage>Should be a string between 1 and 64 characters. Allowed characters are alphanumeric characters, dash and underscores.</ValidationMessage>
|
||||
</name>
|
||||
<instance type="AutoNumberField">
|
||||
<Required>Y</Required>
|
||||
</instance>
|
||||
<pubkey type="TextField">
|
||||
<Required>Y</Required>
|
||||
<ValidationMessage>A public key is required</ValidationMessage>
|
||||
</pubkey>
|
||||
<privkey type="TextField">
|
||||
<Required>Y</Required>
|
||||
<ValidationMessage>A private key is required</ValidationMessage>
|
||||
</privkey>
|
||||
<port type="PortField">
|
||||
<Required>N</Required>
|
||||
</port>
|
||||
<mtu type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>9300</MaximumValue>
|
||||
<Required>N</Required>
|
||||
</mtu>
|
||||
<dns type="CSVListField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([a-fA-F0-9\.:\[\]]*?,)*([a-fA-F0-9\.:\[\]]*)$/</mask>
|
||||
<ValidationMessage>Please use valid IPv4 or IPv6 addresses.</ValidationMessage>
|
||||
</dns>
|
||||
<tunneladdress type="NetworkField">
|
||||
<FieldSeparator>,</FieldSeparator>
|
||||
<Required>N</Required>
|
||||
<asList>Y</asList>
|
||||
</tunneladdress>
|
||||
<disableroutes type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>You have to enable Disable Routes option.</ValidationMessage>
|
||||
<type>DependConstraint</type>
|
||||
<addFields>
|
||||
<field1>gateway</field1>
|
||||
</addFields>
|
||||
</check001>
|
||||
</Constraints>
|
||||
</disableroutes>
|
||||
<gateway type="NetworkField">
|
||||
<Required>N</Required>
|
||||
</gateway>
|
||||
<carp_depend_on type="VirtualIPField">
|
||||
<type>carp</type>
|
||||
<Required>N</Required>
|
||||
<key>mvc</key>
|
||||
</carp_depend_on>
|
||||
<peers type="ModelRelationField">
|
||||
<Model>
|
||||
<template>
|
||||
<source>OPNsense.Wireguard.Client</source>
|
||||
<items>clients.client</items>
|
||||
<display>name</display>
|
||||
</template>
|
||||
</Model>
|
||||
<Multiple>Y</Multiple>
|
||||
<Required>N</Required>
|
||||
<ValidationMessage>Choose an Peer.</ValidationMessage>
|
||||
</peers>
|
||||
</server>
|
||||
</servers>
|
||||
</items>
|
||||
</model>
|
||||
@ -0,0 +1,98 @@
|
||||
{#
|
||||
# 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() {
|
||||
|
||||
$("#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];
|
||||
},
|
||||
epoch: function(column, row) {
|
||||
if (row[column.id]) {
|
||||
return moment.unix(row[column.id]).local().format('YYYY-MM-DD HH:mm:ss');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
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="status" data-type="string" data-width="8em" >{{ lang._('Status') }}</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-formatter="epoch" 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>
|
||||
170
src/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt
Normal file
170
src/opnsense/mvc/app/views/OPNsense/Wireguard/general.volt
Normal file
@ -0,0 +1,170 @@
|
||||
{#
|
||||
# OPNsense (c) 2014-2023 by Deciso B.V.
|
||||
# OPNsense (c) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
# 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() {
|
||||
var data_get_map = {'frm_general_settings':"/api/wireguard/general/get"};
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
|
||||
$("#grid-clients").UIBootgrid(
|
||||
{
|
||||
'search':'/api/wireguard/client/searchClient',
|
||||
'get':'/api/wireguard/client/getClient/',
|
||||
'set':'/api/wireguard/client/setClient/',
|
||||
'add':'/api/wireguard/client/addClient/',
|
||||
'del':'/api/wireguard/client/delClient/',
|
||||
'toggle':'/api/wireguard/client/toggleClient/'
|
||||
}
|
||||
);
|
||||
|
||||
$("#grid-servers").UIBootgrid(
|
||||
{
|
||||
'search':'/api/wireguard/server/searchServer',
|
||||
'get':'/api/wireguard/server/getServer/',
|
||||
'set':'/api/wireguard/server/setServer/',
|
||||
'add':'/api/wireguard/server/addServer/',
|
||||
'del':'/api/wireguard/server/delServer/',
|
||||
'toggle':'/api/wireguard/server/toggleServer/'
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
$("#reconfigureAct").SimpleActionButton({
|
||||
onPreAction: function() {
|
||||
const dfObj = new $.Deferred();
|
||||
saveFormToEndpoint("/api/wireguard/general/set", 'frm_general_settings', function(){
|
||||
dfObj.resolve();
|
||||
});
|
||||
return dfObj;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Move keypair generation button inside the server form and hook api event
|
||||
*/
|
||||
$("#control_label_server\\.pubkey").append($("#keygen_div").detach().show());
|
||||
$("#keygen").click(function(){
|
||||
ajaxGet("/api/wireguard/server/key_pair", {}, function(data, status){
|
||||
if (data.status && data.status === 'ok') {
|
||||
$("#server\\.pubkey").val(data.pubkey);
|
||||
$("#server\\.privkey").val(data.privkey);
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<!-- Navigation bar -->
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<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>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="general" class="tab-pane fade in active">
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_general_settings'])}}
|
||||
</div>
|
||||
</div>
|
||||
<div id="clients" class="tab-pane fade in">
|
||||
<table id="grid-clients" class="table table-responsive" data-editDialog="dialogEditWireguardClient">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="name" data-type="string" data-visible="true">{{ lang._('Name') }}</th>
|
||||
<th data-column-id="serveraddress" data-type="string" data-visible="true">{{ lang._('Endpoint Address') }}</th>
|
||||
<th data-column-id="serverport" data-type="string" data-visible="true">{{ lang._('Endpoint Port') }}</th>
|
||||
<th data-column-id="tunneladdress" data-type="string" data-visible="true">{{ lang._('Allowed IPs') }}</th>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6"></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div id="servers" class="tab-pane fade in">
|
||||
<span id="keygen_div" style="display:none" class="pull-right">
|
||||
<button id="keygen" type="button" class="btn btn-secondary" title="{{ lang._('Generate new keypair.') }}" data-toggle="tooltip">
|
||||
<i class="fa fa-fw fa-gear"></i>
|
||||
</button>
|
||||
</span>
|
||||
<table id="grid-servers" class="table table-responsive" data-editDialog="dialogEditWireguardServer">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="name" data-type="string" data-visible="true">{{ lang._('Name') }}</th>
|
||||
<th data-column-id="interface" data-type="string" data-visible="true">{{ lang._('Interface') }}</th>
|
||||
<th data-column-id="tunneladdress" data-type="string" data-visible="true">{{ lang._('Tunnel Address') }}</th>
|
||||
<th data-column-id="port" data-type="string" data-visible="true">{{ lang._('Port') }}</th>
|
||||
<th data-column-id="peers" data-type="string" data-visible="true">{{ lang._('Endpoints') }}</th>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="7"></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="page-content-main">
|
||||
<div class="content-box">
|
||||
<div class="col-md-12">
|
||||
<br/>
|
||||
<button class="btn btn-primary" id="reconfigureAct"
|
||||
data-endpoint='/api/wireguard/service/reconfigure'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-error-title="{{ lang._('Error reconfiguring Wireguard') }}"
|
||||
type="button"
|
||||
></button>
|
||||
<br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditWireguardClient,'id':'dialogEditWireguardClient','label':lang._('Edit Endpoint')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditWireguardServer,'id':'dialogEditWireguardServer','label':lang._('Edit Local Configuration')])}}
|
||||
46
src/opnsense/scripts/Wireguard/gen_keypair.py
Executable file
46
src/opnsense/scripts/Wireguard/gen_keypair.py
Executable file
@ -0,0 +1,46 @@
|
||||
#!/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
|
||||
|
||||
|
||||
def keypair():
|
||||
sp = subprocess.run(['/usr/bin/wg', 'genkey'], capture_output=True, text=True)
|
||||
if sp.returncode == 0:
|
||||
privkey = sp.stdout.strip()
|
||||
sp = subprocess.run(['/usr/bin/wg', 'pubkey'], input=privkey, capture_output=True, text=True)
|
||||
if sp.returncode == 0:
|
||||
return {'privkey': privkey, 'pubkey': sp.stdout.strip()}
|
||||
return None
|
||||
|
||||
response = keypair()
|
||||
if not response:
|
||||
print(ujson.dumps({'status': 'failed'}))
|
||||
else:
|
||||
response['status'] = 'ok'
|
||||
print(ujson.dumps(response))
|
||||
75
src/opnsense/scripts/Wireguard/reresolve-dns.py
Executable file
75
src/opnsense/scripts/Wireguard/reresolve-dns.py
Executable file
@ -0,0 +1,75 @@
|
||||
#!/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.
|
||||
"""
|
||||
# Python implementation to re-resolve dns entries, for reference see:
|
||||
# https://github.com/WireGuard/wireguard-tools/tree/master/contrib/reresolve-dns
|
||||
import glob
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
|
||||
|
||||
sp = subprocess.run(['/usr/bin/wg', 'show', 'all', 'latest-handshakes'], capture_output=True, text=True)
|
||||
ts_now = time.time()
|
||||
handshakes = {}
|
||||
for line in sp.stdout.split('\n'):
|
||||
parts = line.split()
|
||||
if len(parts) == 3 and parts[2].isdigit():
|
||||
handshakes["%s-%s" % (parts[0], parts[1])] = ts_now - int(parts[2])
|
||||
|
||||
|
||||
for filename in glob.glob('/usr/local/etc/wireguard/*.conf'):
|
||||
this_peer = {}
|
||||
ifname = os.path.basename(filename).split('.')[0]
|
||||
with open(filename, 'r') as fhandle:
|
||||
for line in fhandle:
|
||||
if line.startswith('[Peer]'):
|
||||
this_peer = {'ifname': ifname}
|
||||
elif line.startswith('PublicKey'):
|
||||
this_peer['PublicKey'] = line.split('=', 1)[1].strip()
|
||||
elif line.startswith('Endpoint'):
|
||||
this_peer['Endpoint'] = line.split('=', 1)[1].strip()
|
||||
|
||||
if 'Endpoint' in this_peer and 'PublicKey' in this_peer:
|
||||
peer_key = "%(ifname)s-%(PublicKey)s" % this_peer
|
||||
if handshakes.get(peer_key, 999) > 135:
|
||||
# skip if there has been a handshake recently
|
||||
subprocess.run(
|
||||
[
|
||||
'/usr/bin/wg',
|
||||
'set',
|
||||
ifname,
|
||||
'peer',
|
||||
this_peer['PublicKey'],
|
||||
'endpoint',
|
||||
this_peer['Endpoint']
|
||||
],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
this_peer = {}
|
||||
271
src/opnsense/scripts/Wireguard/wg-service-control.php
Executable file
271
src/opnsense/scripts/Wireguard/wg-service-control.php
Executable file
@ -0,0 +1,271 @@
|
||||
#!/usr/local/bin/php
|
||||
<?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.
|
||||
*/
|
||||
|
||||
require_once('script/load_phalcon.php');
|
||||
require_once('util.inc');
|
||||
require_once('interfaces.inc');
|
||||
|
||||
/**
|
||||
* collect carp status per vhid
|
||||
*/
|
||||
function get_vhid_status()
|
||||
{
|
||||
$vhids = [];
|
||||
$uuids = [];
|
||||
foreach ((new OPNsense\Interfaces\Vip())->vip->iterateItems() as $id => $item) {
|
||||
if ($item->mode == 'carp') {
|
||||
$uuids[(string)$item->vhid] = $id;
|
||||
}
|
||||
}
|
||||
foreach (legacy_interfaces_details() as $ifdata) {
|
||||
if (!empty($ifdata['carp'])) {
|
||||
foreach ($ifdata['carp'] as $data) {
|
||||
if (isset($uuids[$data['vhid']])) {
|
||||
$vhids[$uuids[$data['vhid']]] = $data['status'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $vhids;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mimic wg-quick behaviour, but bound to our config
|
||||
*/
|
||||
function wg_start($server, $fhandle, $ifcfgflag = 'up')
|
||||
{
|
||||
if (!does_interface_exist($server->interface)) {
|
||||
mwexecf('/sbin/ifconfig wg create name %s', [$server->interface]);
|
||||
mwexecf('/sbin/ifconfig %s group wireguard', [$server->interface]);
|
||||
}
|
||||
mwexecf('/usr/bin/wg setconf %s %s', [$server->interface, $server->cnfFilename]);
|
||||
|
||||
foreach (explode(',', (string)$server->tunneladdress) as $alias) {
|
||||
$proto = strpos($alias, ':') === false ? "inet" : "inet6";
|
||||
mwexecf('/sbin/ifconfig %s %s %s alias', [$server->interface, $proto, $alias]);
|
||||
}
|
||||
if (!empty((string)$server->mtu)) {
|
||||
mwexecf('/sbin/ifconfig %s mtu %s', [$server->interface, $server->mtu]);
|
||||
}
|
||||
mwexecf('/sbin/ifconfig %s %s', [$server->interface, $ifcfgflag]);
|
||||
|
||||
if (empty((string)$server->disableroutes)) {
|
||||
/**
|
||||
* Add routes for all configured peers, wg-quick seems to parse 'wg show wgX allowed-ips' for this,
|
||||
* but this should logically congtain the same networks.
|
||||
*
|
||||
* XXX: For some reason these routes look a bit off, not very well integrated into OPNsense.
|
||||
* In the long run it might make sense to have some sort of pluggable model facility
|
||||
* where these (and maybe other) static routes hook into.
|
||||
**/
|
||||
$peers = explode(',', $server->peers);
|
||||
$routes_to_add = ['inet' => [], 'inet6' => []];
|
||||
foreach ((new OPNsense\Wireguard\Client())->clients->client->iterateItems() as $key => $client) {
|
||||
if (empty((string)$client->enabled) || !in_array($key, $peers)) {
|
||||
continue;
|
||||
}
|
||||
foreach (explode(',', (string)$client->tunneladdress) as $tunneladdress) {
|
||||
$ipproto = strpos($tunneladdress, ":") === false ? "inet" : "inet6";
|
||||
/* wg-quick seems to prevent /0 being routed and translates this automatically */
|
||||
if (str_ends_with(trim($tunneladdress), '/0')) {
|
||||
if ($ipproto == 'inet') {
|
||||
array_push($routes_to_add[$ipproto], '0.0.0.0/1', '128.0.0.0/1');
|
||||
} else {
|
||||
array_push($routes_to_add[$ipproto], '::/1', '8000::/1');
|
||||
}
|
||||
} else {
|
||||
$routes_to_add[$ipproto][] = $tunneladdress;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($routes_to_add as $ipproto => $routes) {
|
||||
foreach (array_unique($routes) as $route) {
|
||||
mwexecf('/sbin/route -q -n add -%s %s -interface %s', [$ipproto, $route, $server->interface]);
|
||||
}
|
||||
}
|
||||
} elseif (!empty((string)$server->gateway)) {
|
||||
/* Only bind the gateway ip to the tunnel */
|
||||
$ipprefix = strpos($tunneladdress, ":") === false ? "-4" : "-6";
|
||||
mwexecf('/sbin/route -q -n add %s %s -iface %s', [$ipprefix, $server->gateway, $server->interface]);
|
||||
}
|
||||
|
||||
// flush checksum to ease change detection
|
||||
fseek($fhandle, 0);
|
||||
ftruncate($fhandle, 0);
|
||||
fwrite($fhandle, @md5_file($server->cnfFilename) . "|" . wg_reconfigure_hash($server));
|
||||
syslog(LOG_NOTICE, "Wireguard interface {$server->name} ({$server->interface}) started");
|
||||
}
|
||||
|
||||
/**
|
||||
* stop wireguard tunnel, kill the device, the routes should drop automatically.
|
||||
*/
|
||||
function wg_stop($server)
|
||||
{
|
||||
if (does_interface_exist($server->interface)) {
|
||||
legacy_interface_destroy($server->interface);
|
||||
}
|
||||
syslog(LOG_NOTICE, "Wireguard interface {$server->name} ({$server->interface}) stopped");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate a hash which determines if we are able to reconfigure without a restart of the tunnel.
|
||||
* We currently assume if something changed on the interface or peer routes are being pushed, it's safer to
|
||||
* restart then reload.
|
||||
*/
|
||||
function wg_reconfigure_hash($server)
|
||||
{
|
||||
if (empty((string)$server->disableroutes)) {
|
||||
return md5(uniqid('', true)); // random hash, should always reconfigure
|
||||
}
|
||||
return md5(
|
||||
sprintf(
|
||||
'%s|%s|%s',
|
||||
$server->tunneladdress,
|
||||
$server->mtu,
|
||||
$server->gateway
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The stat hash file answers two questions, [1] has anything changed, which is answered using an md5 hash of the
|
||||
* configuration file. The second question, if something has changed, is it safe to only reload the configuration.
|
||||
* This is answered by wg_reconfigure_hash() for the instance in question.
|
||||
*/
|
||||
function get_stat_hash($fhandle)
|
||||
{
|
||||
fseek($fhandle, 0);
|
||||
$payload = stream_get_contents($fhandle) ?? '';
|
||||
$parts = explode('|', $payload);
|
||||
return [
|
||||
'file' => $parts[0] ?? '',
|
||||
'interface' => $parts[1] ?? ''
|
||||
];
|
||||
}
|
||||
|
||||
$opts = getopt('ah', [], $optind);
|
||||
$args = array_slice($argv, $optind);
|
||||
|
||||
/* setup syslog logging */
|
||||
openlog("wireguard", LOG_ODELAY, LOG_AUTH);
|
||||
|
||||
if (isset($opts['h']) || empty($args) || !in_array($args[0], ['start', 'stop', 'restart', 'configure'])) {
|
||||
echo "Usage: wg-service-control.php [-a] [-h] [stop|start|restart|configure] [uuid]\n\n";
|
||||
echo "\t-a all instances\n";
|
||||
} elseif (isset($opts['a']) || !empty($args[1])) {
|
||||
$server_id = $args[1] ?? null;
|
||||
$action = $args[0];
|
||||
|
||||
$server_devs = [];
|
||||
if (!empty((string)(new OPNsense\Wireguard\General())->enabled)) {
|
||||
$ifdetails = legacy_interfaces_details();
|
||||
$vhids = get_vhid_status();
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $key => $node) {
|
||||
if (empty((string)$node->enabled)) {
|
||||
continue;
|
||||
}
|
||||
if ($server_id != null && $key != $server_id) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* CARP may influence the interface status (up or down).
|
||||
* In order to fluently switch between roles, one should only have to change the interface flag in this
|
||||
* case, which means we can still reconfigure an interface in the usual way and just omit sending traffic
|
||||
* when in BACKUP or INIT mode.
|
||||
*/
|
||||
$carp_if_flag = 'up';
|
||||
if (
|
||||
!empty($vhids[(string)$node->carp_depend_on]) &&
|
||||
$vhids[(string)$node->carp_depend_on] != 'MASTER'
|
||||
) {
|
||||
$carp_if_flag = 'down';
|
||||
}
|
||||
$server_devs[] = (string)$node->interface;
|
||||
$statHandle = fopen($node->statFilename, "a+");
|
||||
if (flock($statHandle, LOCK_EX)) {
|
||||
switch ($action) {
|
||||
case 'stop':
|
||||
wg_stop($node);
|
||||
break;
|
||||
case 'start':
|
||||
wg_start($node, $statHandle, $carp_if_flag);
|
||||
break;
|
||||
case 'restart':
|
||||
wg_stop($node);
|
||||
wg_start($node, $statHandle, $carp_if_flag);
|
||||
break;
|
||||
case 'configure':
|
||||
if (
|
||||
@md5_file($node->cnfFilename) != get_stat_hash($statHandle)['file'] ||
|
||||
!isset($ifdetails[(string)$node->interface])
|
||||
) {
|
||||
if (get_stat_hash($statHandle)['interface'] != wg_reconfigure_hash($node)) {
|
||||
// Fluent reloading not supported for this instance, make sure the user is informed
|
||||
syslog(
|
||||
LOG_NOTICE,
|
||||
"Wireguard interface {$node->name} ({$node->interface}) " .
|
||||
"can not reconfigure without stopping it first."
|
||||
);
|
||||
wg_stop($node);
|
||||
}
|
||||
wg_start($node, $statHandle, $carp_if_flag);
|
||||
} else {
|
||||
// when triggered via a CARP event, check our interface status [UP|DOWN]
|
||||
$tmp = in_array('up', $ifdetails[(string)$node->interface]['flags']) ? 'up' : 'down';
|
||||
if ($tmp != $carp_if_flag) {
|
||||
mwexecf('/sbin/ifconfig %s %s', [$node->interface, $carp_if_flag]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
flock($statHandle, LOCK_UN);
|
||||
}
|
||||
fclose($statHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When -a is specified, cleaup up old or disabled instances (files and interfaces)
|
||||
*/
|
||||
if ($server_id == null) {
|
||||
foreach (glob('/usr/local/etc/wireguard/wg*') as $filename) {
|
||||
$this_dev = explode('.', basename($filename))[0];
|
||||
if (!in_array($this_dev, $server_devs)) {
|
||||
@unlink($filename);
|
||||
if (does_interface_exist($this_dev)) {
|
||||
legacy_interface_destroy($this_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mwexecf('/usr/local/etc/rc.routing_configure');
|
||||
}
|
||||
closelog();
|
||||
72
src/opnsense/scripts/Wireguard/wg_show.py
Executable file
72
src/opnsense/scripts/Wireguard/wg_show.py
Executable file
@ -0,0 +1,72 @@
|
||||
#!/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
|
||||
|
||||
|
||||
interfaces = {}
|
||||
for line in subprocess.run(['/sbin/ifconfig'], capture_output=True, text=True).stdout.split("\n"):
|
||||
if not line.startswith('\t') and line.find('<') > -1:
|
||||
ifname = line.split(':')[0]
|
||||
interfaces[ifname] = 'up' if 'UP' in line.split('<')[1].split('>')[0].split(',') else 'down'
|
||||
|
||||
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]
|
||||
record['status'] = interfaces.get(record['if'], 'down')
|
||||
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))
|
||||
54
src/opnsense/service/conf/actions.d/actions_wireguard.conf
Normal file
54
src/opnsense/service/conf/actions.d/actions_wireguard.conf
Normal file
@ -0,0 +1,54 @@
|
||||
[start]
|
||||
command:/usr/local/opnsense/scripts/Wireguard/wg-service-control.php
|
||||
parameters: start %s
|
||||
type:script
|
||||
message: start wireguard instance %s
|
||||
|
||||
[stop]
|
||||
command:/usr/local/opnsense/scripts/Wireguard/wg-service-control.php
|
||||
parameters: stop %s
|
||||
type:script
|
||||
message: stop wireguard instance %s
|
||||
|
||||
[restart]
|
||||
command:/usr/local/opnsense/scripts/Wireguard/wg-service-control.php
|
||||
parameters: restart %s
|
||||
type:script
|
||||
message: restart wireguard instance %s
|
||||
|
||||
[configure]
|
||||
command:/usr/local/opnsense/scripts/Wireguard/wg-service-control.php
|
||||
parameters: -a configure
|
||||
type:script
|
||||
message: configure wireguard instances
|
||||
|
||||
[renew]
|
||||
command:/usr/local/opnsense/scripts/Wireguard/reresolve-dns.py
|
||||
parameters:
|
||||
type:script
|
||||
message:Renew DNS for WireGuard
|
||||
description:Renew DNS for WireGuard on stale connections
|
||||
|
||||
[gen_keypair]
|
||||
command:/usr/local/opnsense/scripts/Wireguard/gen_keypair.py
|
||||
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:
|
||||
type:script_output
|
||||
message:Show WireGuard config
|
||||
|
||||
[showhandshake]
|
||||
command:/usr/bin/wg show all latest-handshakes
|
||||
parameters:
|
||||
type:script_output
|
||||
message:Show WireGuard handshakes
|
||||
@ -0,0 +1,6 @@
|
||||
###################################################################
|
||||
# Local syslog-ng configuration filter definition [wireguard].
|
||||
###################################################################
|
||||
filter f_local_wireguard {
|
||||
program("wireguard");
|
||||
};
|
||||
@ -0,0 +1,2 @@
|
||||
wireguard:/etc/rc.conf.d/wireguard
|
||||
wireguard-server.conf:/usr/local/etc/wireguard/wg[OPNsense.wireguard.server.servers.server.%.instance].conf
|
||||
@ -0,0 +1,2 @@
|
||||
# disable the wireguard rc scripts when installed, bootup handled via rc.syshook
|
||||
wireguard_enable="NO"
|
||||
@ -0,0 +1,48 @@
|
||||
{% if helpers.exists('OPNsense.wireguard.general.enabled') and OPNsense.wireguard.general.enabled == '1' %}
|
||||
{% if helpers.exists('OPNsense.wireguard.server.servers.server') %}
|
||||
{% for server_list in helpers.toList('OPNsense.wireguard.server.servers.server') %}
|
||||
{% if TARGET_FILTERS['OPNsense.wireguard.server.servers.server.' ~ loop.index0] or TARGET_FILTERS['OPNsense.wireguard.server.servers.server'] %}
|
||||
{% if server_list.enabled == '1' %}
|
||||
####################################################
|
||||
# Interface settings, not used by `wg` #
|
||||
# Only used for reference and detection of changes #
|
||||
# in the configuration #
|
||||
####################################################
|
||||
# Address = {{server_list.tunneladdress|default('')}}
|
||||
# DNS = {{ server_list.dns|default('')}}
|
||||
# MTU = {{ server_list.mtu|default('') }}
|
||||
# disableroutes = {{server_list.disableroutes}}
|
||||
# gateway = {{server_list.gateway}}
|
||||
|
||||
[Interface]
|
||||
PrivateKey = {{ server_list.privkey }}
|
||||
{% if server_list.port|default('') != '' %}
|
||||
ListenPort = {{ server_list.port }}
|
||||
{% endif %}
|
||||
{% if server_list.peers|default('') != '' %}
|
||||
{% for peerlist in server_list.peers.split(",") %}
|
||||
{% set peerlist2_data = helpers.getUUID(peerlist) %}
|
||||
{% if peerlist2_data != {} and peerlist2_data.enabled == '1' %}
|
||||
|
||||
[Peer]
|
||||
# friendly_name = {{ peerlist2_data.name }}
|
||||
PublicKey = {{ peerlist2_data.pubkey }}
|
||||
{% if peerlist2_data.psk|default('') != '' %}
|
||||
PresharedKey = {{ peerlist2_data.psk }}
|
||||
{% endif %}
|
||||
{% if peerlist2_data.serveraddress|default('') != '' %}
|
||||
Endpoint = {{ peerlist2_data.serveraddress }}{% if peerlist2_data.serverport|default('') != '' %}:{{ peerlist2_data.serverport }}{% else %}:51820{% endif %}
|
||||
{% endif %}
|
||||
|
||||
AllowedIPs = {{ peerlist2_data.tunneladdress }}
|
||||
{% if peerlist2_data.keepalive|default('') != '' %}
|
||||
PersistentKeepalive = {{ peerlist2_data.keepalive }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
4
src/www/widgets/include/wireguard.inc
Normal file
4
src/www/widgets/include/wireguard.inc
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
|
||||
$wireguard_title = gettext('WireGuard');
|
||||
$wireguard_title_link = 'ui/wireguard/general';
|
||||
95
src/www/widgets/widgets/wireguard.widget.php
Normal file
95
src/www/widgets/widgets/wireguard.widget.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020-2023 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
|
||||
* 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.
|
||||
*/
|
||||
?>
|
||||
|
||||
<table class="table table-striped table-condensed" id="wg-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= gettext("Interface") ?></th>
|
||||
<th><?= gettext("Endpoint") ?></th>
|
||||
<th><?= gettext("Public Key") ?></th>
|
||||
<th><?= gettext("Latest Handshake") ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot style="display: none;">
|
||||
<tr>
|
||||
<td colspan="4"><?= gettext("No WireGuard instance defined or enabled.") ?></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
.psk_td {
|
||||
max-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
$(window).on("load", function() {
|
||||
function wgUpdateStatus()
|
||||
{
|
||||
ajaxGet("/api/wireguard/service/show", {}, function(data, status) {
|
||||
let $target = $("#wg-table > tbody").empty();
|
||||
if (data.rows !== undefined && data.rows.length > 0) {
|
||||
$("#wg-table > tfoot").hide();
|
||||
for (let i=0; data.rows.length > i; ++i) {
|
||||
let row = data.rows[i];
|
||||
let $tr = $("<tr/>");
|
||||
let ifname = row.ifname ? row.if + ' (' + row.ifname + ') ' : row.if;
|
||||
$tr.append($("<td>").append(ifname));
|
||||
$tr.append($("<td>").append(row.name));
|
||||
$tr.append($("<td class='psk_td'>").append(row['public-key']));
|
||||
let latest_handhake = '';
|
||||
if (row['latest-handshake']) {
|
||||
latest_handhake = moment.unix(row['latest-handshake']).local().format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
$tr.append($("<td>").append(latest_handhake));
|
||||
$target.append($tr);
|
||||
}
|
||||
$(".psk_td").each(function(){
|
||||
$(this).tooltip({title: $(this).text(), container: 'body', trigger: 'hover'});
|
||||
});
|
||||
} else{
|
||||
$("#wg-table > tfoot").show();
|
||||
}
|
||||
setTimeout(wgUpdateStatus, 10000);
|
||||
});
|
||||
};
|
||||
wgUpdateStatus();
|
||||
});
|
||||
</script>
|
||||
Loading…
x
Reference in New Issue
Block a user