Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ 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/cloudflared -- Cloudflare Tunnel Service
net/freeradius -- RADIUS Authentication, Authorization and Accounting Server
net/frr -- The FRRouting Protocol Suite
net/ftp-proxy -- Control ftp-proxy processes
Expand Down
8 changes: 8 additions & 0 deletions net/cloudflared/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
PLUGIN_NAME= cloudflared
PLUGIN_VERSION= 0.1.0
PLUGIN_REVISION= 1
PLUGIN_COMMENT= Cloudflare Tunnel integration
PLUGIN_MAINTAINER= rick+github@insanityinside.net
PLUGIN_DEPENDS= cloudflared

.include "../../Mk/plugins.mk"
7 changes: 7 additions & 0 deletions net/cloudflared/pkg-descr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Integrates the Cloudflare Tunnel daemon (cloudflared) into OPNsense,
allowing self-hosted services to be exposed through Cloudflare Zero Trust
without requiring inbound firewall rules or a public IP address.

WWW: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/

Inspired by original work by Alan Martines <alancpmartines@hotmail.com>.
89 changes: 89 additions & 0 deletions net/cloudflared/src/etc/inc/plugins.inc.d/cloudflared.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

/*
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.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.
*/

function cloudflared_enabled()
{
return (string)(new \OPNsense\Cloudflared\Cloudflared())->general->enabled == '1';
}

function cloudflared_configure()
{
return [
'newwanip' => ['cloudflared_configure_newwanip'],
];
}

function cloudflared_configure_newwanip($verbose = false)
{
if (!cloudflared_enabled()) {
return;
}
if (file_exists('/var/run/cloudflared.pid')) {
return;
}
(new \OPNsense\Core\Backend())->configdRun('cloudflared start');
}

function cloudflared_services()
{
global $config;

$services = [];

if (
isset($config['OPNsense']['Cloudflared']['general']['enabled']) &&
$config['OPNsense']['Cloudflared']['general']['enabled'] == '1'
) {
$services[] = [
'description' => gettext('Cloudflare Tunnel'),
'configd' => [
'start' => ['cloudflared start'],
'restart' => ['cloudflared restart'],
'stop' => ['cloudflared stop'],
],
'name' => 'cloudflared',
'pidfile' => '/var/run/cloudflared.pid',
];
}

return $services;
}

function cloudflared_xmlrpc_sync()
{
$result = [];

$result[] = [
'description' => gettext('Cloudflare Tunnel'),
'section' => 'OPNsense.Cloudflared',
'id' => 'cloudflared',
'services' => ['cloudflared'],
];

return $result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/*
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.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\Cloudflared\Api;

use OPNsense\Base\ApiMutableServiceControllerBase;
use OPNsense\Core\Backend;

class ServiceController extends ApiMutableServiceControllerBase
{
protected static $internalServiceClass = '\OPNsense\Cloudflared\Cloudflared';
protected static $internalServiceTemplate = 'OPNsense/Cloudflared';
protected static $internalServiceEnabled = 'general.enabled';
protected static $internalServiceName = 'cloudflared';

public function reconfigureAction()
{
if ($this->request->isPost()) {
(new Backend())->configdRun('cloudflared reconfigure');
return ['status' => 'ok'];
}
return ['status' => 'failed'];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/*
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.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\Cloudflared\Api;

use OPNsense\Base\ApiMutableModelControllerBase;

class SettingsController extends ApiMutableModelControllerBase
{
protected static $internalModelClass = '\OPNsense\Cloudflared\Cloudflared';
protected static $internalModelName = 'cloudflared';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.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\Cloudflared;

class IndexController extends \OPNsense\Base\IndexController
{
public function indexAction()
{
$this->view->general = $this->getForm("general");
$this->view->pick('OPNsense/Cloudflared/index');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<form>
<field>
<type>header</type>
<label>General Settings</label>
</field>
<field>
<id>cloudflared.general.enabled</id>
<label>Enable</label>
<type>checkbox</type>
<help>Enable the Cloudflare Tunnel service.</help>
</field>
<field>
<id>cloudflared.general.token</id>
<label>Tunnel Token</label>
<type>text</type>
<help>Tunnel token from the Cloudflare Zero Trust dashboard (Networks &gt; Tunnels). The token is stored in a root-readable file and passed to cloudflared via an environment variable.</help>
</field>
<field>
<id>cloudflared.general.protocol</id>
<label>Protocol</label>
<type>dropdown</type>
<help>Transport protocol. Leave on auto unless you have a specific reason to force QUIC or HTTP/2.</help>
</field>
<field>
<id>cloudflared.general.post_quantum</id>
<label>Post-Quantum Encryption</label>
<type>checkbox</type>
<help>Enable post-quantum cryptography for the tunnel connection (requires QUIC).</help>
</field>
<field>
<id>cloudflared.general.quic_disable_pmtu_discovery</id>
<label>Disable QUIC PMTU Discovery</label>
<type>checkbox</type>
<help>Disable Path MTU Discovery for QUIC connections. May help in environments where ICMP is blocked.</help>
</field>
<field>
<id>cloudflared.general.log_level</id>
<label>Log Level</label>
<type>dropdown</type>
<help>Verbosity of cloudflared logging. Defaults to info. Use debug for troubleshooting; warn or error for quieter operation.</help>
</field>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

/*
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.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\System\Status;

use OPNsense\System\AbstractStatus;
use OPNsense\System\SystemStatusCode;

class CloudflaredOverrideStatus extends AbstractStatus
{
public function __construct()
{
$this->internalPriority = 2;
$this->internalPersistent = true;
$this->internalIsBanner = true;
$this->internalTitle = gettext('Cloudflare Tunnel');
$this->internalScope = [
'/ui/cloudflared/'
];
}

public function collectStatus()
{
$this->internalMessage = gettext(
'Cloudflare Tunnel traffic bypasses OPNsense firewall rules; access control must be enforced in ' .
'Cloudflare Access. For optimal QUIC performance, set the recommended kernel tunables. ' .
'See the plugin documentation for details.'
);
$this->internalStatus = SystemStatusCode::NOTICE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<acl>
<page-cloudflared-general>
<name>Services: Cloudflare Tunnel</name>
<patterns>
<pattern>ui/cloudflared/*</pattern>
<pattern>api/cloudflared/*</pattern>
</patterns>
</page-cloudflared-general>
<page-cloudflared-log>
<name>Services: Cloudflare Tunnel: Log File</name>
<patterns>
<pattern>ui/diagnostics/log/core/cloudflared/*</pattern>
<pattern>api/diagnostics/log/core/cloudflared/*</pattern>
</patterns>
</page-cloudflared-log>
</acl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/*
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.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\Cloudflared;

use OPNsense\Base\BaseModel;

class Cloudflared extends BaseModel
{
}
Loading