plugins: remove obsolete, switch to 24.1 branch, sync
This commit is contained in:
parent
6eb9417ac5
commit
69f3f03b28
2
LICENSE
2
LICENSE
|
@ -7,7 +7,6 @@ Copyright (c) 2023 Bernhard Frenking <bernhard@frenking.eu>
|
|||
Copyright (c) 2023 Cannon Matthews <cannonmatthews@google.com>
|
||||
Copyright (c) 2019 Cloudfence - Julio Camargo (JCC)
|
||||
Copyright (c) 2005-2006 Colin Smith <ethethlay@gmail.com>
|
||||
Copyright (c) 2020 D. Domig
|
||||
Copyright (c) 2021 Dan Lundqvist
|
||||
Copyright (c) 2021 David Berry
|
||||
Copyright (c) 2017-2018 David Harrigan
|
||||
|
@ -50,7 +49,6 @@ Copyright (c) 2021 Nicola Pellegrini
|
|||
Copyright (c) 2022 Nikolaj Brinch Jørgensen
|
||||
Copyright (c) 2021 Nim G
|
||||
Copyright (c) 2023 Oliver Hartl
|
||||
Copyright (c) 2022 Patrik Kernstock <patrik@kernstock.net>
|
||||
Copyright (c) 2022 Robbert Rijkse
|
||||
Copyright (c) 2023 sattamjh
|
||||
Copyright (c) 2004-2012 Scott Ullrich <sullrich@gmail.com>
|
||||
|
|
|
@ -45,7 +45,7 @@ VERSIONBIN= ${LOCALBASE}/sbin/opnsense-version
|
|||
_PLUGIN_ABI!= ${VERSIONBIN} -a
|
||||
PLUGIN_ABI?= ${_PLUGIN_ABI}
|
||||
.else
|
||||
PLUGIN_ABI?= 23.7
|
||||
PLUGIN_ABI?= 24.1
|
||||
.endif
|
||||
|
||||
PHPBIN= ${LOCALBASE}/bin/php
|
||||
|
|
|
@ -47,7 +47,6 @@ misc/theme-rebellion -- A suitably dark theme
|
|||
misc/theme-tukan -- The tukan theme - blue/white
|
||||
misc/theme-vicuna -- The vicuna theme - blue sapphire
|
||||
net/chrony -- Chrony time synchronisation
|
||||
net/firewall -- Firewall API supplemental package (pending removal)
|
||||
net/freeradius -- RADIUS Authentication, Authorization and Accounting Server
|
||||
net/frr -- The FRRouting Protocol Suite
|
||||
net/ftp-proxy -- Control ftp-proxy processes
|
||||
|
@ -64,10 +63,8 @@ net/siproxd -- Siproxd is a proxy daemon for the SIP protocol
|
|||
net/sslh -- sslh configuration front-end
|
||||
net/tayga -- Tayga NAT64
|
||||
net/udpbroadcastrelay -- Control ubpbroadcastrelay processes
|
||||
net/upnp -- Universal Plug and Play Service
|
||||
net/upnp -- Universal Plug and Play (UPnP IGD & PCP/NAT-PMP) Service
|
||||
net/vnstat -- Network traffic monitor
|
||||
net/wireguard -- WireGuard VPN service kernel implementation (pending removal)
|
||||
net/wireguard-go -- WireGuard VPN service Go implementation (pending removal)
|
||||
net/wol -- Wake on LAN Service
|
||||
net/zerotier -- Virtual Networks That Just Work
|
||||
net-mgmt/collectd -- Collect system and application performance metrics periodically
|
||||
|
@ -94,7 +91,6 @@ security/tinc -- Tinc VPN
|
|||
security/tor -- The Onion Router
|
||||
security/wazuh-agent -- Agent for the open source security platform Wazuh
|
||||
sysutils/apcupsd -- APCUPSD - APC UPS daemon
|
||||
sysutils/api-backup -- EoL, core endpoint is /api/core/backup/download/this (pending removal)
|
||||
sysutils/apuled -- PC Engine APU LED control (development only)
|
||||
sysutils/dec-hw -- Deciso hardware specific information
|
||||
sysutils/dmidecode -- Display hardware information on the dashboard
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
PLUGIN_NAME= firewall
|
||||
PLUGIN_VERSION= 1.5
|
||||
PLUGIN_COMMENT= Firewall API supplemental package
|
||||
PLUGIN_OBSOLETE= yes
|
||||
PLUGIN_MAINTAINER= ad@opnsense.org
|
||||
PLUGIN_TIER= 2
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
|
@ -1,4 +0,0 @@
|
|||
This package extends the standard OPNsense firewall system with endpoints for machine to machine management tasks.
|
||||
Gui components are initially only intended to ease testing and to explain current functionality.
|
||||
|
||||
In the long term this might replace the default firewall in OPNsense.
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param $fw
|
||||
*/
|
||||
function pfplugin_firewall($fw)
|
||||
{
|
||||
$mdlFilter = new OPNsense\Firewall\Filter();
|
||||
foreach ($mdlFilter->rules->rule->sortedBy(["sequence"]) as $key => $rule) {
|
||||
$content = $rule->serialize();
|
||||
$content["#ref"] = "ui/firewall/filter#" . (string)$rule->getAttributes()['uuid'];
|
||||
$fw->registerFilterRule($rule->getPriority(), $content);
|
||||
}
|
||||
|
||||
foreach ($mdlFilter->snatrules->rule->sortedBy(["sequence"]) as $key => $rule) {
|
||||
$fw->registerSNatRule(50, $rule->serialize());
|
||||
}
|
||||
foreach ($mdlFilter->npt->rule->sortedBy(["sequence"]) as $key => $rule) {
|
||||
$fw->registerNptRule(50, $rule->serialize());
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Firewall\Alias;
|
||||
use OPNsense\Firewall\Category;
|
||||
|
||||
/**
|
||||
* Class FilterBaseController implements actions for various types
|
||||
* @package OPNsense\Firewall\Api
|
||||
*/
|
||||
abstract class FilterBaseController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'filter';
|
||||
protected static $internalModelClass = 'OPNsense\Firewall\Filter';
|
||||
protected static $categorysource = null;
|
||||
|
||||
/**
|
||||
* list categories and usage
|
||||
* @return array
|
||||
*/
|
||||
public function listCategoriesAction()
|
||||
{
|
||||
$response = ['rows' => []];
|
||||
$catcount = [];
|
||||
if (!empty(static::$categorysource)) {
|
||||
$node = $this->getModel();
|
||||
foreach (explode('.', static::$categorysource) as $ref) {
|
||||
$node = $node->$ref;
|
||||
}
|
||||
foreach ($node->iterateItems() as $item) {
|
||||
if (!empty((string)$item->categories)) {
|
||||
foreach (explode(',', (string)$item->categories) as $cat) {
|
||||
if (!isset($catcount[$cat])) {
|
||||
$catcount[$cat] = 0;
|
||||
}
|
||||
$catcount[$cat] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ((new Category())->categories->category->iterateItems() as $key => $category) {
|
||||
$response['rows'][] = [
|
||||
"uuid" => $key,
|
||||
"name" => (string)$category->name,
|
||||
"color" => (string)$category->color,
|
||||
"used" => isset($catcount[$key]) ? $catcount[$key] : 0
|
||||
];
|
||||
}
|
||||
array_multisort(array_column($response['rows'], "name"), SORT_ASC, SORT_NATURAL, $response['rows']);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* list of available network options
|
||||
* @return array
|
||||
*/
|
||||
public function listNetworkSelectOptionsAction()
|
||||
{
|
||||
$result = [
|
||||
'single' => [
|
||||
'label' => gettext("Single host or Network")
|
||||
],
|
||||
'aliases' => [
|
||||
'label' => gettext("Aliases"),
|
||||
'items' => []
|
||||
],
|
||||
'networks' => [
|
||||
'label' => gettext("Networks"),
|
||||
'items' => [
|
||||
'any' => gettext('any'),
|
||||
'(self)' => gettext("This Firewall")
|
||||
]
|
||||
]
|
||||
];
|
||||
foreach ((Config::getInstance()->object())->interfaces->children() as $ifname => $ifdetail) {
|
||||
$descr = htmlspecialchars(!empty($ifdetail->descr) ? $ifdetail->descr : strtoupper($ifname));
|
||||
$result['networks']['items'][$ifname] = $descr . " " . gettext("net");
|
||||
if (!isset($ifdetail->virtual)) {
|
||||
$result['networks']['items'][$ifname . "ip"] = $descr . " " . gettext("address");
|
||||
}
|
||||
}
|
||||
foreach ((new Alias())->aliases->alias->iterateItems() as $alias) {
|
||||
if (strpos((string)$alias->type, "port") === false) {
|
||||
$result['aliases']['items'][(string)$alias->name] = (string)$alias->name;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
public function applyAction($rollback_revision = null)
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
if ($rollback_revision != null) {
|
||||
// background rollback timer
|
||||
(new Backend())->configdpRun('pfplugin rollback_timer', [$rollback_revision], true);
|
||||
}
|
||||
return array("status" => (new Backend())->configdRun('filter reload'));
|
||||
} else {
|
||||
return array("status" => "error");
|
||||
}
|
||||
}
|
||||
|
||||
public function cancelRollbackAction($rollback_revision)
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
return array(
|
||||
"status" => (new Backend())->configdpRun('pfplugin cancel_rollback', [$rollback_revision])
|
||||
);
|
||||
} else {
|
||||
return array("status" => "error");
|
||||
}
|
||||
}
|
||||
|
||||
public function savepointAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
// trigger a save, so we know revision->time matches our running config
|
||||
Config::getInstance()->save();
|
||||
return array(
|
||||
"status" => "ok",
|
||||
"retention" => (string)Config::getInstance()->backupCount(),
|
||||
"revision" => (string)Config::getInstance()->object()->revision->time
|
||||
);
|
||||
} else {
|
||||
return array("status" => "error");
|
||||
}
|
||||
}
|
||||
|
||||
public function revertAction($revision)
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
Config::getInstance()->lock();
|
||||
$filename = Config::getInstance()->getBackupFilename($revision);
|
||||
if (!$filename) {
|
||||
Config::getInstance()->unlock();
|
||||
return ["status" => gettext("unknown (or removed) savepoint")];
|
||||
}
|
||||
$this->getModel()->rollback($revision);
|
||||
Config::getInstance()->unlock();
|
||||
(new Backend())->configdRun('filter reload');
|
||||
return ["status" => "ok"];
|
||||
} else {
|
||||
return array("status" => "error");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall\Api;
|
||||
|
||||
class FilterController extends FilterBaseController
|
||||
{
|
||||
protected static $categorysource = "rules.rule";
|
||||
|
||||
public function searchRuleAction()
|
||||
{
|
||||
$category = $this->request->get('category');
|
||||
$filter_funct = function ($record) use ($category) {
|
||||
return empty($category) || array_intersect(explode(',', $record->categories), $category);
|
||||
};
|
||||
return $this->searchBase("rules.rule", ['enabled', 'sequence', 'description'], "sequence", $filter_funct);
|
||||
}
|
||||
|
||||
public function setRuleAction($uuid)
|
||||
{
|
||||
return $this->setBase("rule", "rules.rule", $uuid);
|
||||
}
|
||||
|
||||
public function addRuleAction()
|
||||
{
|
||||
return $this->addBase("rule", "rules.rule");
|
||||
}
|
||||
|
||||
public function getRuleAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("rule", "rules.rule", $uuid);
|
||||
}
|
||||
|
||||
public function delRuleAction($uuid)
|
||||
{
|
||||
return $this->delBase("rules.rule", $uuid);
|
||||
}
|
||||
|
||||
public function toggleRuleAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("rules.rule", $uuid, $enabled);
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
<?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\Firewall\Api;
|
||||
|
||||
class NptController extends FilterBaseController
|
||||
{
|
||||
protected static $categorysource = "npt.rule";
|
||||
|
||||
public function searchRuleAction()
|
||||
{
|
||||
$category = $this->request->get('category');
|
||||
$filter_funct = function ($record) use ($category) {
|
||||
return empty($category) || array_intersect(explode(',', $record->categories), $category);
|
||||
};
|
||||
return $this->searchBase(
|
||||
"npt.rule",
|
||||
['enabled', 'sequence', 'source_net', 'destination_net', 'trackif', 'description'],
|
||||
"sequence",
|
||||
$filter_funct
|
||||
);
|
||||
}
|
||||
|
||||
public function setRuleAction($uuid)
|
||||
{
|
||||
return $this->setBase("rule", "npt.rule", $uuid);
|
||||
}
|
||||
|
||||
public function addRuleAction()
|
||||
{
|
||||
return $this->addBase("rule", "npt.rule");
|
||||
}
|
||||
|
||||
public function getRuleAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("rule", "npt.rule", $uuid);
|
||||
}
|
||||
|
||||
public function delRuleAction($uuid)
|
||||
{
|
||||
return $this->delBase("npt.rule", $uuid);
|
||||
}
|
||||
|
||||
public function toggleRuleAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("npt.rule", $uuid, $enabled);
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall\Api;
|
||||
|
||||
class SourceNatController extends FilterBaseController
|
||||
{
|
||||
protected static $categorysource = "snatrules.rule";
|
||||
|
||||
public function searchRuleAction()
|
||||
{
|
||||
$category = $this->request->get('category');
|
||||
$filter_funct = function ($record) use ($category) {
|
||||
return empty($category) || array_intersect(explode(',', $record->categories), $category);
|
||||
};
|
||||
return $this->searchBase("snatrules.rule", ['enabled', 'sequence', 'description'], "sequence", $filter_funct);
|
||||
}
|
||||
|
||||
public function setRuleAction($uuid)
|
||||
{
|
||||
return $this->setBase("rule", "snatrules.rule", $uuid);
|
||||
}
|
||||
|
||||
public function addRuleAction()
|
||||
{
|
||||
return $this->addBase("rule", "snatrules.rule");
|
||||
}
|
||||
|
||||
public function getRuleAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("rule", "snatrules.rule", $uuid);
|
||||
}
|
||||
|
||||
public function delRuleAction($uuid)
|
||||
{
|
||||
return $this->delBase("snatrules.rule", $uuid);
|
||||
}
|
||||
|
||||
public function toggleRuleAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("snatrules.rule", $uuid, $enabled);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall;
|
||||
|
||||
class FilterController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Firewall/filter');
|
||||
$this->view->SavePointBtns = true;
|
||||
$this->view->ruleController = "filter";
|
||||
$this->view->gridFields = [
|
||||
[
|
||||
'id' => 'enabled', 'formatter' => 'rowtoggle' ,'width' => '6em', 'heading' => gettext('Enabled')
|
||||
],
|
||||
[
|
||||
'id' => 'sequence','width' => '9em', 'heading' => gettext('Sequence')
|
||||
],
|
||||
[
|
||||
'id' => 'description', 'heading' => gettext('Description')
|
||||
]
|
||||
];
|
||||
$this->view->formDialogFilterRule = $this->getForm("dialogFilterRule");
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
<?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\Firewall;
|
||||
|
||||
class NptController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Firewall/filter');
|
||||
$this->view->ruleController = "npt";
|
||||
$this->view->gridFields = [
|
||||
[
|
||||
'id' => 'enabled', 'formatter' => 'rowtoggle' ,'width' => '6em', 'heading' => gettext('Enabled')
|
||||
],
|
||||
[
|
||||
'id' => 'sequence','width' => '9em', 'heading' => gettext('Sequence')
|
||||
],
|
||||
[
|
||||
'id' => 'source_net', 'heading' => gettext('Internal IPv6 Prefix')
|
||||
],
|
||||
[
|
||||
'id' => 'destination_net', 'heading' => gettext('External IPv6 Prefix')
|
||||
],
|
||||
[
|
||||
'id' => 'trackif', 'heading' => gettext('Track if')
|
||||
],
|
||||
[
|
||||
'id' => 'description', 'heading' => gettext('Description')
|
||||
]
|
||||
];
|
||||
|
||||
$this->view->formDialogFilterRule = $this->getForm("dialogNptRule");
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall;
|
||||
|
||||
class SourceNatController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Firewall/filter');
|
||||
$this->view->SavePointBtns = true;
|
||||
$this->view->ruleController = "source_nat";
|
||||
$this->view->gridFields = [
|
||||
[
|
||||
'id' => 'enabled', 'formatter' => 'rowtoggle' ,'width' => '6em', 'heading' => gettext('Enabled')
|
||||
],
|
||||
[
|
||||
'id' => 'sequence','width' => '9em', 'heading' => gettext('Sequence')
|
||||
],
|
||||
[
|
||||
'id' => 'description', 'heading' => gettext('Description')
|
||||
]
|
||||
];
|
||||
$this->view->formDialogFilterRule = $this->getForm("dialogSNatRule");
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>rule.enabled</id>
|
||||
<label>enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.sequence</id>
|
||||
<label>Sequence</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.action</id>
|
||||
<label>Action</label>
|
||||
<type>dropdown</type>
|
||||
<help>Choose what to do with packets that match the criteria specified below.
|
||||
Hint: the difference between block and reject is that with reject, a packet (TCP RST or ICMP port unreachable for UDP) is returned to the sender, whereas with block the packet is dropped silently. In either case, the original packet is discarded.
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.quick</id>
|
||||
<label>Quick</label>
|
||||
<type>checkbox</type>
|
||||
<help>
|
||||
If a packet matches a rule specifying quick, then that rule is considered the last matching rule and the specified action is taken.
|
||||
When a rule does not have quick enabled, the last matching rule wins.
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.interface</id>
|
||||
<label>Interface</label>
|
||||
<type>select_multiple</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.direction</id>
|
||||
<label>Direction</label>
|
||||
<type>dropdown</type>
|
||||
<help>
|
||||
Direction of the traffic. The default policy is to filter inbound traffic, which sets the policy to the interface originally receiving the traffic.
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.ipprotocol</id>
|
||||
<label>TCP/IP Version</label>
|
||||
<type>dropdown</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.protocol</id>
|
||||
<label>Protocol</label>
|
||||
<type>dropdown</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_net</id>
|
||||
<label>Source</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_port</id>
|
||||
<label>Source port</label>
|
||||
<type>text</type>
|
||||
<advanced>true</advanced>
|
||||
<help>Source port number or well known name (imap, imaps, http, https, ...), for ranges use a dash</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_not</id>
|
||||
<label>Source / Invert</label>
|
||||
<type>checkbox</type>
|
||||
<help>Use this option to invert the sense of the match.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_net</id>
|
||||
<label>Destination</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_not</id>
|
||||
<label>Destination / Invert</label>
|
||||
<type>checkbox</type>
|
||||
<help>Use this option to invert the sense of the match.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_port</id>
|
||||
<label>Destination port</label>
|
||||
<type>text</type>
|
||||
<help>Destination port number or well known name (imap, imaps, http, https, ...), for ranges use a dash</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.gateway</id>
|
||||
<label>Gateway</label>
|
||||
<type>dropdown</type>
|
||||
<help>
|
||||
Leave as 'default' to use the system routing table. Or choose a gateway to utilize policy based routing.
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.log</id>
|
||||
<label>Log</label>
|
||||
<type>checkbox</type>
|
||||
<help>Log packets that are handled by this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.categories</id>
|
||||
<label>Categories</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help>For grouping purposes you may select multiple groups here to organize items.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
</form>
|
|
@ -1,53 +0,0 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>rule.enabled</id>
|
||||
<label>enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.sequence</id>
|
||||
<label>Sequence</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.log</id>
|
||||
<label>Log</label>
|
||||
<type>checkbox</type>
|
||||
<help>Log packets that are handled by this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.interface</id>
|
||||
<label>Interface</label>
|
||||
<type>dropdown</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_net</id>
|
||||
<label>Internal IPv6 Prefix (source)</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_net</id>
|
||||
<label>External IPv6 Prefix (target)</label>
|
||||
<type>text</type>
|
||||
<help>Enter the external IPv6 prefix for this network prefix translation. Leave empty to auto-detect the prefix address using the specified tracking interface instead. The prefix size specified for the internal prefix will also be applied to the external prefix.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.trackif</id>
|
||||
<label>Track interface</label>
|
||||
<type>dropdown</type>
|
||||
<help>Use prefix defined on the selected interface instead of the interface this rule applies to when target prefix is not provided.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.categories</id>
|
||||
<label>Categories</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help>For grouping purposes you may select multiple groups here to organize items.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
</form>
|
|
@ -1,101 +0,0 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>rule.enabled</id>
|
||||
<label>enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.nonat</id>
|
||||
<label>Do not NAT</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enabling this option will disable NAT for traffic matching this rule and stop processing Outbound NAT rules.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.sequence</id>
|
||||
<label>Sequence</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.interface</id>
|
||||
<label>Interface</label>
|
||||
<type>dropdown</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.ipprotocol</id>
|
||||
<label>TCP/IP Version</label>
|
||||
<type>dropdown</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.protocol</id>
|
||||
<label>Protocol</label>
|
||||
<type>dropdown</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_net</id>
|
||||
<label>Source</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_port</id>
|
||||
<label>Source port</label>
|
||||
<type>text</type>
|
||||
<advanced>true</advanced>
|
||||
<help>Source port number or well known name (imap, imaps, http, https, ...), for ranges use a dash</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.source_not</id>
|
||||
<label>Source / Invert</label>
|
||||
<type>checkbox</type>
|
||||
<help>Use this option to invert the sense of the match.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_net</id>
|
||||
<label>Destination</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_not</id>
|
||||
<label>Destination / Invert</label>
|
||||
<type>checkbox</type>
|
||||
<help>Use this option to invert the sense of the match.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.destination_port</id>
|
||||
<label>Destination port</label>
|
||||
<type>text</type>
|
||||
<help>Destination port number or well known name (imap, imaps, http, https, ...), for ranges use a dash</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.target</id>
|
||||
<label>Translation / target</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
Packets matching this rule will be mapped to the IP address given here.
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.target_port</id>
|
||||
<label>Translation port</label>
|
||||
<type>text</type>
|
||||
<help>Destination port number or well known name (imap, imaps, http, https, ...)</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.log</id>
|
||||
<label>Log</label>
|
||||
<type>checkbox</type>
|
||||
<help>Log packets that are handled by this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.categories</id>
|
||||
<label>Categories</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<help>For grouping purposes you may select multiple groups here to organize items.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>rule.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
</form>
|
|
@ -1,23 +0,0 @@
|
|||
<acl>
|
||||
<page-filter-api>
|
||||
<name>Firewall: Automation: Filter</name>
|
||||
<patterns>
|
||||
<pattern>ui/firewall/filter/*</pattern>
|
||||
<pattern>api/firewall/filter/*</pattern>
|
||||
</patterns>
|
||||
</page-filter-api>
|
||||
<page-filter-snat-api>
|
||||
<name>Firewall: Automation: Source NAT</name>
|
||||
<patterns>
|
||||
<pattern>ui/firewall/source_nat/*</pattern>
|
||||
<pattern>api/firewall/source_nat/*</pattern>
|
||||
</patterns>
|
||||
</page-filter-snat-api>
|
||||
<page-firewall-nat-npt>
|
||||
<name>Firewall: Automation: NPTv6</name>
|
||||
<patterns>
|
||||
<pattern>ui/firewall/npt/*</pattern>
|
||||
<pattern>api/firewall/npt/*</pattern>
|
||||
</patterns>
|
||||
</page-firewall-nat-npt>
|
||||
</acl>
|
|
@ -1,138 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall\FieldTypes;
|
||||
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Base\FieldTypes\ArrayField;
|
||||
use OPNsense\Base\FieldTypes\ContainerField;
|
||||
|
||||
/**
|
||||
* Class FilterRuleContainerField
|
||||
* @package OPNsense\Firewall\FieldTypes
|
||||
*/
|
||||
class FilterRuleContainerField extends ContainerField
|
||||
{
|
||||
/**
|
||||
* map rules
|
||||
* @return array
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
$result = array();
|
||||
$map_manual = ['source_net', 'source_not', 'source_port', 'destination_net', 'destination_not',
|
||||
'destination_port', 'enabled', 'description', 'sequence', 'action'];
|
||||
// 1-on-1 map (with type conversion if needed)
|
||||
foreach ($this->iterateItems() as $key => $node) {
|
||||
if (!in_array($key, $map_manual)) {
|
||||
if (is_a($node, "OPNsense\\Base\\FieldTypes\\BooleanField")) {
|
||||
$result[$key] = !empty((string)$node);
|
||||
} elseif (is_a($node, "OPNsense\\Base\\FieldTypes\\ProtocolField")) {
|
||||
if ((string)$node != 'any') {
|
||||
$result[$key] = (string)$node;
|
||||
}
|
||||
} else {
|
||||
$result[$key] = (string)$node;
|
||||
}
|
||||
}
|
||||
}
|
||||
// source / destination mapping
|
||||
$result['source'] = array();
|
||||
if (!empty((string)$this->source_net)) {
|
||||
$result['source']['network'] = (string)$this->source_net;
|
||||
if (!empty((string)$this->source_not)) {
|
||||
$result['source']['not'] = true;
|
||||
}
|
||||
if (!empty((string)$this->source_port)) {
|
||||
$result['source']['port'] = (string)$this->source_port;
|
||||
}
|
||||
}
|
||||
$result['destination'] = array();
|
||||
if (!empty((string)$this->destination_net)) {
|
||||
$result['destination']['network'] = (string)$this->destination_net;
|
||||
if (!empty((string)$this->destination_not)) {
|
||||
$result['destination']['not'] = true;
|
||||
}
|
||||
if (!empty((string)$this->destination_port)) {
|
||||
$result['destination']['port'] = (string)$this->destination_port;
|
||||
}
|
||||
}
|
||||
// field mappings and differences
|
||||
$result['disabled'] = empty((string)$this->enabled);
|
||||
$result['descr'] = (string)$this->description;
|
||||
$result['type'] = (string)$this->action;
|
||||
if (strpos((string)$this->interface, ",") !== false) {
|
||||
$result['floating'] = true;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* rule priority is threaded equally to the legacy rules, first "floating" then groups and single interface
|
||||
* rules are handled last
|
||||
* @return int priority in the ruleset, sequence should determine sort order.
|
||||
*/
|
||||
public function getPriority()
|
||||
{
|
||||
$configObj = Config::getInstance()->object();
|
||||
$interface = (string)$this->interface;
|
||||
if (strpos($interface, ",") !== false) {
|
||||
// floating (multiple interfaces involved)
|
||||
return 1000;
|
||||
} elseif (
|
||||
!empty($configObj->interfaces) &&
|
||||
!empty($configObj->interfaces->$interface) &&
|
||||
!empty($configObj->interfaces->$interface->type) &&
|
||||
$configObj->interfaces->$interface->type == 'group'
|
||||
) {
|
||||
// group type
|
||||
return 2000;
|
||||
} else {
|
||||
// default
|
||||
return 3000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class FilterRuleField
|
||||
* @package OPNsense\Firewall\FieldTypes
|
||||
*/
|
||||
class FilterRuleField extends ArrayField
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function newContainerField($ref, $tagname)
|
||||
{
|
||||
$container_node = new FilterRuleContainerField($ref, $tagname);
|
||||
$parentmodel = $this->getParentModel();
|
||||
$container_node->setParentModel($parentmodel);
|
||||
return $container_node;
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall\FieldTypes;
|
||||
|
||||
use OPNsense\Base\FieldTypes\ArrayField;
|
||||
use OPNsense\Base\FieldTypes\ContainerField;
|
||||
|
||||
/**
|
||||
* Class SourceNatRuleContainerField
|
||||
* @package OPNsense\Firewall\FieldTypes
|
||||
*/
|
||||
class SourceNatRuleContainerField extends ContainerField
|
||||
{
|
||||
/**
|
||||
* map source nat rules
|
||||
* @return array
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
$result = [];
|
||||
$source_mapper = [
|
||||
'enabled' => false,
|
||||
'source_net' => false,
|
||||
'source_not' => false,
|
||||
'source_port' => 'sourceport',
|
||||
'destination_net' => false,
|
||||
'destination_not' => false,
|
||||
'destination_port' => 'dstport',
|
||||
'target_port' => 'natport',
|
||||
'description' => 'descr'
|
||||
];
|
||||
// 1-on-1 map (with type conversion if needed)
|
||||
foreach ($this->iterateItems() as $key => $node) {
|
||||
$target_fieldname = isset($source_mapper[$key]) ? $source_mapper[$key] : $key;
|
||||
if ($target_fieldname) {
|
||||
if (is_a($node, "OPNsense\\Base\\FieldTypes\\BooleanField")) {
|
||||
$result[$target_fieldname] = !empty((string)$node);
|
||||
} elseif (is_a($node, "OPNsense\\Base\\FieldTypes\\ProtocolField")) {
|
||||
if ((string)$node != 'any') {
|
||||
$result[$target_fieldname] = (string)$node;
|
||||
}
|
||||
} else {
|
||||
$result[$target_fieldname] = (string)$node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$result['disabled'] = empty((string)$this->enabled);
|
||||
// source / destination mapping, doesn't use port construct like it would for rules.
|
||||
$result['source'] = array();
|
||||
if (!empty((string)$this->source_net)) {
|
||||
$result['source']['network'] = (string)$this->source_net;
|
||||
if (!empty((string)$this->source_not)) {
|
||||
$result['source']['not'] = true;
|
||||
}
|
||||
}
|
||||
$result['destination'] = array();
|
||||
if (!empty((string)$this->destination_net)) {
|
||||
$result['destination']['network'] = (string)$this->destination_net;
|
||||
if (!empty((string)$this->destination_not)) {
|
||||
$result['destination']['not'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class SourceNatRuleField
|
||||
* @package OPNsense\Firewall\FieldTypes
|
||||
*/
|
||||
class SourceNatRuleField extends ArrayField
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function newContainerField($ref, $tagname)
|
||||
{
|
||||
$container_node = new SourceNatRuleContainerField($ref, $tagname);
|
||||
$parentmodel = $this->getParentModel();
|
||||
$container_node->setParentModel($parentmodel);
|
||||
return $container_node;
|
||||
}
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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\Firewall;
|
||||
|
||||
use OPNsense\Core\Config;
|
||||
use Phalcon\Messages\Message;
|
||||
use OPNsense\Base\BaseModel;
|
||||
use OPNsense\Firewall\Util;
|
||||
|
||||
class Filter extends BaseModel
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function performValidation($validateFullModel = false)
|
||||
{
|
||||
$config = Config::getInstance()->object();
|
||||
|
||||
// standard model validations
|
||||
$messages = parent::performValidation($validateFullModel);
|
||||
foreach ([$this->rules->rule, $this->snatrules->rule] as $rules) {
|
||||
foreach ($rules->iterateItems() as $rule) {
|
||||
if ($validateFullModel || $rule->isFieldChanged()) {
|
||||
// port / protocol validation
|
||||
if (!empty((string)$rule->source_port) && !in_array($rule->protocol, ['TCP', 'UDP'])) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("Source ports are only valid for tcp or udp type rules."),
|
||||
$rule->source_port->__reference
|
||||
));
|
||||
}
|
||||
if (!empty((string)$rule->destination_port) && !in_array($rule->protocol, ['TCP', 'UDP'])) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("Destination ports are only valid for tcp or udp type rules."),
|
||||
$rule->destination_port->__reference
|
||||
));
|
||||
}
|
||||
// validate protocol family
|
||||
$dest_is_addr = Util::isSubnet($rule->destination_net) || Util::isIpAddress($rule->destination_net);
|
||||
$dest_proto = strpos($rule->destination_net, ':') === false ? "inet" : "inet6";
|
||||
if ($dest_is_addr && $dest_proto != $rule->ipprotocol) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("Destination address type should match selected TCP/IP protocol version."),
|
||||
$rule->destination_net->__reference
|
||||
));
|
||||
}
|
||||
$src_is_addr = Util::isSubnet($rule->source_net) || Util::isIpAddress($rule->source_net);
|
||||
$src_proto = strpos($rule->source_net, ':') === false ? "inet" : "inet6";
|
||||
if ($src_is_addr && $src_proto != $rule->ipprotocol) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("Source address type should match selected TCP/IP protocol version."),
|
||||
$rule->source_net->__reference
|
||||
));
|
||||
}
|
||||
// Additional source nat validations
|
||||
if ($rule->target !== null) {
|
||||
$target_is_addr = Util::isSubnet($rule->target) || Util::isIpAddress($rule->target);
|
||||
$target_proto = strpos($rule->target, ':') === false ? "inet" : "inet6";
|
||||
if ($target_is_addr && $target_proto != $rule->ipprotocol) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("Target address type should match selected TCP/IP protocol version."),
|
||||
$rule->target->__reference
|
||||
));
|
||||
}
|
||||
if (!empty((string)$rule->target_port) && !in_array($rule->protocol, ['TCP', 'UDP'])) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("Target ports are only valid for tcp or udp type rules."),
|
||||
$rule->target_port->__reference
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->npt->rule->iterateItems() as $rule) {
|
||||
if ($validateFullModel || $rule->isFieldChanged()) {
|
||||
if (!empty((string)$rule->trackif)) {
|
||||
if (!empty((string)$rule->destination_net)) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext('A track interface is only allowed without an external prefix.'),
|
||||
$rule->trackif->__reference
|
||||
));
|
||||
}
|
||||
|
||||
if (
|
||||
(empty($config->interfaces->{$rule->interface}->ipaddrv6) ||
|
||||
$config->interfaces->{$rule->interface}->ipaddrv6 != 'dhcp6') ||
|
||||
empty($config->interfaces->{$rule->trackif}->{'track6-interface'}) ||
|
||||
$config->interfaces->{$rule->trackif}->{'track6-interface'} != (string)$rule->interface
|
||||
) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext('This interface is not tracking the current rule interface.'),
|
||||
$rule->trackif->__reference
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty((string)$rule->destination_net) && !empty((string)$rule->source_net)) {
|
||||
/* defaults to /128 */
|
||||
$dparts = explode('/', (string)$rule->destination_net . '/128');
|
||||
$sparts = explode('/', (string)$rule->source_net . '/128');
|
||||
if ($dparts[1] != $sparts[1]) {
|
||||
$messages->appendMessage(new Message(
|
||||
gettext("External subnet should match internal subnet."),
|
||||
$rule->destination_net->__reference
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback this model to a previous version.
|
||||
* Make sure to remove this object afterwards, since its contents won't be updated.
|
||||
* @param $revision float|string revision number
|
||||
* @return bool action performed (backup revision existed)
|
||||
*/
|
||||
public function rollback($revision)
|
||||
{
|
||||
$filename = Config::getInstance()->getBackupFilename($revision);
|
||||
if ($filename) {
|
||||
// fiddle with the dom, copy OPNsense->Firewall->Filter from backup to current config
|
||||
$sourcexml = simplexml_load_file($filename);
|
||||
if ($sourcexml->OPNsense->Firewall->Filter) {
|
||||
$sourcedom = dom_import_simplexml($sourcexml->OPNsense->Firewall->Filter);
|
||||
$targetxml = Config::getInstance()->object();
|
||||
$targetdom = dom_import_simplexml($targetxml->OPNsense->Firewall->Filter);
|
||||
$node = $targetdom->ownerDocument->importNode($sourcedom, true);
|
||||
$targetdom->parentNode->replaceChild($node, $targetdom);
|
||||
Config::getInstance()->save();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,263 +0,0 @@
|
|||
<model>
|
||||
<mount>//OPNsense/Firewall/Filter</mount>
|
||||
<version>1.0.2</version>
|
||||
<migration_prefix>MFP</migration_prefix>
|
||||
<description>
|
||||
OPNsense firewall filter rules
|
||||
</description>
|
||||
<items>
|
||||
<rules>
|
||||
<rule type=".\FilterRuleField">
|
||||
<enabled type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<sequence type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>99999</MaximumValue>
|
||||
<ValidationMessage>provide a valid sequence for sorting</ValidationMessage>
|
||||
<Required>Y</Required>
|
||||
<Default>1</Default>
|
||||
</sequence>
|
||||
<action type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<Default>pass</Default>
|
||||
<OptionValues>
|
||||
<pass>Pass</pass>
|
||||
<block>Block</block>
|
||||
<reject>Reject</reject>
|
||||
</OptionValues>
|
||||
</action>
|
||||
<quick type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</quick>
|
||||
<interface type="InterfaceField">
|
||||
<Multiple>Y</Multiple>
|
||||
<AllowDynamic>Y</AllowDynamic>
|
||||
</interface>
|
||||
<direction type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<Default>in</Default>
|
||||
<OptionValues>
|
||||
<in>In</in>
|
||||
<out>Out</out>
|
||||
</OptionValues>
|
||||
</direction>
|
||||
<ipprotocol type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<Default>inet</Default>
|
||||
<OptionValues>
|
||||
<inet>IPv4</inet>
|
||||
<inet6>IPv6</inet6>
|
||||
</OptionValues>
|
||||
</ipprotocol>
|
||||
<protocol type="ProtocolField">
|
||||
<Required>Y</Required>
|
||||
<Default>any</Default>
|
||||
</protocol>
|
||||
<!-- XXX: should map internally to 'source' => array('network' => $source_net, "not" => true|false) -->
|
||||
<source_net type="NetworkAliasField">
|
||||
<Default>any</Default>
|
||||
<Required>Y</Required>
|
||||
</source_net>
|
||||
<source_not type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</source_not>
|
||||
<source_port type="PortField">
|
||||
<EnableWellKnown>Y</EnableWellKnown>
|
||||
<EnableRanges>Y</EnableRanges>
|
||||
<EnableAlias>Y</EnableAlias>
|
||||
<ValidationMessage>Please specify a valid portnumber, name, alias or range</ValidationMessage>
|
||||
</source_port>
|
||||
<!-- XXX: should map internally to 'source' => array('destination' => destination_net, "not" => true|false) -->
|
||||
<destination_net type="NetworkAliasField">
|
||||
<Default>any</Default>
|
||||
<Required>Y</Required>
|
||||
</destination_net>
|
||||
<destination_not type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</destination_not>
|
||||
<destination_port type="PortField">
|
||||
<EnableWellKnown>Y</EnableWellKnown>
|
||||
<EnableRanges>Y</EnableRanges>
|
||||
<EnableAlias>Y</EnableAlias>
|
||||
<ValidationMessage>Please specify a valid portnumber, name, alias or range</ValidationMessage>
|
||||
</destination_port>
|
||||
<gateway type="JsonKeyValueStoreField">
|
||||
<ConfigdPopulateAct>interface gateways list</ConfigdPopulateAct>
|
||||
<SourceFile>/tmp/gateway_list.json</SourceFile>
|
||||
<ConfigdPopulateTTL>20</ConfigdPopulateTTL>
|
||||
<ValidationMessage>Specify a valid gateway from the list matching the networks ip protocol.</ValidationMessage>
|
||||
</gateway>
|
||||
<log type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</log>
|
||||
<categories type="ModelRelationField">
|
||||
<Model>
|
||||
<rulesets>
|
||||
<source>OPNsense.Firewall.Category</source>
|
||||
<items>categories.category</items>
|
||||
<display>name</display>
|
||||
</rulesets>
|
||||
</Model>
|
||||
<Multiple>Y</Multiple>
|
||||
<ValidationMessage>Related category not found.</ValidationMessage>
|
||||
</categories>
|
||||
<description type="TextField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.\-,_\x{00A0}-\x{FFFF}]){0,255}$/u</mask>
|
||||
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
|
||||
</description>
|
||||
</rule>
|
||||
</rules>
|
||||
<snatrules>
|
||||
<rule type=".\SourceNatRuleField">
|
||||
<enabled type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<nonat type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</nonat>
|
||||
<sequence type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>99999</MaximumValue>
|
||||
<ValidationMessage>provide a valid sequence for sorting</ValidationMessage>
|
||||
<Required>Y</Required>
|
||||
<Default>1</Default>
|
||||
</sequence>
|
||||
<interface type="InterfaceField">
|
||||
<Required>Y</Required>
|
||||
<Default>lan</Default>
|
||||
<AllowDynamic>Y</AllowDynamic>
|
||||
</interface>
|
||||
<ipprotocol type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<Default>inet</Default>
|
||||
<OptionValues>
|
||||
<inet>IPv4</inet>
|
||||
<inet6>IPv6</inet6>
|
||||
</OptionValues>
|
||||
</ipprotocol>
|
||||
<protocol type="ProtocolField">
|
||||
<Required>Y</Required>
|
||||
<Default>any</Default>
|
||||
</protocol>
|
||||
<source_net type="NetworkAliasField">
|
||||
<Default>any</Default>
|
||||
<Required>Y</Required>
|
||||
</source_net>
|
||||
<source_not type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</source_not>
|
||||
<source_port type="PortField">
|
||||
<EnableWellKnown>Y</EnableWellKnown>
|
||||
<EnableRanges>Y</EnableRanges>
|
||||
<EnableAlias>Y</EnableAlias>
|
||||
<ValidationMessage>Please specify a valid portnumber, name, alias or range</ValidationMessage>
|
||||
</source_port>
|
||||
<destination_net type="NetworkAliasField">
|
||||
<Default>any</Default>
|
||||
<Required>Y</Required>
|
||||
</destination_net>
|
||||
<destination_not type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</destination_not>
|
||||
<destination_port type="PortField">
|
||||
<EnableWellKnown>Y</EnableWellKnown>
|
||||
<EnableRanges>Y</EnableRanges>
|
||||
<EnableAlias>Y</EnableAlias>
|
||||
<ValidationMessage>Please specify a valid portnumber, name, alias or range</ValidationMessage>
|
||||
</destination_port>
|
||||
<target type="NetworkAliasField">
|
||||
<Default>wanip</Default>
|
||||
<Required>Y</Required>
|
||||
</target>
|
||||
<target_port type="PortField">
|
||||
<EnableWellKnown>Y</EnableWellKnown>
|
||||
<EnableRanges>Y</EnableRanges>
|
||||
</target_port>
|
||||
<log type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</log>
|
||||
<categories type="ModelRelationField">
|
||||
<Model>
|
||||
<rulesets>
|
||||
<source>OPNsense.Firewall.Category</source>
|
||||
<items>categories.category</items>
|
||||
<display>name</display>
|
||||
</rulesets>
|
||||
</Model>
|
||||
<Multiple>Y</Multiple>
|
||||
<ValidationMessage>Related category not found.</ValidationMessage>
|
||||
</categories>
|
||||
<description type="TextField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.\-,_\x{00A0}-\x{FFFF}]){0,255}$/u</mask>
|
||||
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
|
||||
</description>
|
||||
</rule>
|
||||
</snatrules>
|
||||
<npt>
|
||||
<rule type=".\SourceNatRuleField">
|
||||
<enabled type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<log type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</log>
|
||||
<sequence type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>99999</MaximumValue>
|
||||
<ValidationMessage>provide a valid sequence for sorting</ValidationMessage>
|
||||
<Required>Y</Required>
|
||||
<Default>1</Default>
|
||||
</sequence>
|
||||
<interface type="InterfaceField">
|
||||
<Required>Y</Required>
|
||||
<Default>lan</Default>
|
||||
<AllowDynamic>Y</AllowDynamic>
|
||||
</interface>
|
||||
<source_net type="NetworkField">
|
||||
<Required>Y</Required>
|
||||
<AddressFamily>ipv6</AddressFamily>
|
||||
<NetMaskRequired>N</NetMaskRequired>
|
||||
<WildcardEnabled>N</WildcardEnabled>
|
||||
</source_net>
|
||||
<destination_net type="NetworkField">
|
||||
<AddressFamily>ipv6</AddressFamily>
|
||||
<NetMaskRequired>N</NetMaskRequired>
|
||||
<WildcardEnabled>N</WildcardEnabled>
|
||||
</destination_net>
|
||||
<trackif type="InterfaceField">
|
||||
</trackif>
|
||||
<categories type="ModelRelationField">
|
||||
<Model>
|
||||
<rulesets>
|
||||
<source>OPNsense.Firewall.Category</source>
|
||||
<items>categories.category</items>
|
||||
<display>name</display>
|
||||
</rulesets>
|
||||
</Model>
|
||||
<Multiple>Y</Multiple>
|
||||
<ValidationMessage>Related category not found.</ValidationMessage>
|
||||
</categories>
|
||||
<description type="TextField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.\-,_\x{00A0}-\x{FFFF}]){0,255}$/u</mask>
|
||||
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
|
||||
</description>
|
||||
</rule>
|
||||
</npt>
|
||||
</items>
|
||||
</model>
|
|
@ -1,15 +0,0 @@
|
|||
<menu>
|
||||
<Firewall>
|
||||
<Automation cssClass="fa fa-gear">
|
||||
<Filter order="50" url="/ui/firewall/filter/">
|
||||
<FilterRef url="/ui/firewall/filter#*" visibility="hidden"/>
|
||||
</Filter>
|
||||
<SourceNat order="100" VisibleName="Source NAT" url="/ui/firewall/source_nat/">
|
||||
<FilterRef url="/ui/firewall/source_nat#*" visibility="hidden"/>
|
||||
</SourceNat>
|
||||
<Npt order="150" VisibleName="NPTv6" url="/ui/firewall/npt/">
|
||||
<FilterRef url="/ui/firewall/npt#*" visibility="hidden"/>
|
||||
</Npt>
|
||||
</Automation>
|
||||
</Firewall>
|
||||
</menu>
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2020 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\Firewall\Migrations;
|
||||
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Base\BaseModelMigration;
|
||||
|
||||
class MFP1_0_0 extends BaseModelMigration
|
||||
{
|
||||
public function post($model)
|
||||
{
|
||||
// Move OPNsense->Firewall->FilterRule ---> OPNsense->Firewall->Filter
|
||||
$cfgObj = Config::getInstance()->object();
|
||||
if (
|
||||
!empty($cfgObj->OPNsense) && !empty($cfgObj->OPNsense->Firewall)
|
||||
&& !empty($cfgObj->OPNsense->Firewall->FilterRule)
|
||||
) {
|
||||
// model migration created a new, empty rules section
|
||||
if (empty($cfgObj->OPNsense->Firewall->Filter->rules)) {
|
||||
unset($cfgObj->OPNsense->Firewall->Filter->rules);
|
||||
$targetdom = dom_import_simplexml($cfgObj->OPNsense->Firewall->Filter);
|
||||
foreach ($cfgObj->OPNsense->Firewall->FilterRule->children() as $child) {
|
||||
$sourcedom = dom_import_simplexml($child);
|
||||
$targetdom->appendChild($sourcedom);
|
||||
}
|
||||
unset($cfgObj->OPNsense->Firewall->FilterRule);
|
||||
Config::getInstance()->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,250 +0,0 @@
|
|||
<script>
|
||||
$( document ).ready(function() {
|
||||
let initial_load = true;
|
||||
let grid = $("#grid-rules").UIBootgrid({
|
||||
search:'/api/firewall/{{ruleController}}/search_rule/',
|
||||
get:'/api/firewall/{{ruleController}}/get_rule/',
|
||||
set:'/api/firewall/{{ruleController}}/set_rule/',
|
||||
add:'/api/firewall/{{ruleController}}/add_rule/',
|
||||
del:'/api/firewall/{{ruleController}}/del_rule/',
|
||||
toggle:'/api/firewall/{{ruleController}}/toggle_rule/',
|
||||
options:{
|
||||
requestHandler: function(request){
|
||||
if ( $('#category_filter').val().length > 0) {
|
||||
request['category'] = $('#category_filter').val();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
||||
});
|
||||
grid.on("loaded.rs.jquery.bootgrid", function (e){
|
||||
// reload categories before grid load
|
||||
ajaxCall('/api/firewall/{{ruleController}}/list_categories', {}, function(data, status){
|
||||
if (data.rows !== undefined) {
|
||||
let current_selection = $("#category_filter").val();
|
||||
$("#category_filter").empty();
|
||||
for (i=0; i < data.rows.length ; ++i) {
|
||||
let row = data.rows[i];
|
||||
let opt_val = $('<div/>').html(row.name).text();
|
||||
let bgcolor = row.color != "" ? row.color : '31708f;'; // set category color
|
||||
let option = $("<option/>").val(row.uuid).html(row.name);
|
||||
if (row.used > 0) {
|
||||
option.attr(
|
||||
'data-content',
|
||||
"<span>"+opt_val + "</span>"+
|
||||
"<span style='background:#"+bgcolor+";' class='badge pull-right'>" + row.used + "</span>"
|
||||
);
|
||||
option.attr('id', row.uuid);
|
||||
}
|
||||
|
||||
$("#category_filter").append(option);
|
||||
}
|
||||
$("#category_filter").val(current_selection);
|
||||
$("#category_filter").selectpicker('refresh');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// open edit dialog when opened with a uuid reference
|
||||
if (window.location.hash !== "" && window.location.hash.split("-").length >= 4) {
|
||||
grid.on('loaded.rs.jquery.bootgrid', function(){
|
||||
if (initial_load) {
|
||||
$(".command-edit:eq(0)").clone(true).data('row-id', window.location.hash.substr(1)).click();
|
||||
initial_load = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#reconfigureAct").SimpleActionButton();
|
||||
$("#savepointAct").SimpleActionButton({
|
||||
onAction: function(data, status){
|
||||
stdDialogInform(
|
||||
"{{ lang._('Savepoint created') }}",
|
||||
data['revision'],
|
||||
"{{ lang._('Close') }}"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$("#revertAction").on('click', function(){
|
||||
BootstrapDialog.show({
|
||||
type: BootstrapDialog.TYPE_DEFAULT,
|
||||
title: "{{ lang._('Revert to savepoint') }}",
|
||||
message: "<p>{{ lang._('Enter a savepoint to rollback to.') }}</p>" +
|
||||
'<div class="form-group" style="display: block;">' +
|
||||
'<input id="revertToTime" type="text" class="form-control"/>' +
|
||||
'<span class="error text-danger" id="revertToTimeError"></span>'+
|
||||
'</div>',
|
||||
buttons: [{
|
||||
label: "{{ lang._('Revert') }}",
|
||||
cssClass: 'btn-primary',
|
||||
action: function(dialogRef) {
|
||||
ajaxCall("/api/firewall/{{ruleController}}/revert/" + $("#revertToTime").val(), {}, function (data, status) {
|
||||
if (data.status !== "ok") {
|
||||
$("#revertToTime").parent().addClass("has-error");
|
||||
$("#revertToTimeError").html(data.status);
|
||||
} else {
|
||||
std_bootgrid_reload("grid-rules");
|
||||
dialogRef.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}],
|
||||
onshown: function(dialogRef) {
|
||||
$("#revertToTime").parent().removeClass("has-error");
|
||||
$("#revertToTimeError").html("");
|
||||
$("#revertToTime").val("");
|
||||
}
|
||||
});
|
||||
});
|
||||
// move filter into action header
|
||||
$("#type_filter_container").detach().prependTo('#grid-rules-header > .row > .actionBar > .actions');
|
||||
$("#category_filter").change(function(){
|
||||
$('#grid-rules').bootgrid('reload');
|
||||
});
|
||||
|
||||
// replace all "net" selectors with details retrieved from "list_network_select_options" endpoint
|
||||
ajaxGet('/api/firewall/{{ruleController}}/list_network_select_options', [], function(data, status){
|
||||
// fetch options
|
||||
let options = [];
|
||||
if (data.single) {
|
||||
Object.keys(data).forEach((key, idx) => {
|
||||
if (data[key].items !== undefined) {
|
||||
let optgrp = $("<optgroup/>").attr('label', data[key].label);
|
||||
Object.keys(data[key].items).forEach((key2, idx2) => {
|
||||
let this_item = data[key].items[key2];
|
||||
optgrp.append($("<option/>").val(key2).text(this_item));
|
||||
});
|
||||
options.push(optgrp);
|
||||
} else {
|
||||
options.push($("<option/>").val('').text(data[key].label));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (options.length == 0) {
|
||||
// unable to fetch options.
|
||||
return;
|
||||
}
|
||||
$(".net_selector").each(function(){
|
||||
let $items = $("#network_select").clone().show();
|
||||
let $this_input = $items.find('input');
|
||||
let $this_select = $items.find('select');
|
||||
for (i=0; i < options.length; ++i) {
|
||||
$this_select.append(options[i].clone());
|
||||
}
|
||||
$this_select.attr('for', $(this).attr('id')).selectpicker();
|
||||
$this_select.change(function(){
|
||||
let $value = $(this).val();
|
||||
if ($value !== '') {
|
||||
$this_input.val($value);
|
||||
$this_input.hide();
|
||||
} else {
|
||||
$this_input.show();
|
||||
}
|
||||
});
|
||||
$this_input.attr('id', $(this).attr('id'));
|
||||
$this_input.change(function(){
|
||||
$this_select.val($(this).val());
|
||||
if ($this_select.val() === null || $this_select.val() == '') {
|
||||
$this_select.val('');
|
||||
$this_input.show();
|
||||
} else {
|
||||
$this_input.hide();
|
||||
}
|
||||
$this_select.selectpicker('refresh');
|
||||
});
|
||||
$this_input.show();
|
||||
$(this).replaceWith($items);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#rules">{{ lang._('Rules') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content content-box">
|
||||
<div id="rules" class="tab-pane fade in active">
|
||||
<div class="hidden">
|
||||
<!-- filter per type container -->
|
||||
<div id="type_filter_container" class="btn-group">
|
||||
<select id="category_filter" data-title="{{ lang._('Categories') }}" class="selectpicker" data-live-search="true" data-size="5" multiple data-width="200px">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- tab page "rules" -->
|
||||
<table id="grid-rules" class="table table-condensed table-hover table-striped" data-editDialog="DialogFilterRule" data-editAlert="FilterRuleChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
{% for fieldlist in gridFields %}
|
||||
<th
|
||||
data-column-id="{{fieldlist['id']}}"
|
||||
data-width="{{fieldlist['width']|default('')}}"
|
||||
data-type="{{fieldlist['type']|default('string')}}"
|
||||
data-formatter="{{fieldlist['formatter']|default('')}}"
|
||||
>{{fieldlist['heading']|default('')}}</th>
|
||||
{% endfor %}
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div class="col-md-12">
|
||||
<div id="FilterRuleChangeMessage" class="alert alert-info" style="display: none" role="alert">
|
||||
{{ lang._('After changing settings, please remember to apply them with the button below') }}
|
||||
</div>
|
||||
<hr/>
|
||||
<button class="btn btn-primary" id="reconfigureAct"
|
||||
data-endpoint='/api/firewall/{{ruleController}}/apply'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-error-title="{{ lang._('Filter load error') }}"
|
||||
type="button"
|
||||
></button>
|
||||
{% if SavePointBtns is defined %}
|
||||
<div class="pull-right">
|
||||
<button class="btn" id="savepointAct"
|
||||
data-endpoint='/api/firewall/{{ruleController}}/savepoint'
|
||||
data-label="{{ lang._('Savepoint') }}"
|
||||
data-error-title="{{ lang._('snapshot error') }}"
|
||||
type="button"
|
||||
></button>
|
||||
<button class="btn" id="revertAction">
|
||||
{{ lang._('Revert') }}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="network_select" style="display: none;" >
|
||||
<table style="max-width: 348px">
|
||||
<tr>
|
||||
<td>
|
||||
<select data-live-search="true" data-size="5" data-width="348px">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<input style="display:none;" type="text"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogFilterRule,'id':'DialogFilterRule','label':lang._('Edit rule')])}}
|
|
@ -1,40 +0,0 @@
|
|||
#!/usr/local/bin/php
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
if (count($argv) >= 2) {
|
||||
$revision = preg_replace("/[^0-9.]/", "", $argv[1]);
|
||||
if (!empty($revision)) {
|
||||
$lckfile = "/tmp/pfplugin_{$revision}.lock";
|
||||
if (file_exists($lckfile)) {
|
||||
unlink($lckfile);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(1);
|
|
@ -1,54 +0,0 @@
|
|||
#!/usr/local/bin/php
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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');
|
||||
|
||||
if (count($argv) >= 2) {
|
||||
$revision = preg_replace("/[^0-9.]/", "", $argv[1]);
|
||||
if (!empty($revision)) {
|
||||
$lckfile = "/tmp/pfplugin_{$revision}.lock";
|
||||
file_put_contents($lckfile, "");
|
||||
// give the api 60 seconds to callback
|
||||
for ($i=0; $i < 60 ; ++$i) {
|
||||
if (!file_exists($lckfile)) {
|
||||
// got feedback
|
||||
exit(0);
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
@unlink($lckfile);
|
||||
// no feedback, revert
|
||||
$mdlFilter = new OPNsense\Firewall\Filter();
|
||||
if ($mdlFilter->rollback($revision)) {
|
||||
(new OPNsense\Core\Backend())->configdRun('filter reload');
|
||||
} else {
|
||||
syslog(LOG_WARNING, "unable to revert to unexisting revision : {$revision}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
[rollback_timer]
|
||||
command:/usr/local/bin/flock -n -E 0 -o /tmp/pfplugin_rollback_timer.lock /usr/local/opnsense/scripts/pfplugin/rollback_timer
|
||||
parameters: %s
|
||||
type:script
|
||||
message:wait for api feedback or revert to previous filter plugin config
|
||||
|
||||
[cancel_rollback]
|
||||
command: /usr/local/opnsense/scripts/pfplugin/rollback_cancel
|
||||
parameters: %s
|
||||
type:script_output
|
||||
message:cancel pfplugin rollback
|
|
@ -1,10 +0,0 @@
|
|||
PLUGIN_NAME= wireguard-go
|
||||
PLUGIN_VERSION= 1.13
|
||||
PLUGIN_REVISION= 8
|
||||
PLUGIN_COMMENT= WireGuard VPN service Go implementation
|
||||
PLUGIN_CONFLICTS= wireguard
|
||||
PLUGIN_OBSOLETE= yes
|
||||
PLUGIN_DEPENDS= wireguard-go wireguard-tools
|
||||
PLUGIN_MAINTAINER= m.muenz@gmail.com
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
|
@ -1,78 +0,0 @@
|
|||
WireGuard® is an extremely simple yet fast and modern VPN
|
||||
that utilizes state-of-the-art cryptography. It aims to be
|
||||
faster, simpler, leaner, and more useful than IPSec, while
|
||||
avoiding the massive headache. It intends to be considerably
|
||||
more performant than OpenVPN. WireGuard is designed as a
|
||||
general purpose VPN for running on embedded interfaces and
|
||||
super computers alike, fit for many different circumstances.
|
||||
Initially released for the Linux kernel, it is now
|
||||
cross-platform and widely deployable. It is currently under
|
||||
heavy development, but already it might be regarded as the
|
||||
most secure, easiest to use, and simplest VPN solution in
|
||||
the industry.
|
||||
|
||||
WWW: https://www.wireguard.com/
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
1.13
|
||||
|
||||
* Reworked widget and assorted cleanups (contributed by Patrik Kernstock)
|
||||
* Improve widget public key overlapping (contributed by Victor Haggqvist)
|
||||
|
||||
1.12
|
||||
|
||||
* Adjust validation for naming local instance and endpoints
|
||||
|
||||
1.11
|
||||
|
||||
* Add script for renewal of Wireguard DNS-based entries for stale connections (#2956)
|
||||
* Trim whitespace around new public and private keys in config (#2982)
|
||||
|
||||
1.10
|
||||
|
||||
* Remove instance limit
|
||||
|
||||
1.9
|
||||
|
||||
* Rename interface label in filter rules (#2577)
|
||||
|
||||
1.8
|
||||
|
||||
* Empty port in Endpoint is allowed
|
||||
|
||||
1.7
|
||||
|
||||
* Make tunnel address (wg interface address) optional
|
||||
|
||||
1.6
|
||||
|
||||
* Move DNS setting to advanced
|
||||
* Make listen port optional
|
||||
|
||||
1.5
|
||||
|
||||
* Allow synchronization of config
|
||||
|
||||
1.4
|
||||
|
||||
* Add IPv6 gateway support (contributed by Alexander Korinek)
|
||||
|
||||
1.3
|
||||
|
||||
* Client/peer name validation to use HostnameField
|
||||
|
||||
1.2
|
||||
|
||||
* Dashboard widget (contributed by D. Domig)
|
||||
|
||||
1.1
|
||||
|
||||
* Allow adding interface route for PBR
|
||||
|
||||
1.0
|
||||
|
||||
* Support for most features like S2S, Roadwarrior
|
||||
* DNS, MTU, PSK
|
||||
* Allow to disable setting routes for PBR
|
|
@ -1,110 +0,0 @@
|
|||
<?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.
|
||||
*/
|
||||
|
||||
function wireguard_enabled()
|
||||
{
|
||||
$model = new \OPNsense\Wireguard\General();
|
||||
return (string)$model->enabled == '1';
|
||||
}
|
||||
|
||||
function wireguard_services()
|
||||
{
|
||||
$services = [];
|
||||
|
||||
if (!wireguard_enabled()) {
|
||||
return $services;
|
||||
}
|
||||
|
||||
$service = [
|
||||
'description' => gettext('WireGuard VPN'),
|
||||
'configd' => [
|
||||
'restart' => ['wireguard restart'],
|
||||
'start' => ['wireguard start'],
|
||||
'stop' => ['wireguard stop'],
|
||||
],
|
||||
'name' => 'wireguard-go',
|
||||
];
|
||||
|
||||
$services[] = $service;
|
||||
|
||||
return $services;
|
||||
}
|
||||
|
||||
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-go'];
|
||||
|
||||
return [$result];
|
||||
}
|
||||
|
||||
function wireguard_devices()
|
||||
{
|
||||
$names = [];
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $key => $node) {
|
||||
if (!empty((string)$node->enabled)) {
|
||||
$device = 'wg' . $node->instance;
|
||||
$names[$device] = [
|
||||
'descr' => sprintf('%s (WireGuard - %s)', $device, (string)$node->name),
|
||||
'ifdescr' => (string)$node->name,
|
||||
'name' => $device,
|
||||
];
|
||||
}
|
||||
}
|
||||
return [[
|
||||
'configurable' => false,
|
||||
'pattern' => '^wg',
|
||||
'type' => 'wireguard',
|
||||
'volatile' => true,
|
||||
'names' => $names,
|
||||
]];
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# start again to fix problems with failed name resolution (no need to restart)
|
||||
configctl -dq wireguard start
|
|
@ -1,70 +0,0 @@
|
|||
<?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\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', array("enabled", "name", "pubkey", "tunneladdress", "serveraddress", "serverport"));
|
||||
}
|
||||
|
||||
public function getClientAction($uuid = null)
|
||||
{
|
||||
$this->sessionClose();
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
<?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';
|
||||
|
||||
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
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
<?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\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 searchServerAction()
|
||||
{
|
||||
$search = $this->searchBase('servers.server', array("enabled", "instance", "peers", "name", "networks", "pubkey", "port", "tunneladdress"));
|
||||
// prepend "wg" to all instance IDs to use as interface name
|
||||
foreach ($search["rows"] as $key => $server) {
|
||||
$search["rows"][$key]["interface"] = "wg" . $server["instance"];
|
||||
}
|
||||
return $search;
|
||||
}
|
||||
|
||||
public function getServerAction($uuid = null)
|
||||
{
|
||||
$this->sessionClose();
|
||||
return $this->getBase('server', 'servers.server', $uuid);
|
||||
}
|
||||
|
||||
public function addServerAction($uuid = null)
|
||||
{
|
||||
if ($this->request->isPost() && $this->request->hasPost("server")) {
|
||||
if ($uuid != null) {
|
||||
$node = $this->getModel()->getNodeByReference('servers.server.' . $uuid);
|
||||
} else {
|
||||
$node = $this->getModel()->servers->server->Add();
|
||||
}
|
||||
$node->setNodes($this->request->getPost("server"));
|
||||
if (empty((string)$node->pubkey) && empty((string)$node->privkey)) {
|
||||
// generate new keypair
|
||||
$backend = new Backend();
|
||||
$keyspriv = $backend->configdpRun("wireguard genkey", 'private');
|
||||
$keyspub = $backend->configdpRun("wireguard genkey", 'public');
|
||||
$node->privkey = trim($keyspriv);
|
||||
$node->pubkey = trim($keyspub);
|
||||
}
|
||||
return $this->validateAndSave($node, 'server');
|
||||
}
|
||||
return array("result" => "failed");
|
||||
}
|
||||
|
||||
public function delServerAction($uuid)
|
||||
{
|
||||
return $this->delBase('servers.server', $uuid);
|
||||
}
|
||||
|
||||
public function setServerAction($uuid = null)
|
||||
{
|
||||
if ($this->request->isPost() && $this->request->hasPost("server")) {
|
||||
if ($uuid != null) {
|
||||
$node = $this->getModel()->getNodeByReference('servers.server.' . $uuid);
|
||||
} else {
|
||||
$node = $this->getModel()->servers->server->Add();
|
||||
}
|
||||
$node->setNodes($this->request->getPost("server"));
|
||||
if (empty((string)$node->pubkey) && empty((string)$node->privkey)) {
|
||||
// generate new keypair
|
||||
$backend = new Backend();
|
||||
$keyspriv = $backend->configdpRun("wireguard genkey", 'private');
|
||||
$keyspub = $backend->configdpRun("wireguard genkey", 'public');
|
||||
$node->privkey = trim($keyspriv);
|
||||
$node->pubkey = trim($keyspub);
|
||||
}
|
||||
return $this->validateAndSave($node, 'server');
|
||||
}
|
||||
return array("result" => "failed");
|
||||
}
|
||||
|
||||
public function toggleServerAction($uuid)
|
||||
{
|
||||
return $this->toggleBase('servers.server', $uuid);
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
<?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\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableServiceControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Wireguard\General;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* show wireguard config
|
||||
* @return array
|
||||
*/
|
||||
public function showconfAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$response = $backend->configdRun("wireguard showconf");
|
||||
return array("response" => $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* show wireguard handshakes
|
||||
* @return array
|
||||
*/
|
||||
public function showhandshakeAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$response = $backend->configdRun("wireguard showhandshake");
|
||||
return array("response" => $response);
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
<?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');
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<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>
|
|
@ -1,82 +0,0 @@
|
|||
<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.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>
|
|
@ -1,8 +0,0 @@
|
|||
<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>
|
|
@ -1,9 +0,0 @@
|
|||
<acl>
|
||||
<page-wireguard-config>
|
||||
<name>VPN: Wireguard</name>
|
||||
<patterns>
|
||||
<pattern>ui/wireguard/*</pattern>
|
||||
<pattern>api/wireguard/*</pattern>
|
||||
</patterns>
|
||||
</page-wireguard-config>
|
||||
</acl>
|
|
@ -1,31 +0,0 @@
|
|||
<?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
|
||||
{
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
<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">
|
||||
<default></default>
|
||||
<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">
|
||||
<default></default>
|
||||
<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>
|
|
@ -1,35 +0,0 @@
|
|||
<?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
|
||||
{
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<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>
|
|
@ -1,5 +0,0 @@
|
|||
<menu>
|
||||
<VPN>
|
||||
<WireGuard cssClass="fa fa-lock fa-fw" url="/ui/wireguard/general/index" order="150" />
|
||||
</VPN>
|
||||
</menu>
|
|
@ -1,31 +0,0 @@
|
|||
<?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
|
||||
{
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
<model>
|
||||
<mount>//OPNsense/wireguard/server</mount>
|
||||
<description>Wireguard Server configuration</description>
|
||||
<version>0.0.4</version>
|
||||
<items>
|
||||
<servers>
|
||||
<server type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<name type="TextField">
|
||||
<default></default>
|
||||
<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>N</Required>
|
||||
</pubkey>
|
||||
<privkey type="TextField">
|
||||
<Required>N</Required>
|
||||
</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">
|
||||
<default></default>
|
||||
<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>
|
||||
<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>
|
|
@ -1,199 +0,0 @@
|
|||
{#
|
||||
# OPNsense (c) 2014-2018 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.
|
||||
#}
|
||||
|
||||
<!-- 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>
|
||||
<li><a data-toggle="tab" href="#showconf">{{ lang._('Status') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#showhandshake">{{ lang._('Handshakes') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box tab-content">
|
||||
<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 class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Apply') }}</b> <i id="saveAct_progress"></i></button>
|
||||
</div>
|
||||
</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 class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAct_client" type="button"><b>{{ lang._('Apply') }}</b> <i id="saveAct_client_progress"></i></button>
|
||||
<br /><br />
|
||||
</div>
|
||||
</div>
|
||||
<div id="servers" class="tab-pane fade in">
|
||||
<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 class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAct_server" type="button"><b>{{ lang._('Apply') }}</b> <i id="saveAct_server_progress"></i></button>
|
||||
<br /><br />
|
||||
</div>
|
||||
</div>
|
||||
<div id="showconf" class="tab-pane fade in">
|
||||
<pre id="listshowconf"></pre>
|
||||
</div>
|
||||
<div id="showhandshake" class="tab-pane fade in">
|
||||
<pre id="listshowhandshake"></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ 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')])}}
|
||||
|
||||
<script>
|
||||
|
||||
// Put API call into a function, needed for auto-refresh
|
||||
function update_showconf() {
|
||||
ajaxCall(url="/api/wireguard/service/showconf", sendData={}, callback=function(data,status) {
|
||||
$("#listshowconf").text(data['response']);
|
||||
});
|
||||
}
|
||||
|
||||
function update_showhandshake() {
|
||||
ajaxCall(url="/api/wireguard/service/showhandshake", sendData={}, callback=function(data,status) {
|
||||
$("#listshowhandshake").text(data['response']);
|
||||
});
|
||||
}
|
||||
|
||||
$( 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/'
|
||||
}
|
||||
);
|
||||
|
||||
// Call update funcs once when page loaded
|
||||
update_showconf();
|
||||
update_showhandshake();
|
||||
|
||||
// Call function update_neighbor with a auto-refresh of 5 seconds
|
||||
setInterval(update_showconf, 5000);
|
||||
setInterval(update_showhandshake, 5000);
|
||||
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/wireguard/general/set", formid='frm_general_settings',callback_ok=function(){
|
||||
$("#saveAct_progress").addClass("fa fa-spinner fa-pulse");
|
||||
ajaxCall(url="/api/wireguard/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
$("#saveAct_progress").removeClass("fa fa-spinner fa-pulse");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$("#saveAct_client").click(function(){
|
||||
saveFormToEndpoint(url="/api/wireguard/client/set", formid='frm_general_settings',callback_ok=function(){
|
||||
$("#saveAct_client_progress").addClass("fa fa-spinner fa-pulse");
|
||||
ajaxCall(url="/api/wireguard/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
$("#saveAct_client_progress").removeClass("fa fa-spinner fa-pulse");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$("#saveAct_server").click(function(){
|
||||
saveFormToEndpoint(url="/api/wireguard/server/set", formid='frm_general_settings',callback_ok=function(){
|
||||
$("#saveAct_server_progress").addClass("fa fa-spinner fa-pulse");
|
||||
ajaxCall(url="/api/wireguard/service/reconfigure", sendData={}, callback=function(data,status) {
|
||||
$("#saveAct_server_progress").removeClass("fa fa-spinner fa-pulse");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
|
@ -1,55 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2018 Michael Muenz <m.muenz@gmail.com>
|
||||
#
|
||||
# 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 BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
|
||||
|
||||
TMPDIR="/tmp"
|
||||
GENPRIV="/usr/local/bin/wg genkey"
|
||||
GENPUB="/usr/local/bin/wg pubkey"
|
||||
|
||||
cleanup() {
|
||||
# Delete old files
|
||||
rm -f $TMPDIR/wireguard.*
|
||||
}
|
||||
|
||||
private() {
|
||||
# Generate a private key and put it to /tmp
|
||||
umask 077 && ${GENPRIV} | tee ${TMPDIR}/wireguard.priv
|
||||
}
|
||||
|
||||
public() {
|
||||
# Generate a public key and put it to /tmp
|
||||
${GENPUB} < ${TMPDIR}/wireguard.priv | tee ${TMPDIR}/wireguard.pub
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
private)
|
||||
cleanup
|
||||
private
|
||||
;;
|
||||
public)
|
||||
public
|
||||
;;
|
||||
esac
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -f /etc/rc.conf.d/wireguard ]; then
|
||||
. /etc/rc.conf.d/wireguard
|
||||
fi
|
||||
|
||||
for interface in ${wireguard_interfaces}; do
|
||||
ifconfig ${interface} group wireguard
|
||||
done
|
||||
|
||||
/usr/local/etc/rc.routing_configure
|
|
@ -1,45 +0,0 @@
|
|||
#!/usr/local/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
|
||||
set -e
|
||||
shopt -s nocasematch
|
||||
shopt -s extglob
|
||||
export LC_ALL=C
|
||||
|
||||
for CONFIG_FILE in /usr/local/etc/wireguard/*.conf; do
|
||||
|
||||
[[ $CONFIG_FILE =~ /?([a-zA-Z0-9_=+.-]{1,15})\.conf$ ]]
|
||||
INTERFACE="${BASH_REMATCH[1]}"
|
||||
|
||||
process_peer() {
|
||||
[[ $PEER_SECTION -ne 1 || -z $PUBLIC_KEY || -z $ENDPOINT ]] && return 0
|
||||
[[ $(wg show "$INTERFACE" latest-handshakes) =~ ${PUBLIC_KEY//+/\\+}\ ([0-9]+) ]] || return 0
|
||||
(( ($EPOCHSECONDS - ${BASH_REMATCH[1]}) > 135 )) || return 0
|
||||
wg set "$INTERFACE" peer "$PUBLIC_KEY" endpoint "$ENDPOINT"
|
||||
reset_peer_section
|
||||
}
|
||||
|
||||
reset_peer_section() {
|
||||
PEER_SECTION=0
|
||||
PUBLIC_KEY=""
|
||||
ENDPOINT=""
|
||||
}
|
||||
|
||||
reset_peer_section
|
||||
while read -r line || [[ -n $line ]]; do
|
||||
stripped="${line%%\#*}"
|
||||
key="${stripped%%=*}"; key="${key##*([[:space:]])}"; key="${key%%*([[:space:]])}"
|
||||
value="${stripped#*=}"; value="${value##*([[:space:]])}"; value="${value%%*([[:space:]])}"
|
||||
[[ $key == "["* ]] && { process_peer; reset_peer_section; }
|
||||
[[ $key == "[Peer]" ]] && PEER_SECTION=1
|
||||
if [[ $PEER_SECTION -eq 1 ]]; then
|
||||
case "$key" in
|
||||
PublicKey) PUBLIC_KEY="$value"; continue ;;
|
||||
Endpoint) ENDPOINT="$value"; continue ;;
|
||||
esac
|
||||
fi
|
||||
done < "$CONFIG_FILE"
|
||||
process_peer
|
||||
done
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
mkdir -p /var/run/wireguard
|
||||
chmod 755 /var/run/wireguard
|
|
@ -1,43 +0,0 @@
|
|||
[start]
|
||||
command:/usr/local/etc/rc.d/wireguard start; /usr/local/opnsense/scripts/OPNsense/Wireguard/post.sh
|
||||
parameters:
|
||||
type:script
|
||||
message:Starting WireGuard
|
||||
|
||||
[stop]
|
||||
command:/usr/local/etc/rc.d/wireguard stop
|
||||
parameters:
|
||||
type:script
|
||||
message:Stopping WireGuard
|
||||
|
||||
[restart]
|
||||
command:/usr/local/etc/rc.d/wireguard restart; /usr/local/opnsense/scripts/OPNsense/Wireguard/post.sh
|
||||
parameters:
|
||||
type:script
|
||||
message:Restarting WireGuard
|
||||
description: Restart WireGuard
|
||||
|
||||
[renew]
|
||||
command:/usr/local/opnsense/scripts/OPNsense/Wireguard/resolve-dns.bash
|
||||
parameters:
|
||||
type:script
|
||||
message:Renew DNS for WireGuard
|
||||
description:Renew DNS for WireGuard on stale connections
|
||||
|
||||
[genkey]
|
||||
command:/usr/local/opnsense/scripts/OPNsense/Wireguard/genkey.sh
|
||||
parameters: %s
|
||||
type:script_output
|
||||
message:Generating WireGuard keys
|
||||
|
||||
[showconf]
|
||||
command:/usr/local/bin/wg show all
|
||||
parameters:
|
||||
type:script_output
|
||||
message:Show WireGuard config
|
||||
|
||||
[showhandshake]
|
||||
command:/usr/local/bin/wg show all latest-handshakes
|
||||
parameters:
|
||||
type:script_output
|
||||
message:Show WireGuard handshakes
|
|
@ -1,2 +0,0 @@
|
|||
wireguard:/etc/rc.conf.d/wireguard
|
||||
wireguard-server.conf:/usr/local/etc/wireguard/wg[OPNsense.wireguard.server.servers.server.%.instance].conf
|
|
@ -1,15 +0,0 @@
|
|||
{% if helpers.exists('OPNsense.wireguard.general.enabled') and OPNsense.wireguard.general.enabled == '1' %}
|
||||
wireguard_setup="/usr/local/opnsense/scripts/OPNsense/Wireguard/setup.sh"
|
||||
wireguard_enable="YES"
|
||||
{% if helpers.exists('OPNsense.wireguard.server.servers.server') %}
|
||||
{% set activeservers=[] %}
|
||||
{% for servers in helpers.toList('OPNsense.wireguard.server.servers.server') %}
|
||||
{% if servers.enabled == '1' %}
|
||||
{% do activeservers.append("wg" + servers.instance) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
wireguard_interfaces="{{ activeservers | join(' ') }}"
|
||||
{% else %}
|
||||
wireguard_enable="NO"
|
||||
{% endif %}
|
|
@ -1,53 +0,0 @@
|
|||
{% 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]
|
||||
PrivateKey = {{ server_list.privkey }}
|
||||
{% if server_list.tunneladdress|default('') != '' %}
|
||||
Address = {{ server_list.tunneladdress }}
|
||||
{% endif %}
|
||||
{% if server_list.port|default('') != '' %}
|
||||
ListenPort = {{ server_list.port }}
|
||||
{% endif %}
|
||||
{% if server_list.dns|default('') != '' %}
|
||||
DNS = {{ server_list.dns }}
|
||||
{% endif %}
|
||||
{% if server_list.mtu|default('') != '' %}
|
||||
MTU = {{ server_list.mtu }}
|
||||
{% endif %}
|
||||
{% if server_list.disableroutes == '1' %}
|
||||
Table = off
|
||||
{% endif %}
|
||||
{% if server_list.disableroutes == '1' and server_list.gateway|default('') != '' %}
|
||||
PostUp = route {{- ' -6' if ':' in server_list.gateway }} add {{ server_list.gateway }} -iface %i
|
||||
PostDown = route {{- ' -6' if ':' in server_list.gateway }} del {{ server_list.gateway }} -iface %i
|
||||
{% 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 %}
|
|
@ -1,4 +0,0 @@
|
|||
<?php
|
||||
|
||||
$wireguard_title = gettext('WireGuard');
|
||||
$wireguard_title_link = 'ui/wireguard/general/index';
|
|
@ -1,120 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Deciso B.V.
|
||||
* Copyright (C) 2020 D. Domig
|
||||
* Copyright (C) 2022 Patrik Kernstock <patrik@kernstock.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* 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("guiconfig.inc");
|
||||
require_once("widgets/include/wireguard.inc");
|
||||
|
||||
$enabled = ($config["OPNsense"]["wireguard"]["general"]["enabled"] === "1" ? true : false);
|
||||
|
||||
?>
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= gettext("Name") ?></th>
|
||||
<th><?= gettext("Interface") ?></th>
|
||||
<th><?= gettext("Endpoint") ?></th>
|
||||
<th><?= gettext("Public Key") ?></th>
|
||||
<th><?= gettext("Latest Handshake") ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="wg-table-tbody">
|
||||
|
||||
<?php if (!$enabled): ?>
|
||||
<tr>
|
||||
<td colspan="5"><?= gettext("No WireGuard instance defined or enabled.") ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
$(window).on("load", function() {
|
||||
function wgGenerateRow(name, interface, peerName, publicKey, latestHandshake, status)
|
||||
{
|
||||
var tr = ''
|
||||
+'<tr>'
|
||||
+' <td>' + name + '</td>'
|
||||
+' <td>' + interface + '</td>'
|
||||
+' <td>' + peerName + '</td>'
|
||||
+' <td style="overflow: hidden; text-overflow: ellipsis;" title="' + publicKey + '">' + publicKey + '</td>'
|
||||
+' <td>' + latestHandshake + '</td>'
|
||||
+'</tr>';
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
function wgUpdateStatusIf(obj)
|
||||
{
|
||||
// check if at least one peer is set. If not, ignore it.
|
||||
if (Object.keys(obj.peers).length == 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// generate row based on data
|
||||
row = '';
|
||||
for (var peerId in obj.peers) {
|
||||
var peer = obj.peers[peerId];
|
||||
|
||||
// generate table row
|
||||
row += wgGenerateRow(
|
||||
obj.name,
|
||||
obj.interface,
|
||||
peer.name,
|
||||
peer.publicKey,
|
||||
peer.lastHandshake,
|
||||
status
|
||||
);
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
function wgUpdateStatus()
|
||||
{
|
||||
var table = '';
|
||||
ajaxGet("/api/wireguard/general/getStatus", {}, function(data, status) {
|
||||
if (status === 'success') {
|
||||
for (var interface in data.items) {
|
||||
table += wgUpdateStatusIf(data.items[interface]);
|
||||
}
|
||||
}
|
||||
// update table accordingly
|
||||
document.getElementById("wg-table-tbody").innerHTML = table;
|
||||
setTimeout(wgUpdateStatus, 10000);
|
||||
});
|
||||
};
|
||||
|
||||
<?php if ($enabled): ?>
|
||||
wgUpdateStatus();
|
||||
<?php endif; ?>
|
||||
});
|
||||
</script>
|
|
@ -1,9 +0,0 @@
|
|||
PLUGIN_NAME= wireguard
|
||||
PLUGIN_VERSION= 2.6
|
||||
PLUGIN_COMMENT= WireGuard VPN service kernel implementation
|
||||
PLUGIN_DEPENDS= wireguard-kmod
|
||||
PLUGIN_CONFLICTS= wireguard-go
|
||||
PLUGIN_OBSOLETE= yes
|
||||
PLUGIN_MAINTAINER= ad@opnsense.org
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
|
@ -1,127 +0,0 @@
|
|||
WireGuard® is an extremely simple yet fast and modern VPN
|
||||
that utilizes state-of-the-art cryptography. It aims to be
|
||||
faster, simpler, leaner, and more useful than IPSec, while
|
||||
avoiding the massive headache. It intends to be considerably
|
||||
more performant than OpenVPN. WireGuard is designed as a
|
||||
general purpose VPN for running on embedded interfaces and
|
||||
super computers alike, fit for many different circumstances.
|
||||
Initially released for the Linux kernel, it is now
|
||||
cross-platform and widely deployable. It is currently under
|
||||
heavy development, but already it might be regarded as the
|
||||
most secure, easiest to use, and simplest VPN solution in
|
||||
the industry.
|
||||
|
||||
WWW: https://www.wireguard.com/
|
||||
|
||||
Changelog
|
||||
---------
|
||||
|
||||
2.6
|
||||
|
||||
* Consider missing CARP VHID as disabled
|
||||
|
||||
2.5
|
||||
|
||||
* Fix error with empty tunnel address in instance (contributed by Monviech)
|
||||
* Switch "setconf" to "syncconf" on (re)configuration
|
||||
* Fix regression of UUID return in setClientAction()
|
||||
* Reload the packet filter after reconfiguration
|
||||
* Allow instance selection from peer
|
||||
* Use "syncconf" on newwanip event
|
||||
* CARP event handling improvements
|
||||
* Minor UX and woring improvements
|
||||
|
||||
2.4
|
||||
|
||||
* Only invoke routes for attached WireGuard instances
|
||||
* Make bootup device creation more robust
|
||||
* Correct interface group registration
|
||||
|
||||
2.3
|
||||
|
||||
* Create WireGuard devices earlier to allow of to pick up NAT rules correctly
|
||||
* Consolidate the GUI with regard to WireGuard terminology
|
||||
|
||||
2.2
|
||||
|
||||
* Add VHID (CARP) tracking support
|
||||
|
||||
2.1
|
||||
|
||||
* Only reload when interface configuration did not change
|
||||
* Implement 'newwanip' and 'vpn' plugin facilities
|
||||
* Refactor dashboard widget
|
||||
|
||||
2.0
|
||||
|
||||
* Remove wireguard-go support and cleanup some go specific code as it's not being used anymore anyway
|
||||
* Service control handler similar to OpenVPN, which offers control per instance/interface and keeps track of changed interfaces (configure only restarts the changed ones).
|
||||
* Add some basic logging for the service handling and a view to inspect it.
|
||||
* Configuration logs are being flushed to the correct log automatically as mwexecf() sends errors to syslog (which in this scope sends to wireguard)
|
||||
* Reimplement https://github.com/WireGuard/wireguard-tools/tree/master/contrib/reresolve-dns using Python in reresolve-dns.py
|
||||
* Enforce wireguard-tools rc script to be disabled when still installed, this should prevent bootup issues
|
||||
* Move 'interface' calculated field to model for easy reusability
|
||||
* Move diagnostics to VPN: WireGuard: Diagnostics
|
||||
* Change keypair generation to a separate API call and form button to ease copy/paste when adding new servers.
|
||||
* Change plugin maintainer
|
||||
|
||||
1.13
|
||||
|
||||
* Reworked widget and assorted cleanups (contributed by Patrik Kernstock)
|
||||
* Improve widget public key overlapping (contributed by Victor Haggqvist)
|
||||
|
||||
1.12
|
||||
|
||||
* Adjust validation for naming local instance and endpoints
|
||||
|
||||
1.11
|
||||
|
||||
* Add script for renewal of Wireguard DNS-based entries for stale connections (#2956)
|
||||
* Trim whitespace around new public and private keys in config (#2982)
|
||||
|
||||
1.10
|
||||
|
||||
* Remove instance limit
|
||||
|
||||
1.9
|
||||
|
||||
* Rename interface label in filter rules (#2577)
|
||||
|
||||
1.8
|
||||
|
||||
* Empty port in Endpoint is allowed
|
||||
|
||||
1.7
|
||||
|
||||
* Make tunnel address (wg interface address) optional
|
||||
|
||||
1.6
|
||||
|
||||
* Move DNS setting to advanced
|
||||
* Make listen port optional
|
||||
|
||||
1.5
|
||||
|
||||
* Allow synchronization of config
|
||||
|
||||
1.4
|
||||
|
||||
* Add IPv6 gateway support (contributed by Alexander Korinek)
|
||||
|
||||
1.3
|
||||
|
||||
* Client/peer name validation to use HostnameField
|
||||
|
||||
1.2
|
||||
|
||||
* Dashboard widget (contributed by D. Domig)
|
||||
|
||||
1.1
|
||||
|
||||
* Allow adding interface route for PBR
|
||||
|
||||
1.0
|
||||
|
||||
* Support for most features like S2S, Roadwarrior
|
||||
* DNS, MTU, PSK
|
||||
* Allow to disable setting routes for PBR
|
|
@ -1,194 +0,0 @@
|
|||
<?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()
|
||||
{
|
||||
$names = [];
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $key => $node) {
|
||||
if (!empty((string)$node->enabled)) {
|
||||
$names[(string)$node->interface] = [
|
||||
'descr' => sprintf('%s (WireGuard - %s)', (string)$node->interface, (string)$node->name),
|
||||
'ifdescr' => (string)$node->name,
|
||||
'name' => (string)$node->interface
|
||||
];
|
||||
}
|
||||
}
|
||||
return [[
|
||||
'function' => 'wireguard_prepare', /* XXX only (empty) device creation */
|
||||
'configurable' => false,
|
||||
'pattern' => '^wg',
|
||||
'type' => 'wireguard',
|
||||
'volatile' => true,
|
||||
'names' => $names,
|
||||
]];
|
||||
}
|
||||
|
||||
function wireguard_prepare($device)
|
||||
{
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $node) {
|
||||
if ($device != (string)$node->interface) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* deleting the stat file marks the interface for eventual reconfiguration */
|
||||
@unlink((string)$node->statFilename);
|
||||
|
||||
if (!does_interface_exist($device)) {
|
||||
mwexecf('/sbin/ifconfig wg create name %s', $device);
|
||||
mwexecf('/sbin/ifconfig %s group wireguard', $device);
|
||||
}
|
||||
|
||||
return $device;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function wireguard_configure()
|
||||
{
|
||||
return [
|
||||
'newwanip' => ['wireguard_sync: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_sync($verbose = false, $unused = '')
|
||||
{
|
||||
if (!wireguard_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$instances = [];
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $node) {
|
||||
if (!empty((string)$node->enabled)) {
|
||||
$instances[(string)$node->interface] = (string)$node->cnfFilename;
|
||||
}
|
||||
}
|
||||
|
||||
if (!count($instances)) {
|
||||
return;
|
||||
}
|
||||
|
||||
service_log('Synchronizing WireGuard VPN...', $verbose);
|
||||
|
||||
openlog('wireguard', LOG_ODELAY, LOG_AUTH);
|
||||
|
||||
foreach ($instances as $device => $config) {
|
||||
mwexecf('/usr/bin/wg syncconf %s %s', [$device, $config]);
|
||||
}
|
||||
|
||||
closelog();
|
||||
reopenlog();
|
||||
|
||||
service_log("done.\n", $verbose);
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
configctl -dq wireguard configure $1
|
|
@ -1,115 +0,0 @@
|
|||
<?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\Config;
|
||||
use OPNsense\Wireguard\Server;
|
||||
|
||||
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)
|
||||
{
|
||||
$result = $this->getBase('client', 'clients.client', $uuid);
|
||||
if (!empty($result['client'])) {
|
||||
$result['client']['servers'] = [];
|
||||
foreach ((new Server())->servers->server->iterateItems() as $key => $node) {
|
||||
$result['client']['servers'][$key] = [
|
||||
'value' => (string)$node->name,
|
||||
'selected' => in_array($uuid, explode(',', (string)$node->peers)) ? '1' : '0'
|
||||
];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function addClientAction()
|
||||
{
|
||||
return $this->setClientAction(null);
|
||||
}
|
||||
|
||||
public function delClientAction($uuid)
|
||||
{
|
||||
return $this->delBase('clients.client', $uuid);
|
||||
}
|
||||
|
||||
public function setClientAction($uuid)
|
||||
{
|
||||
$add_uuid = null;
|
||||
if (!empty($this->request->getPost(static::$internalModelName)) && $this->request->isPost()) {
|
||||
$servers = [];
|
||||
if (!empty($this->request->getPost(static::$internalModelName)['servers'])) {
|
||||
$servers = explode(',', $this->request->getPost(static::$internalModelName)['servers']);
|
||||
}
|
||||
Config::getInstance()->lock();
|
||||
$mdl = new Server();
|
||||
if (empty($uuid)) {
|
||||
// add new client, generate uuid
|
||||
$uuid = $mdl->servers->generateUUID();
|
||||
$add_uuid = $uuid;
|
||||
}
|
||||
foreach ($mdl->servers->server->iterateItems() as $key => $node) {
|
||||
$peers = array_filter(explode(',', (string)$node->peers));
|
||||
if (in_array($uuid, $peers) && !in_array($key, $servers)) {
|
||||
$node->peers = implode(',', array_diff($peers, [$uuid]));
|
||||
} elseif (!in_array($uuid, $peers) && in_array($key, $servers)) {
|
||||
$node->peers = implode(',', array_merge($peers, [$uuid]));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Save to in memory model.
|
||||
* Ignore validations as $uuid might be new or trigger an existing validation issue.
|
||||
* Persisting the data is handled by setBase()
|
||||
*/
|
||||
$mdl->serializeToConfig(false, true);
|
||||
}
|
||||
$result = $this->setBase('client', 'clients.client', $uuid);
|
||||
if (!empty($add_uuid) && $result['result'] == 'saved') {
|
||||
$result['uuid'] = $add_uuid;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function toggleClientAction($uuid)
|
||||
{
|
||||
return $this->toggleBase('clients.client', $uuid);
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
<?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
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
<?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';
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function reconfigureAction()
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
return ['result' => 'failed'];
|
||||
}
|
||||
|
||||
$this->sessionClose();
|
||||
$backend = new Backend();
|
||||
$backend->configdRun('interface invoke registration');
|
||||
$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);
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
<?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');
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
<?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');
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>client.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will enable or disable the peer.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.name</id>
|
||||
<label>Name</label>
|
||||
<type>text</type>
|
||||
<help>Set the name for this peer.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.pubkey</id>
|
||||
<label>Public key</label>
|
||||
<type>text</type>
|
||||
<help>Public key of this peer. You can generate the key using the private key piped to "wg pubkey".</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>client.psk</id>
|
||||
<label>Pre-shared key</label>
|
||||
<type>text</type>
|
||||
<help>Shared secret (PSK) for this peer. You can generate a key using "wg genpsk".</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.servers</id>
|
||||
<label>Instances</label>
|
||||
<type>select_multiple</type>
|
||||
<help>List of instances this peer belongs 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>
|
|
@ -1,87 +0,0 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>server.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>This will enable or disable the instance.</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 WireGuard device 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 a specific device MTU for this instance.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>server.dns</id>
|
||||
<label>DNS servers</label>
|
||||
<type>select_multiple</type>
|
||||
<style>tokenize</style>
|
||||
<allownew>true</allownew>
|
||||
<advanced>true</advanced>
|
||||
<help>Set specific DNS servers for this instance. Use with care.</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 device. 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>
|
||||
<help>List of peers for this instance.</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 system gateway.</help>
|
||||
</field>
|
||||
</form>
|
|
@ -1,8 +0,0 @@
|
|||
<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>
|
|
@ -1,9 +0,0 @@
|
|||
<acl>
|
||||
<page-wireguard-config>
|
||||
<name>VPN: WireGuard</name>
|
||||
<patterns>
|
||||
<pattern>ui/wireguard/*</pattern>
|
||||
<pattern>api/wireguard/*</pattern>
|
||||
</patterns>
|
||||
</page-wireguard-config>
|
||||
</acl>
|
|
@ -1,35 +0,0 @@
|
|||
<?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
|
||||
{
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
<model>
|
||||
<mount>//OPNsense/wireguard/client</mount>
|
||||
<description>WireGuard peer 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>
|
||||
</pubkey>
|
||||
<psk type="Base64Field"/>
|
||||
<tunneladdress type="NetworkField">
|
||||
<FieldSeparator>,</FieldSeparator>
|
||||
<Required>Y</Required>
|
||||
<asList>Y</asList>
|
||||
</tunneladdress>
|
||||
<serveraddress type="HostnameField"/>
|
||||
<serverport type="PortField"/>
|
||||
<keepalive type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>86400</MaximumValue>
|
||||
<ValidationMessage>Please specify a value between 1 and 86400.</ValidationMessage>
|
||||
</keepalive>
|
||||
</client>
|
||||
</clients>
|
||||
</items>
|
||||
</model>
|
|
@ -1,58 +0,0 @@
|
|||
<?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();
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
<?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
|
||||
{
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<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>
|
|
@ -1,9 +0,0 @@
|
|||
<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>
|
|
@ -1,35 +0,0 @@
|
|||
<?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
|
||||
{
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
<model>
|
||||
<mount>//OPNsense/wireguard/server</mount>
|
||||
<description>WireGuard instance 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"/>
|
||||
<mtu type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>9300</MaximumValue>
|
||||
</mtu>
|
||||
<dns type="CSVListField">
|
||||
<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>
|
||||
<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"/>
|
||||
<carp_depend_on type="VirtualIPField">
|
||||
<type>carp</type>
|
||||
<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>
|
||||
<ValidationMessage>Choose an Peer.</ValidationMessage>
|
||||
</peers>
|
||||
</server>
|
||||
</servers>
|
||||
</items>
|
||||
</model>
|
|
@ -1,97 +0,0 @@
|
|||
{#
|
||||
# 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._('Instance') }}</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._('Device') }}</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>
|
|
@ -1,173 +0,0 @@
|
|||
{#
|
||||
# Copyright (c) 2014-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.
|
||||
#}
|
||||
|
||||
<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-peers").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-instances").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 instance 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="#instances">{{ lang._('Instances') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#peers">{{ lang._('Peers') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content content-box tab-content">
|
||||
<div id="general" class="tab-pane fade in active">
|
||||
{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_general_settings'])}}
|
||||
</div>
|
||||
<div id="peers" class="tab-pane fade in">
|
||||
<table id="grid-peers" class="table table-condensed table-hover table-striped" data-editDialog="dialogEditWireguardClient">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<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>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-fw fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div id="instances" 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-instances" class="table table-condensed table-hover table-striped" data-editDialog="dialogEditWireguardServer">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<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._('Device') }}</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._('Peers') }}</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>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-fw fa-trash-o"></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 peer')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEditWireguardServer,'id':'dialogEditWireguardServer','label':lang._('Edit instance')])}}
|
|
@ -1,46 +0,0 @@
|
|||
#!/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))
|
|
@ -1,75 +0,0 @@
|
|||
#!/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 = {}
|
|
@ -1,303 +0,0 @@
|
|||
#!/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('config.inc');
|
||||
require_once('interfaces.inc');
|
||||
require_once('system.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;
|
||||
$vhids[$id] = ['status' => 'DISABLED', 'vhid' => (string)$item->vhid];
|
||||
}
|
||||
}
|
||||
foreach (legacy_interfaces_details() as $ifdata) {
|
||||
if (!empty($ifdata['carp'])) {
|
||||
foreach ($ifdata['carp'] as $data) {
|
||||
if (isset($uuids[$data['vhid']])) {
|
||||
$vhids[$uuids[$data['vhid']]] = ['status' => $data['status'], 'vhid' => $data['vhid']];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 syncconf %s %s', [$server->interface, $server->cnfFilename]);
|
||||
|
||||
/* The tunneladdress can be empty, so array_filter without callback filters empty strings out. */
|
||||
foreach (array_filter(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 instance {$server->name} ({$server->interface}) started");
|
||||
interfaces_restart_by_device(false, [(string)$server->interface], false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 instance {$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|vhid]\n\n";
|
||||
echo "\t-a all instances\n";
|
||||
} elseif (isset($opts['a']) || !empty($args[1])) {
|
||||
// either a server id (uuid) or a vhid could be offered
|
||||
$server_id = $vhid = null;
|
||||
if (preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $args[1] ?? '') == 1) {
|
||||
$server_id = $args[1];
|
||||
} elseif (!empty($args[1])) {
|
||||
$vhid = explode('@', $args[1])[0];
|
||||
}
|
||||
|
||||
$action = $args[0];
|
||||
|
||||
$server_devs = [];
|
||||
if (!empty((string)(new OPNsense\Wireguard\General())->enabled)) {
|
||||
$vhids = get_vhid_status();
|
||||
foreach ((new OPNsense\Wireguard\Server())->servers->server->iterateItems() as $key => $node) {
|
||||
$carp_depend_on = (string)$node->carp_depend_on;
|
||||
if (empty((string)$node->enabled)) {
|
||||
continue;
|
||||
} elseif ($server_id != null && $key != $server_id) {
|
||||
continue;
|
||||
} elseif ($vhid != null && (!empty($vhids[$carp_depend_on]) && $vhids[$carp_depend_on]['vhid'] != $vhid)) {
|
||||
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[$carp_depend_on]) && $vhids[$carp_depend_on]['status'] != 'MASTER') {
|
||||
$carp_if_flag = 'down';
|
||||
}
|
||||
$server_devs[] = (string)$node->interface;
|
||||
$statHandle = fopen($node->statFilename, "a+");
|
||||
if (flock($statHandle, LOCK_EX)) {
|
||||
$ifdetails = legacy_interfaces_details((string)$node->interface);
|
||||
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':
|
||||
$ifstatus = '-';
|
||||
if (!empty($ifdetails[(string)$node->interface])) {
|
||||
$ifstatus = in_array('up', $ifdetails[(string)$node->interface]['flags']) ? 'up' : 'down';
|
||||
}
|
||||
|
||||
if (!empty($carp_depend_on) && !empty($vhid)) {
|
||||
// CARP event traceability when a vhid is being passed
|
||||
syslog(
|
||||
LOG_NOTICE,
|
||||
sprintf(
|
||||
"Wireguard configure event instance %s (%s) vhid: %s carp: %s interface: %s",
|
||||
$node->name,
|
||||
$node->interface,
|
||||
$vhid,
|
||||
!empty($vhids[$carp_depend_on]) ? $vhids[$carp_depend_on]['status'] : '-',
|
||||
$ifstatus
|
||||
)
|
||||
);
|
||||
}
|
||||
if (
|
||||
@md5_file($node->cnfFilename) != get_stat_hash($statHandle)['file'] ||
|
||||
empty($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 instance {$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]
|
||||
if ($ifstatus != $carp_if_flag) {
|
||||
mwexecf('/sbin/ifconfig %s %s', [$node->interface, $carp_if_flag]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
flock($statHandle, LOCK_UN);
|
||||
}
|
||||
fclose($statHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When -a is specified, cleanup up old or disabled instances (files and interfaces)
|
||||
*/
|
||||
if ($server_id == null && $vhid == 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($server_devs)) {
|
||||
configd_run('filter reload'); /* XXX required for NAT rules, but needs coalescing */
|
||||
}
|
||||
}
|
||||
closelog();
|
|
@ -1,72 +0,0 @@
|
|||
#!/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))
|
|
@ -1,54 +0,0 @@
|
|||
[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 %s
|
||||
type:script
|
||||
message: configure wireguard instances (%s)
|
||||
|
||||
[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
|
|
@ -1,6 +0,0 @@
|
|||
###################################################################
|
||||
# Local syslog-ng configuration filter definition [wireguard].
|
||||
###################################################################
|
||||
filter f_local_wireguard {
|
||||
program("wireguard");
|
||||
};
|
|
@ -1,2 +0,0 @@
|
|||
wireguard:/etc/rc.conf.d/wireguard
|
||||
wireguard-server.conf:/usr/local/etc/wireguard/wg[OPNsense.wireguard.server.servers.server.%.instance].conf
|
|
@ -1,2 +0,0 @@
|
|||
# disable the wireguard rc scripts when installed, bootup handled via rc.syshook
|
||||
wireguard_enable="NO"
|
|
@ -1,48 +0,0 @@
|
|||
{% 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 %}
|
|
@ -1,4 +0,0 @@
|
|||
<?php
|
||||
|
||||
$wireguard_title = gettext('WireGuard');
|
||||
$wireguard_title_link = 'ui/wireguard/general';
|
|
@ -1,95 +0,0 @@
|
|||
<?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("Instance") ?></th>
|
||||
<th><?= gettext("Peer") ?></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>
|
|
@ -1,7 +0,0 @@
|
|||
PLUGIN_NAME= api-backup
|
||||
PLUGIN_VERSION= 1.1
|
||||
PLUGIN_OBSOLETE= yes
|
||||
PLUGIN_COMMENT= EoL, core endpoint is /api/core/backup/download/this
|
||||
PLUGIN_MAINTAINER= franz.fabian.94@gmail.com
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
|
@ -1,12 +0,0 @@
|
|||
Provide the functionality to download the config.xml
|
||||
|
||||
Plugin Changelog
|
||||
================
|
||||
|
||||
1.1
|
||||
|
||||
* add json download functionality
|
||||
|
||||
1.0
|
||||
|
||||
* initial release
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Frank Wall
|
||||
* Copyright (C) 2018 Fabian Franz
|
||||
* 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\Backup\Api;
|
||||
|
||||
use OPNsense\Base\ApiControllerBase;
|
||||
|
||||
class BackupController extends ApiControllerBase
|
||||
{
|
||||
const CONFIG_XML = '/conf/config.xml';
|
||||
|
||||
/**
|
||||
* download system config
|
||||
* @param string $format set to 'json' to get a base64 encoded config backup
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function downloadAction($format = 'plain')
|
||||
{
|
||||
$data = file_get_contents(self::CONFIG_XML);
|
||||
$status = $data === false ? 'error' : 'success';
|
||||
|
||||
if ($format == 'json') {
|
||||
$response = array(
|
||||
'status' => $status,
|
||||
'filename' => 'config.xml',
|
||||
'filetype' => 'application/xml',
|
||||
'content' => base64_encode($data),
|
||||
);
|
||||
return $response;
|
||||
} else {
|
||||
$this->response->setStatusCode(200, "OK");
|
||||
$this->response->setContentType('application/xml', 'UTF-8');
|
||||
$this->response->setHeader("Content-Disposition", "attachment; filename=\"config.xml\"");
|
||||
$data = file_get_contents(self::CONFIG_XML);
|
||||
$this->response->setContent($data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* process API results, serialize return data to json.
|
||||
* @param $dispatcher
|
||||
* @return string json data
|
||||
*/
|
||||
public function afterExecuteRoute($dispatcher)
|
||||
{
|
||||
// check if reponse headers are already set
|
||||
if ($this->response->getHeaders()->get("Status") != null) {
|
||||
// Headers already set, send unmodified response.
|
||||
} else {
|
||||
// process response, serialize to json object
|
||||
$data = $dispatcher->getReturnedValue();
|
||||
if (is_array($data)) {
|
||||
$this->response->setContentType('application/json', 'UTF-8');
|
||||
if ($this->isExternalClient()) {
|
||||
$this->response->setContent(json_encode($data));
|
||||
} else {
|
||||
$this->response->setContent(htmlspecialchars(json_encode($data), ENT_NOQUOTES));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->response->send();
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<acl>
|
||||
<page-Backup>
|
||||
<name>Backup API</name>
|
||||
<patterns>
|
||||
<pattern>api/backup/*</pattern>
|
||||
</patterns>
|
||||
</page-Backup>
|
||||
</acl>
|
Loading…
Reference in New Issue