Skip to content

Commit cbe0e9b

Browse files
net/cloudflared: rework to use FreeBSD port with enhancements
Reworks the original plugin by Alan Martines to address the architectural feedback on PR opnsense#5406: the custom binary installer is replaced with PLUGIN_DEPENDS= cloudflared, delegating binary management entirely to pkg via the FreeBSD ports tree. The plugin is now a pure configuration wrapper. Binary and service: - Remove install_binary.sh and bundled rc.d script; use FreeBSD port - Pass tunnel token via TUNNEL_TOKEN env var (cloudflared_env in rc.subr) so it does not appear in ps aux; /etc/rc.conf.d/cloudflared chmod 600 - Add config.yml template; move options out of rc.conf.d command args - Hardcode no-autoupdate: true (pkg manages the binary; self-update is inappropriate) New features: - Transport protocol selector: Auto (QUIC with HTTP/2 fallback, default), QUIC-only (UDP 7844), HTTP/2-only (TCP 443) - Automatic outbound firewall rule for TCP/UDP 7844 via cloudflared_firewall() hook; UDP active for Auto and QUIC-only modes, TCP for Auto and HTTP/2-only - quic-disable-pmtu-discovery option: workaround for intermittent QUIC stream errors on networks where ICMP is filtered - Log viewer tab with client-side pagination (25/50/100/200 lines/page, Older/Newer navigation) and Follow mode for live tailing - Crash recovery: monitor.sh syshook and cron job restart cloudflared if it exits unexpectedly; sentinel file suppresses watchdog after intentional stop - newwanip/newwanip6 hook to restart on WAN IP change if daemon exits Reliability fixes: - Improve tunnel health detection: cross-check Prometheus metrics against log output to catch stale ha_connections; report accurate down state Other: - Security notice in UI: tunnel traffic bypasses OPNsense firewall rules - Translations for 20 languages in addition to the original pt_BR (machine generated) - BSD license headers on all scripts - README.md entry Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 373768c commit cbe0e9b

46 files changed

Lines changed: 2405 additions & 306 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ misc/theme-rebellion -- A suitably dark theme
4949
misc/theme-tukan -- The tukan theme - blue/white
5050
misc/theme-vicuna -- The vicuna theme - blue sapphire
5151
net/chrony -- Chrony time synchronisation
52+
net/cloudflared -- Cloudflare tunnel
5253
net/freeradius -- RADIUS Authentication, Authorization and Accounting Server
5354
net/frr -- The FRRouting Protocol Suite
5455
net/ftp-proxy -- Control ftp-proxy processes

net/cloudflared/LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 2-Clause License
22

3-
Copyright (c) 2026, Alan Martines
3+
Copyright (c) 2026, Alan Martines, Richard Aspden
44

55
Redistribution and use in source and binary forms, with or without
66
modification, are permitted provided that the following conditions are met:

net/cloudflared/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ PLUGIN_NAME= cloudflared
22
PLUGIN_VERSION= 0.1.0
33
PLUGIN_REVISION= 1
44
PLUGIN_COMMENT= Cloudflare Tunnel (cloudflared) integration
5-
PLUGIN_MAINTAINER= alancpmartines@hotmail.com
6-
PLUGIN_DEPENDS= fetch
5+
PLUGIN_MAINTAINER= rick+github@insanityinside.net
6+
PLUGIN_DEPENDS= cloudflared
77

88
.include "../../Mk/plugins.mk"

net/cloudflared/pkg-descr

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ Cloudflare Tunnel (cloudflared) integration for OPNsense.
22

33
Provides a native MVC interface to manage token-based Cloudflare Zero
44
Trust tunnels without opening firewall ports or requiring a static IP.
5-
Follows Method 1: Token-based Setup using binaries from the kjake
6-
FreeBSD fork of cloudflared.
5+
Uses the cloudflared binary from the FreeBSD ports collection
6+
(net/cloudflared).
77

88
Features:
99
- Token-based tunnel authentication via Cloudflare Zero Trust
10-
- Integrated binary installer with automatic FreeBSD version and
11-
architecture detection
10+
- Transport protocol selection: Auto (QUIC with HTTP/2 fallback),
11+
QUIC-only, or HTTP/2-only
12+
- Automatic outbound firewall rules for QUIC (UDP 7844) and HTTP/2 (TCP 7844)
1213
- QUIC kernel tuning (kern.ipc.maxsockbuf, net.inet.udp.recvspace)
1314
- Post-quantum encryption support (--post-quantum)
1415
- Real-time tunnel health status in the UI
16+
- Log viewer with pagination and live follow mode
17+
- Automatic crash recovery and restart on WAN IP change
1518
- Appears in System: Diagnostics: Services
1619

