Add NetBird package

This commit is contained in:
bcmmbaga
2025-06-26 00:10:53 +03:00
parent 167a4bd686
commit 840498a1ea
18 changed files with 1159 additions and 1 deletions
+35 -1
View File
@@ -1 +1,35 @@
# pfsense-netbird
# NetBird Package for pfSense
![My Logo](assets/netbird.png)
## 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

+30
View File
@@ -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>
+18
View File
@@ -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"
+18
View File
@@ -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
+11
View File
@@ -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}
+7
View File
@@ -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');
+50
View File
@@ -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>
+5
View File
@@ -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
+7
View File
@@ -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