mirror of
https://github.com/netbirdio/pfsense-netbird.git
synced 2026-05-22 18:04:30 -07:00
Add NetBird package
This commit is contained in:
@@ -1 +1,35 @@
|
||||
# pfsense-netbird
|
||||
# NetBird Package for pfSense
|
||||
|
||||

|
||||
|
||||
## Build Instructions
|
||||
|
||||
Use **FreeBSD 15.0-CURRENT** as your base system for building the package.
|
||||
|
||||
### Steps:
|
||||
|
||||
```
|
||||
git clone git@github.com:netbirdio/pfsense-netbird.git
|
||||
cd pfSense-pkg-NetBird/
|
||||
make
|
||||
make package
|
||||
```
|
||||
|
||||
The `make package` command will generate a file like:
|
||||
|
||||
```
|
||||
/work/pkg/pfSense-pkg-NetBird-<version>.pkg
|
||||
```
|
||||
|
||||
You can then transfer this file to your pfSense system and install it manually.
|
||||
|
||||
## Installation on pfSense
|
||||
|
||||
To install the package manually on pfSense:
|
||||
|
||||
```
|
||||
pkg remove pfSense-pkg-NetBird-<version>
|
||||
pkg add pfSense-pkg-NetBird-<version>.pkg
|
||||
```
|
||||
|
||||
Once installed, **NetBird** will appear under the **VPN** menu in the pfSense Web UI.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
@@ -0,0 +1,30 @@
|
||||
PORTNAME= netbird
|
||||
DISTVERSIONPREFIX= v
|
||||
DISTVERSION= 0.47.0
|
||||
CATEGORIES= security net net-vpn
|
||||
|
||||
MAINTAINER= hakan.external@netbird.io
|
||||
COMMENT= Peer-to-peer VPN that seamlessly connects your devices
|
||||
WWW= https://netbird.io/
|
||||
|
||||
LICENSE= BSD3CLAUSE
|
||||
LICENSE_FILE= ${WRKSRC}/LICENSE
|
||||
|
||||
NOT_FOR_ARCHS= i386
|
||||
NOT_FOR_ARCHS_REASON= "no 32-bit builds supported"
|
||||
|
||||
RUN_DEPENDS= ca_root_nss>0:security/ca_root_nss
|
||||
|
||||
USES= go:1.23,modules
|
||||
USE_RC_SUBR= netbird
|
||||
|
||||
GO_MODULE= github.com/netbirdio/netbird
|
||||
GO_TARGET= ./client:netbird
|
||||
GO_BUILDFLAGS= -tags freebsd -o ${PORTNAME} -ldflags "\
|
||||
-s -w -X github.com/netbirdio/netbird/version.version=${PORTVERSION}"
|
||||
|
||||
WRKSRC= ${WRKDIR}/netbird-${PORTVERSION}
|
||||
|
||||
PLIST_FILES= bin/netbird
|
||||
|
||||
.include <bsd.port.mk>
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# PROVIDE: netbird
|
||||
# REQUIRE: SERVERS
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="netbird"
|
||||
netbird_env="IS_DAEMON=1"
|
||||
pidfile="/var/run/${name}.pid"
|
||||
command="/usr/sbin/daemon"
|
||||
daemon_args="-P ${pidfile} -r -t \"${name}: daemon\""
|
||||
command_args="${daemon_args} /usr/local/bin/netbird service run --config /var/db/netbird/config.json --log-level info --daemon-addr unix:///var/run/netbird.sock --log-file /var/log/netbird/client.log"
|
||||
|
||||
run_rc_command "$1"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
NetBird is an open-source WireGuard-based overlay network combined with
|
||||
Zero Trust Network Access, providing secure and reliable connectivity
|
||||
to internal resources.
|
||||
|
||||
Key features:
|
||||
- Zero-config VPN: Easily create secure connections between devices without
|
||||
manual network setup.
|
||||
- Built on WireGuard: Leverages WireGuard's high-performance encryption for
|
||||
fast and secure communication.
|
||||
- Self-hosted or Cloud-managed: Users can deploy their own NetBird management
|
||||
server or use NetBird Cloud for centralized control.
|
||||
- Access Control & Routing: Fine-grained access control policies and automatic
|
||||
network routing simplify connectivity.
|
||||
- This FreeBSD port provides the NetBird client daemon and CLI tools, allowing
|
||||
FreeBSD systems to join a NetBird mesh network and securely communicate with
|
||||
other peers.
|
||||
|
||||
For more details, visit: https://netbird.io
|
||||
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{ type: install
|
||||
message: <<EOM
|
||||
At this time this code is new, unvetted, possibly buggy, and should be
|
||||
considered "experimental". It might contain security issues. We gladly
|
||||
welcome your testing and bug reports, but do keep in mind that this code
|
||||
is new, so some caution should be exercised at the moment for using it
|
||||
in mission critical environments.
|
||||
EOM
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/bin/php -f /etc/rc.packages %%PORTNAME%% ${2}
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "${2}" != "POST-INSTALL" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
${PKG_ROOTDIR}/usr/local/bin/php -f ${PKG_ROOTDIR}/etc/rc.packages %%PORTNAME%% ${2}
|
||||
@@ -0,0 +1,262 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
|
||||
<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
|
||||
<packagegui>
|
||||
<copyright>
|
||||
<![CDATA[
|
||||
/*
|
||||
* netbird.xml
|
||||
*
|
||||
* part of pfSense (https://www.pfsense.org)
|
||||
* Copyright (c) 2022-2025 Rubicon Communications, LLC (Netgate)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
]]>
|
||||
</copyright>
|
||||
<name>netbird</name>
|
||||
<version>%%PKGVERSION%%</version>
|
||||
<title>VPN/NetBird</title>
|
||||
<include_file>/usr/local/pkg/netbird/netbird.inc</include_file>
|
||||
<aftersaveredirect>/pkg_edit.php?xml=netbird.xml</aftersaveredirect>
|
||||
<menu>
|
||||
<name>NetBird</name>
|
||||
<section>VPN</section>
|
||||
<configfile>netbird.xml</configfile>
|
||||
<url>/pkg_edit.php?xml=netbird/netbird_auth.xml</url>
|
||||
</menu>
|
||||
<menu>
|
||||
<name>NetBird</name>
|
||||
<section>Status</section>
|
||||
<configfile>netbird.xml</configfile>
|
||||
<url>/netbird_status.php</url>
|
||||
</menu>
|
||||
<tabs>
|
||||
<tab>
|
||||
<text>Authentication</text>
|
||||
<url>pkg_edit.php?xml=netbird/netbird_auth.xml</url>
|
||||
</tab>
|
||||
<tab>
|
||||
<text>Settings</text>
|
||||
<url>pkg_edit.php?xml=netbird.xml</url>
|
||||
<active/>
|
||||
</tab>
|
||||
<tab>
|
||||
<text>Status</text>
|
||||
<url>netbird_status.php</url>
|
||||
</tab>
|
||||
</tabs>
|
||||
<fields>
|
||||
<field>
|
||||
<name>General</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>WireGuard Port</fielddescr>
|
||||
<fieldname>wireguardport</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Wireguard interface listening port
|
||||
]]>
|
||||
</description>
|
||||
<type>input</type>
|
||||
<default_value>51820</default_value>
|
||||
<required/>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>Firewall</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Allow Configuration</fielddescr>
|
||||
<fieldname>allowfirewallconfig</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Allow the client to manage and enforce firewall rules
|
||||
]]>
|
||||
</description>
|
||||
<sethelp>
|
||||
<![CDATA[
|
||||
If disabled the client won't modify firewall rules
|
||||
]]>
|
||||
</sethelp>
|
||||
<type>checkbox</type>
|
||||
<default_value>on</default_value>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Block Inbound Connection</fielddescr>
|
||||
<fieldname>blockinboundconn</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Block all inbound connections to the local machine and any routed networks
|
||||
]]>
|
||||
</description>
|
||||
<sethelp>
|
||||
<![CDATA[
|
||||
This overrides any policies received from the management service
|
||||
]]>
|
||||
</sethelp>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>SSH</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Enable</fielddescr>
|
||||
<fieldname>enablessh</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Allows incoming SSH connections
|
||||
]]>
|
||||
</description>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>DNS</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Enable</fielddescr>
|
||||
<fieldname>enabledns</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Allows the client to configure DNS settings
|
||||
]]>
|
||||
</description>
|
||||
<type>checkbox</type>
|
||||
<default_value>on</default_value>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>Routing</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Access LAN</fielddescr>
|
||||
<fieldname>accesslan</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Allow access to local networks (LAN) when using this peer as a router or exit node
|
||||
]]>
|
||||
</description>
|
||||
<type>checkbox</type>
|
||||
<default_value>on</default_value>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Accept Client Routes</fielddescr>
|
||||
<fieldname>allowclientroutes</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Accept and process client routes received from the management
|
||||
]]>
|
||||
</description>
|
||||
<type>checkbox</type>
|
||||
<default_value>on</default_value>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Allow Server Routes</fielddescr>
|
||||
<fieldname>allowserverroutes</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Enable this peer to act as a router for server routes received from the management
|
||||
]]>
|
||||
</description>
|
||||
<type>checkbox</type>
|
||||
<default_value>on</default_value>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>Post-Quantum</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Enable Rosenpass</fielddescr>
|
||||
<fieldname>enablerosenpass</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Enable the Rosenpass to provide post-quantum secure connections
|
||||
]]>
|
||||
</description>
|
||||
<sethelp>
|
||||
<![CDATA[
|
||||
Experimental
|
||||
]]>
|
||||
</sethelp>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Rosenpass Permissive Mode</fielddescr>
|
||||
<fieldname>rosenpasspermissive</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Enable this peer to accept WireGuard connections from peers that do not have Rosenpass enabled
|
||||
]]>
|
||||
</description>
|
||||
<sethelp>
|
||||
<![CDATA[
|
||||
Experimental
|
||||
]]>
|
||||
</sethelp>
|
||||
<type>checkbox</type>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>Logging</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Syslog Logging</fielddescr>
|
||||
<fieldname>syslogenable</fieldname>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Enable syslog output
|
||||
]]>
|
||||
</description>
|
||||
<type>checkbox</type>
|
||||
<default_value>on</default_value>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Syslog Settings</fielddescr>
|
||||
<fieldname>loglevel</fieldname>
|
||||
<description>Set the syslog logging level</description>
|
||||
<type>select</type>
|
||||
<default_value>info</default_value>
|
||||
<options>
|
||||
<option><name>INFO</name><value>info</value></option>
|
||||
<option><name>DEBUG</name><value>debug</value></option>
|
||||
</options>
|
||||
<required/>
|
||||
</field>
|
||||
|
||||
</fields>
|
||||
<note>
|
||||
<![CDATA[
|
||||
Changes to these settings may temporarily disrupt connections and access to NetBird.
|
||||
]]>
|
||||
</note>
|
||||
|
||||
<custom_php_after_head_command>
|
||||
<![CDATA[netbird_display_connection_info();]]>
|
||||
</custom_php_after_head_command>
|
||||
<custom_php_validation_command>
|
||||
<![CDATA[netbird_validate_input($_POST, $input_errors);]]>
|
||||
</custom_php_validation_command>
|
||||
<custom_php_resync_config_command>
|
||||
<![CDATA[netbird_resync_config();]]>
|
||||
</custom_php_resync_config_command>
|
||||
</packagegui>
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/*
|
||||
* netbird.xml
|
||||
*
|
||||
* part of pfSense (https://www.pfsense.org)
|
||||
* Copyright (c) 2022-2025 Rubicon Communications, LLC (Netgate)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
require_once('service-utils.inc');
|
||||
|
||||
define('NETBIRD_BIN', '/usr/local/bin/netbird');
|
||||
define('PKG_BIN', '/usr/sbin/pkg');
|
||||
|
||||
|
||||
function netbird_resync_config()
|
||||
{
|
||||
if (netbird_is_connected()) {
|
||||
if (!netbird_disconnect()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$cmd = [NETBIRD_BIN, 'up'];
|
||||
|
||||
if (!empty($_POST['wireguardport'])) {
|
||||
$cmd[] = '--wireguard-port=' . escapeshellarg((int)$_POST['wireguardport']);
|
||||
}
|
||||
if (!empty($_POST['loglevel'])) {
|
||||
$cmd[] = '--log-level=' . escapeshellarg($_POST['loglevel']);
|
||||
}
|
||||
|
||||
$options = [
|
||||
'enablessh' => ['--allow-server-ssh', true],
|
||||
'blockinboundconn' => ['--block-inbound', true],
|
||||
'allowfirewallconfig' => ['--disable-firewall', false],
|
||||
'enabledns' => ['--disable-dns', false],
|
||||
'accesslan' => ['--block-lan-access', false],
|
||||
'allowclientroutes' => ['--disable-client-routes', false],
|
||||
'allowserverroutes' => ['--disable-server-routes', false],
|
||||
'enablerosenpass' => ['--enable-rosenpass', true],
|
||||
'rosenpasspermissive' => ['--rosenpass-permissive', true],
|
||||
];
|
||||
|
||||
foreach ($options as $key => [$flag, $enabled_value]) {
|
||||
$is_checked = ($_POST[$key] ?? '') === 'on';
|
||||
$cmd[] = $flag . '=' . ($is_checked === $enabled_value ? 'true' : 'false');
|
||||
}
|
||||
|
||||
exec(implode(' ', $cmd));
|
||||
}
|
||||
|
||||
|
||||
function netbird_validate_input($post, &$input_errors)
|
||||
{
|
||||
$wireguard_port = $post['wireguard_port'];
|
||||
if (!empty($wireguard_port) && (!ctype_digit($wireguard_port) || !is_port($wireguard_port))){
|
||||
$input_errors[] = sprintf(gettext('WireGuard port (%s) is not a valid port.'), $wireguard_port);
|
||||
}
|
||||
}
|
||||
|
||||
function netbird_is_connected(): bool
|
||||
{
|
||||
$status = netbird_get_status();
|
||||
return !empty($status['management']['connected']);
|
||||
}
|
||||
|
||||
function netbird_is_running(): bool
|
||||
{
|
||||
return is_service_running('netbird');
|
||||
}
|
||||
|
||||
function netbird_disconnect(): bool
|
||||
{
|
||||
$cmd = implode(' ', [NETBIRD_BIN, 'down']);
|
||||
exec($cmd, $out, $result_code);
|
||||
|
||||
return $result_code === 0 && !empty($out);
|
||||
}
|
||||
|
||||
function netbird_get_status()
|
||||
{
|
||||
$cmd = implode(' ', [NETBIRD_BIN, 'status', '--json']);
|
||||
exec($cmd, $out, $rc);
|
||||
|
||||
if ($rc !==0 || empty($out)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = json_decode(implode('', $out), true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE || !is_array($status)) {
|
||||
return false;
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
function netbird_display_connection_info(): void
|
||||
{
|
||||
if (!netbird_is_running()) {
|
||||
$message = gettext('NetBird is not running.');
|
||||
$type = 'danger';
|
||||
$closable = false;
|
||||
} elseif (!netbird_is_connected()) {
|
||||
$message = gettext('NetBird is not connected. Refresh or check the NetBird status page.');
|
||||
$type = 'warning';
|
||||
$closable = false;
|
||||
} else {
|
||||
$message = gettext('NetBird is connected.');
|
||||
$type = 'info';
|
||||
$closable = true;
|
||||
}
|
||||
|
||||
print_info_box($message, $type, $closable ? 'close' : false);
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*
|
||||
* netbird_auth.inc
|
||||
*
|
||||
* part of pfSense (https://www.pfsense.org)
|
||||
* Copyright (c) 2022-2025 Rubicon Communications, LLC (Netgate)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
require_once('netbird/netbird.inc');
|
||||
|
||||
|
||||
function netbird_auth_apply_config()
|
||||
{
|
||||
if (!empty($_POST['disconnect'])) {
|
||||
netbird_disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (netbird_is_connected() && !netbird_disconnect()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cmd = sprintf(
|
||||
'%s up -m %s -k %s',
|
||||
escapeshellcmd(NETBIRD_BIN),
|
||||
escapeshellarg($_POST['managementurl']),
|
||||
escapeshellarg($_POST['setupkey'])
|
||||
);
|
||||
exec($cmd);
|
||||
}
|
||||
|
||||
|
||||
function netbird_auth_validate_input($post, &$input_errors)
|
||||
{
|
||||
if (!empty($post['disconnect'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$managementurl = $post['managementurl'];
|
||||
$setupkey = $post['setupkey'];
|
||||
|
||||
if (!empty($managementurl) && !is_URL($managementurl)) {
|
||||
$input_errors[] = sprintf(gettext('Management URL (%s) is not a valid URL.'), $managementurl);
|
||||
}
|
||||
if (empty($setupkey)) {
|
||||
$input_errors[] = gettext('Setup Key is required.');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd">
|
||||
<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?>
|
||||
<packagegui>
|
||||
<copyright>
|
||||
<![CDATA[
|
||||
/*
|
||||
* netbird_auth.xml
|
||||
*
|
||||
* part of pfSense (https://www.pfsense.org)
|
||||
* Copyright (c) 2022-2025 Rubicon Communications, LLC (Netgate)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
]]>
|
||||
</copyright>
|
||||
<name>netbird_auth</name>
|
||||
<version>%%PKGVERSION%%</version>
|
||||
<title>VPN/NetBird</title>
|
||||
<include_file>/usr/local/pkg/netbird/netbird_auth.inc</include_file>
|
||||
<aftersaveredirect>/pkg_edit.php?xml=netbird/netbird_auth.xml</aftersaveredirect>
|
||||
<tabs>
|
||||
<tab>
|
||||
<text>Authentication</text>
|
||||
<url>pkg_edit.php?xml=netbird/netbird_auth.xml</url>
|
||||
<active/>
|
||||
</tab>
|
||||
<tab>
|
||||
<text>Settings</text>
|
||||
<url>pkg_edit.php?xml=netbird.xml</url>
|
||||
</tab>
|
||||
<tab>
|
||||
<text>Status</text>
|
||||
<url>netbird_status.php</url>
|
||||
</tab>
|
||||
</tabs>
|
||||
<fields>
|
||||
<field>
|
||||
<name>Authentication</name>
|
||||
<type>listtopic</type>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Management URL</fielddescr>
|
||||
<fieldname>managementurl</fieldname>
|
||||
<description>
|
||||
<![CDATA[Base URL of management service]]>
|
||||
</description>
|
||||
<type>input</type>
|
||||
<default_value>https://api.netbird.io:443</default_value>
|
||||
<required/>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Setup Key</fielddescr>
|
||||
<fieldname>setupkey</fieldname>
|
||||
<description>
|
||||
<![CDATA[Set the authentication setup key]]>
|
||||
</description>
|
||||
<type>input</type>
|
||||
<required/>
|
||||
</field>
|
||||
<field>
|
||||
<fielddescr>Disconnect</fielddescr>
|
||||
<fieldname>disconnect</fieldname>
|
||||
<type>button</type>
|
||||
<buttonicon>fa-solid fa-right-from-bracket</buttonicon>
|
||||
<buttonclass>btn-danger</buttonclass>
|
||||
<description>
|
||||
<![CDATA[
|
||||
Disconnect the peer from management service (if connected)
|
||||
]]>
|
||||
</description>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<custom_php_after_head_command>
|
||||
<![CDATA[netbird_display_connection_info();]]>
|
||||
</custom_php_after_head_command>
|
||||
<custom_php_validation_command>
|
||||
<![CDATA[netbird_auth_validate_input($_POST, $input_errors);]]>
|
||||
</custom_php_validation_command>
|
||||
<custom_php_resync_config_command>
|
||||
<![CDATA[netbird_auth_apply_config();]]>
|
||||
</custom_php_resync_config_command>
|
||||
</packagegui>
|
||||
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
/*
|
||||
* netbird_status.inc
|
||||
*
|
||||
* part of pfSense (https://www.pfsense.org)
|
||||
* Copyright (c) 2022-2025 Rubicon Communications, LLC (Netgate)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
require_once('vendor/autoload.php');
|
||||
|
||||
use Nette\Utils\Html;
|
||||
|
||||
require_once('netbird/netbird.inc');
|
||||
|
||||
function netbird_get_pkg_info(array $field_map, array $packages)
|
||||
{
|
||||
$delimiter = "\t";
|
||||
$format = implode($delimiter, $field_map);
|
||||
$package_list = implode(' ', $packages);
|
||||
|
||||
$cmd = implode(' ', [PKG_BIN, 'query', escapeshellarg($format), $package_list]);
|
||||
exec($cmd, $out, $result_code);
|
||||
|
||||
if ($result_code !== 0 || empty($out)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$return_keys = array_values(array_flip($field_map));
|
||||
foreach ($out as $row_idx => $row_string){
|
||||
foreach (explode($delimiter, $row_string) as $field_idx => $field_string){
|
||||
$result[$row_idx][$return_keys[$field_idx]] = $field_string;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function netbird_display_peer_connection_status()
|
||||
{
|
||||
$summary = netbird_get_peer_connection_status();
|
||||
echo netbird_render_status_html_table('Connection Status', $summary);
|
||||
}
|
||||
|
||||
function netbird_display_peers_details_status(): void
|
||||
{
|
||||
$status = netbird_get_status();
|
||||
$peers = $status['peers'] ?? [];
|
||||
|
||||
$summary = netbird_get_peers_detail(
|
||||
$peers,
|
||||
$status['quantumResistance'] ?? false,
|
||||
$status['quantumResistancePermissive'] ?? false
|
||||
);
|
||||
echo netbird_render_status_html_table('Peers Detail', $summary);
|
||||
}
|
||||
|
||||
function netbird_render_status_html_table(string $name, string $summary): string
|
||||
{
|
||||
$table = Html::el('table')
|
||||
->class('table table-hover table-condensed')->addHtml(
|
||||
Html::el('tbody')->addHtml(
|
||||
Html::el('tr')->addHtml(
|
||||
Html::el('td')->addHtml(
|
||||
Html::el('h5')->addHtml(
|
||||
Html::el('a')->setText($name)
|
||||
)
|
||||
)
|
||||
)
|
||||
)->addHtml(Html::el('tr')->addHtml(
|
||||
Html::el('td')->addHtml(
|
||||
Html::el('pre')->addAttributes([
|
||||
'style' => 'max-height: 500px; overflow-y: auto;'
|
||||
])->setText($summary)
|
||||
)
|
||||
))
|
||||
);
|
||||
|
||||
return $table->toHtml();
|
||||
}
|
||||
|
||||
function netbird_get_peer_connection_status(): string
|
||||
{
|
||||
$status = netbird_get_status();
|
||||
if (!$status) {
|
||||
return 'No status available.';
|
||||
}
|
||||
|
||||
// Management
|
||||
$management = $status['management'] ?? [];
|
||||
if (!empty($management['connected'])) {
|
||||
$management_str = "Connected";
|
||||
if (!empty($management['url'])) {
|
||||
$management_str .= " to {$management['url']}";
|
||||
}
|
||||
} else {
|
||||
$management_str = "Disconnected";
|
||||
if (!empty($management['error'])) {
|
||||
$management_str .= ", reason: {$management['error']}";
|
||||
}
|
||||
}
|
||||
|
||||
// Signal
|
||||
$signal = $status['signal'] ?? [];
|
||||
if (!empty($signal['connected'])) {
|
||||
$signal_str = "Connected";
|
||||
if (!empty($signal['url'])) {
|
||||
$signal_str .= " to {$signal['url']}";
|
||||
}
|
||||
} else {
|
||||
$signal_str = "Disconnected";
|
||||
if (!empty($signal['error'])) {
|
||||
$signal_str .= ", reason: {$signal['error']}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Interface
|
||||
$interface_type = !empty($status['kernelInterface']) ? "Kernel" : "Userspace";
|
||||
$interface_ip = $status['netbirdIp'] ?? 'N/A';
|
||||
if (empty($interface_ip)) {
|
||||
$interface_type = "N/A";
|
||||
$interface_ip = "N/A";
|
||||
}
|
||||
|
||||
// Relays
|
||||
$relays_str = '';
|
||||
if (!empty($status['relays']['details'])) {
|
||||
foreach ($status['relays']['details'] as $relay) {
|
||||
$available = !empty($relay['available']) ? "Available" : "Unavailable";
|
||||
$reason = !empty($relay['error']) ? ", reason: {$relay['error']}" : "";
|
||||
$relays_str .= "\n [{$relay['uri']}] is {$available}{$reason}";
|
||||
}
|
||||
} else {
|
||||
$relays_str = sprintf("%d/%d Available", $status['relays']['available'] ?? 0, $status['relays']['total'] ?? 0);
|
||||
}
|
||||
|
||||
// DNS/Nameservers
|
||||
$dnsStr = '';
|
||||
if (!empty($status['dnsServers'])) {
|
||||
foreach ($status['dnsServers'] as $group) {
|
||||
$enabled = !empty($group['enabled']) ? "Available" : "Unavailable";
|
||||
$reason = !empty($group['error']) ? ", reason: {$group['error']}" : "";
|
||||
$domains = !empty($group['domains']) ? implode(", ", $group['domains']) : ".";
|
||||
$servers = implode(", ", $group['servers']);
|
||||
$dnsStr .= "\n [{$servers}] for [{$domains}] is {$enabled}{$reason}";
|
||||
}
|
||||
} else {
|
||||
$enabled_dns_count = 0;
|
||||
foreach ($status['dnsServers'] ?? [] as $group) {
|
||||
if (!empty($group['enabled'])) {
|
||||
$enabled_dns_count++;
|
||||
}
|
||||
}
|
||||
$dnsStr = sprintf("%d/%d Available", $enabled_dns_count, count($status['dnsServers'] ?? []));
|
||||
}
|
||||
|
||||
// Quantum resistance
|
||||
$quantum = "false";
|
||||
if (!empty($status['rosenpassEnabled'])) {
|
||||
$quantum = "true" . (!empty($status['rosenpassPermissive']) ? " (permissive)" : "");
|
||||
}
|
||||
|
||||
// Lazy connection
|
||||
$lazy = !empty($status['lazyConnectionEnabled']) ? "true" : "false";
|
||||
|
||||
// Networks
|
||||
$networks = !empty($status['networks']) ? implode(", ", $status['networks']) : "-";
|
||||
|
||||
// Peers
|
||||
$peers_count = sprintf("%d/%d Connected", $status['peers']['connected'] ?? 0, $status['peers']['total'] ?? 0);
|
||||
|
||||
|
||||
$info_lines = [
|
||||
'Daemon version' => $status['daemonVersion'],
|
||||
'CLI version' => $status['cliVersion'],
|
||||
'Management' => $management_str,
|
||||
'Signal' => $signal_str,
|
||||
'Relays' => $relays_str,
|
||||
'Nameservers' => $dnsStr,
|
||||
'FQDN' => $status['fqdn'],
|
||||
'NetBird IP' => $interface_ip,
|
||||
'Interface type' => $interface_type,
|
||||
'Quantum resistance' => $quantum,
|
||||
'Lazy connection' => $lazy,
|
||||
'Networks' => $networks,
|
||||
'Forwarding rules' => $status['forwardingRules'],
|
||||
'Peers count' => $peers_count,
|
||||
];
|
||||
|
||||
$lines = [];
|
||||
foreach ($info_lines as $key => $value) {
|
||||
$lines[] = "{$key}: {$value}";
|
||||
}
|
||||
|
||||
return implode("\n", $lines);
|
||||
}
|
||||
|
||||
function netbird_get_peers_detail(array $peers, bool $rosenpass_enabled, bool $rosenpass_permissive): string {
|
||||
$peers_str = '';
|
||||
|
||||
$details = !empty($peers['details']) ? $peers['details'] : [];
|
||||
foreach ($details as $peer_state) {
|
||||
$local_ice = !empty($peer_state['iceCandidateType']['local']) ? $peer_state['iceCandidateType']['local'] : '-';
|
||||
$remote_ice = !empty($peer_state['iceCandidateType']['remote']) ? $peer_state['iceCandidateType']['remote'] : '-';
|
||||
|
||||
$local_ice_endpoint = !empty($peer_state['iceCandidateType']['local']) ? $peer_state['iceCandidateType']['local'] : '-';
|
||||
$remote_ice_endpoint = !empty($peer_state['iceCandidateType']['remote']) ? $peer_state['iceCandidateType']['remote'] : '-';
|
||||
|
||||
$rosenpass_enabled_status = 'false';
|
||||
if ($rosenpass_enabled) {
|
||||
if (!empty($peer_state['quantumResistance'])) {
|
||||
$rosenpass_enabled_status = 'true';
|
||||
} else {
|
||||
if ($rosenpass_permissive) {
|
||||
$rosenpass_enabled_status = "false (remote didn't enable quantum resistance)";
|
||||
} else {
|
||||
$rosenpass_enabled_status = "false (connection won't work without a permissive mode)";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!empty($peer_state['quantumResistance'])) {
|
||||
$rosenpass_enabled_status = "false (connection might not work without a remote permissive mode)";
|
||||
}
|
||||
}
|
||||
|
||||
$networks = '-';
|
||||
if (!empty($peer_state['networks']) && is_array($peer_state['networks'])) {
|
||||
sort($peer_state['networks']);
|
||||
$networks = implode(', ', $peer_state['networks']);
|
||||
}
|
||||
|
||||
$lastStatus_update = (!empty($peer_state['lastStatus_update'])) ? new DateTimeImmutable($peer_state['lastStatus_update']) : new DateTimeImmutable('@0');
|
||||
$last_wireguard_handshake = (!empty($peer_state['lastStatus_update'])) ? new DateTimeImmutable($peer_state['lastStatus_update']) : new DateTimeImmutable('@0');
|
||||
|
||||
$latency = isset($peer_state['latency']) ? floatval($peer_state['latency']) / 1_000_000 . ' ms' : '-';
|
||||
|
||||
$peer_str = sprintf(
|
||||
"\n %s:\n".
|
||||
" NetBird IP: %s\n".
|
||||
" Public key: %s\n".
|
||||
" Status: %s\n".
|
||||
" -- detail --\n".
|
||||
" Connection type: %s\n".
|
||||
" ICE candidate (Local/Remote): %s/%s\n".
|
||||
" ICE candidate endpoints (Local/Remote): %s/%s\n".
|
||||
" Relay server address: %s\n".
|
||||
" Last connection update: %s\n".
|
||||
" Last WireGuard handshake: %s\n".
|
||||
" Transfer status (received/sent) %s/%s\n".
|
||||
" Quantum resistance: %s\n".
|
||||
" Networks: %s\n".
|
||||
" Latency: %s\n",
|
||||
// FQDN safe string fallback
|
||||
$peer_state['fqdn'],
|
||||
$peer_state['netbirdIp'],
|
||||
$peer_state['publicKey'] ,
|
||||
$peer_state['status'],
|
||||
$peer_state['connectionType'] ?? '-',
|
||||
$local_ice,
|
||||
$remote_ice,
|
||||
$local_ice_endpoint,
|
||||
$remote_ice_endpoint,
|
||||
$peer_state['relayAddress'] ?? '-',
|
||||
netbird_get_elapsed_time($lastStatus_update),
|
||||
netbird_get_elapsed_time($last_wireguard_handshake),
|
||||
netbird_format_bytes((int)($peer_state['transferReceived'] ?? 0)),
|
||||
netbird_format_bytes((int)($peer_state['transferSent'] ?? 0)),
|
||||
$rosenpass_enabled_status,
|
||||
$networks,
|
||||
$latency
|
||||
);
|
||||
|
||||
$peers_str .= $peer_str;
|
||||
}
|
||||
|
||||
return $peers_str;
|
||||
}
|
||||
|
||||
function netbird_get_elapsed_time(DateTimeInterface $dt): string {
|
||||
if ($dt->getTimestamp() === 0) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$units = ['y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second'];
|
||||
$diff = (new DateTimeImmutable())->diff($dt);
|
||||
|
||||
foreach ($units as $key => $label) {
|
||||
$value = $diff->$key;
|
||||
if ($value > 0) {
|
||||
return "$value $label" . ($value > 1 ? 's' : '') . " ago";
|
||||
}
|
||||
}
|
||||
|
||||
return 'Now';
|
||||
}
|
||||
|
||||
function netbird_format_bytes(int $bytes): string {
|
||||
$unit = 1024;
|
||||
|
||||
if ($bytes < $unit) {
|
||||
return $bytes . ' B';
|
||||
}
|
||||
|
||||
$units = ['Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei'];
|
||||
$exp = (int) (log($bytes) / log($unit));
|
||||
$prefix = $units[$exp - 1];
|
||||
$value = $bytes / ($unit ** $exp);
|
||||
|
||||
return sprintf('%.1f %sB', $value, $prefix);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<pfsensepkgs>
|
||||
<package>
|
||||
<name>NetBird</name>
|
||||
<descr><![CDATA[NetBird is an open-source WireGuard-based overlay network combined with Zero Trust Network Access,
|
||||
providing secure and reliable connectivity to internal resources.]]></descr>
|
||||
<website>https://netbird.io/</website>
|
||||
<pkginfolink>https://github.com/netbirdio/netbird</pkginfolink>
|
||||
<version>%%PKGVERSION%%</version>
|
||||
<configurationfile>netbird.xml</configurationfile>
|
||||
</package>
|
||||
</pfsensepkgs>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/*
|
||||
* netbird_status.php
|
||||
*
|
||||
* part of pfSense (https://www.pfsense.org)
|
||||
* Copyright (c) 2022-2025 Rubicon Communications, LLC (Netgate)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
require_once('guiconfig.inc');
|
||||
require_once('util.inc');
|
||||
require_once('netbird/netbird_status.inc');
|
||||
|
||||
$tabs = [
|
||||
[gettext('Authentication'), false, 'pkg_edit.php?xml=netbird/netbird_auth.xml'],
|
||||
[gettext('Settings'), false, 'pkg_edit.php?xml=netbird.xml'],
|
||||
[gettext('Status'), true, '/netbird_status.php'],
|
||||
];
|
||||
$pgtitle = [gettext('Status'), gettext('NetBird')];
|
||||
$pglinks = ['', '@self'];
|
||||
$field_map = ['name' => '%n', 'version' => '%v', 'comment' => '%c'];
|
||||
$packages = ['pfSense-pkg-netBird', 'netbird'];
|
||||
|
||||
include('head.inc');
|
||||
|
||||
netbird_display_connection_info();
|
||||
|
||||
display_top_tabs($tabs);
|
||||
|
||||
if (netbird_is_running()):
|
||||
?>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title"><?= gettext("NetBird Status") ?>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<?php netbird_display_peer_connection_status(); ?>
|
||||
<?php
|
||||
if (netbird_is_connected()){
|
||||
netbird_display_peers_details_status();
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title"><?=gettext('Package Versions')?></h2>
|
||||
</div>
|
||||
<div class="table-responsive panel-body">
|
||||
<table class="table table-hover table-striped table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?=gettext('Name')?></th>
|
||||
<th><?=gettext('Version')?></th>
|
||||
<th><?=gettext('Comment')?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach (netbird_get_pkg_info($field_map, $packages) as $package): ?>
|
||||
<tr>
|
||||
<td><?=htmlspecialchars($package['name'])?></td>
|
||||
<td><?=htmlspecialchars($package['version'])?></td>
|
||||
<td><?=htmlspecialchars($package['comment'])?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
include('foot.inc');
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
PORTNAME= pfSense-pkg-NetBird
|
||||
PORTVERSION= 0.1.0
|
||||
CATEGORIES= security
|
||||
MASTER_SITES= # empty
|
||||
DISTFILES= # empty
|
||||
EXTRACT_ONLY= # empty
|
||||
|
||||
MAINTAINER= dev@netbird.io
|
||||
COMMENT= pfSense package NetBird
|
||||
|
||||
LICENSE= APACHE20
|
||||
|
||||
RUN_DEPENDS= netbird>0:security/netbird
|
||||
|
||||
NO_ARCH= yes
|
||||
NO_BUILD= yes
|
||||
NO_MTREE= yes
|
||||
|
||||
SUB_FILES= pkg-install pkg-deinstall
|
||||
SUB_LIST= PORTNAME=${PORTNAME}
|
||||
|
||||
do-extract:
|
||||
${MKDIR} ${WRKSRC}
|
||||
|
||||
do-install:
|
||||
${MKDIR} ${STAGEDIR}${DATADIR}
|
||||
${MKDIR} ${STAGEDIR}${PREFIX}/pkg/netbird
|
||||
${MKDIR} ${STAGEDIR}${PREFIX}/www
|
||||
|
||||
${INSTALL_DATA} ${FILESDIR}${DATADIR}/info.xml \
|
||||
${STAGEDIR}${DATADIR}
|
||||
|
||||
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/*.xml \
|
||||
${STAGEDIR}${PREFIX}/pkg
|
||||
|
||||
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/netbird/*.inc \
|
||||
${STAGEDIR}${PREFIX}/pkg/netbird
|
||||
|
||||
${INSTALL_DATA} ${FILESDIR}${PREFIX}/pkg/netbird/*.xml \
|
||||
${STAGEDIR}${PREFIX}/pkg/netbird
|
||||
|
||||
${INSTALL_DATA} ${FILESDIR}${PREFIX}/www/*.php \
|
||||
${STAGEDIR}${PREFIX}/www
|
||||
|
||||
@${REINPLACE_CMD} -i '' -e "s|%%PKGVERSION%%|${PKGVERSION}|" \
|
||||
${STAGEDIR}${DATADIR}/info.xml \
|
||||
${STAGEDIR}${PREFIX}/pkg/netbird.xml \
|
||||
${STAGEDIR}${PREFIX}/pkg/netbird/netbird_auth.xml
|
||||
|
||||
.include <bsd.port.mk>
|
||||
@@ -0,0 +1,5 @@
|
||||
NetBird is an open-source WireGuard-based overlay network combined with
|
||||
Zero Trust Network Access, providing secure and reliable connectivity
|
||||
to internal resources.
|
||||
|
||||
WWW: https://netbird.io
|
||||
@@ -0,0 +1,7 @@
|
||||
pkg/netbird.xml
|
||||
pkg/netbird/netbird.inc
|
||||
pkg/netbird/netbird_status.inc
|
||||
pkg/netbird/netbird_auth.inc
|
||||
pkg/netbird/netbird_auth.xml
|
||||
%%DATADIR%%/info.xml
|
||||
www/netbird_status.php
|
||||
Reference in New Issue
Block a user