17-
WWW: https://github.com/AlanMartines/os-cloudflared
20+
WWW: https://github.com/cloudflare/cloudflared
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# DO NOT EDIT THIS FILE -- OPNsense auto-generated file
2+
#
3+
# User-defined crontab files can be loaded via /etc/cron.d
4+
# or /usr/local/etc/cron.d and follow the same format as
5+
# /etc/crontab, see the crontab(5) manual page.
6+
SHELL=/bin/sh
7+
PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
8+
#minute hour mday month wday who command
9+
* * * * * root /usr/local/opnsense/scripts/OPNsense/Cloudflared/monitor.sh

net/cloudflared/src/etc/inc/plugins.inc.d/cloudflared.inc

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
/*
44
* Copyright (C) 2026 Alan Martines <alancpmartines@hotmail.com>
5+
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.net>
56
* All rights reserved.
67
*
78
* Redistribution and use in source and binary forms, with or without
@@ -32,6 +33,79 @@ function cloudflared_enabled()
3233
return (string)$model->general->enabled == '1';
3334
}
3435

36+
function cloudflared_configure()
37+
{
38+
return [
39+
'newwanip' => ['cloudflared_configure_newwanip:10'],
40+
'newwanip6' => ['cloudflared_configure_newwanip:10'],
41+
];
42+
}
43+
44+
function cloudflared_configure_newwanip($verbose = false)
45+
{
46+
if (!cloudflared_enabled()) {
47+
return;
48+
}
49+
if (file_exists('/var/run/cloudflared.stopped')) {
50+
return;
51+
}
52+
$pidfile = '/var/run/cloudflared.pid';
53+
if (file_exists($pidfile)) {
54+
$pid = (int)trim(file_get_contents($pidfile));
55+
if ($pid > 0 && posix_kill($pid, 0)) {
56+
return;
57+
}
58+
}
59+
$backend = new \OPNsense\Core\Backend();
60+
$backend->configdRun('cloudflared start');
61+
}
62+
63+
function cloudflared_firewall($fw)
64+
{
65+
if (!cloudflared_enabled()) {
66+
return;
67+
}
68+
69+
$model = new \OPNsense\Cloudflared\Cloudflared();
70+
$protocol = (string)$model->general->protocol;
71+
72+
if ($protocol !== 'http2') {
73+
$fw->registerFilterRule(
74+
1,
75+
[
76+
'descr' => 'Allow Cloudflare Tunnel QUIC (autogenerated)',
77+
'direction' => 'out',
78+
'from' => '(self)',
79+
'to' => 'any',
80+
'to_port' => '7844',
81+
'protocol' => 'udp',
82+
'type' => 'pass',
83+
'quick' => true,
84+
'statetype' => 'keep',
85+
'#ref' => 'ui/cloudflared/general/index',
86+
]
87+
);
88+
}
89+
90+
if ($protocol !== 'quic') {
91+
$fw->registerFilterRule(
92+
1,
93+
[
94+
'descr' => 'Allow Cloudflare Tunnel HTTP/2 (autogenerated)',
95+
'direction' => 'out',
96+
'from' => '(self)',
97+
'to' => 'any',
98+
'to_port' => '7844',
99+
'protocol' => 'tcp',
100+
'type' => 'pass',
101+
'quick' => true,
102+
'statetype' => 'keep',
103+
'#ref' => 'ui/cloudflared/general/index',
104+
]
105+
);
106+
}
107+
}
108+
35109
function cloudflared_services()
36110
{
37111
$services = [];
Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,44 @@
11
<?php
22

3+
/*
4+
* Copyright (C) 2026 Alan Martines <alancpmartines@hotmail.com>
5+
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.net>
6+
* All rights reserved.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20+
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21+
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22+
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*/
29+
330
namespace OPNsense\Cloudflared\Api;
431

532
use OPNsense\Base\ApiMutableServiceControllerBase;
633
use OPNsense\Core\Backend;
734

