mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-22 21:39:08 +02:00
Merge remote-tracking branch 'origin/main' into feat-post_quantum_ml_kem
# Conflicts: # .github/workflows/wasm-build-validation.yml
This commit is contained in:
@@ -34,7 +34,7 @@ jobs:
|
||||
while IFS= read -r dir; do
|
||||
echo "=== Checking $dir ==="
|
||||
# Search for problematic imports, excluding test files
|
||||
RESULTS=$(grep -r "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\)" "$dir" --include="*.go" 2>/dev/null | grep -v "_test.go" | grep -v "test_" | grep -v "/test/" | grep -v "tools/idp-migrate/" | grep -v "tools/mysql-migrate/" || true)
|
||||
RESULTS=$(grep -r "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\)" "$dir" --include="*.go" 2>/dev/null | grep -v "_test.go" | grep -v "test_" | grep -v "/test/" | grep -v "tools/idp-migrate/" || true)
|
||||
if [ -n "$RESULTS" ]; then
|
||||
echo "❌ Found problematic dependencies:"
|
||||
echo "$RESULTS"
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
IMPORTERS=$(go list -json -deps ./... 2>/dev/null | jq -r "select(.Imports[]? == \"$package\") | .ImportPath")
|
||||
|
||||
# Check if any importer is NOT in management/signal/relay
|
||||
BSD_IMPORTER=$(echo "$IMPORTERS" | grep -v "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\|combined\|tools/idp-migrate\|tools/mysql-migrate\)" | head -1)
|
||||
BSD_IMPORTER=$(echo "$IMPORTERS" | grep -v "github.com/netbirdio/netbird/\(management\|signal\|relay\|proxy\|combined\|tools/idp-migrate\)" | head -1)
|
||||
|
||||
if [ -n "$BSD_IMPORTER" ]; then
|
||||
echo "❌ $package ($license) is imported by BSD-licensed code: $BSD_IMPORTER"
|
||||
|
||||
@@ -3,9 +3,16 @@ name: Post release topic on Discourse
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_run:
|
||||
workflows: [Release]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
post:
|
||||
if: github.event_name == 'release'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: roots/discourse-topic-github-release-action@557d74ea05b6cc0c47f555c1d5d28a89d904005b # v1.1.0
|
||||
@@ -15,3 +22,78 @@ jobs:
|
||||
discourse-author-username: NetBird
|
||||
discourse-category: 17
|
||||
discourse-tags: releases
|
||||
|
||||
# goreleaser publishes the release of a pushed tag with GITHUB_TOKEN, and events
|
||||
# raised by that token start no workflow, so the release event above never fires.
|
||||
post-tag-release:
|
||||
if: >-
|
||||
github.event_name == 'workflow_run' &&
|
||||
github.event.workflow_run.event == 'push' &&
|
||||
github.event.workflow_run.conclusion == 'success' &&
|
||||
startsWith(github.event.workflow_run.head_branch, 'v') &&
|
||||
!contains(github.event.workflow_run.head_branch, '-')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Post the release topic
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ github.event.workflow_run.head_branch }}
|
||||
DISCOURSE_API_KEY: ${{ secrets.DISCOURSE_RELEASES_API_KEY }}
|
||||
DISCOURSE_URL: https://forum.netbird.io
|
||||
DISCOURSE_USER: NetBird
|
||||
DISCOURSE_CATEGORY: "17"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if ! release=$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" 2>gh.err); then
|
||||
if grep -q 'HTTP 404' gh.err; then
|
||||
echo "no release for ${TAG}, nothing to announce"
|
||||
exit 0
|
||||
fi
|
||||
cat gh.err >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# A release a person published already fired the release event above.
|
||||
author=$(jq -r '.author.login' <<<"$release")
|
||||
if [ "$author" != "github-actions[bot]" ] || [ "$(jq -r '.draft' <<<"$release")" = "true" ]; then
|
||||
echo "${TAG} published by ${author}, announced by the release event"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Same title and body as the action above, so both paths read alike.
|
||||
title="${GITHUB_REPOSITORY#*/} ${TAG} released"
|
||||
|
||||
# A re-run of a successful Release run fires this event again. A failed lookup
|
||||
# stops the step rather than risk a duplicate topic.
|
||||
search=$(curl -fsS --retry 3 --proto '=https' --proto-redir '=https' -G \
|
||||
-H "Api-Key: ${DISCOURSE_API_KEY}" \
|
||||
-H "Api-Username: ${DISCOURSE_USER}" \
|
||||
"${DISCOURSE_URL}/search.json" \
|
||||
--data-urlencode "q=\"${title}\" in:title")
|
||||
existing=$(jq -r --arg t "$title" --argjson c "$DISCOURSE_CATEGORY" \
|
||||
'[(.topics // [])[] | select(.category_id == $c and (.title | ascii_downcase) == ($t | ascii_downcase))] | length' \
|
||||
<<<"$search")
|
||||
if [ "$existing" != "0" ]; then
|
||||
echo "topic '${title}' already exists"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# goreleaser leaves the body empty; the notes are written on the release page afterwards.
|
||||
url=$(jq -r '.html_url' <<<"$release")
|
||||
body=$(jq -r '.body // ""' <<<"$release")
|
||||
if [ -z "${body//[[:space:]]/}" ]; then
|
||||
body="Release notes and downloads: ${url}"
|
||||
fi
|
||||
|
||||
jq -n \
|
||||
--arg title "$title" \
|
||||
--arg raw "$(printf '[%s](%s)\n\n%s' "$title" "$url" "$body")" \
|
||||
--argjson category "$DISCOURSE_CATEGORY" \
|
||||
'{title: $title, raw: $raw, category: $category, tags: ["releases"]}' \
|
||||
| curl -fsS -X POST "${DISCOURSE_URL}/posts.json" \
|
||||
-H "Api-Key: ${DISCOURSE_API_KEY}" \
|
||||
-H "Api-Username: ${DISCOURSE_USER}" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data @- \
|
||||
| jq -r '"posted \(env.DISCOURSE_URL)/t/\(.topic_slug)/\(.topic_id)"'
|
||||
|
||||
@@ -307,7 +307,7 @@ jobs:
|
||||
sh -c ' \
|
||||
apk update; apk add --no-cache \
|
||||
ca-certificates iptables ip6tables dbus dbus-dev libpcap-dev build-base; \
|
||||
go test -buildvcs=false -tags "devcert privileged" -v -timeout 10m -p 1 $(go list -e -buildvcs=false ./... | grep -v -e /management -e /signal -e /relay -e /proxy -e /combined -e /client/ui -e /upload-server -e /client/testutil/privileged -e tools/mysql-migrate)
|
||||
go test -buildvcs=false -tags "devcert privileged" -v -timeout 10m -p 1 $(go list -e -buildvcs=false ./... | grep -v -e /management -e /signal -e /relay -e /proxy -e /combined -e /client/ui -e /upload-server -e /client/testutil/privileged)
|
||||
'
|
||||
|
||||
test_relay:
|
||||
@@ -498,7 +498,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: ["amd64"]
|
||||
store: ["sqlite", "postgres", "mysql"]
|
||||
store: ["sqlite", "postgres"]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
@@ -547,10 +547,6 @@ jobs:
|
||||
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
|
||||
run: echo "$DOCKER_TOKEN" | sudo docker login --username "$DOCKER_USER" --password-stdin
|
||||
|
||||
- name: download mysql image
|
||||
if: matrix.store == 'mysql'
|
||||
run: docker pull mlsmaycon/warmed-mysql:8
|
||||
|
||||
# The -json stream goes through tools/gotestsummary so the log shows one
|
||||
# line per test, the output of failed tests, the head of a timeout panic
|
||||
# with the still-running tests, and the slowest tests per package.
|
||||
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
# resolve; the Where-Object pipeline then drops the broken package by
|
||||
# path. Without -e, go list aborts with empty stdout.
|
||||
run: |
|
||||
$packages = go list -e ./... | Where-Object { $_ -notmatch '/management' } | Where-Object { $_ -notmatch '/relay' } | Where-Object { $_ -notmatch '/signal' } | Where-Object { $_ -notmatch '/proxy' } | Where-Object { $_ -notmatch '/combined' } | Where-Object { $_ -notmatch '/client/ui$' } | Where-Object { $_ -notmatch '/tools/mysql-migrate' }
|
||||
$packages = go list -e ./... | Where-Object { $_ -notmatch '/management' } | Where-Object { $_ -notmatch '/relay' } | Where-Object { $_ -notmatch '/signal' } | Where-Object { $_ -notmatch '/proxy' } | Where-Object { $_ -notmatch '/combined' } | Where-Object { $_ -notmatch '/client/ui$' }
|
||||
$goExe = "C:\hostedtoolcache\windows\go\${{ steps.go.outputs.go-version }}\x64\bin\go.exe"
|
||||
$cmd = "$goExe test -tags `"devcert privileged`" -timeout 10m -p 1 $($packages -join ' ') > test-out.txt 2>&1"
|
||||
Set-Content -Path "${{ github.workspace }}\run-tests.cmd" -Value $cmd
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
store: ["sqlite", "postgres", "mysql"]
|
||||
store: ["sqlite", "postgres"]
|
||||
services:
|
||||
postgres:
|
||||
image: ${{ (matrix.store == 'postgres') && 'postgres' || '' }}
|
||||
@@ -35,19 +35,6 @@ jobs:
|
||||
--health-timeout 5s
|
||||
ports:
|
||||
- 5432:5432
|
||||
mysql:
|
||||
image: ${{ (matrix.store == 'mysql') && 'mysql' || '' }}
|
||||
env:
|
||||
MYSQL_USER: netbird
|
||||
MYSQL_PASSWORD: mysql
|
||||
MYSQL_ROOT_PASSWORD: mysqlroot
|
||||
MYSQL_DATABASE: netbird
|
||||
options: >-
|
||||
--health-cmd "mysqladmin ping --silent"
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
ports:
|
||||
- 3306:3306
|
||||
steps:
|
||||
- name: Set Database Connection String
|
||||
run: |
|
||||
@@ -56,11 +43,6 @@ jobs:
|
||||
else
|
||||
echo "NETBIRD_STORE_ENGINE_POSTGRES_DSN==" >> $GITHUB_ENV
|
||||
fi
|
||||
if [ "${{ matrix.store }}" == "mysql" ]; then
|
||||
echo "NETBIRD_STORE_ENGINE_MYSQL_DSN=netbird:mysql@tcp($(hostname -I | awk '{print $1}'):3306)/netbird" >> $GITHUB_ENV
|
||||
else
|
||||
echo "NETBIRD_STORE_ENGINE_MYSQL_DSN==" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Install jq
|
||||
run: sudo apt-get install -y jq
|
||||
@@ -86,15 +68,6 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-
|
||||
|
||||
- name: Setup MySQL privileges
|
||||
if: matrix.store == 'mysql'
|
||||
run: |
|
||||
sleep 10
|
||||
mysql -h 127.0.0.1 -u root -pmysqlroot -e "
|
||||
GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO 'netbird'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
"
|
||||
|
||||
- name: cp setup.env
|
||||
run: cp infrastructure_files/tests/setup.env infrastructure_files/
|
||||
|
||||
@@ -114,7 +87,6 @@ jobs:
|
||||
CI_NETBIRD_AUTH_SUPPORTED_SCOPES: "openid profile email offline_access api email_verified"
|
||||
CI_NETBIRD_STORE_CONFIG_ENGINE: ${{ matrix.store }}
|
||||
NETBIRD_STORE_ENGINE_POSTGRES_DSN: ${{ env.NETBIRD_STORE_ENGINE_POSTGRES_DSN }}
|
||||
NETBIRD_STORE_ENGINE_MYSQL_DSN: ${{ env.NETBIRD_STORE_ENGINE_MYSQL_DSN }}
|
||||
CI_NETBIRD_MGMT_IDP_SIGNKEY_REFRESH: false
|
||||
|
||||
- name: check values
|
||||
@@ -143,7 +115,6 @@ jobs:
|
||||
CI_NETBIRD_SIGNAL_PORT: 12345
|
||||
CI_NETBIRD_STORE_CONFIG_ENGINE: ${{ matrix.store }}
|
||||
NETBIRD_STORE_ENGINE_POSTGRES_DSN: "${{ env.NETBIRD_STORE_ENGINE_POSTGRES_DSN }}$"
|
||||
NETBIRD_STORE_ENGINE_MYSQL_DSN: "${{ env.NETBIRD_STORE_ENGINE_MYSQL_DSN }}$"
|
||||
CI_NETBIRD_MGMT_IDP_SIGNKEY_REFRESH: false
|
||||
CI_NETBIRD_TURN_EXTERNAL_IP: "1.2.3.4"
|
||||
CI_NETBIRD_MGMT_DISABLE_DEFAULT_POLICY: false
|
||||
@@ -182,7 +153,6 @@ jobs:
|
||||
grep -A 10 PKCEAuthorizationFlow management.json | grep -A 10 ProviderConfig | grep Scope | grep "$CI_NETBIRD_AUTH_SUPPORTED_SCOPES"
|
||||
grep -A 10 PKCEAuthorizationFlow management.json | grep -A 10 ProviderConfig | grep -A 3 RedirectURLs | grep "http://localhost:53000"
|
||||
grep "external-ip" turnserver.conf | grep $CI_NETBIRD_TURN_EXTERNAL_IP
|
||||
grep "NETBIRD_STORE_ENGINE_MYSQL_DSN=$NETBIRD_STORE_ENGINE_MYSQL_DSN" docker-compose.yml
|
||||
grep NETBIRD_STORE_ENGINE_POSTGRES_DSN docker-compose.yml | egrep "$NETBIRD_STORE_ENGINE_POSTGRES_DSN"
|
||||
# check relay values
|
||||
grep "NB_EXPOSED_ADDRESS=rels://$CI_NETBIRD_DOMAIN:33445" docker-compose.yml
|
||||
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
|
||||
echo "Size: ${SIZE} bytes (${SIZE_MB} MB)"
|
||||
|
||||
if [ ${SIZE} -gt 67108864 ]; then
|
||||
echo "Wasm binary size (${SIZE_MB}MB) exceeds 64MB limit!"
|
||||
if [ ${SIZE} -gt 73400320 ]; then
|
||||
echo "Wasm binary size (${SIZE_MB}MB) exceeds 70MB limit!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -280,28 +280,6 @@ builds:
|
||||
- -s -w -X github.com/netbirdio/netbird/version.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
|
||||
- id: netbird-mysql-migrate
|
||||
dir: tools/mysql-migrate
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
- >-
|
||||
{{- if eq .Runtime.Goos "linux" }}
|
||||
{{- if eq .Arch "arm64"}}CC=aarch64-linux-gnu-gcc{{- end }}
|
||||
{{- if eq .Arch "arm"}}CC=arm-linux-gnueabihf-gcc{{- end }}
|
||||
{{- end }}
|
||||
binary: netbird-mysql-migrate
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- arm
|
||||
goarm:
|
||||
- 7
|
||||
ldflags:
|
||||
- -s -w -X github.com/netbirdio/netbird/version.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} -X main.builtBy=goreleaser
|
||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||
|
||||
universal_binaries:
|
||||
- id: netbird
|
||||
|
||||
@@ -318,10 +296,6 @@ archives:
|
||||
builds:
|
||||
- netbird-idp-migrate
|
||||
name_template: "netbird-idp-migrate_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
- id: netbird-mysql-migrate
|
||||
builds:
|
||||
- netbird-mysql-migrate
|
||||
name_template: "netbird-mysql-migrate_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
- id: nblink
|
||||
builds:
|
||||
- nblink
|
||||
|
||||
@@ -58,23 +58,17 @@ func (p *Preferences) SetManagementURL(url string) {
|
||||
p.configInput.ManagementURL = url
|
||||
}
|
||||
|
||||
// GetAdminURL reads URL from config file
|
||||
// GetAdminURL returns the default admin panel URL.
|
||||
//
|
||||
// Deprecated: the admin URL is no longer stored or used by the client.
|
||||
func (p *Preferences) GetAdminURL() (string, error) {
|
||||
if p.configInput.AdminURL != "" {
|
||||
return p.configInput.AdminURL, nil
|
||||
}
|
||||
|
||||
cfg, err := profilemanager.ReadConfigOrDefault(p.configInput.ConfigPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cfg.AdminURL.String(), err
|
||||
return profilemanager.DefaultAdminURL, nil
|
||||
}
|
||||
|
||||
// SetAdminURL stores the given URL and waits for commit
|
||||
func (p *Preferences) SetAdminURL(url string) {
|
||||
p.configInput.AdminURL = url
|
||||
}
|
||||
// SetAdminURL is a no-op kept for API compatibility.
|
||||
//
|
||||
// Deprecated: the admin URL is no longer stored or used by the client.
|
||||
func (p *Preferences) SetAdminURL(_ string) {}
|
||||
|
||||
// HasPreSharedKey reports whether a pre-shared key is staged, persisted, or
|
||||
// enforced by MDM; the key itself is never handed to the native layer.
|
||||
|
||||
@@ -43,13 +43,14 @@ func TestPreferences_ReadUncommitedValues(t *testing.T) {
|
||||
cfgFile := filepath.Join(t.TempDir(), "netbird.json")
|
||||
p := NewPreferences(cfgFile)
|
||||
|
||||
// The admin URL is deprecated: setting it is a no-op.
|
||||
p.SetAdminURL(exampleString)
|
||||
resp, err := p.GetAdminURL()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read admin url: %s", err)
|
||||
}
|
||||
|
||||
if resp != exampleString {
|
||||
if resp != profilemanager.DefaultAdminURL {
|
||||
t.Errorf("unexpected admin url: %s", resp)
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ func TestPreferences_Commit(t *testing.T) {
|
||||
t.Fatalf("failed to read admin url: %s", err)
|
||||
}
|
||||
|
||||
if resp != exampleURL {
|
||||
if resp != profilemanager.DefaultAdminURL {
|
||||
t.Errorf("unexpected admin url: %s", resp)
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -157,7 +157,8 @@ func init() {
|
||||
|
||||
rootCmd.PersistentFlags().StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp|npipe]://[path|host:port|name]")
|
||||
rootCmd.PersistentFlags().StringVarP(&managementURL, "management-url", "m", "", fmt.Sprintf("Management Service URL [http|https]://[host]:[port] (default \"%s\")", profilemanager.DefaultManagementURL))
|
||||
rootCmd.PersistentFlags().StringVar(&adminURL, "admin-url", "", fmt.Sprintf("Admin Panel URL [http|https]://[host]:[port] (default \"%s\")", profilemanager.DefaultAdminURL))
|
||||
rootCmd.PersistentFlags().StringVar(&adminURL, "admin-url", "", "(DEPRECATED) Admin Panel URL - This flag is no longer functional")
|
||||
_ = rootCmd.PersistentFlags().MarkDeprecated("admin-url", "the admin-url flag is no longer functional and will be removed in a future version")
|
||||
rootCmd.PersistentFlags().StringVarP(&logLevel, "log-level", "l", "info", "sets NetBird log level")
|
||||
rootCmd.PersistentFlags().StringSliceVar(&logFiles, "log-file", []string{defaultLogFile}, "sets NetBird log paths written to simultaneously. If `console` is specified the log will be output to stdout. If `syslog` is specified the log will be sent to syslog daemon. You can pass the flag multiple times or separate entries by `,` character")
|
||||
rootCmd.PersistentFlags().StringVarP(&setupKey, "setup-key", "k", "", "Setup key obtained from the Management Service Dashboard (used to register peer)")
|
||||
|
||||
@@ -493,7 +493,6 @@ func setupSetConfigReq(customDNSAddressConverted []byte, cmd *cobra.Command, pro
|
||||
req.Username = username
|
||||
|
||||
req.ManagementUrl = managementURL
|
||||
req.AdminURL = adminURL
|
||||
req.NatExternalIPs = natExternalIPs
|
||||
req.CustomDNSAddress = customDNSAddressConverted
|
||||
req.ExtraIFaceBlacklist = extraIFaceBlackList
|
||||
|
||||
@@ -12,11 +12,10 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
wgnetstack "golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal"
|
||||
"github.com/netbirdio/netbird/client/internal/auth"
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
@@ -256,10 +255,10 @@ func New(opts Options) (*Client, error) {
|
||||
}
|
||||
|
||||
if opts.Performance.PreallocatedBuffersPerPool != nil {
|
||||
wgdevice.SetPreallocatedBuffersPerPool(*opts.Performance.PreallocatedBuffersPerPool)
|
||||
wgbackend.SetPreallocatedBuffersPerPool(*opts.Performance.PreallocatedBuffersPerPool)
|
||||
}
|
||||
if opts.Performance.MaxBatchSize != nil {
|
||||
wgdevice.SetMaxBatchSizeOverride(*opts.Performance.MaxBatchSize)
|
||||
wgbackend.SetMaxBatchSizeOverride(*opts.Performance.MaxBatchSize)
|
||||
}
|
||||
|
||||
return &Client{
|
||||
@@ -651,7 +650,7 @@ func (c *Client) getEngine() (*internal.Engine, error) {
|
||||
return engine, nil
|
||||
}
|
||||
|
||||
func (c *Client) getNet() (*wgnetstack.Net, netip.Addr, error) {
|
||||
func (c *Client) getNet() (*wgbackend.NetstackNet, netip.Addr, error) {
|
||||
engine, err := c.getEngine()
|
||||
if err != nil {
|
||||
return nil, netip.Addr{}, err
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// EnvForceUserspaceFirewall forces the use of the userspace packet filter even when
|
||||
@@ -20,5 +19,5 @@ type IFaceMapper interface {
|
||||
IsUserspaceBind() bool
|
||||
SetFilter(device.PacketFilter) error
|
||||
GetDevice() *device.FilteredDevice
|
||||
GetWGDevice() *wgdevice.Device
|
||||
GetWGDevice() *wgbackend.Device
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
log "github.com/sirupsen/logrus"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||
"github.com/netbirdio/netbird/client/firewall/firewalld"
|
||||
@@ -31,6 +30,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nbid "github.com/netbirdio/netbird/client/internal/acl/id"
|
||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||
@@ -121,7 +121,7 @@ type Iface interface {
|
||||
Name() string
|
||||
Address() wgaddr.Address
|
||||
SetFilter(device.PacketFilter) error
|
||||
GetWGDevice() *wgdevice.Device
|
||||
GetWGDevice() *wgbackend.Device
|
||||
}
|
||||
|
||||
// InterfaceAllower opens the NetBird interface in the host firewall so it
|
||||
|
||||
@@ -5,17 +5,17 @@ import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/stretchr/testify/require"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/mocks"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
)
|
||||
|
||||
@@ -791,10 +791,10 @@ func setupRoutedManager(tb testing.TB, network string) *Manager {
|
||||
}
|
||||
},
|
||||
GetDeviceFunc: func() *device.FilteredDevice {
|
||||
return &device.FilteredDevice{Device: dev}
|
||||
return &device.FilteredDevice{TUN: dev}
|
||||
},
|
||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
||||
return &wgdevice.Device{}
|
||||
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||
return &wgbackend.Device{}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@ import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/mocks"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// TestAddRouteFilteringReturnsExistingRule verifies that adding the same route
|
||||
@@ -180,10 +180,10 @@ func TestBlockInvalidRoutedDualStack(t *testing.T) {
|
||||
}
|
||||
},
|
||||
GetDeviceFunc: func() *device.FilteredDevice {
|
||||
return &device.FilteredDevice{Device: dev}
|
||||
return &device.FilteredDevice{TUN: dev}
|
||||
},
|
||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
||||
return &wgdevice.Device{}
|
||||
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||
return &wgbackend.Device{}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -228,10 +228,10 @@ func TestBlockInvalidRoutedIdempotent(t *testing.T) {
|
||||
}
|
||||
},
|
||||
GetDeviceFunc: func() *device.FilteredDevice {
|
||||
return &device.FilteredDevice{Device: dev}
|
||||
return &device.FilteredDevice{TUN: dev}
|
||||
},
|
||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
||||
return &wgdevice.Device{}
|
||||
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||
return &wgbackend.Device{}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -291,10 +291,10 @@ func TestBlockRuleNotAccumulatedOnRepeatedEnableRouting(t *testing.T) {
|
||||
}
|
||||
},
|
||||
GetDeviceFunc: func() *device.FilteredDevice {
|
||||
return &device.FilteredDevice{Device: dev}
|
||||
return &device.FilteredDevice{TUN: dev}
|
||||
},
|
||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
||||
return &wgdevice.Device{}
|
||||
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||
return &wgbackend.Device{}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -410,10 +410,10 @@ func setupTestManager(t *testing.T) *Manager {
|
||||
}
|
||||
},
|
||||
GetDeviceFunc: func() *device.FilteredDevice {
|
||||
return &device.FilteredDevice{Device: dev}
|
||||
return &device.FilteredDevice{TUN: dev}
|
||||
},
|
||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
||||
return &wgdevice.Device{}
|
||||
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||
return &wgbackend.Device{}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
||||
"github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack"
|
||||
@@ -22,6 +21,7 @@ import (
|
||||
nbiface "github.com/netbirdio/netbird/client/iface"
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/netflow"
|
||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
@@ -34,7 +34,7 @@ type IFaceMock struct {
|
||||
NameFunc func() string
|
||||
SetFilterFunc func(device.PacketFilter) error
|
||||
AddressFunc func() wgaddr.Address
|
||||
GetWGDeviceFunc func() *wgdevice.Device
|
||||
GetWGDeviceFunc func() *wgbackend.Device
|
||||
GetDeviceFunc func() *device.FilteredDevice
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (i *IFaceMock) Name() string {
|
||||
return i.NameFunc()
|
||||
}
|
||||
|
||||
func (i *IFaceMock) GetWGDevice() *wgdevice.Device {
|
||||
func (i *IFaceMock) GetWGDevice() *wgbackend.Device {
|
||||
if i.GetWGDeviceFunc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
|
||||
nblog "github.com/netbirdio/netbird/client/firewall/uspfilter/log"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// PacketCapture captures raw packets for debugging. Implementations must be
|
||||
@@ -23,7 +23,7 @@ type PacketCapture interface {
|
||||
type endpoint struct {
|
||||
logger *nblog.Logger
|
||||
dispatcher stack.NetworkDispatcher
|
||||
device *wgdevice.Device
|
||||
device *wgbackend.Device
|
||||
mtu atomic.Uint32
|
||||
capture atomic.Pointer[PacketCapture]
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"gvisor.dev/gvisor/pkg/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
@@ -26,6 +25,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack"
|
||||
nblog "github.com/netbirdio/netbird/client/firewall/uspfilter/log"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||
)
|
||||
|
||||
@@ -43,7 +43,7 @@ const (
|
||||
|
||||
// IFace provides the WireGuard device and overlay addresses the forwarder needs.
|
||||
type IFace interface {
|
||||
GetWGDevice() *wgdevice.Device
|
||||
GetWGDevice() *wgbackend.Device
|
||||
Address() wgaddr.Address
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package bind
|
||||
|
||||
import (
|
||||
wireguard "golang.zx2c4.com/wireguard/conn"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nbnet "github.com/netbirdio/netbird/client/net"
|
||||
)
|
||||
|
||||
@@ -10,6 +9,6 @@ import (
|
||||
func init() {
|
||||
listener := nbnet.NewListener()
|
||||
if listener.ListenConfig.Control != nil {
|
||||
*wireguard.ControlFns = append(*wireguard.ControlFns, listener.ListenConfig.Control)
|
||||
*wgbackend.ControlFns = append(*wgbackend.ControlFns, listener.ListenConfig.Control)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package bind
|
||||
import (
|
||||
"net"
|
||||
|
||||
wgConn "golang.zx2c4.com/wireguard/conn"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type Endpoint = wgConn.StdNetEndpoint
|
||||
type Endpoint = wgbackend.StdNetEndpoint
|
||||
|
||||
func EndpointToUDPAddr(e Endpoint) *net.UDPAddr {
|
||||
return &net.UDPAddr{
|
||||
|
||||
@@ -15,10 +15,10 @@ import (
|
||||
"github.com/pion/transport/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/ipv6"
|
||||
wgConn "golang.zx2c4.com/wireguard/conn"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nbnet "github.com/netbirdio/netbird/client/net"
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ type receiverCreator struct {
|
||||
iceBind *ICEBind
|
||||
}
|
||||
|
||||
func (rc receiverCreator) CreateReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxOffload bool, msgPool *sync.Pool) wgConn.ReceiveFunc {
|
||||
func (rc receiverCreator) CreateReceiverFn(pc wgbackend.BatchReader, conn *net.UDPConn, rxOffload bool, msgPool *sync.Pool) wgbackend.ReceiveFunc {
|
||||
return rc.iceBind.createReceiverFn(pc, conn, rxOffload, msgPool)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func (rc receiverCreator) CreateReceiverFn(pc wgConn.BatchReader, conn *net.UDPC
|
||||
// without port, in the format of 127.1.x.x where x.x is the last two octets of the peer address. We try to avoid to
|
||||
// use the port because in the Send function the wgConn.Endpoint the port info is not exported.
|
||||
type ICEBind struct {
|
||||
*wgConn.StdNetBind
|
||||
*wgbackend.StdNetBind
|
||||
|
||||
transportNet transport.Net
|
||||
address wgaddr.Address
|
||||
@@ -74,7 +74,7 @@ type ICEBind struct {
|
||||
}
|
||||
|
||||
func NewICEBind(transportNet transport.Net, address wgaddr.Address, mtu uint16) *ICEBind {
|
||||
b, _ := wgConn.NewStdNetBind().(*wgConn.StdNetBind)
|
||||
b, _ := wgbackend.NewStdNetBind().(*wgbackend.StdNetBind)
|
||||
ib := &ICEBind{
|
||||
StdNetBind: b,
|
||||
transportNet: transportNet,
|
||||
@@ -90,11 +90,11 @@ func NewICEBind(transportNet transport.Net, address wgaddr.Address, mtu uint16)
|
||||
rc := receiverCreator{
|
||||
ib,
|
||||
}
|
||||
ib.StdNetBind = wgConn.NewStdNetBindWithReceiverCreator(rc)
|
||||
ib.StdNetBind = wgbackend.NewStdNetBindWithReceiverCreator(rc)
|
||||
return ib
|
||||
}
|
||||
|
||||
func (s *ICEBind) Open(uport uint16) ([]wgConn.ReceiveFunc, uint16, error) {
|
||||
func (s *ICEBind) Open(uport uint16) ([]wgbackend.ReceiveFunc, uint16, error) {
|
||||
s.closedChanMu.Lock()
|
||||
defer s.closedChanMu.Unlock()
|
||||
|
||||
@@ -190,7 +190,7 @@ func (b *ICEBind) ReceiveFromEndpoint(ctx context.Context, ep *Endpoint, buf []b
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ICEBind) Send(bufs [][]byte, ep wgConn.Endpoint) error {
|
||||
func (b *ICEBind) Send(bufs [][]byte, ep wgbackend.Endpoint) error {
|
||||
b.endpointsMu.Lock()
|
||||
conn, ok := b.endpoints[ep.DstIP()]
|
||||
b.endpointsMu.Unlock()
|
||||
@@ -206,7 +206,7 @@ func (b *ICEBind) Send(bufs [][]byte, ep wgConn.Endpoint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxOffload bool, msgsPool *sync.Pool) wgConn.ReceiveFunc {
|
||||
func (s *ICEBind) createReceiverFn(pc wgbackend.BatchReader, conn *net.UDPConn, rxOffload bool, msgsPool *sync.Pool) wgbackend.ReceiveFunc {
|
||||
s.muUDPMux.Lock()
|
||||
defer s.muUDPMux.Unlock()
|
||||
|
||||
@@ -218,7 +218,7 @@ func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxO
|
||||
}
|
||||
s.createOrUpdateMux()
|
||||
|
||||
return func(bufs [][]byte, sizes []int, eps []wgConn.Endpoint) (n int, err error) {
|
||||
return func(bufs [][]byte, sizes []int, eps []wgbackend.Endpoint) (n int, err error) {
|
||||
msgs := getMessages(msgsPool)
|
||||
for i := range bufs {
|
||||
(*msgs)[i].Buffers[0] = bufs[i]
|
||||
@@ -229,13 +229,13 @@ func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxO
|
||||
var numMsgs int
|
||||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
||||
if rxOffload {
|
||||
readAt := len(*msgs) - (wgConn.IdealBatchSize / wgConn.UdpSegmentMaxDatagrams)
|
||||
readAt := len(*msgs) - (wgbackend.IdealBatchSize / wgbackend.UdpSegmentMaxDatagrams)
|
||||
//nolint:staticcheck
|
||||
_, err = pc.ReadBatch((*msgs)[readAt:], 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
numMsgs, err = wgConn.SplitCoalescedMessages(*msgs, readAt, wgConn.GetGSOSize)
|
||||
numMsgs, err = wgbackend.SplitCoalescedMessages(*msgs, readAt, wgbackend.GetGSOSize)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -278,8 +278,8 @@ func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxO
|
||||
s.activityRecorder.record(addrPort)
|
||||
}
|
||||
|
||||
ep := &wgConn.StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
|
||||
wgConn.GetSrcFromControl(msg.OOB[:msg.NN], ep)
|
||||
ep := &wgbackend.StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
|
||||
wgbackend.GetSrcFromControl(msg.OOB[:msg.NN], ep)
|
||||
eps[i] = ep
|
||||
}
|
||||
return numMsgs, nil
|
||||
@@ -363,7 +363,7 @@ func (s *ICEBind) parseSTUNMessage(raw []byte) (*stun.Message, error) {
|
||||
|
||||
// receiveRelayed is a receive function that is used to receive packets from the relayed connection and forward to the
|
||||
// WireGuard. Critical part is do not block if the Closed() has been called.
|
||||
func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgConn.Endpoint) (int, error) {
|
||||
func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgbackend.Endpoint) (int, error) {
|
||||
closedChan := c.currentClosedChan()
|
||||
|
||||
select {
|
||||
@@ -375,7 +375,7 @@ func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgConn.Endpo
|
||||
}
|
||||
copy(buffs[0], msg.Buffer)
|
||||
sizes[0] = len(msg.Buffer)
|
||||
eps[0] = wgConn.Endpoint(msg.Endpoint)
|
||||
eps[0] = wgbackend.Endpoint(msg.Endpoint)
|
||||
|
||||
if isTransportPkg(buffs, sizes[0]) {
|
||||
if ep, ok := eps[0].(*Endpoint); ok {
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
wgConn "golang.zx2c4.com/wireguard/conn"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// startReceivers runs every receive function the way wireguard-go's device
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
// calling Bind.Close, closeBindLocked waits on exactly that WaitGroup while
|
||||
// holding device.net, so a receive function that never returns wedges the
|
||||
// device and every goroutine that needs the same lock.
|
||||
func startReceivers(fns []wgConn.ReceiveFunc) *sync.WaitGroup {
|
||||
func startReceivers(fns []wgbackend.ReceiveFunc) *sync.WaitGroup {
|
||||
wg, _ := startReceiversEntered(fns)
|
||||
return wg
|
||||
}
|
||||
@@ -23,18 +24,18 @@ func startReceivers(fns []wgConn.ReceiveFunc) *sync.WaitGroup {
|
||||
// function has been called at least once. A receive function that has been
|
||||
// entered is either inside its blocking receive or about to be, which is a
|
||||
// stronger signal to synchronise on than a bare sleep.
|
||||
func startReceiversEntered(fns []wgConn.ReceiveFunc) (*sync.WaitGroup, <-chan struct{}) {
|
||||
func startReceiversEntered(fns []wgbackend.ReceiveFunc) (*sync.WaitGroup, <-chan struct{}) {
|
||||
var wg sync.WaitGroup
|
||||
var entered sync.WaitGroup
|
||||
wg.Add(len(fns))
|
||||
entered.Add(len(fns))
|
||||
|
||||
for i := range fns {
|
||||
go func(fn wgConn.ReceiveFunc) {
|
||||
go func(fn wgbackend.ReceiveFunc) {
|
||||
defer wg.Done()
|
||||
buffs := [][]byte{make([]byte, 1500)}
|
||||
sizes := make([]int, 1)
|
||||
eps := make([]wgConn.Endpoint, 1)
|
||||
eps := make([]wgbackend.Endpoint, 1)
|
||||
first := true
|
||||
for {
|
||||
if first {
|
||||
|
||||
@@ -16,10 +16,9 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
func TestICEBind_CreatesReceiverForBothIPv4AndIPv6(t *testing.T) {
|
||||
@@ -370,16 +369,16 @@ func TestICEBind_OpenDoesNotDiscoverInterfaces(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestICEBind_DeviceUpDoesNotWaitOnInterfaceDiscovery(t *testing.T) {
|
||||
tunDev, _, err := netstack.CreateNetTUN([]netip.Addr{netip.MustParseAddr("100.64.0.1")}, nil, 1280)
|
||||
tunDev, _, err := wgbackend.CreateNetTUN([]netip.Addr{netip.MustParseAddr("100.64.0.1")}, nil, 1280)
|
||||
require.NoError(t, err)
|
||||
|
||||
var dev *device.Device
|
||||
var dev *wgbackend.Device
|
||||
n := newCountingNet()
|
||||
n.before = func() {
|
||||
_ = dev.IpcGetOperation(io.Discard)
|
||||
}
|
||||
iceBind := NewICEBind(n, testAddress(), 1280)
|
||||
dev = device.NewDevice(tunDev, iceBind, device.NewLogger(device.LogLevelSilent, ""))
|
||||
dev = wgbackend.NewDevice(tunDev, iceBind, wgbackend.NewLogger(wgbackend.LogLevelSilent, ""))
|
||||
|
||||
upDone := make(chan error, 1)
|
||||
go func() {
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
"sync"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/conn"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// RelayBindJS is a conn.Bind implementation for WebAssembly environments.
|
||||
// Do not limit to build only js, because we want to be able to run tests
|
||||
type RelayBindJS struct {
|
||||
*conn.StdNetBind
|
||||
*wgbackend.StdNetBind
|
||||
|
||||
recvChan chan recvMessage
|
||||
endpoints map[netip.Addr]net.Conn
|
||||
@@ -34,12 +34,12 @@ func NewRelayBindJS() *RelayBindJS {
|
||||
}
|
||||
|
||||
// Open creates a receive function for handling relay packets in WASM.
|
||||
func (s *RelayBindJS) Open(uport uint16) ([]conn.ReceiveFunc, uint16, error) {
|
||||
func (s *RelayBindJS) Open(uport uint16) ([]wgbackend.ReceiveFunc, uint16, error) {
|
||||
log.Debugf("Open: creating receive function for port %d", uport)
|
||||
|
||||
s.ctx, s.cancel = context.WithCancel(context.Background())
|
||||
|
||||
receiveFn := func(bufs [][]byte, sizes []int, eps []conn.Endpoint) (int, error) {
|
||||
receiveFn := func(bufs [][]byte, sizes []int, eps []wgbackend.Endpoint) (int, error) {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return 0, net.ErrClosed
|
||||
@@ -49,13 +49,13 @@ func (s *RelayBindJS) Open(uport uint16) ([]conn.ReceiveFunc, uint16, error) {
|
||||
}
|
||||
copy(bufs[0], msg.Buffer)
|
||||
sizes[0] = len(msg.Buffer)
|
||||
eps[0] = conn.Endpoint(msg.Endpoint)
|
||||
eps[0] = wgbackend.Endpoint(msg.Endpoint)
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Open: receive function created, returning port %d", uport)
|
||||
return []conn.ReceiveFunc{receiveFn}, uport, nil
|
||||
return []wgbackend.ReceiveFunc{receiveFn}, uport, nil
|
||||
}
|
||||
|
||||
func (s *RelayBindJS) Close() error {
|
||||
@@ -78,7 +78,7 @@ func (s *RelayBindJS) ReceiveFromEndpoint(ctx context.Context, ep *Endpoint, buf
|
||||
}
|
||||
|
||||
// Send forwards packets through the relay connection for WASM.
|
||||
func (s *RelayBindJS) Send(bufs [][]byte, ep conn.Endpoint) error {
|
||||
func (s *RelayBindJS) Send(bufs [][]byte, ep wgbackend.Endpoint) error {
|
||||
if ep == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/ipv4"
|
||||
wgConn "golang.zx2c4.com/wireguard/conn"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// magicCookieBytes is the STUN magic cookie as it appears on the wire. In a
|
||||
@@ -165,7 +166,7 @@ func TestReceiveFn_ClearsSizeOfConsumedPacket(t *testing.T) {
|
||||
// A leftover size from an earlier read, which is what makes the missing reset
|
||||
// observable.
|
||||
sizes := []int{148}
|
||||
eps := make([]wgConn.Endpoint, 1)
|
||||
eps := make([]wgbackend.Endpoint, 1)
|
||||
|
||||
n, err := recvFn(bufs, sizes, eps)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -5,16 +5,16 @@ package configurer
|
||||
import (
|
||||
"net"
|
||||
|
||||
"golang.zx2c4.com/wireguard/ipc"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
func openUAPI(deviceName string) (net.Listener, error) {
|
||||
uapiSock, err := ipc.UAPIOpen(deviceName)
|
||||
uapiSock, err := wgbackend.UAPIOpen(deviceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener, err := ipc.UAPIListen(deviceName, uapiSock)
|
||||
listener, err := wgbackend.UAPIListen(deviceName, uapiSock)
|
||||
if err != nil {
|
||||
_ = uapiSock.Close()
|
||||
return nil, err
|
||||
|
||||
@@ -3,9 +3,9 @@ package configurer
|
||||
import (
|
||||
"net"
|
||||
|
||||
"golang.zx2c4.com/wireguard/ipc"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
func openUAPI(deviceName string) (net.Listener, error) {
|
||||
return ipc.UAPIListen(deviceName)
|
||||
return wgbackend.UAPIListen(deviceName)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,10 @@ import (
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
wgconn "golang.zx2c4.com/wireguard/conn"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nbnet "github.com/netbirdio/netbird/client/net"
|
||||
"github.com/netbirdio/netbird/monotime"
|
||||
)
|
||||
@@ -22,7 +21,7 @@ import (
|
||||
var ErrAllowedIPNotFound = fmt.Errorf("allowed IP not found")
|
||||
|
||||
type WGUSPConfigurer struct {
|
||||
device *device.Device
|
||||
device *wgbackend.Device
|
||||
deviceName string
|
||||
activityRecorder *bind.ActivityRecorder
|
||||
statsCache *statsCache
|
||||
@@ -31,14 +30,14 @@ type WGUSPConfigurer struct {
|
||||
}
|
||||
|
||||
// NewUSPConfigurer creates a userspace configurer and starts its UAPI listener.
|
||||
func NewUSPConfigurer(device *device.Device, deviceName string, activityRecorder *bind.ActivityRecorder) *WGUSPConfigurer {
|
||||
func NewUSPConfigurer(device *wgbackend.Device, deviceName string, activityRecorder *bind.ActivityRecorder) *WGUSPConfigurer {
|
||||
wgCfg := NewUSPConfigurerNoUAPI(device, deviceName, activityRecorder)
|
||||
wgCfg.startUAPI()
|
||||
return wgCfg
|
||||
}
|
||||
|
||||
// NewUSPConfigurerNoUAPI creates a userspace configurer without a UAPI listener.
|
||||
func NewUSPConfigurerNoUAPI(device *device.Device, deviceName string, activityRecorder *bind.ActivityRecorder) *WGUSPConfigurer {
|
||||
func NewUSPConfigurerNoUAPI(device *wgbackend.Device, deviceName string, activityRecorder *bind.ActivityRecorder) *WGUSPConfigurer {
|
||||
wgCfg := &WGUSPConfigurer{
|
||||
device: device,
|
||||
deviceName: deviceName,
|
||||
@@ -59,7 +58,7 @@ func (c *WGUSPConfigurer) ConfigureInterface(privateKey string, port int) error
|
||||
return fmt.Errorf("invalid listen port %d", port)
|
||||
}
|
||||
|
||||
if err := c.device.SetPrivateKey(device.NoisePrivateKey(key)); err != nil {
|
||||
if err := c.device.SetPrivateKey(wgbackend.NoisePrivateKey(key)); err != nil {
|
||||
return fmt.Errorf("set private key: %w", err)
|
||||
}
|
||||
if err := c.device.SetListenPort(uint16(port)); err != nil {
|
||||
@@ -80,8 +79,8 @@ func (c *WGUSPConfigurer) SetPresharedKey(peerKey string, psk wgtypes.Key, updat
|
||||
return err
|
||||
}
|
||||
|
||||
presharedKey := device.NoisePresharedKey(psk)
|
||||
return c.device.ConfigurePeer(device.NoisePublicKey(parsedPeerKey), device.PeerConfig{
|
||||
presharedKey := wgbackend.NoisePresharedKey(psk)
|
||||
return c.device.ConfigurePeer(wgbackend.NoisePublicKey(parsedPeerKey), wgbackend.PeerConfig{
|
||||
PresharedKey: &presharedKey,
|
||||
UpdateOnly: updateOnly,
|
||||
})
|
||||
@@ -99,7 +98,7 @@ func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix,
|
||||
return err
|
||||
}
|
||||
|
||||
cfg := device.PeerConfig{
|
||||
cfg := wgbackend.PeerConfig{
|
||||
PersistentKeepalive: &keepAlive,
|
||||
AllowedIPs: prefixes,
|
||||
}
|
||||
@@ -116,11 +115,11 @@ func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix,
|
||||
}
|
||||
|
||||
if preSharedKey != nil {
|
||||
psk := device.NoisePresharedKey(*preSharedKey)
|
||||
psk := wgbackend.NoisePresharedKey(*preSharedKey)
|
||||
cfg.PresharedKey = &psk
|
||||
}
|
||||
|
||||
if err := c.device.ConfigurePeer(device.NoisePublicKey(peerKeyParsed), cfg); err != nil {
|
||||
if err := c.device.ConfigurePeer(wgbackend.NoisePublicKey(peerKeyParsed), cfg); err != nil {
|
||||
return fmt.Errorf("configure peer: %w", err)
|
||||
}
|
||||
|
||||
@@ -138,7 +137,7 @@ func (c *WGUSPConfigurer) RemoveEndpointAddress(peerKey string) error {
|
||||
return fmt.Errorf("parse peer key: %w", err)
|
||||
}
|
||||
|
||||
peer := c.device.LookupPeer(device.NoisePublicKey(peerKeyParsed))
|
||||
peer := c.device.LookupPeer(wgbackend.NoisePublicKey(peerKeyParsed))
|
||||
if peer == nil {
|
||||
return ErrPeerNotFound
|
||||
}
|
||||
@@ -147,7 +146,7 @@ func (c *WGUSPConfigurer) RemoveEndpointAddress(peerKey string) error {
|
||||
peer.ZeroAndFlushAll()
|
||||
|
||||
var noKeepAlive time.Duration
|
||||
if err := c.device.ConfigurePeer(device.NoisePublicKey(peerKeyParsed), device.PeerConfig{
|
||||
if err := c.device.ConfigurePeer(wgbackend.NoisePublicKey(peerKeyParsed), wgbackend.PeerConfig{
|
||||
PersistentKeepalive: &noKeepAlive,
|
||||
UpdateOnly: true,
|
||||
}); err != nil {
|
||||
@@ -163,7 +162,7 @@ func (c *WGUSPConfigurer) RemovePeer(peerKey string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
c.device.RemovePeer(device.NoisePublicKey(peerKeyParsed))
|
||||
c.device.RemovePeer(wgbackend.NoisePublicKey(peerKeyParsed))
|
||||
c.activityRecorder.Remove(peerKey)
|
||||
return nil
|
||||
}
|
||||
@@ -178,7 +177,7 @@ func (c *WGUSPConfigurer) AddAllowedIP(peerKey string, allowedIP netip.Prefix) e
|
||||
return fmt.Errorf("invalid allowed IP %v", allowedIP)
|
||||
}
|
||||
|
||||
peer := c.device.LookupPeer(device.NoisePublicKey(peerKeyParsed))
|
||||
peer := c.device.LookupPeer(wgbackend.NoisePublicKey(peerKeyParsed))
|
||||
if peer == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -198,7 +197,7 @@ func (c *WGUSPConfigurer) RemoveAllowedIP(peerKey string, allowedIP netip.Prefix
|
||||
return ErrAllowedIPNotFound
|
||||
}
|
||||
|
||||
peer := c.device.LookupPeer(device.NoisePublicKey(peerKeyParsed))
|
||||
peer := c.device.LookupPeer(wgbackend.NoisePublicKey(peerKeyParsed))
|
||||
if peer == nil {
|
||||
return ErrPeerNotFound
|
||||
}
|
||||
@@ -284,7 +283,7 @@ func (c *WGUSPConfigurer) fetchStats() (map[string]WGStats, error) {
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func peerStats(peer *device.Peer) Peer {
|
||||
func peerStats(peer *wgbackend.Peer) Peer {
|
||||
stats := Peer{
|
||||
PublicKey: wgtypes.Key(peer.PublicKey()).String(),
|
||||
AllowedIPs: prefixesToIPNets(peer.AllowedIPs()),
|
||||
@@ -299,7 +298,7 @@ func peerStats(peer *device.Peer) Peer {
|
||||
return stats
|
||||
}
|
||||
|
||||
func endpointAddrPort(endpoint wgconn.Endpoint) (netip.AddrPort, bool) {
|
||||
func endpointAddrPort(endpoint wgbackend.Endpoint) (netip.AddrPort, bool) {
|
||||
if endpoint == nil {
|
||||
return netip.AddrPort{}, false
|
||||
}
|
||||
|
||||
@@ -8,11 +8,10 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
wgconn "golang.zx2c4.com/wireguard/conn"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// newTestUSPConfigurer builds a configurer over a real wireguard-go device backed by an
|
||||
@@ -20,7 +19,7 @@ import (
|
||||
func newTestUSPConfigurer(t *testing.T) *WGUSPConfigurer {
|
||||
t.Helper()
|
||||
|
||||
dev := wgdevice.NewDevice(newIdleTUN(), wgconn.NewDefaultBind(), wgdevice.NewLogger(wgdevice.LogLevelSilent, ""))
|
||||
dev := wgbackend.NewDevice(newIdleTUN(), wgbackend.NewDefaultBind(), wgbackend.NewLogger(wgbackend.LogLevelSilent, ""))
|
||||
t.Cleanup(dev.Close)
|
||||
|
||||
c := NewUSPConfigurerNoUAPI(dev, "wgtest0", bind.NewActivityRecorder())
|
||||
|
||||
@@ -11,20 +11,20 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// idleTUN never reports an up event, so the wireguard-go device stays down: no socket is
|
||||
// opened, no peer goroutine starts, and the configuration state is all the tests observe.
|
||||
type idleTUN struct {
|
||||
events chan tun.Event
|
||||
events chan wgbackend.TUNEvent
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
func newIdleTUN() *idleTUN {
|
||||
return &idleTUN{events: make(chan tun.Event), closed: make(chan struct{})}
|
||||
return &idleTUN{events: make(chan wgbackend.TUNEvent), closed: make(chan struct{})}
|
||||
}
|
||||
|
||||
func (t *idleTUN) File() *os.File { return nil }
|
||||
@@ -40,7 +40,7 @@ func (t *idleTUN) MTU() (int, error) { return 1420, nil }
|
||||
|
||||
func (t *idleTUN) Name() (string, error) { return "idle", nil }
|
||||
|
||||
func (t *idleTUN) Events() <-chan tun.Event { return t.events }
|
||||
func (t *idleTUN) Events() <-chan wgbackend.TUNEvent { return t.events }
|
||||
|
||||
func (t *idleTUN) Close() error {
|
||||
close(t.closed)
|
||||
@@ -142,12 +142,12 @@ func TestRemoveEndpointAddressKeepsThePeerAndStopsTheKeepalive(t *testing.T) {
|
||||
endpoint := &net.UDPAddr{IP: net.IPv4(192, 0, 2, 10), Port: 51820}
|
||||
prefixes := []netip.Prefix{netip.MustParsePrefix("100.64.0.1/32")}
|
||||
require.NoError(t, c.UpdatePeer(peerKey, prefixes, 25*time.Second, endpoint, nil), "add peer")
|
||||
before := c.device.LookupPeer(wgdevice.NoisePublicKey(priv.PublicKey()))
|
||||
before := c.device.LookupPeer(wgbackend.NoisePublicKey(priv.PublicKey()))
|
||||
require.NotNil(t, before, "the peer must be on the device")
|
||||
|
||||
require.NoError(t, c.RemoveEndpointAddress(peerKey), "remove endpoint address")
|
||||
|
||||
assert.Same(t, before, c.device.LookupPeer(wgdevice.NoisePublicKey(priv.PublicKey())),
|
||||
assert.Same(t, before, c.device.LookupPeer(wgbackend.NoisePublicKey(priv.PublicKey())),
|
||||
"the peer object must survive the endpoint removal")
|
||||
stats, err := c.FullStats()
|
||||
require.NoError(t, err, "read device stats")
|
||||
|
||||
@@ -3,13 +3,10 @@
|
||||
package iface
|
||||
|
||||
import (
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type WGTunDevice interface {
|
||||
@@ -21,7 +18,7 @@ type WGTunDevice interface {
|
||||
DeviceName() string
|
||||
Close() error
|
||||
FilteredDevice() *device.FilteredDevice
|
||||
Device() *wgdevice.Device
|
||||
GetNet() *netstack.Net
|
||||
Device() *wgbackend.Device
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
GetICEBind() device.EndpointManager
|
||||
}
|
||||
|
||||
@@ -8,14 +8,12 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// WGTunDevice ignore the WGTunDevice interface on Android because the creation of the tun device is different on this platform
|
||||
@@ -30,7 +28,7 @@ type WGTunDevice struct {
|
||||
disableDNS bool
|
||||
|
||||
name string
|
||||
device *device.Device
|
||||
device *wgbackend.Device
|
||||
filteredDevice *FilteredDevice
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
configurer WGConfigurer
|
||||
@@ -74,7 +72,7 @@ func (t *WGTunDevice) Create(routes []string, dns string, searchDomains []string
|
||||
return nil, err
|
||||
}
|
||||
|
||||
unmonitoredTUN, name, err := tun.CreateUnmonitoredTUNFromFD(fd)
|
||||
unmonitoredTUN, name, err := wgbackend.CreateUnmonitoredTUNFromFD(fd)
|
||||
if err != nil {
|
||||
_ = unix.Close(fd)
|
||||
log.Errorf("failed to create Android interface: %s", err)
|
||||
@@ -87,7 +85,7 @@ func (t *WGTunDevice) Create(routes []string, dns string, searchDomains []string
|
||||
t.filteredDevice = newDeviceFilter(t.renewableTun)
|
||||
|
||||
log.Debugf("attaching to interface %v", name)
|
||||
t.device = device.NewDevice(t.filteredDevice, t.iceBind, device.NewLogger(wgLogLevel(), "[netbird] "))
|
||||
t.device = wgbackend.NewDevice(t.filteredDevice, t.iceBind, wgbackend.NewLogger(wgLogLevel(), "[netbird] "))
|
||||
// without this property mobile devices can discover remote endpoints if the configured one was wrong.
|
||||
// this helps with support for the older NetBird clients that had a hardcoded direct mode
|
||||
// t.device.DisableSomeRoamingForBrokenMobileSemantics()
|
||||
@@ -121,7 +119,7 @@ func (t *WGTunDevice) RenewTun(fd int) error {
|
||||
return fmt.Errorf("device not initialized")
|
||||
}
|
||||
|
||||
unmonitoredTUN, _, err := tun.CreateUnmonitoredTUNFromFD(fd)
|
||||
unmonitoredTUN, _, err := wgbackend.CreateUnmonitoredTUNFromFD(fd)
|
||||
if err != nil {
|
||||
_ = unix.Close(fd)
|
||||
log.Errorf("failed to renew Android interface: %s", err)
|
||||
@@ -155,7 +153,7 @@ func (t *WGTunDevice) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *WGTunDevice) Device() *device.Device {
|
||||
func (t *WGTunDevice) Device() *wgbackend.Device {
|
||||
return t.device
|
||||
}
|
||||
|
||||
@@ -175,7 +173,7 @@ func (t *WGTunDevice) FilteredDevice() *FilteredDevice {
|
||||
return t.filteredDevice
|
||||
}
|
||||
|
||||
func (t *WGTunDevice) GetNet() *netstack.Net {
|
||||
func (t *WGTunDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,12 @@ import (
|
||||
"os/exec"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type TunDevice struct {
|
||||
@@ -25,7 +23,7 @@ type TunDevice struct {
|
||||
mtu uint16
|
||||
iceBind *bind.ICEBind
|
||||
|
||||
device *device.Device
|
||||
device *wgbackend.Device
|
||||
filteredDevice *FilteredDevice
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
configurer WGConfigurer
|
||||
@@ -43,17 +41,17 @@ func NewTunDevice(name string, address wgaddr.Address, port int, key string, mtu
|
||||
}
|
||||
|
||||
func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
tunDevice, err := tun.CreateTUN(t.name, int(t.mtu))
|
||||
tunDevice, err := wgbackend.CreateTUN(t.name, int(t.mtu))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating tun device: %s", err)
|
||||
}
|
||||
t.filteredDevice = newDeviceFilter(tunDevice)
|
||||
|
||||
// We need to create a wireguard-go device and listen to configuration requests
|
||||
t.device = device.NewDevice(
|
||||
t.device = wgbackend.NewDevice(
|
||||
t.filteredDevice,
|
||||
t.iceBind,
|
||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
)
|
||||
|
||||
err = t.assignAddr()
|
||||
@@ -125,7 +123,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
||||
}
|
||||
|
||||
// Device returns the wireguard device
|
||||
func (t *TunDevice) Device() *device.Device {
|
||||
func (t *TunDevice) Device() *wgbackend.Device {
|
||||
return t.device
|
||||
}
|
||||
|
||||
@@ -160,7 +158,7 @@ func (t *TunDevice) assignAddr() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunDevice) GetNet() *netstack.Net {
|
||||
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// PacketFilter interface for firewall abilities
|
||||
@@ -42,7 +43,7 @@ type PacketCapture interface {
|
||||
|
||||
// FilteredDevice to override Read or Write of packets
|
||||
type FilteredDevice struct {
|
||||
tun.Device
|
||||
wgbackend.TUN
|
||||
|
||||
filter PacketFilter
|
||||
capture atomic.Pointer[PacketCapture]
|
||||
@@ -54,9 +55,9 @@ type FilteredDevice struct {
|
||||
}
|
||||
|
||||
// newDeviceFilter constructor function
|
||||
func newDeviceFilter(device tun.Device) *FilteredDevice {
|
||||
func newDeviceFilter(device wgbackend.TUN) *FilteredDevice {
|
||||
return &FilteredDevice{
|
||||
Device: device,
|
||||
TUN: device,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +67,7 @@ func newDeviceFilter(device tun.Device) *FilteredDevice {
|
||||
func (d *FilteredDevice) Close() error {
|
||||
var err error
|
||||
d.closeOnce.Do(func() {
|
||||
err = d.Device.Close()
|
||||
err = d.TUN.Close()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -142,14 +143,14 @@ func (d *FilteredDevice) Write(bufs [][]byte, offset int) (int, error) {
|
||||
// wintun read path and converting them into errors.
|
||||
func (d *FilteredDevice) deviceRead(bufs [][]byte, sizes []int, offset int) (n int, err error) {
|
||||
defer d.recoverFromPanic("read", &n, &err)
|
||||
return d.Device.Read(bufs, sizes, offset)
|
||||
return d.TUN.Read(bufs, sizes, offset)
|
||||
}
|
||||
|
||||
// deviceWrite calls the underlying device Write, recovering from panics in the
|
||||
// wintun write path and converting them into errors.
|
||||
func (d *FilteredDevice) deviceWrite(bufs [][]byte, offset int) (n int, err error) {
|
||||
defer d.recoverFromPanic("write", &n, &err)
|
||||
return d.Device.Write(bufs, offset)
|
||||
return d.TUN.Write(bufs, offset)
|
||||
}
|
||||
|
||||
// recoverFromPanic converts a panic in the underlying device into a regular
|
||||
|
||||
@@ -6,14 +6,12 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type TunDevice struct {
|
||||
@@ -25,7 +23,7 @@ type TunDevice struct {
|
||||
iceBind *bind.ICEBind
|
||||
tunFd int
|
||||
|
||||
device *device.Device
|
||||
device *wgbackend.Device
|
||||
filteredDevice *FilteredDevice
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
configurer WGConfigurer
|
||||
@@ -50,7 +48,7 @@ var ErrInvalidTunnelFD = fmt.Errorf("invalid tunnel file descriptor: fd is 0 (Sw
|
||||
func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
log.Infof("create tun interface")
|
||||
|
||||
var tunDevice tun.Device
|
||||
var tunDevice wgbackend.TUN
|
||||
var err error
|
||||
|
||||
// Validate the tunnel file descriptor.
|
||||
@@ -79,7 +77,7 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
_ = unix.Close(dupTunFd)
|
||||
return nil, err
|
||||
}
|
||||
tunDevice, err = tun.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
|
||||
tunDevice, err = wgbackend.CreateTUNFromFile(os.NewFile(uintptr(dupTunFd), "/dev/tun"), 0)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to create new tun device from fd: %v", err)
|
||||
_ = unix.Close(dupTunFd)
|
||||
@@ -88,7 +86,7 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
|
||||
t.filteredDevice = newDeviceFilter(tunDevice)
|
||||
log.Debug("Attaching to interface")
|
||||
t.device = device.NewDevice(t.filteredDevice, t.iceBind, device.NewLogger(wgLogLevel(), "[netbird] "))
|
||||
t.device = wgbackend.NewDevice(t.filteredDevice, t.iceBind, wgbackend.NewLogger(wgLogLevel(), "[netbird] "))
|
||||
// without this property mobile devices can discover remote endpoints if the configured one was wrong.
|
||||
// this helps with support for the older NetBird clients that had a hardcoded direct mode
|
||||
// t.device.DisableSomeRoamingForBrokenMobileSemantics()
|
||||
@@ -118,7 +116,7 @@ func (t *TunDevice) Up() (*udpmux.UniversalUDPMuxDefault, error) {
|
||||
return udpMux, nil
|
||||
}
|
||||
|
||||
func (t *TunDevice) Device() *device.Device {
|
||||
func (t *TunDevice) Device() *wgbackend.Device {
|
||||
return t.device
|
||||
}
|
||||
|
||||
@@ -163,7 +161,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
||||
return t.filteredDevice
|
||||
}
|
||||
|
||||
func (t *TunDevice) GetNet() *netstack.Net {
|
||||
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,11 @@ import (
|
||||
|
||||
"github.com/pion/transport/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nbnet "github.com/netbirdio/netbird/client/net"
|
||||
"github.com/netbirdio/netbird/sharedsock"
|
||||
)
|
||||
@@ -170,7 +169,7 @@ func (t *TunKernelDevice) DeviceName() string {
|
||||
}
|
||||
|
||||
// Device returns the wireguard device, not applicable for kernel devices
|
||||
func (t *TunKernelDevice) Device() *device.Device {
|
||||
func (t *TunKernelDevice) Device() *wgbackend.Device {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -183,7 +182,7 @@ func (t *TunKernelDevice) assignAddr() error {
|
||||
return t.link.assignAddr(&t.address)
|
||||
}
|
||||
|
||||
func (t *TunKernelDevice) GetNet() *netstack.Net {
|
||||
func (t *TunKernelDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,20 +6,18 @@ import (
|
||||
"net/netip"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/conn"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nbnet "github.com/netbirdio/netbird/client/net"
|
||||
)
|
||||
|
||||
type Bind interface {
|
||||
conn.Bind
|
||||
wgbackend.Bind
|
||||
GetICEMux() (*udpmux.UniversalUDPMuxDefault, error)
|
||||
ActivityRecorder() *bind.ActivityRecorder
|
||||
EndpointManager
|
||||
@@ -34,13 +32,13 @@ type TunNetstackDevice struct {
|
||||
listenAddress string
|
||||
bind Bind
|
||||
|
||||
device *device.Device
|
||||
device *wgbackend.Device
|
||||
filteredDevice *FilteredDevice
|
||||
nsTun *nbnetstack.NetStackTun
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
configurer WGConfigurer
|
||||
|
||||
net *netstack.Net
|
||||
net *wgbackend.NetstackNet
|
||||
}
|
||||
|
||||
func NewNetstackDevice(name string, address wgaddr.Address, wgPort int, key string, mtu uint16, bind Bind, listenAddress string) *TunNetstackDevice {
|
||||
@@ -78,10 +76,10 @@ func (t *TunNetstackDevice) create() (WGConfigurer, error) {
|
||||
t.filteredDevice = newDeviceFilter(tunIface)
|
||||
t.net = net
|
||||
|
||||
t.device = device.NewDevice(
|
||||
t.device = wgbackend.NewDevice(
|
||||
t.filteredDevice,
|
||||
t.bind,
|
||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
)
|
||||
|
||||
t.configurer = configurer.NewUSPConfigurerNoUAPI(t.device, t.name, t.bind.ActivityRecorder())
|
||||
@@ -156,11 +154,11 @@ func (t *TunNetstackDevice) FilteredDevice() *FilteredDevice {
|
||||
}
|
||||
|
||||
// Device returns the wireguard device
|
||||
func (t *TunNetstackDevice) Device() *device.Device {
|
||||
func (t *TunNetstackDevice) Device() *wgbackend.Device {
|
||||
return t.device
|
||||
}
|
||||
|
||||
func (t *TunNetstackDevice) GetNet() *netstack.Net {
|
||||
func (t *TunNetstackDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return t.net
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,12 @@ import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type TunDevice struct {
|
||||
@@ -24,7 +22,7 @@ type TunDevice struct {
|
||||
mtu uint16
|
||||
iceBind *bind.ICEBind
|
||||
|
||||
device *device.Device
|
||||
device *wgbackend.Device
|
||||
filteredDevice *FilteredDevice
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
configurer WGConfigurer
|
||||
@@ -45,7 +43,7 @@ func NewTunDevice(name string, address wgaddr.Address, port int, key string, mtu
|
||||
|
||||
func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
log.Info("create tun interface")
|
||||
tunIface, err := tun.CreateTUN(t.name, int(t.mtu))
|
||||
tunIface, err := wgbackend.CreateTUN(t.name, int(t.mtu))
|
||||
if err != nil {
|
||||
log.Debugf("failed to create tun interface (%s, %d): %s", t.name, int(t.mtu), err)
|
||||
return nil, fmt.Errorf("error creating tun device: %s", err)
|
||||
@@ -53,10 +51,10 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
t.filteredDevice = newDeviceFilter(tunIface)
|
||||
|
||||
// We need to create a wireguard-go device and listen to configuration requests
|
||||
t.device = device.NewDevice(
|
||||
t.device = wgbackend.NewDevice(
|
||||
t.filteredDevice,
|
||||
t.iceBind,
|
||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
)
|
||||
|
||||
err = t.assignAddr()
|
||||
@@ -132,7 +130,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
||||
}
|
||||
|
||||
// Device returns the wireguard device
|
||||
func (t *TunDevice) Device() *device.Device {
|
||||
func (t *TunDevice) Device() *wgbackend.Device {
|
||||
return t.device
|
||||
}
|
||||
|
||||
@@ -143,7 +141,7 @@ func (t *TunDevice) assignAddr() error {
|
||||
return link.assignAddr(&t.address)
|
||||
}
|
||||
|
||||
func (t *TunDevice) GetNet() *netstack.Net {
|
||||
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,13 @@ import (
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/bind"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
const defaultWindowsGUIDSTring = "{f2f29e61-d91f-4d76-8151-119b20c4bdeb}"
|
||||
@@ -27,8 +25,8 @@ type TunDevice struct {
|
||||
mtu uint16
|
||||
iceBind *bind.ICEBind
|
||||
|
||||
device *device.Device
|
||||
nativeTunDevice *tun.NativeTun
|
||||
device *wgbackend.Device
|
||||
nativeTunDevice *wgbackend.NativeTUN
|
||||
filteredDevice *FilteredDevice
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
configurer WGConfigurer
|
||||
@@ -60,18 +58,18 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||
return nil, err
|
||||
}
|
||||
log.Info("create tun interface")
|
||||
tunDevice, err := tun.CreateTUNWithRequestedGUID(t.name, &guid, int(t.mtu))
|
||||
tunDevice, err := wgbackend.CreateTUNWithRequestedGUID(t.name, &guid, int(t.mtu))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating tun device: %s", err)
|
||||
}
|
||||
t.nativeTunDevice = tunDevice.(*tun.NativeTun)
|
||||
t.nativeTunDevice = tunDevice.(*wgbackend.NativeTUN)
|
||||
t.filteredDevice = newDeviceFilter(tunDevice)
|
||||
|
||||
// We need to create a wireguard-go device and listen to configuration requests
|
||||
t.device = device.NewDevice(
|
||||
t.device = wgbackend.NewDevice(
|
||||
t.filteredDevice,
|
||||
t.iceBind,
|
||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||
)
|
||||
|
||||
luid := winipcfg.LUID(t.nativeTunDevice.LUID())
|
||||
@@ -172,7 +170,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
||||
}
|
||||
|
||||
// Device returns the wireguard device
|
||||
func (t *TunDevice) Device() *device.Device {
|
||||
func (t *TunDevice) Device() *wgbackend.Device {
|
||||
return t.device
|
||||
}
|
||||
|
||||
@@ -209,7 +207,7 @@ func (t *TunDevice) assignAddr() error {
|
||||
return luid.SetIPAddresses([]netip.Prefix{v4Prefix})
|
||||
}
|
||||
|
||||
func (t *TunDevice) GetNet() *netstack.Net {
|
||||
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ import (
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// closeAwareDevice wraps a tun.Device along with a flag
|
||||
@@ -23,15 +24,15 @@ import (
|
||||
// goroutine is awaited and closed only once.
|
||||
type closeAwareDevice struct {
|
||||
isClosed atomic.Bool
|
||||
tun.Device
|
||||
wgbackend.TUN
|
||||
closeEventCh chan struct{}
|
||||
wg sync.WaitGroup
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func newClosableDevice(tunDevice tun.Device) *closeAwareDevice {
|
||||
func newClosableDevice(tunDevice wgbackend.TUN) *closeAwareDevice {
|
||||
return &closeAwareDevice{
|
||||
Device: tunDevice,
|
||||
TUN: tunDevice,
|
||||
isClosed: atomic.Bool{},
|
||||
closeEventCh: make(chan struct{}),
|
||||
}
|
||||
@@ -39,18 +40,18 @@ func newClosableDevice(tunDevice tun.Device) *closeAwareDevice {
|
||||
|
||||
// redirectEvents redirects the Events() method of the underlying tun.Device
|
||||
// to the given channel (RenewableTUN's events channel).
|
||||
func (c *closeAwareDevice) redirectEvents(out chan tun.Event) {
|
||||
func (c *closeAwareDevice) redirectEvents(out chan wgbackend.TUNEvent) {
|
||||
c.wg.Add(1)
|
||||
go func() {
|
||||
defer c.wg.Done()
|
||||
for {
|
||||
select {
|
||||
case ev, ok := <-c.Device.Events():
|
||||
case ev, ok := <-c.TUN.Events():
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if ev == tun.EventDown {
|
||||
if ev == wgbackend.TUNEventDown {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -72,7 +73,7 @@ func (c *closeAwareDevice) Close() (err error) {
|
||||
c.closeOnce.Do(func() {
|
||||
c.isClosed.Store(true)
|
||||
close(c.closeEventCh)
|
||||
err = c.Device.Close()
|
||||
err = c.TUN.Close()
|
||||
c.wg.Wait()
|
||||
})
|
||||
|
||||
@@ -87,7 +88,7 @@ type RenewableTUN struct {
|
||||
devices []*closeAwareDevice
|
||||
mu sync.Mutex
|
||||
cond *sync.Cond
|
||||
events chan tun.Event
|
||||
events chan wgbackend.TUNEvent
|
||||
closed atomic.Bool
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ func NewRenewableTUN() *RenewableTUN {
|
||||
r := &RenewableTUN{
|
||||
devices: make([]*closeAwareDevice, 0),
|
||||
mu: sync.Mutex{},
|
||||
events: make(chan tun.Event, 16),
|
||||
events: make(chan wgbackend.TUNEvent, 16),
|
||||
}
|
||||
r.cond = sync.NewCond(&r.mu)
|
||||
return r
|
||||
@@ -225,7 +226,7 @@ func (r *RenewableTUN) Name() (string, error) {
|
||||
|
||||
// Events returns a channel that is fed events from the underlying tun.Device's events channel
|
||||
// once it is added.
|
||||
func (r *RenewableTUN) Events() <-chan tun.Event {
|
||||
func (r *RenewableTUN) Events() <-chan wgbackend.TUNEvent {
|
||||
return r.events
|
||||
}
|
||||
|
||||
@@ -259,7 +260,7 @@ func (r *RenewableTUN) BatchSize() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (r *RenewableTUN) AddDevice(device tun.Device) {
|
||||
func (r *RenewableTUN) AddDevice(device wgbackend.TUN) {
|
||||
r.mu.Lock()
|
||||
if r.closed.Load() {
|
||||
r.mu.Unlock()
|
||||
|
||||
@@ -3,13 +3,13 @@ package device
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.zx2c4.com/wireguard/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
func wgLogLevel() int {
|
||||
if os.Getenv("NB_WG_DEBUG") == "true" {
|
||||
return device.LogLevelVerbose
|
||||
return wgbackend.LogLevelVerbose
|
||||
} else {
|
||||
return device.LogLevelSilent
|
||||
return wgbackend.LogLevelSilent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package iface
|
||||
|
||||
import (
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type WGTunDevice interface {
|
||||
@@ -19,8 +16,8 @@ type WGTunDevice interface {
|
||||
DeviceName() string
|
||||
Close() error
|
||||
FilteredDevice() *device.FilteredDevice
|
||||
Device() *wgdevice.Device
|
||||
GetNet() *netstack.Net
|
||||
Device() *wgbackend.Device
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
RenewTun(fd int) error
|
||||
GetICEBind() device.EndpointManager
|
||||
}
|
||||
|
||||
@@ -10,17 +10,15 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/pion/transport/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
"github.com/netbirdio/netbird/client/errors"
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||
"github.com/netbirdio/netbird/monotime"
|
||||
)
|
||||
@@ -271,7 +269,7 @@ func (w *WGIface) GetDevice() *device.FilteredDevice {
|
||||
}
|
||||
|
||||
// GetWGDevice returns the WireGuard device
|
||||
func (w *WGIface) GetWGDevice() *wgdevice.Device {
|
||||
func (w *WGIface) GetWGDevice() *wgbackend.Device {
|
||||
return w.tun.Device()
|
||||
}
|
||||
|
||||
@@ -344,7 +342,7 @@ func (w *WGIface) waitUntilRemoved() error {
|
||||
}
|
||||
|
||||
// GetNet returns the netstack.Net for the netstack device
|
||||
func (w *WGIface) GetNet() *netstack.Net {
|
||||
func (w *WGIface) GetNet() *wgbackend.NetstackNet {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||
)
|
||||
|
||||
@@ -34,14 +33,14 @@ func (f *fakeTunDevice) Create() (device.WGConfigurer, error) {
|
||||
func (f *fakeTunDevice) Up() (*udpmux.UniversalUDPMuxDefault, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
func (f *fakeTunDevice) UpdateAddr(wgaddr.Address) error { return nil }
|
||||
func (f *fakeTunDevice) WgAddress() wgaddr.Address { return wgaddr.Address{} }
|
||||
func (f *fakeTunDevice) MTU() uint16 { return DefaultMTU }
|
||||
func (f *fakeTunDevice) DeviceName() string { return "nb-close-test" }
|
||||
func (f *fakeTunDevice) UpdateAddr(wgaddr.Address) error { return nil }
|
||||
func (f *fakeTunDevice) WgAddress() wgaddr.Address { return wgaddr.Address{} }
|
||||
func (f *fakeTunDevice) MTU() uint16 { return DefaultMTU }
|
||||
func (f *fakeTunDevice) DeviceName() string { return "nb-close-test" }
|
||||
func (f *fakeTunDevice) FilteredDevice() *device.FilteredDevice { return nil }
|
||||
func (f *fakeTunDevice) Device() *wgdevice.Device { return nil }
|
||||
func (f *fakeTunDevice) GetNet() *netstack.Net { return nil }
|
||||
func (f *fakeTunDevice) GetICEBind() device.EndpointManager { return nil }
|
||||
func (f *fakeTunDevice) Device() *wgbackend.Device { return nil }
|
||||
func (f *fakeTunDevice) GetNet() *wgbackend.NetstackNet { return nil }
|
||||
func (f *fakeTunDevice) GetICEBind() device.EndpointManager { return nil }
|
||||
|
||||
func (f *fakeTunDevice) Close() error {
|
||||
close(f.closeStarted)
|
||||
@@ -62,6 +61,10 @@ func (fakeProxyFactory) Free() error { return nil }
|
||||
// WGIface.GetDevice() which needs the same mutex. The fix is to drop
|
||||
// the lock before tun.Close() returns control.
|
||||
func TestWGIface_CloseReleasesMutexBeforeTunClose(t *testing.T) {
|
||||
// Netstack mode skips the platform interface cleanup in Close, so only
|
||||
// the mutex and tun close behavior is exercised.
|
||||
t.Setenv(nbnetstack.EnvUseNetstackMode, "true")
|
||||
|
||||
tun := &fakeTunDevice{
|
||||
closeStarted: make(chan struct{}),
|
||||
unblockClose: make(chan struct{}),
|
||||
@@ -105,7 +108,10 @@ func TestWGIface_CloseReleasesMutexBeforeTunClose(t *testing.T) {
|
||||
|
||||
close(tun.unblockClose)
|
||||
select {
|
||||
case <-closeDone:
|
||||
case err := <-closeDone:
|
||||
if err != nil {
|
||||
t.Errorf("WGIface.Close() returned an error: %v", err)
|
||||
}
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("WGIface.Close() never returned after the tun was unblocked")
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: golang.zx2c4.com/wireguard/tun (interfaces: Device)
|
||||
// Source: github.com/netbirdio/wireguard-go/tun (interfaces: Device)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
os "os"
|
||||
reflect "reflect"
|
||||
|
||||
tun "github.com/netbirdio/wireguard-go/tun"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
tun "golang.zx2c4.com/wireguard/tun"
|
||||
)
|
||||
|
||||
// MockDevice is a mock of Device interface.
|
||||
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
"net"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type Dialer interface {
|
||||
@@ -13,10 +14,10 @@ type Dialer interface {
|
||||
}
|
||||
|
||||
type NSDialer struct {
|
||||
net *netstack.Net
|
||||
net *wgbackend.NetstackNet
|
||||
}
|
||||
|
||||
func NewNSDialer(net *netstack.Net) *NSDialer {
|
||||
func NewNSDialer(net *wgbackend.NetstackNet) *NSDialer {
|
||||
return &NSDialer{
|
||||
net: net,
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"strconv"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
const EnvSkipProxy = "NB_NETSTACK_SKIP_PROXY"
|
||||
@@ -19,7 +19,7 @@ type NetStackTun struct { //nolint:revive
|
||||
listenAddress string
|
||||
|
||||
proxy *Proxy
|
||||
tundev tun.Device
|
||||
tundev wgbackend.TUN
|
||||
}
|
||||
|
||||
func NewNetStackTun(listenAddress string, addresses []netip.Addr, dnsAddress netip.Addr, mtu int) *NetStackTun {
|
||||
@@ -31,8 +31,8 @@ func NewNetStackTun(listenAddress string, addresses []netip.Addr, dnsAddress net
|
||||
}
|
||||
}
|
||||
|
||||
func (t *NetStackTun) Create() (tun.Device, *netstack.Net, error) {
|
||||
nsTunDev, tunNet, err := netstack.CreateNetTUN(
|
||||
func (t *NetStackTun) Create() (wgbackend.TUN, *wgbackend.NetstackNet, error) {
|
||||
nsTunDev, tunNet, err := wgbackend.CreateNetTUN(
|
||||
t.addresses,
|
||||
[]netip.Addr{t.dnsAddress},
|
||||
t.mtu)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/stun/v3"
|
||||
"github.com/pion/transport/v3"
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/conn"
|
||||
|
||||
type (
|
||||
BatchReader = conn.BatchReader
|
||||
Bind = conn.Bind
|
||||
Endpoint = conn.Endpoint
|
||||
ReceiveFunc = conn.ReceiveFunc
|
||||
StdNetBind = conn.StdNetBind
|
||||
StdNetEndpoint = conn.StdNetEndpoint
|
||||
)
|
||||
|
||||
const (
|
||||
IdealBatchSize = conn.IdealBatchSize
|
||||
UdpSegmentMaxDatagrams = conn.UdpSegmentMaxDatagrams
|
||||
)
|
||||
|
||||
var (
|
||||
ControlFns = conn.ControlFns
|
||||
GetGSOSize = conn.GetGSOSize
|
||||
GetSrcFromControl = conn.GetSrcFromControl
|
||||
NewDefaultBind = conn.NewDefaultBind
|
||||
NewStdNetBind = conn.NewStdNetBind
|
||||
NewStdNetBindWithReceiverCreator = conn.NewStdNetBindWithReceiverCreator
|
||||
SplitCoalescedMessages = conn.SplitCoalescedMessages
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/device"
|
||||
|
||||
type (
|
||||
Device = device.Device
|
||||
NoisePresharedKey = device.NoisePresharedKey
|
||||
NoisePrivateKey = device.NoisePrivateKey
|
||||
NoisePublicKey = device.NoisePublicKey
|
||||
Peer = device.Peer
|
||||
PeerConfig = device.PeerConfig
|
||||
)
|
||||
|
||||
const (
|
||||
LogLevelSilent = device.LogLevelSilent
|
||||
LogLevelVerbose = device.LogLevelVerbose
|
||||
)
|
||||
|
||||
var (
|
||||
NewDevice = device.NewDevice
|
||||
NewLogger = device.NewLogger
|
||||
SetMaxBatchSizeOverride = device.SetMaxBatchSizeOverride
|
||||
SetPreallocatedBuffersPerPool = device.SetPreallocatedBuffersPerPool
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
// Package wgbackend is the single place in the client's hand-written code that names
|
||||
// the WireGuard implementation. Other packages import it instead of the wireguard-go
|
||||
// packages, so swapping the implementation only touches the aliases here and the
|
||||
// generated mocks.
|
||||
package wgbackend
|
||||
@@ -0,0 +1,10 @@
|
||||
//go:build linux || darwin || freebsd || openbsd
|
||||
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/ipc"
|
||||
|
||||
var (
|
||||
UAPIListen = ipc.UAPIListen
|
||||
UAPIOpen = ipc.UAPIOpen
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/ipc"
|
||||
|
||||
var UAPIListen = ipc.UAPIListen
|
||||
@@ -0,0 +1,19 @@
|
||||
package wgbackend
|
||||
|
||||
import (
|
||||
"github.com/netbirdio/wireguard-go/tun"
|
||||
"github.com/netbirdio/wireguard-go/tun/netstack"
|
||||
)
|
||||
|
||||
type (
|
||||
// TUN is the packet device the WireGuard device reads from and writes to.
|
||||
TUN = tun.Device
|
||||
// TUNEvent is a status change reported by a TUN.
|
||||
TUNEvent = tun.Event
|
||||
// NetstackNet is the userspace network stack a netstack TUN is attached to.
|
||||
NetstackNet = netstack.Net
|
||||
)
|
||||
|
||||
const TUNEventDown = tun.EventDown
|
||||
|
||||
var CreateNetTUN = netstack.CreateNetTUN
|
||||
@@ -0,0 +1,5 @@
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/tun"
|
||||
|
||||
var CreateUnmonitoredTUNFromFD = tun.CreateUnmonitoredTUNFromFD
|
||||
@@ -0,0 +1,10 @@
|
||||
//go:build linux || darwin || freebsd || openbsd
|
||||
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/tun"
|
||||
|
||||
var (
|
||||
CreateTUN = tun.CreateTUN
|
||||
CreateTUNFromFile = tun.CreateTUNFromFile
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
package wgbackend
|
||||
|
||||
import "github.com/netbirdio/wireguard-go/tun"
|
||||
|
||||
type NativeTUN = tun.NativeTun
|
||||
|
||||
var CreateTUNWithRequestedGUID = tun.CreateTUNWithRequestedGUID
|
||||
@@ -198,6 +198,15 @@ FunctionEnd
|
||||
######################################################################
|
||||
Section -MainProgram
|
||||
${INSTALL_TYPE}
|
||||
; The previous uninstaller stops the service and the UI only when its uninstall key
|
||||
; is found and endpoint protection lets the unsigned uninstaller run. Extraction
|
||||
; fails on any exe that is still running.
|
||||
DetailPrint "Stopping Netbird service..."
|
||||
ExecWait '"$INSTDIR\${MAIN_APP_EXE}" service stop'
|
||||
DetailPrint "Terminating ${UI_APP_NAME} process..."
|
||||
ExecWait '"$SYSDIR\taskkill.exe" /im ${UI_APP_EXE}.exe /f'
|
||||
; Both return before the processes release their image files.
|
||||
Sleep 3000
|
||||
# SetOverwrite ifnewer
|
||||
SetOutPath "$INSTDIR"
|
||||
!ifndef ARCH
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// MockIFaceMapper is a mock of IFaceMapper interface.
|
||||
@@ -108,10 +108,10 @@ func (mr *MockIFaceMapperMockRecorder) GetDevice() *gomock.Call {
|
||||
}
|
||||
|
||||
// GetWGDevice mocks base method.
|
||||
func (m *MockIFaceMapper) GetWGDevice() *wgdevice.Device {
|
||||
func (m *MockIFaceMapper) GetWGDevice() *wgbackend.Device {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetWGDevice")
|
||||
ret0, _ := ret[0].(*wgdevice.Device)
|
||||
ret0, _ := ret[0].(*wgbackend.Device)
|
||||
return ret0
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,6 @@ The IP addresses in the interfaces file are anonymized using the same process as
|
||||
Configuration
|
||||
The config.txt file contains anonymized configuration information of the NetBird client. Sensitive information such as private keys and SSH keys are excluded. The following fields are anonymized:
|
||||
- ManagementURL
|
||||
- AdminURL
|
||||
- NATExternalIPs
|
||||
- CustomDNSAddress
|
||||
|
||||
@@ -603,9 +602,6 @@ func (g *BundleGenerator) addConfig() error {
|
||||
if g.internalConfig.ManagementURL != nil {
|
||||
configContent.WriteString(fmt.Sprintf("ManagementURL: %s\n", g.anonymizer.AnonymizeURI(g.internalConfig.ManagementURL.String())))
|
||||
}
|
||||
if g.internalConfig.AdminURL != nil {
|
||||
configContent.WriteString(fmt.Sprintf("AdminURL: %s\n", g.anonymizer.AnonymizeURI(g.internalConfig.AdminURL.String())))
|
||||
}
|
||||
configContent.WriteString(fmt.Sprintf("NATExternalIPs: %v\n", anonymizeNATExternalIPs(g.internalConfig.NATExternalIPs, g.anonymizer)))
|
||||
if g.internalConfig.CustomDNSAddress != "" {
|
||||
configContent.WriteString(fmt.Sprintf("CustomDNSAddress: %s\n", g.anonymizer.AnonymizeString(g.internalConfig.CustomDNSAddress)))
|
||||
@@ -614,9 +610,6 @@ func (g *BundleGenerator) addConfig() error {
|
||||
if g.internalConfig.ManagementURL != nil {
|
||||
configContent.WriteString(fmt.Sprintf("ManagementURL: %s\n", g.internalConfig.ManagementURL.String()))
|
||||
}
|
||||
if g.internalConfig.AdminURL != nil {
|
||||
configContent.WriteString(fmt.Sprintf("AdminURL: %s\n", g.internalConfig.AdminURL.String()))
|
||||
}
|
||||
configContent.WriteString(fmt.Sprintf("NATExternalIPs: %v\n", g.internalConfig.NATExternalIPs))
|
||||
if g.internalConfig.CustomDNSAddress != "" {
|
||||
configContent.WriteString(fmt.Sprintf("CustomDNSAddress: %s\n", g.internalConfig.CustomDNSAddress))
|
||||
|
||||
@@ -856,14 +856,12 @@ func TestAddConfig_AllFieldsCovered(t *testing.T) {
|
||||
}
|
||||
|
||||
mURL, _ := url.Parse("https://api.example.com:443")
|
||||
aURL, _ := url.Parse("https://admin.example.com:443")
|
||||
bTrue := true
|
||||
iVal := 42
|
||||
cfg := &profilemanager.Config{
|
||||
PrivateKey: "priv",
|
||||
PreSharedKey: "psk",
|
||||
ManagementURL: mURL,
|
||||
AdminURL: aURL,
|
||||
WgIface: "wt0",
|
||||
WgPort: 51820,
|
||||
NetworkMonitor: &bTrue,
|
||||
@@ -947,7 +945,7 @@ func TestAddConfig_AllFieldsCovered(t *testing.T) {
|
||||
}
|
||||
|
||||
// renderAddConfigSpecific renders the fields handled by the anonymize/non-anonymize
|
||||
// branches in addConfig (ManagementURL, AdminURL, NATExternalIPs, CustomDNSAddress).
|
||||
// branches in addConfig (ManagementURL, NATExternalIPs, CustomDNSAddress).
|
||||
// addCommonConfigFields covers the rest. Keeping this in the test mirrors the
|
||||
// production shape without needing to write an actual zip.
|
||||
func renderAddConfigSpecific(g *BundleGenerator) string {
|
||||
@@ -956,9 +954,6 @@ func renderAddConfigSpecific(g *BundleGenerator) string {
|
||||
if g.internalConfig.ManagementURL != nil {
|
||||
sb.WriteString("ManagementURL: " + g.anonymizer.AnonymizeURI(g.internalConfig.ManagementURL.String()) + "\n")
|
||||
}
|
||||
if g.internalConfig.AdminURL != nil {
|
||||
sb.WriteString("AdminURL: " + g.anonymizer.AnonymizeURI(g.internalConfig.AdminURL.String()) + "\n")
|
||||
}
|
||||
sb.WriteString("NATExternalIPs: x\n")
|
||||
if g.internalConfig.CustomDNSAddress != "" {
|
||||
sb.WriteString("CustomDNSAddress: " + g.anonymizer.AnonymizeString(g.internalConfig.CustomDNSAddress) + "\n")
|
||||
@@ -967,9 +962,6 @@ func renderAddConfigSpecific(g *BundleGenerator) string {
|
||||
if g.internalConfig.ManagementURL != nil {
|
||||
sb.WriteString("ManagementURL: " + g.internalConfig.ManagementURL.String() + "\n")
|
||||
}
|
||||
if g.internalConfig.AdminURL != nil {
|
||||
sb.WriteString("AdminURL: " + g.internalConfig.AdminURL.String() + "\n")
|
||||
}
|
||||
sb.WriteString("NATExternalIPs: x\n")
|
||||
if g.internalConfig.CustomDNSAddress != "" {
|
||||
sb.WriteString("CustomDNSAddress: " + g.internalConfig.CustomDNSAddress + "\n")
|
||||
|
||||
@@ -35,11 +35,7 @@ func parseBackupResolvConf() (*resolvConf, error) {
|
||||
}
|
||||
|
||||
func parseResolvConfFile(resolvConfFile string) (*resolvConf, error) {
|
||||
rconf := &resolvConf{
|
||||
searchDomains: make([]string, 0),
|
||||
nameServers: make([]netip.Addr, 0),
|
||||
others: make([]string, 0),
|
||||
}
|
||||
rconf := newResolvConf()
|
||||
|
||||
file, err := os.Open(resolvConfFile)
|
||||
if err != nil {
|
||||
@@ -56,56 +52,74 @@ func parseResolvConfFile(resolvConfFile string) (*resolvConf, error) {
|
||||
return rconf, fmt.Errorf("failed to read %s file: %w", resolvConfFile, err)
|
||||
}
|
||||
|
||||
return parseResolvConf(cur)
|
||||
}
|
||||
|
||||
// parseResolvConf parses resolv.conf content. The returned config is never nil, so callers can
|
||||
// fall back to its empty lists on error.
|
||||
func parseResolvConf(cur []byte) (*resolvConf, error) {
|
||||
rconf := newResolvConf()
|
||||
|
||||
if len(cur) == 0 {
|
||||
return rconf, fmt.Errorf("file is empty")
|
||||
}
|
||||
|
||||
for _, line := range strings.Split(string(cur), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "domain") {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "options") && strings.Contains(line, "rotate") {
|
||||
line = strings.ReplaceAll(line, "rotate", "")
|
||||
splitLines := strings.Fields(line)
|
||||
if len(splitLines) == 1 {
|
||||
continue
|
||||
}
|
||||
line = strings.Join(splitLines, " ")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "search") {
|
||||
splitLines := strings.Fields(line)
|
||||
if len(splitLines) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
rconf.searchDomains = splitLines[1:]
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "nameserver") {
|
||||
splitLines := strings.Fields(line)
|
||||
if len(splitLines) != 2 {
|
||||
continue
|
||||
}
|
||||
if addr, err := netip.ParseAddr(splitLines[1]); err == nil {
|
||||
rconf.nameServers = append(rconf.nameServers, addr.Unmap())
|
||||
} else {
|
||||
log.Warnf("invalid nameserver address in resolv.conf: %s, skipping", splitLines[1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if line != "" {
|
||||
rconf.others = append(rconf.others, line)
|
||||
}
|
||||
parseResolvConfLine(rconf, strings.TrimSpace(line))
|
||||
}
|
||||
return rconf, nil
|
||||
}
|
||||
|
||||
func parseResolvConfLine(rconf *resolvConf, line string) {
|
||||
if strings.HasPrefix(line, "#") {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "domain") {
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "options") && strings.Contains(line, "rotate") {
|
||||
line = strings.ReplaceAll(line, "rotate", "")
|
||||
splitLines := strings.Fields(line)
|
||||
if len(splitLines) == 1 {
|
||||
return
|
||||
}
|
||||
line = strings.Join(splitLines, " ")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "search") {
|
||||
splitLines := strings.Fields(line)
|
||||
if len(splitLines) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
rconf.searchDomains = splitLines[1:]
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "nameserver") {
|
||||
splitLines := strings.Fields(line)
|
||||
if len(splitLines) != 2 {
|
||||
return
|
||||
}
|
||||
if addr, err := netip.ParseAddr(splitLines[1]); err == nil {
|
||||
rconf.nameServers = append(rconf.nameServers, addr.Unmap())
|
||||
} else {
|
||||
log.Warnf("invalid nameserver address in resolv.conf: %s, skipping", splitLines[1])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if line != "" {
|
||||
rconf.others = append(rconf.others, line)
|
||||
}
|
||||
}
|
||||
|
||||
func newResolvConf() *resolvConf {
|
||||
return &resolvConf{
|
||||
searchDomains: make([]string, 0),
|
||||
nameServers: make([]netip.Addr, 0),
|
||||
others: make([]string, 0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
@@ -23,7 +25,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type repairConfFn func([]string, netip.Addr, *resolvConf, *statemanager.Manager) error
|
||||
// repairConfFn writes the NetBird-managed resolv.conf and returns the exact content it wrote.
|
||||
type repairConfFn func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error)
|
||||
|
||||
type repair struct {
|
||||
operationFile string
|
||||
@@ -43,7 +46,9 @@ func newRepair(operationFile string, updateFn repairConfFn) *repair {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *repair) watchFileChanges(nbSearchDomains []string, nbNameserverIP netip.Addr, stateManager *statemanager.Manager) {
|
||||
// watchFileChanges keeps resolv.conf pointing at NetBird. written is the content NetBird last
|
||||
// wrote to the file, used to recognize the echo of its own writes.
|
||||
func (f *repair) watchFileChanges(nbSearchDomains []string, nbNameserverIP netip.Addr, written []byte, stateManager *statemanager.Manager) {
|
||||
if f.inotify != nil {
|
||||
return
|
||||
}
|
||||
@@ -54,54 +59,80 @@ func (f *repair) watchFileChanges(nbSearchDomains []string, nbNameserverIP netip
|
||||
log.Errorf("failed to start inotify watcher for resolv.conf: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := inotify.Add(f.watchDir); err != nil {
|
||||
log.Errorf("failed to add inotify watch for resolv.conf: %s", err)
|
||||
if err := inotify.Close(); err != nil {
|
||||
log.Debugf("failed to close resolv.conf inotify: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
f.inotify = inotify
|
||||
|
||||
f.inotifyWg.Add(1)
|
||||
go func() {
|
||||
defer f.inotifyWg.Done()
|
||||
for event := range f.inotify.Events {
|
||||
if !f.isEventRelevant(event) {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Tracef("%s changed, check if it is broken", f.operationFile)
|
||||
|
||||
rConf, err := parseResolvConfFile(f.operationFile)
|
||||
if err != nil {
|
||||
log.Warnf("failed to parse resolv conf: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("check resolv.conf parameters: %s", rConf)
|
||||
if !isNbParamsMissing(nbSearchDomains, nbNameserverIP, rConf) {
|
||||
log.Tracef("resolv.conf still correct, skip the update")
|
||||
continue
|
||||
}
|
||||
log.Info("broken params in resolv.conf, repairing it...")
|
||||
|
||||
err = f.inotify.Remove(f.watchDir)
|
||||
if err != nil {
|
||||
log.Errorf("failed to rm inotify watch for resolv.conf: %s", err)
|
||||
}
|
||||
|
||||
err = f.updateFn(nbSearchDomains, nbNameserverIP, rConf, stateManager)
|
||||
if err != nil {
|
||||
log.Errorf("failed to repair resolv.conf: %v", err)
|
||||
}
|
||||
|
||||
err = f.inotify.Add(f.watchDir)
|
||||
if err != nil {
|
||||
log.Errorf("failed to re-add inotify watch for resolv.conf: %s", err)
|
||||
return
|
||||
// A change that landed before the watch was armed produced no event.
|
||||
lastWritten := f.checkAndRepair(nbSearchDomains, nbNameserverIP, written, stateManager)
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-inotify.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if !f.isEventRelevant(event) {
|
||||
continue
|
||||
}
|
||||
case err, ok := <-inotify.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
// fsnotify stops delivering events until an error is received, and an
|
||||
// error such as a queue overflow means events were dropped.
|
||||
log.Warnf("resolv.conf inotify error, checking the file: %v", err)
|
||||
}
|
||||
lastWritten = f.checkAndRepair(nbSearchDomains, nbNameserverIP, lastWritten, stateManager)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
err = f.inotify.Add(f.watchDir)
|
||||
// checkAndRepair rewrites resolv.conf when NetBird's parameters are missing from it and returns
|
||||
// the content NetBird last wrote. The watch stays armed while repairing, so a third-party write
|
||||
// racing the repair still raises an event; the echo of NetBird's own write is skipped by content.
|
||||
func (f *repair) checkAndRepair(nbSearchDomains []string, nbNameserverIP netip.Addr, lastWritten []byte, stateManager *statemanager.Manager) []byte {
|
||||
content, err := os.ReadFile(f.operationFile)
|
||||
if err != nil {
|
||||
log.Errorf("failed to add inotify watch for resolv.conf: %s", err)
|
||||
return
|
||||
log.Warnf("failed to read resolv.conf: %s", err)
|
||||
return lastWritten
|
||||
}
|
||||
|
||||
if bytes.Equal(content, lastWritten) {
|
||||
log.Tracef("%s still holds the NetBird managed content, skip the check", f.operationFile)
|
||||
return lastWritten
|
||||
}
|
||||
|
||||
log.Tracef("%s changed, check if it is broken", f.operationFile)
|
||||
|
||||
rConf, err := parseResolvConf(content)
|
||||
if err != nil {
|
||||
log.Warnf("failed to parse resolv conf: %s", err)
|
||||
return lastWritten
|
||||
}
|
||||
|
||||
log.Debugf("check resolv.conf parameters: %s", rConf)
|
||||
if !isNbParamsMissing(nbSearchDomains, nbNameserverIP, rConf) {
|
||||
log.Tracef("resolv.conf still correct, skip the update")
|
||||
return lastWritten
|
||||
}
|
||||
log.Info("broken params in resolv.conf, repairing it...")
|
||||
|
||||
written, err := f.updateFn(nbSearchDomains, nbNameserverIP, rConf, stateManager)
|
||||
if err != nil {
|
||||
log.Errorf("failed to repair resolv.conf: %v", err)
|
||||
return lastWritten
|
||||
}
|
||||
return written
|
||||
}
|
||||
|
||||
func (f *repair) stopWatchFileChanges() {
|
||||
|
||||
@@ -4,12 +4,19 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||
"github.com/netbirdio/netbird/util"
|
||||
)
|
||||
@@ -106,14 +113,14 @@ nameserver 8.8.8.8`,
|
||||
|
||||
var changed bool
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) error {
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error) {
|
||||
changed = true
|
||||
cancel()
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
r := newRepair(operationFile, updateFn)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), nil)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), nil, nil)
|
||||
|
||||
err = os.WriteFile(operationFile, []byte(tt.touchedConfContent), 0755)
|
||||
if err != nil {
|
||||
@@ -153,14 +160,14 @@ searchdomain netbird.cloud something`
|
||||
|
||||
var changed bool
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) error {
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error) {
|
||||
changed = true
|
||||
cancel()
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
r := newRepair(tmpLink, updateFn)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), nil)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), nil, nil)
|
||||
|
||||
err = os.WriteFile(tmpLink, []byte(modifyContent), 0755)
|
||||
if err != nil {
|
||||
@@ -175,3 +182,149 @@ searchdomain netbird.cloud something`
|
||||
t.Errorf("unexpected result: want: %v, got: %v", true, false)
|
||||
}
|
||||
}
|
||||
|
||||
// systemd-resolved can rewrite resolv.conf twice in a row, e.g. on restart. When the second write
|
||||
// lands right after NetBird's repair, the watcher must still see it and repair again; otherwise the
|
||||
// host silently stays on the upstream resolver until the next unrelated change of the file.
|
||||
func Test_repairCatchesWriteRacingRepair(t *testing.T) {
|
||||
good := "nameserver 10.0.0.1\nsearch netbird.cloud\n"
|
||||
upstream := "nameserver 8.8.8.8\nsearch .\n"
|
||||
operationFile := filepath.Join(t.TempDir(), "resolv.conf")
|
||||
require.NoError(t, os.WriteFile(operationFile, []byte(good), 0644))
|
||||
|
||||
var calls atomic.Int32
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error) {
|
||||
n := calls.Add(1)
|
||||
if err := os.WriteFile(operationFile, []byte(good), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 1 {
|
||||
// the third party's second write lands right after the repair
|
||||
if err := writeFileAtomic(operationFile, upstream); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return []byte(good), nil
|
||||
}
|
||||
|
||||
r := newRepair(operationFile, updateFn)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), []byte(good), nil)
|
||||
t.Cleanup(r.stopWatchFileChanges)
|
||||
|
||||
require.NoError(t, writeFileAtomic(operationFile, upstream))
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
content, err := os.ReadFile(operationFile)
|
||||
return err == nil && string(content) == good
|
||||
}, 2*time.Second, 10*time.Millisecond, "resolv.conf should be repaired after the racing write")
|
||||
assert.GreaterOrEqual(t, calls.Load(), int32(2), "the racing write should trigger a second repair")
|
||||
}
|
||||
|
||||
// A change made between NetBird's write and the arming of the watch produces no event, so the
|
||||
// watcher must check the file as soon as it starts.
|
||||
func Test_repairChecksFileWhenArmed(t *testing.T) {
|
||||
good := "nameserver 10.0.0.1\nsearch netbird.cloud\n"
|
||||
operationFile := filepath.Join(t.TempDir(), "resolv.conf")
|
||||
require.NoError(t, os.WriteFile(operationFile, []byte("nameserver 8.8.8.8\n"), 0644))
|
||||
|
||||
repaired := make(chan struct{}, 1)
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error) {
|
||||
select {
|
||||
case repaired <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
return []byte(good), os.WriteFile(operationFile, []byte(good), 0644)
|
||||
}
|
||||
|
||||
r := newRepair(operationFile, updateFn)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), []byte(good), nil)
|
||||
t.Cleanup(r.stopWatchFileChanges)
|
||||
|
||||
select {
|
||||
case <-repaired:
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("watcher should repair a file changed before it was armed")
|
||||
}
|
||||
}
|
||||
|
||||
// When NetBird has more search domains than resolv.conf can hold, its own write lacks some of them
|
||||
// and fails the parameter check. The watcher must recognize that write as its own and not repair
|
||||
// it again in a loop.
|
||||
func Test_repairNoLoopOnTruncatedSearchDomains(t *testing.T) {
|
||||
nbDomains := make([]string, 0, fileMaxNumberOfSearchDomains+2)
|
||||
for i := range fileMaxNumberOfSearchDomains + 2 {
|
||||
nbDomains = append(nbDomains, fmt.Sprintf("d%d.netbird.cloud", i))
|
||||
}
|
||||
truncated := fmt.Sprintf("nameserver 10.0.0.1\nsearch %s\n", strings.Join(nbDomains[:fileMaxNumberOfSearchDomains], " "))
|
||||
|
||||
operationFile := filepath.Join(t.TempDir(), "resolv.conf")
|
||||
require.NoError(t, os.WriteFile(operationFile, []byte(truncated), 0644))
|
||||
|
||||
var calls atomic.Int32
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error) {
|
||||
calls.Add(1)
|
||||
return []byte(truncated), os.WriteFile(operationFile, []byte(truncated), 0644)
|
||||
}
|
||||
|
||||
r := newRepair(operationFile, updateFn)
|
||||
r.watchFileChanges(nbDomains, netip.MustParseAddr("10.0.0.1"), []byte(truncated), nil)
|
||||
t.Cleanup(r.stopWatchFileChanges)
|
||||
|
||||
require.NoError(t, writeFileAtomic(operationFile, "nameserver 8.8.8.8\n"))
|
||||
|
||||
require.Eventually(t, func() bool { return calls.Load() >= 1 }, 2*time.Second, 10*time.Millisecond,
|
||||
"the third-party write should be repaired")
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.Equal(t, int32(1), calls.Load(), "NetBird's own truncated write should not trigger another repair")
|
||||
}
|
||||
|
||||
// fsnotify blocks its reader until an error is received, and an error such as a queue overflow
|
||||
// means events were dropped. The watcher must consume errors and check the file, so it keeps working
|
||||
// and catches a change whose event was lost.
|
||||
func Test_repairChecksFileOnWatcherError(t *testing.T) {
|
||||
good := "nameserver 10.0.0.1\nsearch netbird.cloud\n"
|
||||
operationFile := filepath.Join(t.TempDir(), "resolv.conf")
|
||||
require.NoError(t, os.WriteFile(operationFile, []byte(good), 0644))
|
||||
|
||||
// A hard link in another directory changes the file without an event in the watched one,
|
||||
// standing in for an event the kernel dropped.
|
||||
alias := filepath.Join(t.TempDir(), "alias")
|
||||
require.NoError(t, os.Link(operationFile, alias))
|
||||
|
||||
repaired := make(chan struct{}, 1)
|
||||
updateFn := func([]string, netip.Addr, *resolvConf, *statemanager.Manager) ([]byte, error) {
|
||||
select {
|
||||
case repaired <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
return []byte(good), os.WriteFile(operationFile, []byte(good), 0644)
|
||||
}
|
||||
|
||||
r := newRepair(operationFile, updateFn)
|
||||
r.watchFileChanges([]string{"netbird.cloud"}, netip.MustParseAddr("10.0.0.1"), []byte(good), nil)
|
||||
t.Cleanup(r.stopWatchFileChanges)
|
||||
|
||||
require.NoError(t, os.WriteFile(alias, []byte("nameserver 8.8.8.8\n"), 0644))
|
||||
|
||||
select {
|
||||
case r.inotify.Errors <- fsnotify.ErrEventOverflow:
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("watcher should consume inotify errors")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-repaired:
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("watcher should check the file after an inotify error")
|
||||
}
|
||||
}
|
||||
|
||||
// writeFileAtomic replaces the file the way systemd-resolved does: write a temporary file in the same
|
||||
// directory, then rename it over the target.
|
||||
func writeFileAtomic(target, content string) error {
|
||||
tmp := target + ".tmp"
|
||||
if err := os.WriteFile(tmp, []byte(content), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmp, target)
|
||||
}
|
||||
|
||||
@@ -61,11 +61,11 @@ func (f *fileConfigurator) applyDNSConfig(config HostDNSConfig, stateManager *st
|
||||
|
||||
f.repair.stopWatchFileChanges()
|
||||
|
||||
err = f.updateConfig(nbSearchDomains, f.nbNameserverIP, resolvConf, stateManager)
|
||||
written, err := f.updateConfig(nbSearchDomains, f.nbNameserverIP, resolvConf, stateManager)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.repair.watchFileChanges(nbSearchDomains, f.nbNameserverIP, stateManager)
|
||||
f.repair.watchFileChanges(nbSearchDomains, f.nbNameserverIP, written, stateManager)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (f *fileConfigurator) getOriginalNameservers() []netip.Addr {
|
||||
return f.originalNameservers
|
||||
}
|
||||
|
||||
func (f *fileConfigurator) updateConfig(nbSearchDomains []string, nbNameserverIP netip.Addr, cfg *resolvConf, stateManager *statemanager.Manager) error {
|
||||
func (f *fileConfigurator) updateConfig(nbSearchDomains []string, nbNameserverIP netip.Addr, cfg *resolvConf, stateManager *statemanager.Manager) ([]byte, error) {
|
||||
searchDomainList := mergeSearchDomains(nbSearchDomains, cfg.searchDomains)
|
||||
|
||||
buf := prepareResolvConfContent(
|
||||
@@ -90,7 +90,7 @@ func (f *fileConfigurator) updateConfig(nbSearchDomains []string, nbNameserverIP
|
||||
if restoreErr != nil {
|
||||
log.Errorf("attempt to restore default file failed with error: %s", err)
|
||||
}
|
||||
return fmt.Errorf("creating resolver file %s. Error: %w", defaultResolvConfPath, err)
|
||||
return nil, fmt.Errorf("creating resolver file %s. Error: %w", defaultResolvConfPath, err)
|
||||
}
|
||||
|
||||
log.Infof("created a NetBird managed %s file with the DNS settings. Added %d search domains. Search list: %s", defaultResolvConfPath, len(searchDomainList), searchDomainList)
|
||||
@@ -100,7 +100,7 @@ func (f *fileConfigurator) updateConfig(nbSearchDomains []string, nbNameserverIP
|
||||
log.Errorf("failed to create unclean shutdown resolv.conf backup: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (f *fileConfigurator) restoreHostDNS() error {
|
||||
|
||||
@@ -7,14 +7,15 @@ import (
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/miekg/dns"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type responseWriter struct {
|
||||
local net.Addr
|
||||
remote net.Addr
|
||||
packet gopacket.Packet
|
||||
device tun.Device
|
||||
device wgbackend.TUN
|
||||
}
|
||||
|
||||
// LocalAddr returns the net.Addr of the server
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/firewall/uspfilter"
|
||||
@@ -23,6 +22,7 @@ import (
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/local"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||
@@ -83,7 +83,7 @@ func (w *mocWGIface) GetStats(_ string) (configurer.WGStats, error) {
|
||||
return configurer.WGStats{}, nil
|
||||
}
|
||||
|
||||
func (w *mocWGIface) GetNet() *netstack.Net {
|
||||
func (w *mocWGIface) GetNet() *wgbackend.NetstackNet {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ func (s *ServiceViaMemory) filterDNSTraffic() error {
|
||||
if s.tcpDNS == nil {
|
||||
if dev := s.wgInterface.GetDevice(); dev != nil {
|
||||
// MTU only affects TCP segment sizing; DNS messages are small so this has no practical impact.
|
||||
s.tcpDNS = newTCPDNSServer(s.dnsMux, dev.Device, s.runtimeIP, uint16(s.runtimePort), iface.DefaultMTU)
|
||||
s.tcpDNS = newTCPDNSServer(s.dnsMux, dev.TUN, s.runtimeIP, uint16(s.runtimePort), iface.DefaultMTU)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ func (s *ServiceViaMemory) filterDNSTraffic() error {
|
||||
writer := &responseWriter{
|
||||
remote: remoteAddrFromPacket(packet),
|
||||
packet: packet,
|
||||
device: dev.Device,
|
||||
device: dev.TUN,
|
||||
}
|
||||
go s.dnsMux.ServeDNS(writer, msg)
|
||||
return true
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/miekg/dns"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
"gvisor.dev/gvisor/pkg/buffer"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||
@@ -21,6 +20,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -38,7 +39,7 @@ type tcpDNSServer struct {
|
||||
s *stack.Stack
|
||||
ep *dnsEndpoint
|
||||
mux *dns.ServeMux
|
||||
tunDev tun.Device
|
||||
tunDev wgbackend.TUN
|
||||
ip netip.Addr
|
||||
port uint16
|
||||
mtu uint16
|
||||
@@ -49,7 +50,7 @@ type tcpDNSServer struct {
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
func newTCPDNSServer(mux *dns.ServeMux, tunDev tun.Device, ip netip.Addr, port uint16, mtu uint16) *tcpDNSServer {
|
||||
func newTCPDNSServer(mux *dns.ServeMux, tunDev wgbackend.TUN, ip netip.Addr, port uint16, mtu uint16) *tcpDNSServer {
|
||||
return &tcpDNSServer{
|
||||
mux: mux,
|
||||
tunDev: tunDev,
|
||||
@@ -270,7 +271,7 @@ func (t *tcpDNSServer) handleTCPDNS(r *tcp.ForwarderRequest) {
|
||||
// dnsEndpoint implements stack.LinkEndpoint for writing packets back via the tun device.
|
||||
type dnsEndpoint struct {
|
||||
dispatcher stack.NetworkDispatcher
|
||||
tunDev tun.Device
|
||||
tunDev wgbackend.TUN
|
||||
mtu atomic.Uint32
|
||||
}
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@ import (
|
||||
|
||||
"github.com/miekg/dns"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/resutil"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
@@ -714,7 +714,7 @@ func toTCPClient(c *dns.Client) *dns.Client {
|
||||
|
||||
// ExchangeWithNetstack performs a DNS exchange using netstack for dialing.
|
||||
// This is needed when netstack is enabled to reach peer IPs through the tunnel.
|
||||
func ExchangeWithNetstack(ctx context.Context, nsNet *netstack.Net, r *dns.Msg, upstream string) (*dns.Msg, error) {
|
||||
func ExchangeWithNetstack(ctx context.Context, nsNet *wgbackend.NetstackNet, r *dns.Msg, upstream string) (*dns.Msg, error) {
|
||||
// If request came in over TCP, go straight to TCP upstream
|
||||
if dnsProtocolFromContext(ctx) == protoTCP {
|
||||
rm, err := netstackExchange(ctx, nsNet, r, upstream, protoTCP)
|
||||
@@ -758,7 +758,7 @@ func ExchangeWithNetstack(ctx context.Context, nsNet *netstack.Net, r *dns.Msg,
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func netstackExchange(ctx context.Context, nsNet *netstack.Net, r *dns.Msg, upstream, network string) (*dns.Msg, error) {
|
||||
func netstackExchange(ctx context.Context, nsNet *wgbackend.NetstackNet, r *dns.Msg, upstream, network string) (*dns.Msg, error) {
|
||||
conn, err := nsNet.DialContext(ctx, network, upstream)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("with %s: %w", network, err)
|
||||
|
||||
@@ -9,15 +9,15 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
)
|
||||
|
||||
type upstreamResolver struct {
|
||||
*upstreamResolverBase
|
||||
nsNet *netstack.Net
|
||||
nsNet *wgbackend.NetstackNet
|
||||
}
|
||||
|
||||
func newUpstreamResolver(
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||
)
|
||||
|
||||
@@ -128,7 +128,7 @@ func (m *mockNetstackProvider) ToInterface() *net.Interface { return nil }
|
||||
func (m *mockNetstackProvider) IsUserspaceBind() bool { return false }
|
||||
func (m *mockNetstackProvider) GetFilter() device.PacketFilter { return nil }
|
||||
func (m *mockNetstackProvider) GetDevice() *device.FilteredDevice { return nil }
|
||||
func (m *mockNetstackProvider) GetNet() *netstack.Net { return nil }
|
||||
func (m *mockNetstackProvider) GetNet() *wgbackend.NetstackNet { return nil }
|
||||
func (m *mockNetstackProvider) GetInterfaceGUIDString() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ package dns
|
||||
import (
|
||||
"net"
|
||||
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// WGIface defines subset methods of interface required for manager
|
||||
@@ -19,5 +18,5 @@ type WGIface interface {
|
||||
IsUserspaceBind() bool
|
||||
GetFilter() device.PacketFilter
|
||||
GetDevice() *device.FilteredDevice
|
||||
GetNet() *netstack.Net
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package dns
|
||||
|
||||
import (
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
// WGIface defines subset methods of interface required for manager
|
||||
@@ -14,6 +13,6 @@ type WGIface interface {
|
||||
IsUserspaceBind() bool
|
||||
GetFilter() device.PacketFilter
|
||||
GetDevice() *device.FilteredDevice
|
||||
GetNet() *netstack.Net
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
GetInterfaceGUIDString() (string, error)
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/miekg/dns"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/dns/resutil"
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
"github.com/netbirdio/netbird/route"
|
||||
@@ -90,7 +90,7 @@ func NewDNSForwarder(listenAddress netip.AddrPort, ttl uint32, firewall firewall
|
||||
}
|
||||
|
||||
func (f *DNSForwarder) Listen(entries []*ForwarderEntry) error {
|
||||
var netstackNet *netstack.Net
|
||||
var netstackNet *wgbackend.NetstackNet
|
||||
if f.wgIface != nil {
|
||||
netstackNet = f.wgIface.GetNet()
|
||||
}
|
||||
@@ -153,7 +153,7 @@ func (f *DNSForwarder) Listen(entries []*ForwarderEntry) error {
|
||||
return <-errCh
|
||||
}
|
||||
|
||||
func (f *DNSForwarder) createUDPListener(netstackNet *netstack.Net) (net.PacketConn, error) {
|
||||
func (f *DNSForwarder) createUDPListener(netstackNet *wgbackend.NetstackNet) (net.PacketConn, error) {
|
||||
if netstackNet != nil {
|
||||
return netstackNet.ListenUDPAddrPort(f.listenAddress)
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (f *DNSForwarder) createUDPListener(netstackNet *netstack.Net) (net.PacketC
|
||||
return net.ListenUDP("udp", net.UDPAddrFromAddrPort(f.listenAddress))
|
||||
}
|
||||
|
||||
func (f *DNSForwarder) createTCPListener(netstackNet *netstack.Net) (net.Listener, error) {
|
||||
func (f *DNSForwarder) createTCPListener(netstackNet *wgbackend.NetstackNet) (net.Listener, error) {
|
||||
if netstackNet != nil {
|
||||
return netstackNet.ListenTCPAddrPort(f.listenAddress)
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ import (
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||
"github.com/netbirdio/netbird/client/internal/peer"
|
||||
nbdns "github.com/netbirdio/netbird/dns"
|
||||
@@ -28,7 +28,7 @@ const (
|
||||
|
||||
// wgIface defines the interface for WireGuard interface operations needed by the DNS forwarder.
|
||||
type wgIface interface {
|
||||
GetNet() *netstack.Net
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
Address() wgaddr.Address
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
"github.com/pion/stun/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/anonymize"
|
||||
@@ -37,6 +35,7 @@ import (
|
||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/acl"
|
||||
"github.com/netbirdio/netbird/client/internal/certproof"
|
||||
"github.com/netbirdio/netbird/client/internal/debug"
|
||||
@@ -254,7 +253,7 @@ type Engine struct {
|
||||
// wgInterface. Reaching the device through wgInterface requires
|
||||
// syncMsgMux, which handleSync holds while it adds and removes peers;
|
||||
// SetPerformance must stay reachable exactly when that work is stuck.
|
||||
wgDevice atomic.Pointer[wgdevice.Device]
|
||||
wgDevice atomic.Pointer[wgbackend.Device]
|
||||
|
||||
udpMux *udpmux.UniversalUDPMuxDefault
|
||||
|
||||
@@ -2788,7 +2787,7 @@ func (e *Engine) stopDNSForwarder() {
|
||||
e.dnsForwardMgr = nil
|
||||
}
|
||||
|
||||
func (e *Engine) GetNet() (*netstack.Net, error) {
|
||||
func (e *Engine) GetNet() (*wgbackend.NetstackNet, error) {
|
||||
e.syncMsgMux.Lock()
|
||||
intf := e.wgInterface
|
||||
e.syncMsgMux.Unlock()
|
||||
|
||||
@@ -14,10 +14,9 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/stdnet"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
@@ -61,11 +60,11 @@ type MockWGIface struct {
|
||||
SetFilterFunc func(filter device.PacketFilter) error
|
||||
GetFilterFunc func() device.PacketFilter
|
||||
GetDeviceFunc func() *device.FilteredDevice
|
||||
GetWGDeviceFunc func() *wgdevice.Device
|
||||
GetWGDeviceFunc func() *wgbackend.Device
|
||||
GetStatsFunc func() (map[string]configurer.WGStats, error)
|
||||
GetInterfaceGUIDStringFunc func() (string, error)
|
||||
GetProxyFunc func() wgproxy.Proxy
|
||||
GetNetFunc func() *netstack.Net
|
||||
GetNetFunc func() *wgbackend.NetstackNet
|
||||
LastActivitiesFunc func() map[string]monotime.Time
|
||||
}
|
||||
|
||||
@@ -149,7 +148,7 @@ func (m *MockWGIface) GetDevice() *device.FilteredDevice {
|
||||
return m.GetDeviceFunc()
|
||||
}
|
||||
|
||||
func (m *MockWGIface) GetWGDevice() *wgdevice.Device {
|
||||
func (m *MockWGIface) GetWGDevice() *wgbackend.Device {
|
||||
return m.GetWGDeviceFunc()
|
||||
}
|
||||
|
||||
@@ -161,7 +160,7 @@ func (m *MockWGIface) GetProxy() wgproxy.Proxy {
|
||||
return m.GetProxyFunc()
|
||||
}
|
||||
|
||||
func (m *MockWGIface) GetNet() *netstack.Net {
|
||||
func (m *MockWGIface) GetNet() *wgbackend.NetstackNet {
|
||||
return m.GetNetFunc()
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,13 @@ import (
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/iface/wgproxy"
|
||||
"github.com/netbirdio/netbird/monotime"
|
||||
)
|
||||
@@ -37,9 +36,9 @@ type wgIfaceBase interface {
|
||||
SetFilter(filter device.PacketFilter) error
|
||||
GetFilter() device.PacketFilter
|
||||
GetDevice() *device.FilteredDevice
|
||||
GetWGDevice() *wgdevice.Device
|
||||
GetWGDevice() *wgbackend.Device
|
||||
GetStats() (map[string]configurer.WGStats, error)
|
||||
GetNet() *netstack.Net
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
FullStats() (*configurer.Stats, error)
|
||||
LastActivities() map[string]monotime.Time
|
||||
SetPresharedKey(peerKey string, psk wgtypes.Key, updateOnly bool) error
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
icemaker "github.com/netbirdio/netbird/client/internal/peer/ice"
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
"github.com/pion/logging"
|
||||
"github.com/pion/randutil"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package ice
|
||||
|
||||
import (
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
|
||||
"github.com/netbirdio/netbird/client/internal/stdnet"
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package peer
|
||||
|
||||
import (
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pion/ice/v4"
|
||||
"github.com/netbirdio/ice/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -36,7 +36,8 @@ const (
|
||||
DefaultManagementURL = "https://api.netbird.io:443"
|
||||
// oldDefaultManagementURL points to the NetBird's old cloud management endpoint
|
||||
oldDefaultManagementURL = "https://api.wiretrustee.com:443"
|
||||
// DefaultAdminURL points to NetBird's cloud management console
|
||||
// DefaultAdminURL points to NetBird's cloud management console. It is only
|
||||
// reported by the deprecated mobile admin URL getters.
|
||||
DefaultAdminURL = "https://app.netbird.io:443"
|
||||
)
|
||||
|
||||
@@ -60,7 +61,6 @@ var DefaultInterfaceBlacklist = []string{
|
||||
// ConfigInput carries configuration changes to the client
|
||||
type ConfigInput struct {
|
||||
ManagementURL string
|
||||
AdminURL string
|
||||
ConfigPath string
|
||||
StateFilePath string
|
||||
PreSharedKey *string
|
||||
@@ -114,7 +114,6 @@ type Config struct {
|
||||
PrivateKey string
|
||||
PreSharedKey string
|
||||
ManagementURL *url.URL
|
||||
AdminURL *url.URL
|
||||
WgIface string
|
||||
WgPort int
|
||||
NetworkMonitor *bool
|
||||
@@ -508,29 +507,6 @@ func (config *Config) apply(input ConfigInput) (updated bool, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if config.AdminURL == nil {
|
||||
log.Infof("using default Admin URL %s", DefaultAdminURL)
|
||||
config.AdminURL, err = parseURL("Admin URL", DefaultAdminURL)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
// The admin panel is opened, not dialed, so unlike the Management URL its
|
||||
// path is part of what identifies it: a panel served under /netbird is not
|
||||
// the one served at the root.
|
||||
if input.AdminURL != "" {
|
||||
newURL, err := parseURL("Admin Panel URL", input.AdminURL)
|
||||
if err != nil {
|
||||
return updated, err
|
||||
}
|
||||
if !SameServiceURLIncludingPath(newURL, config.AdminURL) {
|
||||
log.Infof("new Admin Panel URL provided, updated to %#v (old value %#v)",
|
||||
newURL.String(), config.AdminURL.String())
|
||||
config.AdminURL = newURL
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
|
||||
if input.WireguardPort != nil && *input.WireguardPort != config.WgPort {
|
||||
log.Infof("updating Wireguard port %d (old value %d)",
|
||||
*input.WireguardPort, config.WgPort)
|
||||
@@ -1027,8 +1003,7 @@ func ParseServiceURL(serviceName, serviceURL string) (*url.URL, error) {
|
||||
// matches only another nil one.
|
||||
//
|
||||
// The path plays no part: a management URL is dialed, and only its host and
|
||||
// port are. util.SameServiceURL is this comparison plus the path, which is
|
||||
// what SameServiceURLIncludingPath needs and delegates to.
|
||||
// port are. util.SameServiceURL is this comparison plus the path.
|
||||
func SameServiceURL(a, b *url.URL) bool {
|
||||
if a == nil || b == nil {
|
||||
return a == b
|
||||
@@ -1039,25 +1014,6 @@ func SameServiceURL(a, b *url.URL) bool {
|
||||
util.ServiceURLPort(a) == util.ServiceURLPort(b)
|
||||
}
|
||||
|
||||
// SameServiceURLIncludingPath is SameServiceURL plus everything a URL carries
|
||||
// past its endpoint: path, query, fragment and userinfo.
|
||||
//
|
||||
// Use it for a URL that gets opened rather than dialed. The admin panel can
|
||||
// live under a path, so two URLs with the same endpoint and different paths are
|
||||
// two different panels — where for a URL the client dials over gRPC only the
|
||||
// endpoint is ever used. Equivalent spellings still compare equal: a missing
|
||||
// path and "/" are the same root, and so is a trailing slash on any path.
|
||||
func SameServiceURLIncludingPath(a, b *url.URL) bool {
|
||||
if a == nil || b == nil {
|
||||
return a == b
|
||||
}
|
||||
|
||||
return util.SameServiceURL(a, b) &&
|
||||
a.RawQuery == b.RawQuery &&
|
||||
a.Fragment == b.Fragment &&
|
||||
a.User.String() == b.User.String()
|
||||
}
|
||||
|
||||
func parseURL(serviceName, serviceURL string) (*url.URL, error) {
|
||||
parsedMgmtURL, err := url.ParseRequestURI(serviceURL)
|
||||
if err != nil {
|
||||
|
||||
@@ -36,17 +36,14 @@ func TestGetConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.Equal(t, config.ManagementURL.String(), DefaultManagementURL)
|
||||
assert.Equal(t, config.AdminURL.String(), DefaultAdminURL)
|
||||
|
||||
managementURL := "https://test.management.url:33071"
|
||||
adminURL := "https://app.admin.url:443"
|
||||
path := filepath.Join(t.TempDir(), "config.json")
|
||||
preSharedKey := "preSharedKey"
|
||||
|
||||
// case 2: new config has to be generated
|
||||
config, err = UpdateOrCreateConfig(ConfigInput{
|
||||
ManagementURL: managementURL,
|
||||
AdminURL: adminURL,
|
||||
ConfigPath: path,
|
||||
PreSharedKey: &preSharedKey,
|
||||
})
|
||||
@@ -64,7 +61,6 @@ func TestGetConfig(t *testing.T) {
|
||||
// case 3: existing config -> fetch it
|
||||
config, err = UpdateOrCreateConfig(ConfigInput{
|
||||
ManagementURL: managementURL,
|
||||
AdminURL: adminURL,
|
||||
ConfigPath: path,
|
||||
PreSharedKey: &preSharedKey,
|
||||
})
|
||||
@@ -79,7 +75,6 @@ func TestGetConfig(t *testing.T) {
|
||||
newManagementURL := "https://test.newManagement.url:33071"
|
||||
config, err = UpdateOrCreateConfig(ConfigInput{
|
||||
ManagementURL: newManagementURL,
|
||||
AdminURL: adminURL,
|
||||
ConfigPath: path,
|
||||
PreSharedKey: &preSharedKey,
|
||||
})
|
||||
@@ -164,7 +159,6 @@ func TestNewProfileDefaults(t *testing.T) {
|
||||
require.NoError(t, err, "should create new config")
|
||||
|
||||
assert.Equal(t, DefaultManagementURL, config.ManagementURL.String(), "ManagementURL should have default")
|
||||
assert.Equal(t, DefaultAdminURL, config.AdminURL.String(), "AdminURL should have default")
|
||||
assert.NotEmpty(t, config.PrivateKey, "PrivateKey should be generated")
|
||||
assert.NotEmpty(t, config.SSHKey, "SSHKey should be generated")
|
||||
assert.Equal(t, iface.WgInterfaceDefault, config.WgIface, "WgIface should have default")
|
||||
|
||||
@@ -334,40 +334,34 @@ func TestCreateInMemoryConfigCarriesAnIdentity(t *testing.T) {
|
||||
require.NotEmpty(t, cfg.SSHKey)
|
||||
}
|
||||
|
||||
// The admin panel is opened, not dialed, so its path identifies it. Comparing
|
||||
// it as a bare endpoint left a custom panel URL unable to change.
|
||||
func TestAdminURLPathIsPartOfTheIdentity(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "panel.json")
|
||||
_, err := UpdateOrCreateConfig(ConfigInput{
|
||||
ConfigPath: path,
|
||||
AdminURL: "https://app.example.com/netbird",
|
||||
})
|
||||
// Profiles written before the admin URL was dropped still carry an AdminURL key.
|
||||
// It must not break loading, and the next write must drop it.
|
||||
func TestLegacyAdminURLIsIgnored(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "legacy.json")
|
||||
_, err := UpdateOrCreateConfig(ConfigInput{ConfigPath: path})
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg, err := GetExistingConfig(path)
|
||||
raw, err := os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "https://app.example.com:443/netbird", cfg.AdminURL.String())
|
||||
|
||||
// Equivalent spellings of the same panel are still not a change.
|
||||
for _, same := range []string{
|
||||
"https://app.example.com/netbird",
|
||||
"https://app.example.com:443/netbird",
|
||||
"https://app.example.com/netbird/",
|
||||
"https://APP.example.com/netbird",
|
||||
} {
|
||||
changed, err := cfg.WouldChange(ConfigInput{AdminURL: same})
|
||||
require.NoError(t, err)
|
||||
require.False(t, changed, "%q is the stored panel written differently", same)
|
||||
}
|
||||
|
||||
// A different path is a different panel, and it must be persisted.
|
||||
changed, err := cfg.WouldChange(ConfigInput{AdminURL: "https://app.example.com/other"})
|
||||
var stored map[string]json.RawMessage
|
||||
require.NoError(t, json.Unmarshal(raw, &stored))
|
||||
stored["AdminURL"] = json.RawMessage(`{"Scheme":"https","Host":"panel.example.com:443","Path":"/netbird"}`)
|
||||
rewritten, err := json.Marshal(stored)
|
||||
require.NoError(t, err)
|
||||
require.True(t, changed, "a different panel path is a change")
|
||||
require.NoError(t, os.WriteFile(path, rewritten, 0600))
|
||||
|
||||
updated, err := UpdateConfig(ConfigInput{ConfigPath: path, AdminURL: "https://app.example.com/other"})
|
||||
_, err = GetExistingConfig(path)
|
||||
require.NoError(t, err, "a legacy AdminURL key must not prevent loading the profile")
|
||||
|
||||
port := 51999
|
||||
_, err = UpdateConfig(ConfigInput{ConfigPath: path, WireguardPort: &port})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "https://app.example.com:443/other", updated.AdminURL.String(), "the new panel path was not persisted")
|
||||
|
||||
raw, err = os.ReadFile(path)
|
||||
require.NoError(t, err)
|
||||
stored = nil
|
||||
require.NoError(t, json.Unmarshal(raw, &stored))
|
||||
require.NotContains(t, stored, "AdminURL", "the legacy AdminURL key should be dropped on write")
|
||||
}
|
||||
|
||||
// unsetOnDisk rewrites the stored config so the named fields carry a JSON null,
|
||||
|
||||
@@ -4,10 +4,9 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
)
|
||||
|
||||
type wgIfaceBase interface {
|
||||
@@ -20,5 +19,5 @@ type wgIfaceBase interface {
|
||||
IsUserspaceBind() bool
|
||||
GetFilter() device.PacketFilter
|
||||
GetDevice() *device.FilteredDevice
|
||||
GetNet() *netstack.Net
|
||||
GetNet() *wgbackend.NetstackNet
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/device"
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
"github.com/netbirdio/netbird/client/internal/routemanager/refcounter"
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ func (m *reconcileWGMock) ToInterface() *net.Interface { return n
|
||||
func (m *reconcileWGMock) IsUserspaceBind() bool { return false }
|
||||
func (m *reconcileWGMock) GetFilter() device.PacketFilter { return nil }
|
||||
func (m *reconcileWGMock) GetDevice() *device.FilteredDevice { return nil }
|
||||
func (m *reconcileWGMock) GetNet() *netstack.Net { return nil }
|
||||
func (m *reconcileWGMock) GetNet() *wgbackend.NetstackNet { return nil }
|
||||
|
||||
// TestReconcilePeerAllowedIPs verifies the declarative reconcile re-applies every routed prefix
|
||||
// tracked for the peer (self-heal, independent of refcount level) and stays scoped to that peer.
|
||||
|
||||
@@ -61,23 +61,17 @@ func (p *Preferences) SetManagementURL(url string) {
|
||||
p.configInput.ManagementURL = url
|
||||
}
|
||||
|
||||
// GetAdminURL read url from config file
|
||||
// GetAdminURL returns the default admin panel URL.
|
||||
//
|
||||
// Deprecated: the admin URL is no longer stored or used by the client.
|
||||
func (p *Preferences) GetAdminURL() (string, error) {
|
||||
if p.configInput.AdminURL != "" {
|
||||
return p.configInput.AdminURL, nil
|
||||
}
|
||||
|
||||
cfg, err := profilemanager.ReadConfigOrDefault(p.configInput.ConfigPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return cfg.AdminURL.String(), err
|
||||
return profilemanager.DefaultAdminURL, nil
|
||||
}
|
||||
|
||||
// SetAdminURL store the given url and wait for commit
|
||||
func (p *Preferences) SetAdminURL(url string) {
|
||||
p.configInput.AdminURL = url
|
||||
}
|
||||
// SetAdminURL is a no-op kept for API compatibility.
|
||||
//
|
||||
// Deprecated: the admin URL is no longer stored or used by the client.
|
||||
func (p *Preferences) SetAdminURL(_ string) {}
|
||||
|
||||
// HasPreSharedKey reports whether a pre-shared key is staged, persisted, or
|
||||
// enforced by MDM; the key itself is never handed to the native layer.
|
||||
|
||||
@@ -47,13 +47,14 @@ func TestPreferences_ReadUncommitedValues(t *testing.T) {
|
||||
stateFile := filepath.Join(t.TempDir(), "state.json")
|
||||
p := NewPreferences(cfgFile, stateFile)
|
||||
|
||||
// The admin URL is deprecated: setting it is a no-op.
|
||||
p.SetAdminURL(exampleString)
|
||||
resp, err := p.GetAdminURL()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read admin url: %s", err)
|
||||
}
|
||||
|
||||
if resp != exampleString {
|
||||
if resp != profilemanager.DefaultAdminURL {
|
||||
t.Errorf("unexpected admin url: %s", resp)
|
||||
}
|
||||
|
||||
@@ -100,7 +101,7 @@ func TestPreferences_Commit(t *testing.T) {
|
||||
t.Fatalf("failed to read admin url: %s", err)
|
||||
}
|
||||
|
||||
if resp != exampleURL {
|
||||
if resp != profilemanager.DefaultAdminURL {
|
||||
t.Errorf("unexpected admin url: %s", resp)
|
||||
}
|
||||
|
||||
|
||||
@@ -595,9 +595,6 @@ func (s *Server) setConfigInputFromRequest(msg *proto.SetConfigRequest) (profile
|
||||
if msg.ManagementUrl != "" {
|
||||
config.ManagementURL = msg.ManagementUrl
|
||||
}
|
||||
if msg.AdminURL != "" {
|
||||
config.AdminURL = msg.AdminURL
|
||||
}
|
||||
if msg.InterfaceName != nil {
|
||||
config.InterfaceName = msg.InterfaceName
|
||||
}
|
||||
@@ -2413,7 +2410,6 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p
|
||||
// overlay (Loader lives outside profilemanager).
|
||||
cfg.ApplyMDMPolicy(s.mdmLoader.Load())
|
||||
managementURL := cfg.ManagementURL
|
||||
adminURL := cfg.AdminURL
|
||||
|
||||
var preSharedKey = cfg.PreSharedKey
|
||||
if preSharedKey != "" {
|
||||
@@ -2469,7 +2465,6 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p
|
||||
return &proto.GetConfigResponse{
|
||||
ManagementUrl: managementURL.String(),
|
||||
PreSharedKey: preSharedKey,
|
||||
AdminURL: adminURL.String(),
|
||||
InterfaceName: cfg.WgIface,
|
||||
WireguardPort: int64(cfg.WgPort),
|
||||
Mtu: int64(cfg.MTU),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@@ -129,7 +130,10 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "https://new-api.netbird.io:443", cfg.ManagementURL.String())
|
||||
require.Equal(t, "https://new-admin.netbird.io:443", cfg.AdminURL.String())
|
||||
// Older clients still send the deprecated admin URL; it must be ignored.
|
||||
raw, err := os.ReadFile(cfgPath)
|
||||
require.NoError(t, err)
|
||||
require.NotContains(t, string(raw), "new-admin.netbird.io", "deprecated AdminURL must not be persisted")
|
||||
require.Equal(t, rosenpassEnabled, cfg.RosenpassEnabled)
|
||||
require.Equal(t, rosenpassPermissive, cfg.RosenpassPermissive)
|
||||
require.NotNil(t, cfg.ServerSSHAllowed)
|
||||
@@ -182,11 +186,11 @@ func verifyAllFieldsCovered(t *testing.T, req *proto.SetConfigRequest) {
|
||||
"CleanNATExternalIPs": true, // control flag for clearing
|
||||
"CleanDNSLabels": true, // control flag for clearing
|
||||
"LazyConnectionEnabled": true, // deprecated: proto field retained for compat, no longer applied
|
||||
"AdminURL": true, // deprecated: proto field retained for compat, no longer applied
|
||||
}
|
||||
|
||||
expectedFields := map[string]bool{
|
||||
"ManagementUrl": true,
|
||||
"AdminURL": true,
|
||||
"RosenpassEnabled": true,
|
||||
"RosenpassPermissive": true,
|
||||
"ServerSSHAllowed": true,
|
||||
@@ -249,7 +253,6 @@ func TestCLIFlags_MappedToSetConfig(t *testing.T) {
|
||||
// This map must be updated when adding new config-related CLI flags.
|
||||
flagToField := map[string]string{
|
||||
"management-url": "ManagementUrl",
|
||||
"admin-url": "AdminURL",
|
||||
"enable-rosenpass": "RosenpassEnabled",
|
||||
"rosenpass-permissive": "RosenpassPermissive",
|
||||
"allow-server-ssh": "ServerSSHAllowed",
|
||||
@@ -286,6 +289,7 @@ func TestCLIFlags_MappedToSetConfig(t *testing.T) {
|
||||
fieldsWithoutCLIFlags := map[string]bool{
|
||||
"DisableNotifications": true, // Only settable via UI
|
||||
"LazyConnectionEnabled": true, // deprecated: no longer settable (managed by server + NB_LAZY_CONN)
|
||||
"AdminURL": true, // deprecated: the admin-url flag is no longer functional
|
||||
}
|
||||
|
||||
// Get all SetConfigRequest fields to verify our map is complete.
|
||||
|
||||
@@ -166,7 +166,8 @@ func (c *Client) ExecuteCommandWithIO(ctx context.Context, command string) error
|
||||
case <-ctx.Done():
|
||||
_ = session.Signal(ssh.SIGTERM)
|
||||
select {
|
||||
case <-done:
|
||||
case err := <-done:
|
||||
log.Debugf("session ended after SIGTERM: %v", err)
|
||||
return ctx.Err()
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
return ctx.Err()
|
||||
@@ -205,7 +206,8 @@ func (c *Client) ExecuteCommandWithPTY(ctx context.Context, command string) erro
|
||||
case <-ctx.Done():
|
||||
_ = session.Signal(ssh.SIGTERM)
|
||||
select {
|
||||
case <-done:
|
||||
case err := <-done:
|
||||
log.Debugf("session ended after SIGTERM: %v", err)
|
||||
return ctx.Err()
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
return ctx.Err()
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
cryptossh "golang.org/x/crypto/ssh"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
||||
|
||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||
sshauth "github.com/netbirdio/netbird/client/ssh/auth"
|
||||
"github.com/netbirdio/netbird/client/ssh/detection"
|
||||
"github.com/netbirdio/netbird/shared/auth"
|
||||
@@ -167,7 +167,7 @@ type Server struct {
|
||||
allowSFTP bool
|
||||
jwtEnabled bool
|
||||
|
||||
netstackNet *netstack.Net
|
||||
netstackNet *wgbackend.NetstackNet
|
||||
|
||||
wgAddress wgaddr.Address
|
||||
|
||||
@@ -445,7 +445,7 @@ func (s *Server) buildSessionInfo(state *sessionState) SessionInfo {
|
||||
}
|
||||
|
||||
// SetNetstackNet sets the netstack network for userspace networking
|
||||
func (s *Server) SetNetstackNet(net *netstack.Net) {
|
||||
func (s *Server) SetNetstackNet(net *wgbackend.NetstackNet) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.netstackNet = net
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "lf",
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"tailwindStylesheet": "./src/globals.css",
|
||||
"tailwindFunctions": ["cn", "clsx", "cva", "tw"]
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ Settings.SetConfig(p: SetConfigParams): Promise<void> // partial update
|
||||
Settings.GetFeatures(): Promise<Features> // operator-disabled UI sections
|
||||
```
|
||||
|
||||
`SetConfig` is a partial update: only fields you set are pushed to the daemon. `profileName` + `username` are always required; the typed fields in `SetConfigParams` are optional (`field?: T | null`). `managementUrl` and `adminUrl` are always-string for historical reasons.
|
||||
`SetConfig` is a partial update: only fields you set are pushed to the daemon. `profileName` + `username` are always required; the typed fields in `SetConfigParams` are optional (`field?: T | null`). `managementUrl` is always-string for historical reasons.
|
||||
|
||||
**PSK mask quirk:** `GetConfig` returns existing pre-shared keys as `"**********"`. If you send the mask back, `wgtypes.ParseKey` fails on the next connect. `SettingsContext.save` drops the field when it equals `"**********"`. See `modules/settings/SettingsContext.tsx`.
|
||||
|
||||
@@ -242,7 +242,7 @@ The tray also reads a tray-only synthetic `"Error"` for icon purposes; the front
|
||||
|
||||
`Config` (read-only mirror, all required):
|
||||
```ts
|
||||
{ managementUrl, adminUrl, configFile, logFile, preSharedKey, interfaceName: string;
|
||||
{ managementUrl, configFile, logFile, preSharedKey, interfaceName: string;
|
||||
wireguardPort, mtu, sshJwtCacheTtl: number;
|
||||
disableAutoConnect, serverSshAllowed,
|
||||
rosenpassEnabled, rosenpassPermissive,
|
||||
@@ -254,7 +254,7 @@ The tray also reads a tray-only synthetic `"Error"` for icon purposes; the front
|
||||
disableSshAuth: boolean; }
|
||||
```
|
||||
|
||||
`SetConfigParams` has all `Config` fields as `field?: T | null` (partial update), plus the write-only `disableFirewall?: boolean | null`, plus `profileName` / `username` / `managementUrl` / `adminUrl` as required strings.
|
||||
`SetConfigParams` has all `Config` fields as `field?: T | null` (partial update), plus the write-only `disableFirewall?: boolean | null`, plus `profileName` / `username` / `managementUrl` as required strings.
|
||||
|
||||
`Features`: `{ disableProfiles, disableUpdateSettings, disableNetworks: boolean }`.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user