mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
stunnel: initial release (#1840)
* stunnel: boilerplate for https://github.com/opnsense/plugins/issues/1829 * stunnel: work in progress for https://github.com/opnsense/plugins/issues/1829 * stunnel: add service control and acl for https://github.com/opnsense/plugins/issues/1829 * stunnel: add cipher selection for https://github.com/opnsense/plugins/issues/1829 Since stunnel uses different parameter pairs for TLSv1.[1,2] and TLSv1.3, we'll try to sort them out in our config template. When no TLSv1.3 ciphers are allowed, we should limit the sslVersionMax parameter as well as it seems. * stunnel: set TLS1.2 as minimum * stunnel: disable rc conf when no services are active https://github.com/opnsense/plugins/issues/1829 * stunnel: CRL support for https://github.com/opnsense/plugins/issues/1829 * stunnel: simplify cert creation, combine cert+key in one file. for https://github.com/opnsense/plugins/issues/1829 * stunnel: syslog and log viewer for https://github.com/opnsense/plugins/issues/1829 * stunnel: add hasync anchor, for https://github.com/opnsense/plugins/issues/1829
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
PLUGIN_NAME= stunnel
|
||||
PLUGIN_VERSION= 0.1
|
||||
PLUGIN_COMMENT= stunnel TLS proxy
|
||||
PLUGIN_MAINTAINER= ad@opnsense.org
|
||||
PLUGIN_DEPENDS= stunnel
|
||||
PLUGIN_DEVEL= yes
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
||||
@@ -0,0 +1,2 @@
|
||||
Stunnel is a proxy designed to add TLS encryption functionality to existing clients and servers without any changes in the programs' code.
|
||||
(https://www.stunnel.org/)
|
||||
@@ -0,0 +1,107 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
function stunnel_configure()
|
||||
{
|
||||
return array(
|
||||
'crl' => array('stunnel_refresh_crls')
|
||||
);
|
||||
}
|
||||
|
||||
function stunnel_refresh_crls()
|
||||
{
|
||||
$stunnel = new OPNsense\Stunnel\Stunnel();
|
||||
$configObj = OPNsense\Core\Config::getInstance()->object();
|
||||
foreach ($stunnel->services->service->__items as $service) {
|
||||
if (!empty((string)$service->enabled) && !empty((string)$service->enableCRL)) {
|
||||
foreach (explode(",", (string)$service->cacert) as $cacert) {
|
||||
$this_ca = null;
|
||||
if (!empty($configObj->ca)) {
|
||||
foreach ($configObj->ca as $ca) {
|
||||
if ((string)$ca->refid == $cacert && !empty((string)$ca->prv)) {
|
||||
$this_ca = $ca;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this_ca) {
|
||||
$ca_hash = null;
|
||||
$ca_crt = base64_decode((string)$this_ca->crt);
|
||||
$ca_key = base64_decode((string)$this_ca->prv);
|
||||
$process = proc_open("openssl x509 -hash -noout", [["pipe", "r"], ["pipe", "w"]], $pipes);
|
||||
if (is_resource($process)) {
|
||||
fwrite($pipes[0], $ca_crt);
|
||||
fclose($pipes[0]);
|
||||
$ca_hash = trim(stream_get_contents($pipes[1]));
|
||||
fclose($pipes[1]);
|
||||
proc_close($process);
|
||||
}
|
||||
if ($ca_hash) {
|
||||
$crlres = openssl_crl_new($ca_crt, 0, 9999);
|
||||
if (!empty($configObj->crl)) {
|
||||
foreach ($configObj->crl as $crl) {
|
||||
if ($crl->caref == $cacert && !empty((string)$crl->cert)) {
|
||||
foreach ($crl->cert as $cert) {
|
||||
openssl_crl_revoke_cert(
|
||||
$crlres,
|
||||
base64_decode((string)$cert->crt),
|
||||
(string)$cert->revoke_time,
|
||||
(string)$cert->reason
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$crl_text = "";
|
||||
openssl_crl_export($crlres, $crl_text, $ca_key);
|
||||
file_put_contents("/var/run/stunnel/certs/{$ca_hash}.r0", $crl_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stunnel_syslog()
|
||||
{
|
||||
$logfacilities = array();
|
||||
$logfacilities['stunnel'] = array(
|
||||
'facility' => array('stunnel')
|
||||
);
|
||||
return $logfacilities;
|
||||
}
|
||||
|
||||
function stunnel_xmlrpc_sync()
|
||||
{
|
||||
$result = array();
|
||||
$result[] = array(
|
||||
'description' => gettext('Stunnel'),
|
||||
'section' => 'OPNsense.Stunnel',
|
||||
'id' => 'stunnel',
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?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\Stunnel\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableServiceControllerBase;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
class ServiceController extends ApiMutableServiceControllerBase
|
||||
{
|
||||
protected static $internalServiceClass = '\OPNsense\Stunnel\Stunnel';
|
||||
protected static $internalServiceEnabled = 'general.enabled';
|
||||
protected static $internalServiceTemplate = 'OPNsense/Stunnel';
|
||||
protected static $internalServiceName = 'stunnel';
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?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\Stunnel\Api;
|
||||
|
||||
use \OPNsense\Base\ApiMutableModelControllerBase;
|
||||
|
||||
class ServicesController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'stunnel';
|
||||
protected static $internalModelClass = 'OPNsense\Stunnel\Stunnel';
|
||||
|
||||
protected function save()
|
||||
{
|
||||
// hook service enable status on enabled tunnels
|
||||
$this->getModel()->general->enabled = "0";
|
||||
foreach ($this->getModel()->services->service->__items as $service) {
|
||||
if ((string)$service->enabled == "1") {
|
||||
$this->getModel()->general->enabled = "1";
|
||||
break;
|
||||
}
|
||||
}
|
||||
parent::save();
|
||||
}
|
||||
|
||||
public function searchItemAction()
|
||||
{
|
||||
return $this->searchBase("services.service", array('enabled', 'description'), "description");
|
||||
}
|
||||
|
||||
public function setItemAction($uuid)
|
||||
{
|
||||
return $this->setBase("service", "services.service", $uuid);
|
||||
}
|
||||
|
||||
public function addItemAction()
|
||||
{
|
||||
return $this->addBase("service", "services.service");
|
||||
}
|
||||
|
||||
public function getItemAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("service", "services.service", $uuid);
|
||||
}
|
||||
|
||||
public function delItemAction($uuid)
|
||||
{
|
||||
return $this->delBase("services.service", $uuid);
|
||||
}
|
||||
|
||||
public function toggleItemAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase("services.service", $uuid, $enabled);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<?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\Stunnel;
|
||||
use OPNsense\Base\{IndexController};
|
||||
|
||||
class ServicesController extends IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Stunnel/services');
|
||||
$this->view->formDialogService = $this->getForm("dialogService");
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>service.enabled</id>
|
||||
<label>enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable this rule</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.accept_address</id>
|
||||
<label>Listen address</label>
|
||||
<type>text</type>
|
||||
<help>If possible, a loopback address is the safest choice here, you can forward traffic to it using the firewall.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.accept_port</id>
|
||||
<label>Listen port</label>
|
||||
<type>text</type>
|
||||
<help>The port on which connections will be accepted.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.connect_address</id>
|
||||
<label>Target hostname</label>
|
||||
<type>text</type>
|
||||
<help>The other end of this tunnel.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.connect_port</id>
|
||||
<label>Target port</label>
|
||||
<type>text</type>
|
||||
<help>The port to forward traffic to.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.servercert</id>
|
||||
<label>Certificate</label>
|
||||
<type>dropdown</type>
|
||||
<help><![CDATA[Select a certificate to use for this service.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.cacert</id>
|
||||
<label>CA to validate connections to</label>
|
||||
<type>select_multiple</type>
|
||||
<help><![CDATA[Select a Certificate Authority to validate connections to. To create a CA, go to <a href="/system_camanager.php">CA Manager</a>.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.enableCRL</id>
|
||||
<label>enable CRL</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[
|
||||
Enable certificate revocation lists, when selected a CRL with the format XXXXXXXX.r0 is required in the chroot (/var/run/stunnel/certs/).
|
||||
When certificates are managed from this machine, the attached CRLs will be generated automatically.
|
||||
For more information about this option, see CRLpath in stunnels manual.
|
||||
|
||||
If configured and a valid CRL is not available, all connections will be denied.
|
||||
Additions may need a restart of stunnel (when the certificate was already used).
|
||||
]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.ciphers</id>
|
||||
<label>Ciphers</label>
|
||||
<type>select_multiple</type>
|
||||
<help><![CDATA[Select all accepted TLS ciphers.]]></help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>service.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
</field>
|
||||
</form>
|
||||
@@ -0,0 +1,9 @@
|
||||
<acl>
|
||||
<page-services-stunnel>
|
||||
<name>Services: Stunnel</name>
|
||||
<patterns>
|
||||
<pattern>ui/stunnel/*</pattern>
|
||||
<pattern>api/stunnel/*</pattern>
|
||||
</patterns>
|
||||
</page-services-stunnel>
|
||||
</acl>
|
||||
@@ -0,0 +1,8 @@
|
||||
<menu>
|
||||
<VPN>
|
||||
<Stunnel cssClass="fa fa-dot-circle-o fa-fw" order="110">
|
||||
<Configuration url="/ui/stunnel/services/"/>
|
||||
<LogFile VisibleName="Log File" url="/ui/diagnostics/log/core/stunnel"/>
|
||||
</Stunnel>
|
||||
</VPN>
|
||||
</menu>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?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\Stunnel;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class Stunnel extends BaseModel
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<model>
|
||||
<mount>//OPNsense/Stunnel</mount>
|
||||
<version>1.0.0</version>
|
||||
<migration_prefix>MFP</migration_prefix>
|
||||
<description>
|
||||
OPNsense firewall filter rules
|
||||
</description>
|
||||
<items>
|
||||
<general>
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
</general>
|
||||
<services>
|
||||
<service type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<accept_port type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>65535</MaximumValue>
|
||||
<ValidationMessage>port needs to be an integer value between 1 and 65535</ValidationMessage>
|
||||
<Required>Y</Required>
|
||||
</accept_port>
|
||||
<accept_address type="NetworkField">
|
||||
<Required>Y</Required>
|
||||
<NetMaskAllowed>N</NetMaskAllowed>
|
||||
<default>127.0.0.1</default>
|
||||
</accept_address>
|
||||
<connect_address type="HostnameField">
|
||||
<Required>Y</Required>
|
||||
</connect_address>
|
||||
<connect_port type="IntegerField">
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>65535</MaximumValue>
|
||||
<ValidationMessage>port needs to be an integer value between 1 and 65535</ValidationMessage>
|
||||
<Required>Y</Required>
|
||||
</connect_port>
|
||||
<cacert type="CertificateField">
|
||||
<Required>N</Required>
|
||||
<multiple>Y</multiple>
|
||||
<Type>ca</Type>
|
||||
<ValidationMessage>Please select a valid certificate from the list</ValidationMessage>
|
||||
</cacert>
|
||||
<enableCRL type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</enableCRL>
|
||||
<ciphers type="JsonKeyValueStoreField">
|
||||
<default>TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-CHACHA20-POLY1305,DHE-RSA-AES128-GCM-SHA256,DHE-RSA-AES256-GCM-SHA384</default>
|
||||
<Required>Y</Required>
|
||||
<multiple>Y</multiple>
|
||||
<ConfigdPopulateAct>stunnel ssl ciphers</ConfigdPopulateAct>
|
||||
<SourceFile>/tmp/stunnel_ciphers_list.json</SourceFile>
|
||||
<ConfigdPopulateTTL>360</ConfigdPopulateTTL>
|
||||
<ValidationMessage>Please specify valid tls ciphers.</ValidationMessage>
|
||||
</ciphers>
|
||||
<servercert type="CertificateField">
|
||||
<Required>Y</Required>
|
||||
<Type>cert</Type>
|
||||
<ValidationMessage>Please select a valid certificate from the list</ValidationMessage>
|
||||
</servercert>
|
||||
<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>
|
||||
</service>
|
||||
</services>
|
||||
</items>
|
||||
</model>
|
||||
@@ -0,0 +1,89 @@
|
||||
{#
|
||||
# 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.
|
||||
#}
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
$("#grid-services").UIBootgrid(
|
||||
{ search:'/api/stunnel/services/searchItem/',
|
||||
get:'/api/stunnel/services/getItem/',
|
||||
set:'/api/stunnel/services/setItem/',
|
||||
add:'/api/stunnel/services/addItem/',
|
||||
del:'/api/stunnel/services/delItem/',
|
||||
toggle:'/api/stunnel/services/toggleItem/'
|
||||
}
|
||||
);
|
||||
$("#reconfigureAct").SimpleActionButton();
|
||||
updateServiceControlUI('stunnel');
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" id="destinations" href="#tab_services">{{ lang._('Services') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content content-box">
|
||||
<div id="tab_services" class="tab-pane fade in active">
|
||||
<!-- tab page "services" -->
|
||||
<table id="grid-services" class="table table-condensed table-hover table-striped" data-editDialog="DialogService" data-editAlert="stunnelChangeMessage">
|
||||
<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-width="6em" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="description" data-type="string">{{ lang._('Description') }}</th>
|
||||
<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>
|
||||
<div class="col-md-12">
|
||||
<div id="stunnelChangeMessage" 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/stunnel/service/reconfigure'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-service-widget="stunnel"
|
||||
data-error-title="{{ lang._('Error reconfiguring stunnel') }}"
|
||||
type="button"
|
||||
></button>
|
||||
<br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogService, 'id':'DialogService','label':lang._('Edit Service')])}}
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/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('plugins.inc');
|
||||
require_once("legacy_bindings.inc");
|
||||
|
||||
use OPNsense\Stunnel\Stunnel;
|
||||
use OPNsense\Core\Config;
|
||||
|
||||
$base_path = "/usr/local/etc/stunnel/certs";
|
||||
$stunnel = new Stunnel();
|
||||
$configObj = Config::getInstance()->object();
|
||||
$all_certs = [];
|
||||
foreach ($stunnel->services->service->__items as $service) {
|
||||
if (!empty((string)$service->enabled)) {
|
||||
$this_uuid = $service->getAttributes()['uuid'];
|
||||
$srv_certid = (string)$service->servercert;
|
||||
foreach ($configObj->cert as $cert) {
|
||||
if ($srv_certid == (string)$cert->refid) {
|
||||
$all_certs["{$base_path}/{$this_uuid}.crt"] =
|
||||
base64_decode((string)$cert->crt) . "\n" . base64_decode((string)$cert->prv);
|
||||
}
|
||||
}
|
||||
if (!empty((string)$service->cacert)) {
|
||||
$all_certs["{$base_path}/{$this_uuid}.ca"] = "";
|
||||
foreach (explode(",", (string)$service->cacert) as $caid) {
|
||||
foreach ($configObj->ca as $ca) {
|
||||
if ((string)$ca->refid == $caid) {
|
||||
$all_certs["{$base_path}/{$this_uuid}.ca"] .= base64_decode((string)$ca->crt)."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_dir("/usr/local/etc/stunnel/certs")) {
|
||||
mkdir("/usr/local/etc/stunnel/certs", 0700, true);
|
||||
chown("/usr/local/etc/stunnel/certs", "stunnel");
|
||||
chgrp("/usr/local/etc/stunnel/certs", "stunnel");
|
||||
}
|
||||
|
||||
// cleanup stunnel cert directory
|
||||
foreach (glob("{$base_path}/*") as $filename) {
|
||||
if (!isset($all_certs[$filename])) {
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($all_certs as $filename => $content) {
|
||||
file_put_contents($filename, $content);
|
||||
chown($filename, "stunnel");
|
||||
}
|
||||
|
||||
// trigger certificate revocation lists update
|
||||
plugins_configure('crl');
|
||||
@@ -0,0 +1,29 @@
|
||||
[ssl.ciphers]
|
||||
command:/usr/local/opnsense/scripts/system/ssl_ciphers.py --format=key_value
|
||||
parameters:
|
||||
type:script_output
|
||||
message:List SSL ciphers
|
||||
|
||||
[start]
|
||||
command:/usr/local/etc/rc.d/stunnel start
|
||||
parameters:
|
||||
type:script
|
||||
message:stunnel service start
|
||||
|
||||
[stop]
|
||||
command:/usr/local/etc/rc.d/stunnel stop
|
||||
parameters:
|
||||
type:script
|
||||
message:stunnel service stop
|
||||
|
||||
[restart]
|
||||
command:/usr/local/etc/rc.d/stunnel restart
|
||||
parameters:
|
||||
type:script
|
||||
message:stunnel service restart
|
||||
|
||||
[status]
|
||||
command:/usr/local/etc/rc.d/stunnel status; exit 0
|
||||
parameters:
|
||||
type:script_output
|
||||
message:stunnel status
|
||||
@@ -0,0 +1,2 @@
|
||||
stunnel.conf:/usr/local/etc/stunnel/stunnel.conf
|
||||
rc.conf.d:/etc/rc.conf.d/stunnel
|
||||
@@ -0,0 +1,12 @@
|
||||
{% if not helpers.empty('OPNsense.Stunnel.general.enabled') %}
|
||||
stunnel_enable="YES"
|
||||
stunnel_pidfile="/var/run/stunnel/stunnel.pid"
|
||||
|
||||
mkdir -p /var/run/stunnel/certs
|
||||
chown -R stunnel:stunnel /var/run/stunnel
|
||||
chmod -R 700 /var/run/stunnel
|
||||
|
||||
/usr/local/opnsense/scripts/stunnel/generate_certs.php > /dev/null 2>&1
|
||||
{% else %}
|
||||
stunnel_enable="NO"
|
||||
{% endif %}
|
||||
@@ -0,0 +1,44 @@
|
||||
setuid = stunnel
|
||||
setgid = stunnel
|
||||
chroot = /var/run/stunnel
|
||||
pid = /stunnel.pid
|
||||
debug = info
|
||||
logId = unique
|
||||
|
||||
|
||||
{% if helpers.exists('OPNsense.Stunnel.services.service') %}
|
||||
{% for service in helpers.toList('OPNsense.Stunnel.services.service') %}
|
||||
{% if service.enabled|default('0') == '1' %}
|
||||
|
||||
|
||||
; **************************************************************************
|
||||
; * {{ service.description }}
|
||||
; **************************************************************************
|
||||
[{{service['@uuid']}}]
|
||||
accept = {% if service.accept_address %}{{service.accept_address}}:{% endif %}{{service.accept_port}}
|
||||
connect = {% if service.connect_address.find(":") > -1 %}[{{service.connect_address}}]{% else %}{{service.connect_address}}{% endif %}:{{service.connect_port}}
|
||||
cert = /usr/local/etc/stunnel/certs/{{service['@uuid']}}.crt
|
||||
{% if service.cacert|default('') != '' %}
|
||||
CAfile = /usr/local/etc/stunnel/certs/{{service['@uuid']}}.ca
|
||||
requireCert = yes
|
||||
verifyChain = yes
|
||||
{% if service.enableCRL|default('0') == '1' %}
|
||||
CRLpath = /certs/
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set ciphers =[] %}
|
||||
{% set ciphersuites =[] %}
|
||||
{% for cipher in service.ciphers.split(',') %}
|
||||
{% if cipher.startswith('TLS') %}
|
||||
{% do ciphersuites.append(cipher) %}
|
||||
{% else %}
|
||||
{% do ciphers.append(cipher) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
ciphers = {{ ciphers|join(':') }}
|
||||
ciphersuites = {{ ciphersuites|join(':') }}
|
||||
sslVersionMin=TLSv1.2
|
||||
sslVersionMax={% if ciphersuites %}TLSv1.3{% else %}TLSv1.2{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,6 @@
|
||||
###################################################################
|
||||
# Local syslog-ng configuration filter definition [stunnel].
|
||||
###################################################################
|
||||
filter f_local_stunnel {
|
||||
program("stunnel");
|
||||
};
|
||||
Reference in New Issue
Block a user