835
class ServiceController extends ApiMutableServiceControllerBase
936
{
10-
protected static $internalServiceClass = 'OPNsense\Cloudflared\Cloudflared';
37+
protected static $internalServiceClass = '\OPNsense\Cloudflared\Cloudflared';
1138
protected static $internalServiceEnabled = 'general.enabled';
1239
protected static $internalServiceTemplate = 'OPNsense/Cloudflared';
1340
protected static $internalServiceName = 'cloudflared';
1441

15-
/**
16-
* Reconfigura o serviço: cria diretórios, recarrega templates,
17-
* aplica sysctl tunables e reinicia o serviço.
18-
*/
1942
public function reconfigureAction()
2043
{
2144
if ($this->request->isPost()) {
@@ -37,20 +60,11 @@ public function tunnelStatusAction()
3760
return $data;
3861
}
3962

40-
public function installAction()
63+
public function logAction()
4164
{
42-
if ($this->request->isPost()) {
43-
$backend = new Backend();
44-
$response = $backend->configdRun("cloudflared install_binary");
45-
if ($response === null) {
46-
return ['response' => 'ERROR: configd did not respond. Run "service configd restart" on OPNsense.'];
47-
}
48-
$response = trim($response);
49-
if ($response === '' || $response === 'FAILED') {
50-
return ['response' => 'ERROR: Action not found. Run "service configd restart" on OPNsense to reload actions.'];
51-
}
52-
return ['response' => $response];
53-
}
54-
return ['response' => 'error'];
65+
$backend = new Backend();
66+
$raw = $backend->configdRun("cloudflared log");
67+
$lines = $raw !== null ? explode("\n", rtrim($raw)) : [];
68+
return ['lines' => $lines, 'total' => count($lines)];
5569
}
5670
}
Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,38 @@
11
<?php
22

3+
/*
4+
* Copyright (C) 2026 Alan Martines <alancpmartines@hotmail.com>
5+
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.net>
6+
* All rights reserved.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20+
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21+
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22+
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*/
29+
330
namespace OPNsense\Cloudflared\Api;
431

532
use OPNsense\Base\ApiMutableModelControllerBase;
6-
use OPNsense\Cloudflared\Cloudflared;
733

834
class SettingsController extends ApiMutableModelControllerBase
935
{
1036
protected static $internalModelName = 'Cloudflared';
11-
protected static $internalModelClass = 'OPNsense\Cloudflared\Cloudflared';
37+
protected static $internalModelClass = '\OPNsense\Cloudflared\Cloudflared';
1238
}

net/cloudflared/src/opnsense/mvc/app/controllers/OPNsense/Cloudflared/IndexController.php

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,30 @@
11
<?php
22

3-
/**
4-
* Copyright (C) 2026 Alan Martines <alancpmartines@hotmail.com>
5-
* All rights reserved.
3+
/*
4+
* Copyright (C) 2026 Alan Martines <alancpmartines@hotmail.com>
5+
* Copyright (C) 2026 Richard Aspden <rick+github@insanityinside.net>
6+
* All rights reserved.
67
*
7-
* Redistribution and use in source and binary forms, with or without
8-
* modification, are permitted provided that the following conditions are met:
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
910
*
10-
* 1. Redistributions of source code must retain the above copyright notice,
11-
* this list of conditions and the following disclaimer.
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
1213
*
13-
* 2. Redistributions in binary form must reproduce the above copyright
14-
* notice, this list of conditions and the following disclaimer in the
15-
* documentation and/or other materials provided with the distribution.
14+
* 2. Redistributions in binary form must reproduce the above copyright
15+
* notice, this list of conditions and the following disclaimer in the
16+
* documentation and/or other materials provided with the distribution.
1617
*
17-
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18-
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19-
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20-
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21-
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22-
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25-
* ARISING IN ANY WAY OUT OF THE USE of THIS SOFTWARE, EVEN IF ADVISED OF THE
26-
* POSSIBILITY OF SUCH DAMAGE.
18+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19+
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20+
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21+
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
22+
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
2728
*/
2829

2930
namespace OPNsense\Cloudflared;

net/cloudflared/src/opnsense/mvc/app/controllers/OPNsense/Cloudflared/forms/general.xml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,24 @@
1111
<type>password</type>
1212
<help>The token for your Cloudflare Tunnel. Get it from one.dash.cloudflare.com > Access > Tunnels.</help>
1313
</field>
14-
<field>
15-
<id>Cloudflared.general.no_autoupdate</id>
16-
<label>Disable Auto-Update</label>
17-
<type>checkbox</type>
18-
<help>Pass --no-autoupdate to cloudflared. Recommended when managing updates manually via the Install/Update Binary button.</help>
19-
</field>
2014
<field>
2115
<id>Cloudflared.general.post_quantum</id>
2216
<label>Enable Post-Quantum Encryption</label>
2317
<type>checkbox</type>
2418
<help>Pass --post-quantum to enable post-quantum cryptography for the tunnel connection.</help>
2519
</field>
20+
<field>
21+
<id>Cloudflared.general.quic_disable_pmtu_discovery</id>
22+
<label>Disable QUIC PMTU Discovery</label>
23+
<type>checkbox</type>
24+
<help>Pass --quic-disable-pmtu-discovery to cloudflared. Workaround for intermittent "failed to accept QUIC stream" errors on networks where ICMP is filtered and path MTU discovery does not work correctly.</help>
25+
</field>
26+
<field>
27+
<id>Cloudflared.general.protocol</id>
28+
<label>Protocol</label>
29+
<type>dropdown</type>
30+
<help>Transport protocol for the tunnel connection. Auto tries QUIC first and falls back to HTTP/2 if unavailable. Outbound firewall rules are automatically added: UDP 7844 for Auto and QUIC modes, TCP 7844 for Auto and HTTP/2 modes.</help>
31+
</field>
2632
<field>
2733
<id>Cloudflared.general.kern_ipc_maxsockbuf</id>
2834
<label>Max Socket Buffer (kern.ipc.maxsockbuf)</label>

0 commit comments

Comments
 (0)