mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-29 07:49:14 +01: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
|
while IFS= read -r dir; do
|
||||||
echo "=== Checking $dir ==="
|
echo "=== Checking $dir ==="
|
||||||
# Search for problematic imports, excluding test files
|
# 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
|
if [ -n "$RESULTS" ]; then
|
||||||
echo "❌ Found problematic dependencies:"
|
echo "❌ Found problematic dependencies:"
|
||||||
echo "$RESULTS"
|
echo "$RESULTS"
|
||||||
@@ -93,7 +93,7 @@ jobs:
|
|||||||
IMPORTERS=$(go list -json -deps ./... 2>/dev/null | jq -r "select(.Imports[]? == \"$package\") | .ImportPath")
|
IMPORTERS=$(go list -json -deps ./... 2>/dev/null | jq -r "select(.Imports[]? == \"$package\") | .ImportPath")
|
||||||
|
|
||||||
# Check if any importer is NOT in management/signal/relay
|
# 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
|
if [ -n "$BSD_IMPORTER" ]; then
|
||||||
echo "❌ $package ($license) is imported by BSD-licensed code: $BSD_IMPORTER"
|
echo "❌ $package ($license) is imported by BSD-licensed code: $BSD_IMPORTER"
|
||||||
|
|||||||
@@ -3,9 +3,16 @@ name: Post release topic on Discourse
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
workflow_run:
|
||||||
|
workflows: [Release]
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
post:
|
post:
|
||||||
|
if: github.event_name == 'release'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: roots/discourse-topic-github-release-action@557d74ea05b6cc0c47f555c1d5d28a89d904005b # v1.1.0
|
- uses: roots/discourse-topic-github-release-action@557d74ea05b6cc0c47f555c1d5d28a89d904005b # v1.1.0
|
||||||
@@ -15,3 +22,78 @@ jobs:
|
|||||||
discourse-author-username: NetBird
|
discourse-author-username: NetBird
|
||||||
discourse-category: 17
|
discourse-category: 17
|
||||||
discourse-tags: releases
|
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 ' \
|
sh -c ' \
|
||||||
apk update; apk add --no-cache \
|
apk update; apk add --no-cache \
|
||||||
ca-certificates iptables ip6tables dbus dbus-dev libpcap-dev build-base; \
|
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:
|
test_relay:
|
||||||
@@ -498,7 +498,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
arch: ["amd64"]
|
arch: ["amd64"]
|
||||||
store: ["sqlite", "postgres", "mysql"]
|
store: ["sqlite", "postgres"]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -547,10 +547,6 @@ jobs:
|
|||||||
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
|
DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }}
|
||||||
run: echo "$DOCKER_TOKEN" | sudo docker login --username "$DOCKER_USER" --password-stdin
|
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
|
# 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
|
# 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.
|
# 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
|
# resolve; the Where-Object pipeline then drops the broken package by
|
||||||
# path. Without -e, go list aborts with empty stdout.
|
# path. Without -e, go list aborts with empty stdout.
|
||||||
run: |
|
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"
|
$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"
|
$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
|
Set-Content -Path "${{ github.workspace }}\run-tests.cmd" -Value $cmd
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
store: ["sqlite", "postgres", "mysql"]
|
store: ["sqlite", "postgres"]
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: ${{ (matrix.store == 'postgres') && 'postgres' || '' }}
|
image: ${{ (matrix.store == 'postgres') && 'postgres' || '' }}
|
||||||
@@ -35,19 +35,6 @@ jobs:
|
|||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
ports:
|
ports:
|
||||||
- 5432:5432
|
- 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:
|
steps:
|
||||||
- name: Set Database Connection String
|
- name: Set Database Connection String
|
||||||
run: |
|
run: |
|
||||||
@@ -56,11 +43,6 @@ jobs:
|
|||||||
else
|
else
|
||||||
echo "NETBIRD_STORE_ENGINE_POSTGRES_DSN==" >> $GITHUB_ENV
|
echo "NETBIRD_STORE_ENGINE_POSTGRES_DSN==" >> $GITHUB_ENV
|
||||||
fi
|
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
|
- name: Install jq
|
||||||
run: sudo apt-get install -y jq
|
run: sudo apt-get install -y jq
|
||||||
@@ -86,15 +68,6 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-
|
${{ 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
|
- name: cp setup.env
|
||||||
run: cp infrastructure_files/tests/setup.env infrastructure_files/
|
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_AUTH_SUPPORTED_SCOPES: "openid profile email offline_access api email_verified"
|
||||||
CI_NETBIRD_STORE_CONFIG_ENGINE: ${{ matrix.store }}
|
CI_NETBIRD_STORE_CONFIG_ENGINE: ${{ matrix.store }}
|
||||||
NETBIRD_STORE_ENGINE_POSTGRES_DSN: ${{ env.NETBIRD_STORE_ENGINE_POSTGRES_DSN }}
|
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_MGMT_IDP_SIGNKEY_REFRESH: false
|
||||||
|
|
||||||
- name: check values
|
- name: check values
|
||||||
@@ -143,7 +115,6 @@ jobs:
|
|||||||
CI_NETBIRD_SIGNAL_PORT: 12345
|
CI_NETBIRD_SIGNAL_PORT: 12345
|
||||||
CI_NETBIRD_STORE_CONFIG_ENGINE: ${{ matrix.store }}
|
CI_NETBIRD_STORE_CONFIG_ENGINE: ${{ matrix.store }}
|
||||||
NETBIRD_STORE_ENGINE_POSTGRES_DSN: "${{ env.NETBIRD_STORE_ENGINE_POSTGRES_DSN }}$"
|
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_MGMT_IDP_SIGNKEY_REFRESH: false
|
||||||
CI_NETBIRD_TURN_EXTERNAL_IP: "1.2.3.4"
|
CI_NETBIRD_TURN_EXTERNAL_IP: "1.2.3.4"
|
||||||
CI_NETBIRD_MGMT_DISABLE_DEFAULT_POLICY: false
|
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 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 -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 "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"
|
grep NETBIRD_STORE_ENGINE_POSTGRES_DSN docker-compose.yml | egrep "$NETBIRD_STORE_ENGINE_POSTGRES_DSN"
|
||||||
# check relay values
|
# check relay values
|
||||||
grep "NB_EXPOSED_ADDRESS=rels://$CI_NETBIRD_DOMAIN:33445" docker-compose.yml
|
grep "NB_EXPOSED_ADDRESS=rels://$CI_NETBIRD_DOMAIN:33445" docker-compose.yml
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
|
|
||||||
echo "Size: ${SIZE} bytes (${SIZE_MB} MB)"
|
echo "Size: ${SIZE} bytes (${SIZE_MB} MB)"
|
||||||
|
|
||||||
if [ ${SIZE} -gt 67108864 ]; then
|
if [ ${SIZE} -gt 73400320 ]; then
|
||||||
echo "Wasm binary size (${SIZE_MB}MB) exceeds 64MB limit!"
|
echo "Wasm binary size (${SIZE_MB}MB) exceeds 70MB limit!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
- -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 }}"
|
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:
|
universal_binaries:
|
||||||
- id: netbird
|
- id: netbird
|
||||||
|
|
||||||
@@ -318,10 +296,6 @@ archives:
|
|||||||
builds:
|
builds:
|
||||||
- netbird-idp-migrate
|
- netbird-idp-migrate
|
||||||
name_template: "netbird-idp-migrate_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
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
|
- id: nblink
|
||||||
builds:
|
builds:
|
||||||
- nblink
|
- nblink
|
||||||
|
|||||||
@@ -58,23 +58,17 @@ func (p *Preferences) SetManagementURL(url string) {
|
|||||||
p.configInput.ManagementURL = url
|
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) {
|
func (p *Preferences) GetAdminURL() (string, error) {
|
||||||
if p.configInput.AdminURL != "" {
|
return profilemanager.DefaultAdminURL, nil
|
||||||
return p.configInput.AdminURL, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := profilemanager.ReadConfigOrDefault(p.configInput.ConfigPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return cfg.AdminURL.String(), err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAdminURL stores the given URL and waits for commit
|
// SetAdminURL is a no-op kept for API compatibility.
|
||||||
func (p *Preferences) SetAdminURL(url string) {
|
//
|
||||||
p.configInput.AdminURL = url
|
// 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
|
// HasPreSharedKey reports whether a pre-shared key is staged, persisted, or
|
||||||
// enforced by MDM; the key itself is never handed to the native layer.
|
// 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")
|
cfgFile := filepath.Join(t.TempDir(), "netbird.json")
|
||||||
p := NewPreferences(cfgFile)
|
p := NewPreferences(cfgFile)
|
||||||
|
|
||||||
|
// The admin URL is deprecated: setting it is a no-op.
|
||||||
p.SetAdminURL(exampleString)
|
p.SetAdminURL(exampleString)
|
||||||
resp, err := p.GetAdminURL()
|
resp, err := p.GetAdminURL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to read admin url: %s", err)
|
t.Fatalf("failed to read admin url: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp != exampleString {
|
if resp != profilemanager.DefaultAdminURL {
|
||||||
t.Errorf("unexpected admin url: %s", resp)
|
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)
|
t.Fatalf("failed to read admin url: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp != exampleURL {
|
if resp != profilemanager.DefaultAdminURL {
|
||||||
t.Errorf("unexpected admin url: %s", resp)
|
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().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().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().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().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)")
|
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.Username = username
|
||||||
|
|
||||||
req.ManagementUrl = managementURL
|
req.ManagementUrl = managementURL
|
||||||
req.AdminURL = adminURL
|
|
||||||
req.NatExternalIPs = natExternalIPs
|
req.NatExternalIPs = natExternalIPs
|
||||||
req.CustomDNSAddress = customDNSAddressConverted
|
req.CustomDNSAddress = customDNSAddressConverted
|
||||||
req.ExtraIFaceBlacklist = extraIFaceBlackList
|
req.ExtraIFaceBlacklist = extraIFaceBlackList
|
||||||
|
|||||||
@@ -12,11 +12,10 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"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"
|
||||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
"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"
|
||||||
"github.com/netbirdio/netbird/client/internal/auth"
|
"github.com/netbirdio/netbird/client/internal/auth"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
@@ -256,10 +255,10 @@ func New(opts Options) (*Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if opts.Performance.PreallocatedBuffersPerPool != nil {
|
if opts.Performance.PreallocatedBuffersPerPool != nil {
|
||||||
wgdevice.SetPreallocatedBuffersPerPool(*opts.Performance.PreallocatedBuffersPerPool)
|
wgbackend.SetPreallocatedBuffersPerPool(*opts.Performance.PreallocatedBuffersPerPool)
|
||||||
}
|
}
|
||||||
if opts.Performance.MaxBatchSize != nil {
|
if opts.Performance.MaxBatchSize != nil {
|
||||||
wgdevice.SetMaxBatchSizeOverride(*opts.Performance.MaxBatchSize)
|
wgbackend.SetMaxBatchSizeOverride(*opts.Performance.MaxBatchSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Client{
|
return &Client{
|
||||||
@@ -651,7 +650,7 @@ func (c *Client) getEngine() (*internal.Engine, error) {
|
|||||||
return engine, nil
|
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()
|
engine, err := c.getEngine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, netip.Addr{}, err
|
return nil, netip.Addr{}, err
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package firewall
|
package firewall
|
||||||
|
|
||||||
import (
|
import (
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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
|
// EnvForceUserspaceFirewall forces the use of the userspace packet filter even when
|
||||||
@@ -20,5 +19,5 @@ type IFaceMapper interface {
|
|||||||
IsUserspaceBind() bool
|
IsUserspaceBind() bool
|
||||||
SetFilter(device.PacketFilter) error
|
SetFilter(device.PacketFilter) error
|
||||||
GetDevice() *device.FilteredDevice
|
GetDevice() *device.FilteredDevice
|
||||||
GetWGDevice() *wgdevice.Device
|
GetWGDevice() *wgbackend.Device
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
|
|
||||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
"github.com/netbirdio/netbird/client/firewall/firewalld"
|
"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/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/netstack"
|
"github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nbid "github.com/netbirdio/netbird/client/internal/acl/id"
|
nbid "github.com/netbirdio/netbird/client/internal/acl/id"
|
||||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||||
@@ -121,7 +121,7 @@ type Iface interface {
|
|||||||
Name() string
|
Name() string
|
||||||
Address() wgaddr.Address
|
Address() wgaddr.Address
|
||||||
SetFilter(device.PacketFilter) error
|
SetFilter(device.PacketFilter) error
|
||||||
GetWGDevice() *wgdevice.Device
|
GetWGDevice() *wgbackend.Device
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterfaceAllower opens the NetBird interface in the host firewall so it
|
// InterfaceAllower opens the NetBird interface in the host firewall so it
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"go.uber.org/mock/gomock"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
"go.uber.org/mock/gomock"
|
||||||
|
|
||||||
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/mocks"
|
"github.com/netbirdio/netbird/client/iface/mocks"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -791,10 +791,10 @@ func setupRoutedManager(tb testing.TB, network string) *Manager {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
GetDeviceFunc: func() *device.FilteredDevice {
|
GetDeviceFunc: func() *device.FilteredDevice {
|
||||||
return &device.FilteredDevice{Device: dev}
|
return &device.FilteredDevice{TUN: dev}
|
||||||
},
|
},
|
||||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||||
return &wgdevice.Device{}
|
return &wgbackend.Device{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"go.uber.org/mock/gomock"
|
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
"go.uber.org/mock/gomock"
|
||||||
|
|
||||||
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/mocks"
|
"github.com/netbirdio/netbird/client/iface/mocks"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAddRouteFilteringReturnsExistingRule verifies that adding the same route
|
// TestAddRouteFilteringReturnsExistingRule verifies that adding the same route
|
||||||
@@ -180,10 +180,10 @@ func TestBlockInvalidRoutedDualStack(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
GetDeviceFunc: func() *device.FilteredDevice {
|
GetDeviceFunc: func() *device.FilteredDevice {
|
||||||
return &device.FilteredDevice{Device: dev}
|
return &device.FilteredDevice{TUN: dev}
|
||||||
},
|
},
|
||||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||||
return &wgdevice.Device{}
|
return &wgbackend.Device{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,10 +228,10 @@ func TestBlockInvalidRoutedIdempotent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
GetDeviceFunc: func() *device.FilteredDevice {
|
GetDeviceFunc: func() *device.FilteredDevice {
|
||||||
return &device.FilteredDevice{Device: dev}
|
return &device.FilteredDevice{TUN: dev}
|
||||||
},
|
},
|
||||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||||
return &wgdevice.Device{}
|
return &wgbackend.Device{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,10 +291,10 @@ func TestBlockRuleNotAccumulatedOnRepeatedEnableRouting(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
GetDeviceFunc: func() *device.FilteredDevice {
|
GetDeviceFunc: func() *device.FilteredDevice {
|
||||||
return &device.FilteredDevice{Device: dev}
|
return &device.FilteredDevice{TUN: dev}
|
||||||
},
|
},
|
||||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||||
return &wgdevice.Device{}
|
return &wgbackend.Device{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,10 +410,10 @@ func setupTestManager(t *testing.T) *Manager {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
GetDeviceFunc: func() *device.FilteredDevice {
|
GetDeviceFunc: func() *device.FilteredDevice {
|
||||||
return &device.FilteredDevice{Device: dev}
|
return &device.FilteredDevice{TUN: dev}
|
||||||
},
|
},
|
||||||
GetWGDeviceFunc: func() *wgdevice.Device {
|
GetWGDeviceFunc: func() *wgbackend.Device {
|
||||||
return &wgdevice.Device{}
|
return &wgbackend.Device{}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
|
|
||||||
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
fw "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack"
|
"github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack"
|
||||||
@@ -22,6 +21,7 @@ import (
|
|||||||
nbiface "github.com/netbirdio/netbird/client/iface"
|
nbiface "github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
"github.com/netbirdio/netbird/client/internal/netflow"
|
"github.com/netbirdio/netbird/client/internal/netflow"
|
||||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
@@ -34,7 +34,7 @@ type IFaceMock struct {
|
|||||||
NameFunc func() string
|
NameFunc func() string
|
||||||
SetFilterFunc func(device.PacketFilter) error
|
SetFilterFunc func(device.PacketFilter) error
|
||||||
AddressFunc func() wgaddr.Address
|
AddressFunc func() wgaddr.Address
|
||||||
GetWGDeviceFunc func() *wgdevice.Device
|
GetWGDeviceFunc func() *wgbackend.Device
|
||||||
GetDeviceFunc func() *device.FilteredDevice
|
GetDeviceFunc func() *device.FilteredDevice
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ func (i *IFaceMock) Name() string {
|
|||||||
return i.NameFunc()
|
return i.NameFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IFaceMock) GetWGDevice() *wgdevice.Device {
|
func (i *IFaceMock) GetWGDevice() *wgbackend.Device {
|
||||||
if i.GetWGDeviceFunc == nil {
|
if i.GetWGDeviceFunc == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
|
|
||||||
nblog "github.com/netbirdio/netbird/client/firewall/uspfilter/log"
|
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
|
// PacketCapture captures raw packets for debugging. Implementations must be
|
||||||
@@ -23,7 +23,7 @@ type PacketCapture interface {
|
|||||||
type endpoint struct {
|
type endpoint struct {
|
||||||
logger *nblog.Logger
|
logger *nblog.Logger
|
||||||
dispatcher stack.NetworkDispatcher
|
dispatcher stack.NetworkDispatcher
|
||||||
device *wgdevice.Device
|
device *wgbackend.Device
|
||||||
mtu atomic.Uint32
|
mtu atomic.Uint32
|
||||||
capture atomic.Pointer[PacketCapture]
|
capture atomic.Pointer[PacketCapture]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"gvisor.dev/gvisor/pkg/buffer"
|
"gvisor.dev/gvisor/pkg/buffer"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||||
@@ -26,6 +25,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack"
|
"github.com/netbirdio/netbird/client/firewall/uspfilter/conntrack"
|
||||||
nblog "github.com/netbirdio/netbird/client/firewall/uspfilter/log"
|
nblog "github.com/netbirdio/netbird/client/firewall/uspfilter/log"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
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.
|
// IFace provides the WireGuard device and overlay addresses the forwarder needs.
|
||||||
type IFace interface {
|
type IFace interface {
|
||||||
GetWGDevice() *wgdevice.Device
|
GetWGDevice() *wgbackend.Device
|
||||||
Address() wgaddr.Address
|
Address() wgaddr.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package bind
|
package bind
|
||||||
|
|
||||||
import (
|
import (
|
||||||
wireguard "golang.zx2c4.com/wireguard/conn"
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
|
|
||||||
nbnet "github.com/netbirdio/netbird/client/net"
|
nbnet "github.com/netbirdio/netbird/client/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -10,6 +9,6 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
listener := nbnet.NewListener()
|
listener := nbnet.NewListener()
|
||||||
if listener.ListenConfig.Control != nil {
|
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 (
|
import (
|
||||||
"net"
|
"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 {
|
func EndpointToUDPAddr(e Endpoint) *net.UDPAddr {
|
||||||
return &net.UDPAddr{
|
return &net.UDPAddr{
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ import (
|
|||||||
"github.com/pion/transport/v3"
|
"github.com/pion/transport/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
wgConn "golang.zx2c4.com/wireguard/conn"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nbnet "github.com/netbirdio/netbird/client/net"
|
nbnet "github.com/netbirdio/netbird/client/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ type receiverCreator struct {
|
|||||||
iceBind *ICEBind
|
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)
|
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
|
// 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.
|
// use the port because in the Send function the wgConn.Endpoint the port info is not exported.
|
||||||
type ICEBind struct {
|
type ICEBind struct {
|
||||||
*wgConn.StdNetBind
|
*wgbackend.StdNetBind
|
||||||
|
|
||||||
transportNet transport.Net
|
transportNet transport.Net
|
||||||
address wgaddr.Address
|
address wgaddr.Address
|
||||||
@@ -74,7 +74,7 @@ type ICEBind struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewICEBind(transportNet transport.Net, address wgaddr.Address, mtu uint16) *ICEBind {
|
func NewICEBind(transportNet transport.Net, address wgaddr.Address, mtu uint16) *ICEBind {
|
||||||
b, _ := wgConn.NewStdNetBind().(*wgConn.StdNetBind)
|
b, _ := wgbackend.NewStdNetBind().(*wgbackend.StdNetBind)
|
||||||
ib := &ICEBind{
|
ib := &ICEBind{
|
||||||
StdNetBind: b,
|
StdNetBind: b,
|
||||||
transportNet: transportNet,
|
transportNet: transportNet,
|
||||||
@@ -90,11 +90,11 @@ func NewICEBind(transportNet transport.Net, address wgaddr.Address, mtu uint16)
|
|||||||
rc := receiverCreator{
|
rc := receiverCreator{
|
||||||
ib,
|
ib,
|
||||||
}
|
}
|
||||||
ib.StdNetBind = wgConn.NewStdNetBindWithReceiverCreator(rc)
|
ib.StdNetBind = wgbackend.NewStdNetBindWithReceiverCreator(rc)
|
||||||
return ib
|
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()
|
s.closedChanMu.Lock()
|
||||||
defer s.closedChanMu.Unlock()
|
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()
|
b.endpointsMu.Lock()
|
||||||
conn, ok := b.endpoints[ep.DstIP()]
|
conn, ok := b.endpoints[ep.DstIP()]
|
||||||
b.endpointsMu.Unlock()
|
b.endpointsMu.Unlock()
|
||||||
@@ -206,7 +206,7 @@ func (b *ICEBind) Send(bufs [][]byte, ep wgConn.Endpoint) error {
|
|||||||
return nil
|
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()
|
s.muUDPMux.Lock()
|
||||||
defer s.muUDPMux.Unlock()
|
defer s.muUDPMux.Unlock()
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxO
|
|||||||
}
|
}
|
||||||
s.createOrUpdateMux()
|
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)
|
msgs := getMessages(msgsPool)
|
||||||
for i := range bufs {
|
for i := range bufs {
|
||||||
(*msgs)[i].Buffers[0] = bufs[i]
|
(*msgs)[i].Buffers[0] = bufs[i]
|
||||||
@@ -229,13 +229,13 @@ func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxO
|
|||||||
var numMsgs int
|
var numMsgs int
|
||||||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
||||||
if rxOffload {
|
if rxOffload {
|
||||||
readAt := len(*msgs) - (wgConn.IdealBatchSize / wgConn.UdpSegmentMaxDatagrams)
|
readAt := len(*msgs) - (wgbackend.IdealBatchSize / wgbackend.UdpSegmentMaxDatagrams)
|
||||||
//nolint:staticcheck
|
//nolint:staticcheck
|
||||||
_, err = pc.ReadBatch((*msgs)[readAt:], 0)
|
_, err = pc.ReadBatch((*msgs)[readAt:], 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
numMsgs, err = wgConn.SplitCoalescedMessages(*msgs, readAt, wgConn.GetGSOSize)
|
numMsgs, err = wgbackend.SplitCoalescedMessages(*msgs, readAt, wgbackend.GetGSOSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -278,8 +278,8 @@ func (s *ICEBind) createReceiverFn(pc wgConn.BatchReader, conn *net.UDPConn, rxO
|
|||||||
s.activityRecorder.record(addrPort)
|
s.activityRecorder.record(addrPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
ep := &wgConn.StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
|
ep := &wgbackend.StdNetEndpoint{AddrPort: addrPort} // TODO: remove allocation
|
||||||
wgConn.GetSrcFromControl(msg.OOB[:msg.NN], ep)
|
wgbackend.GetSrcFromControl(msg.OOB[:msg.NN], ep)
|
||||||
eps[i] = ep
|
eps[i] = ep
|
||||||
}
|
}
|
||||||
return numMsgs, nil
|
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
|
// 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.
|
// 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()
|
closedChan := c.currentClosedChan()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@@ -375,7 +375,7 @@ func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgConn.Endpo
|
|||||||
}
|
}
|
||||||
copy(buffs[0], msg.Buffer)
|
copy(buffs[0], msg.Buffer)
|
||||||
sizes[0] = len(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 isTransportPkg(buffs, sizes[0]) {
|
||||||
if ep, ok := eps[0].(*Endpoint); ok {
|
if ep, ok := eps[0].(*Endpoint); ok {
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
// 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
|
// calling Bind.Close, closeBindLocked waits on exactly that WaitGroup while
|
||||||
// holding device.net, so a receive function that never returns wedges the
|
// holding device.net, so a receive function that never returns wedges the
|
||||||
// device and every goroutine that needs the same lock.
|
// 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)
|
wg, _ := startReceiversEntered(fns)
|
||||||
return wg
|
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
|
// 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
|
// entered is either inside its blocking receive or about to be, which is a
|
||||||
// stronger signal to synchronise on than a bare sleep.
|
// 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 wg sync.WaitGroup
|
||||||
var entered sync.WaitGroup
|
var entered sync.WaitGroup
|
||||||
wg.Add(len(fns))
|
wg.Add(len(fns))
|
||||||
entered.Add(len(fns))
|
entered.Add(len(fns))
|
||||||
|
|
||||||
for i := range fns {
|
for i := range fns {
|
||||||
go func(fn wgConn.ReceiveFunc) {
|
go func(fn wgbackend.ReceiveFunc) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
buffs := [][]byte{make([]byte, 1500)}
|
buffs := [][]byte{make([]byte, 1500)}
|
||||||
sizes := make([]int, 1)
|
sizes := make([]int, 1)
|
||||||
eps := make([]wgConn.Endpoint, 1)
|
eps := make([]wgbackend.Endpoint, 1)
|
||||||
first := true
|
first := true
|
||||||
for {
|
for {
|
||||||
if first {
|
if first {
|
||||||
|
|||||||
@@ -16,10 +16,9 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
"golang.org/x/net/ipv6"
|
"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/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestICEBind_CreatesReceiverForBothIPv4AndIPv6(t *testing.T) {
|
func TestICEBind_CreatesReceiverForBothIPv4AndIPv6(t *testing.T) {
|
||||||
@@ -370,16 +369,16 @@ func TestICEBind_OpenDoesNotDiscoverInterfaces(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestICEBind_DeviceUpDoesNotWaitOnInterfaceDiscovery(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)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var dev *device.Device
|
var dev *wgbackend.Device
|
||||||
n := newCountingNet()
|
n := newCountingNet()
|
||||||
n.before = func() {
|
n.before = func() {
|
||||||
_ = dev.IpcGetOperation(io.Discard)
|
_ = dev.IpcGetOperation(io.Discard)
|
||||||
}
|
}
|
||||||
iceBind := NewICEBind(n, testAddress(), 1280)
|
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)
|
upDone := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/conn"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RelayBindJS is a conn.Bind implementation for WebAssembly environments.
|
// 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
|
// Do not limit to build only js, because we want to be able to run tests
|
||||||
type RelayBindJS struct {
|
type RelayBindJS struct {
|
||||||
*conn.StdNetBind
|
*wgbackend.StdNetBind
|
||||||
|
|
||||||
recvChan chan recvMessage
|
recvChan chan recvMessage
|
||||||
endpoints map[netip.Addr]net.Conn
|
endpoints map[netip.Addr]net.Conn
|
||||||
@@ -34,12 +34,12 @@ func NewRelayBindJS() *RelayBindJS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open creates a receive function for handling relay packets in WASM.
|
// 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)
|
log.Debugf("Open: creating receive function for port %d", uport)
|
||||||
|
|
||||||
s.ctx, s.cancel = context.WithCancel(context.Background())
|
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 {
|
select {
|
||||||
case <-s.ctx.Done():
|
case <-s.ctx.Done():
|
||||||
return 0, net.ErrClosed
|
return 0, net.ErrClosed
|
||||||
@@ -49,13 +49,13 @@ func (s *RelayBindJS) Open(uport uint16) ([]conn.ReceiveFunc, uint16, error) {
|
|||||||
}
|
}
|
||||||
copy(bufs[0], msg.Buffer)
|
copy(bufs[0], msg.Buffer)
|
||||||
sizes[0] = len(msg.Buffer)
|
sizes[0] = len(msg.Buffer)
|
||||||
eps[0] = conn.Endpoint(msg.Endpoint)
|
eps[0] = wgbackend.Endpoint(msg.Endpoint)
|
||||||
return 1, nil
|
return 1, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Open: receive function created, returning port %d", uport)
|
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 {
|
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.
|
// 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 {
|
if ep == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/net/ipv4"
|
"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
|
// 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
|
// A leftover size from an earlier read, which is what makes the missing reset
|
||||||
// observable.
|
// observable.
|
||||||
sizes := []int{148}
|
sizes := []int{148}
|
||||||
eps := make([]wgConn.Endpoint, 1)
|
eps := make([]wgbackend.Endpoint, 1)
|
||||||
|
|
||||||
n, err := recvFn(bufs, sizes, eps)
|
n, err := recvFn(bufs, sizes, eps)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ package configurer
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/ipc"
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
func openUAPI(deviceName string) (net.Listener, error) {
|
func openUAPI(deviceName string) (net.Listener, error) {
|
||||||
uapiSock, err := ipc.UAPIOpen(deviceName)
|
uapiSock, err := wgbackend.UAPIOpen(deviceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
listener, err := ipc.UAPIListen(deviceName, uapiSock)
|
listener, err := wgbackend.UAPIListen(deviceName, uapiSock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = uapiSock.Close()
|
_ = uapiSock.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package configurer
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/ipc"
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
func openUAPI(deviceName string) (net.Listener, error) {
|
func openUAPI(deviceName string) (net.Listener, error) {
|
||||||
return ipc.UAPIListen(deviceName)
|
return wgbackend.UAPIListen(deviceName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
wgconn "golang.zx2c4.com/wireguard/conn"
|
|
||||||
"golang.zx2c4.com/wireguard/device"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nbnet "github.com/netbirdio/netbird/client/net"
|
nbnet "github.com/netbirdio/netbird/client/net"
|
||||||
"github.com/netbirdio/netbird/monotime"
|
"github.com/netbirdio/netbird/monotime"
|
||||||
)
|
)
|
||||||
@@ -22,7 +21,7 @@ import (
|
|||||||
var ErrAllowedIPNotFound = fmt.Errorf("allowed IP not found")
|
var ErrAllowedIPNotFound = fmt.Errorf("allowed IP not found")
|
||||||
|
|
||||||
type WGUSPConfigurer struct {
|
type WGUSPConfigurer struct {
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
deviceName string
|
deviceName string
|
||||||
activityRecorder *bind.ActivityRecorder
|
activityRecorder *bind.ActivityRecorder
|
||||||
statsCache *statsCache
|
statsCache *statsCache
|
||||||
@@ -31,14 +30,14 @@ type WGUSPConfigurer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewUSPConfigurer creates a userspace configurer and starts its UAPI listener.
|
// 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 := NewUSPConfigurerNoUAPI(device, deviceName, activityRecorder)
|
||||||
wgCfg.startUAPI()
|
wgCfg.startUAPI()
|
||||||
return wgCfg
|
return wgCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUSPConfigurerNoUAPI creates a userspace configurer without a UAPI listener.
|
// 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{
|
wgCfg := &WGUSPConfigurer{
|
||||||
device: device,
|
device: device,
|
||||||
deviceName: deviceName,
|
deviceName: deviceName,
|
||||||
@@ -59,7 +58,7 @@ func (c *WGUSPConfigurer) ConfigureInterface(privateKey string, port int) error
|
|||||||
return fmt.Errorf("invalid listen port %d", port)
|
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)
|
return fmt.Errorf("set private key: %w", err)
|
||||||
}
|
}
|
||||||
if err := c.device.SetListenPort(uint16(port)); err != nil {
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
presharedKey := device.NoisePresharedKey(psk)
|
presharedKey := wgbackend.NoisePresharedKey(psk)
|
||||||
return c.device.ConfigurePeer(device.NoisePublicKey(parsedPeerKey), device.PeerConfig{
|
return c.device.ConfigurePeer(wgbackend.NoisePublicKey(parsedPeerKey), wgbackend.PeerConfig{
|
||||||
PresharedKey: &presharedKey,
|
PresharedKey: &presharedKey,
|
||||||
UpdateOnly: updateOnly,
|
UpdateOnly: updateOnly,
|
||||||
})
|
})
|
||||||
@@ -99,7 +98,7 @@ func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := device.PeerConfig{
|
cfg := wgbackend.PeerConfig{
|
||||||
PersistentKeepalive: &keepAlive,
|
PersistentKeepalive: &keepAlive,
|
||||||
AllowedIPs: prefixes,
|
AllowedIPs: prefixes,
|
||||||
}
|
}
|
||||||
@@ -116,11 +115,11 @@ func (c *WGUSPConfigurer) UpdatePeer(peerKey string, allowedIps []netip.Prefix,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if preSharedKey != nil {
|
if preSharedKey != nil {
|
||||||
psk := device.NoisePresharedKey(*preSharedKey)
|
psk := wgbackend.NoisePresharedKey(*preSharedKey)
|
||||||
cfg.PresharedKey = &psk
|
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)
|
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)
|
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 {
|
if peer == nil {
|
||||||
return ErrPeerNotFound
|
return ErrPeerNotFound
|
||||||
}
|
}
|
||||||
@@ -147,7 +146,7 @@ func (c *WGUSPConfigurer) RemoveEndpointAddress(peerKey string) error {
|
|||||||
peer.ZeroAndFlushAll()
|
peer.ZeroAndFlushAll()
|
||||||
|
|
||||||
var noKeepAlive time.Duration
|
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,
|
PersistentKeepalive: &noKeepAlive,
|
||||||
UpdateOnly: true,
|
UpdateOnly: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@@ -163,7 +162,7 @@ func (c *WGUSPConfigurer) RemovePeer(peerKey string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.device.RemovePeer(device.NoisePublicKey(peerKeyParsed))
|
c.device.RemovePeer(wgbackend.NoisePublicKey(peerKeyParsed))
|
||||||
c.activityRecorder.Remove(peerKey)
|
c.activityRecorder.Remove(peerKey)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -178,7 +177,7 @@ func (c *WGUSPConfigurer) AddAllowedIP(peerKey string, allowedIP netip.Prefix) e
|
|||||||
return fmt.Errorf("invalid allowed IP %v", allowedIP)
|
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 {
|
if peer == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -198,7 +197,7 @@ func (c *WGUSPConfigurer) RemoveAllowedIP(peerKey string, allowedIP netip.Prefix
|
|||||||
return ErrAllowedIPNotFound
|
return ErrAllowedIPNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
peer := c.device.LookupPeer(device.NoisePublicKey(peerKeyParsed))
|
peer := c.device.LookupPeer(wgbackend.NoisePublicKey(peerKeyParsed))
|
||||||
if peer == nil {
|
if peer == nil {
|
||||||
return ErrPeerNotFound
|
return ErrPeerNotFound
|
||||||
}
|
}
|
||||||
@@ -284,7 +283,7 @@ func (c *WGUSPConfigurer) fetchStats() (map[string]WGStats, error) {
|
|||||||
return stats, nil
|
return stats, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func peerStats(peer *device.Peer) Peer {
|
func peerStats(peer *wgbackend.Peer) Peer {
|
||||||
stats := Peer{
|
stats := Peer{
|
||||||
PublicKey: wgtypes.Key(peer.PublicKey()).String(),
|
PublicKey: wgtypes.Key(peer.PublicKey()).String(),
|
||||||
AllowedIPs: prefixesToIPNets(peer.AllowedIPs()),
|
AllowedIPs: prefixesToIPNets(peer.AllowedIPs()),
|
||||||
@@ -299,7 +298,7 @@ func peerStats(peer *device.Peer) Peer {
|
|||||||
return stats
|
return stats
|
||||||
}
|
}
|
||||||
|
|
||||||
func endpointAddrPort(endpoint wgconn.Endpoint) (netip.AddrPort, bool) {
|
func endpointAddrPort(endpoint wgbackend.Endpoint) (netip.AddrPort, bool) {
|
||||||
if endpoint == nil {
|
if endpoint == nil {
|
||||||
return netip.AddrPort{}, false
|
return netip.AddrPort{}, false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
wgconn "golang.zx2c4.com/wireguard/conn"
|
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"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
|
// newTestUSPConfigurer builds a configurer over a real wireguard-go device backed by an
|
||||||
@@ -20,7 +19,7 @@ import (
|
|||||||
func newTestUSPConfigurer(t *testing.T) *WGUSPConfigurer {
|
func newTestUSPConfigurer(t *testing.T) *WGUSPConfigurer {
|
||||||
t.Helper()
|
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)
|
t.Cleanup(dev.Close)
|
||||||
|
|
||||||
c := NewUSPConfigurerNoUAPI(dev, "wgtest0", bind.NewActivityRecorder())
|
c := NewUSPConfigurerNoUAPI(dev, "wgtest0", bind.NewActivityRecorder())
|
||||||
|
|||||||
@@ -11,20 +11,20 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"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
|
// 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.
|
// opened, no peer goroutine starts, and the configuration state is all the tests observe.
|
||||||
type idleTUN struct {
|
type idleTUN struct {
|
||||||
events chan tun.Event
|
events chan wgbackend.TUNEvent
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIdleTUN() *idleTUN {
|
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 }
|
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) 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 {
|
func (t *idleTUN) Close() error {
|
||||||
close(t.closed)
|
close(t.closed)
|
||||||
@@ -142,12 +142,12 @@ func TestRemoveEndpointAddressKeepsThePeerAndStopsTheKeepalive(t *testing.T) {
|
|||||||
endpoint := &net.UDPAddr{IP: net.IPv4(192, 0, 2, 10), Port: 51820}
|
endpoint := &net.UDPAddr{IP: net.IPv4(192, 0, 2, 10), Port: 51820}
|
||||||
prefixes := []netip.Prefix{netip.MustParsePrefix("100.64.0.1/32")}
|
prefixes := []netip.Prefix{netip.MustParsePrefix("100.64.0.1/32")}
|
||||||
require.NoError(t, c.UpdatePeer(peerKey, prefixes, 25*time.Second, endpoint, nil), "add peer")
|
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.NotNil(t, before, "the peer must be on the device")
|
||||||
|
|
||||||
require.NoError(t, c.RemoveEndpointAddress(peerKey), "remove endpoint address")
|
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")
|
"the peer object must survive the endpoint removal")
|
||||||
stats, err := c.FullStats()
|
stats, err := c.FullStats()
|
||||||
require.NoError(t, err, "read device stats")
|
require.NoError(t, err, "read device stats")
|
||||||
|
|||||||
@@ -3,13 +3,10 @@
|
|||||||
package iface
|
package iface
|
||||||
|
|
||||||
import (
|
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/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WGTunDevice interface {
|
type WGTunDevice interface {
|
||||||
@@ -21,7 +18,7 @@ type WGTunDevice interface {
|
|||||||
DeviceName() string
|
DeviceName() string
|
||||||
Close() error
|
Close() error
|
||||||
FilteredDevice() *device.FilteredDevice
|
FilteredDevice() *device.FilteredDevice
|
||||||
Device() *wgdevice.Device
|
Device() *wgbackend.Device
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
GetICEBind() device.EndpointManager
|
GetICEBind() device.EndpointManager
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"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/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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
|
// 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
|
disableDNS bool
|
||||||
|
|
||||||
name string
|
name string
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
filteredDevice *FilteredDevice
|
filteredDevice *FilteredDevice
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
@@ -74,7 +72,7 @@ func (t *WGTunDevice) Create(routes []string, dns string, searchDomains []string
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
unmonitoredTUN, name, err := tun.CreateUnmonitoredTUNFromFD(fd)
|
unmonitoredTUN, name, err := wgbackend.CreateUnmonitoredTUNFromFD(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = unix.Close(fd)
|
_ = unix.Close(fd)
|
||||||
log.Errorf("failed to create Android interface: %s", err)
|
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)
|
t.filteredDevice = newDeviceFilter(t.renewableTun)
|
||||||
|
|
||||||
log.Debugf("attaching to interface %v", name)
|
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.
|
// 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
|
// this helps with support for the older NetBird clients that had a hardcoded direct mode
|
||||||
// t.device.DisableSomeRoamingForBrokenMobileSemantics()
|
// t.device.DisableSomeRoamingForBrokenMobileSemantics()
|
||||||
@@ -121,7 +119,7 @@ func (t *WGTunDevice) RenewTun(fd int) error {
|
|||||||
return fmt.Errorf("device not initialized")
|
return fmt.Errorf("device not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
unmonitoredTUN, _, err := tun.CreateUnmonitoredTUNFromFD(fd)
|
unmonitoredTUN, _, err := wgbackend.CreateUnmonitoredTUNFromFD(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = unix.Close(fd)
|
_ = unix.Close(fd)
|
||||||
log.Errorf("failed to renew Android interface: %s", err)
|
log.Errorf("failed to renew Android interface: %s", err)
|
||||||
@@ -155,7 +153,7 @@ func (t *WGTunDevice) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *WGTunDevice) Device() *device.Device {
|
func (t *WGTunDevice) Device() *wgbackend.Device {
|
||||||
return t.device
|
return t.device
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +173,7 @@ func (t *WGTunDevice) FilteredDevice() *FilteredDevice {
|
|||||||
return t.filteredDevice
|
return t.filteredDevice
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *WGTunDevice) GetNet() *netstack.Net {
|
func (t *WGTunDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
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/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TunDevice struct {
|
type TunDevice struct {
|
||||||
@@ -25,7 +23,7 @@ type TunDevice struct {
|
|||||||
mtu uint16
|
mtu uint16
|
||||||
iceBind *bind.ICEBind
|
iceBind *bind.ICEBind
|
||||||
|
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
filteredDevice *FilteredDevice
|
filteredDevice *FilteredDevice
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
@@ -43,17 +41,17 @@ func NewTunDevice(name string, address wgaddr.Address, port int, key string, mtu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunDevice) Create() (WGConfigurer, error) {
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating tun device: %s", err)
|
return nil, fmt.Errorf("error creating tun device: %s", err)
|
||||||
}
|
}
|
||||||
t.filteredDevice = newDeviceFilter(tunDevice)
|
t.filteredDevice = newDeviceFilter(tunDevice)
|
||||||
|
|
||||||
// We need to create a wireguard-go device and listen to configuration requests
|
// We need to create a wireguard-go device and listen to configuration requests
|
||||||
t.device = device.NewDevice(
|
t.device = wgbackend.NewDevice(
|
||||||
t.filteredDevice,
|
t.filteredDevice,
|
||||||
t.iceBind,
|
t.iceBind,
|
||||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||||
)
|
)
|
||||||
|
|
||||||
err = t.assignAddr()
|
err = t.assignAddr()
|
||||||
@@ -125,7 +123,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Device returns the wireguard device
|
// Device returns the wireguard device
|
||||||
func (t *TunDevice) Device() *device.Device {
|
func (t *TunDevice) Device() *wgbackend.Device {
|
||||||
return t.device
|
return t.device
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +158,7 @@ func (t *TunDevice) assignAddr() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunDevice) GetNet() *netstack.Net {
|
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PacketFilter interface for firewall abilities
|
// PacketFilter interface for firewall abilities
|
||||||
@@ -42,7 +43,7 @@ type PacketCapture interface {
|
|||||||
|
|
||||||
// FilteredDevice to override Read or Write of packets
|
// FilteredDevice to override Read or Write of packets
|
||||||
type FilteredDevice struct {
|
type FilteredDevice struct {
|
||||||
tun.Device
|
wgbackend.TUN
|
||||||
|
|
||||||
filter PacketFilter
|
filter PacketFilter
|
||||||
capture atomic.Pointer[PacketCapture]
|
capture atomic.Pointer[PacketCapture]
|
||||||
@@ -54,9 +55,9 @@ type FilteredDevice struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newDeviceFilter constructor function
|
// newDeviceFilter constructor function
|
||||||
func newDeviceFilter(device tun.Device) *FilteredDevice {
|
func newDeviceFilter(device wgbackend.TUN) *FilteredDevice {
|
||||||
return &FilteredDevice{
|
return &FilteredDevice{
|
||||||
Device: device,
|
TUN: device,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ func newDeviceFilter(device tun.Device) *FilteredDevice {
|
|||||||
func (d *FilteredDevice) Close() error {
|
func (d *FilteredDevice) Close() error {
|
||||||
var err error
|
var err error
|
||||||
d.closeOnce.Do(func() {
|
d.closeOnce.Do(func() {
|
||||||
err = d.Device.Close()
|
err = d.TUN.Close()
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -142,14 +143,14 @@ func (d *FilteredDevice) Write(bufs [][]byte, offset int) (int, error) {
|
|||||||
// wintun read path and converting them into errors.
|
// wintun read path and converting them into errors.
|
||||||
func (d *FilteredDevice) deviceRead(bufs [][]byte, sizes []int, offset int) (n int, err error) {
|
func (d *FilteredDevice) deviceRead(bufs [][]byte, sizes []int, offset int) (n int, err error) {
|
||||||
defer d.recoverFromPanic("read", &n, &err)
|
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
|
// deviceWrite calls the underlying device Write, recovering from panics in the
|
||||||
// wintun write path and converting them into errors.
|
// wintun write path and converting them into errors.
|
||||||
func (d *FilteredDevice) deviceWrite(bufs [][]byte, offset int) (n int, err error) {
|
func (d *FilteredDevice) deviceWrite(bufs [][]byte, offset int) (n int, err error) {
|
||||||
defer d.recoverFromPanic("write", &n, &err)
|
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
|
// recoverFromPanic converts a panic in the underlying device into a regular
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/unix"
|
"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/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TunDevice struct {
|
type TunDevice struct {
|
||||||
@@ -25,7 +23,7 @@ type TunDevice struct {
|
|||||||
iceBind *bind.ICEBind
|
iceBind *bind.ICEBind
|
||||||
tunFd int
|
tunFd int
|
||||||
|
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
filteredDevice *FilteredDevice
|
filteredDevice *FilteredDevice
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
@@ -50,7 +48,7 @@ var ErrInvalidTunnelFD = fmt.Errorf("invalid tunnel file descriptor: fd is 0 (Sw
|
|||||||
func (t *TunDevice) Create() (WGConfigurer, error) {
|
func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||||
log.Infof("create tun interface")
|
log.Infof("create tun interface")
|
||||||
|
|
||||||
var tunDevice tun.Device
|
var tunDevice wgbackend.TUN
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Validate the tunnel file descriptor.
|
// Validate the tunnel file descriptor.
|
||||||
@@ -79,7 +77,7 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
|||||||
_ = unix.Close(dupTunFd)
|
_ = unix.Close(dupTunFd)
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
log.Errorf("Unable to create new tun device from fd: %v", err)
|
log.Errorf("Unable to create new tun device from fd: %v", err)
|
||||||
_ = unix.Close(dupTunFd)
|
_ = unix.Close(dupTunFd)
|
||||||
@@ -88,7 +86,7 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
|||||||
|
|
||||||
t.filteredDevice = newDeviceFilter(tunDevice)
|
t.filteredDevice = newDeviceFilter(tunDevice)
|
||||||
log.Debug("Attaching to interface")
|
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.
|
// 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
|
// this helps with support for the older NetBird clients that had a hardcoded direct mode
|
||||||
// t.device.DisableSomeRoamingForBrokenMobileSemantics()
|
// t.device.DisableSomeRoamingForBrokenMobileSemantics()
|
||||||
@@ -118,7 +116,7 @@ func (t *TunDevice) Up() (*udpmux.UniversalUDPMuxDefault, error) {
|
|||||||
return udpMux, nil
|
return udpMux, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunDevice) Device() *device.Device {
|
func (t *TunDevice) Device() *wgbackend.Device {
|
||||||
return t.device
|
return t.device
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +161,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
|||||||
return t.filteredDevice
|
return t.filteredDevice
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunDevice) GetNet() *netstack.Net {
|
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/pion/transport/v3"
|
"github.com/pion/transport/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
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/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nbnet "github.com/netbirdio/netbird/client/net"
|
nbnet "github.com/netbirdio/netbird/client/net"
|
||||||
"github.com/netbirdio/netbird/sharedsock"
|
"github.com/netbirdio/netbird/sharedsock"
|
||||||
)
|
)
|
||||||
@@ -170,7 +169,7 @@ func (t *TunKernelDevice) DeviceName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Device returns the wireguard device, not applicable for kernel devices
|
// Device returns the wireguard device, not applicable for kernel devices
|
||||||
func (t *TunKernelDevice) Device() *device.Device {
|
func (t *TunKernelDevice) Device() *wgbackend.Device {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +182,7 @@ func (t *TunKernelDevice) assignAddr() error {
|
|||||||
return t.link.assignAddr(&t.address)
|
return t.link.assignAddr(&t.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunKernelDevice) GetNet() *netstack.Net {
|
func (t *TunKernelDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,18 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
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/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nbnet "github.com/netbirdio/netbird/client/net"
|
nbnet "github.com/netbirdio/netbird/client/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Bind interface {
|
type Bind interface {
|
||||||
conn.Bind
|
wgbackend.Bind
|
||||||
GetICEMux() (*udpmux.UniversalUDPMuxDefault, error)
|
GetICEMux() (*udpmux.UniversalUDPMuxDefault, error)
|
||||||
ActivityRecorder() *bind.ActivityRecorder
|
ActivityRecorder() *bind.ActivityRecorder
|
||||||
EndpointManager
|
EndpointManager
|
||||||
@@ -34,13 +32,13 @@ type TunNetstackDevice struct {
|
|||||||
listenAddress string
|
listenAddress string
|
||||||
bind Bind
|
bind Bind
|
||||||
|
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
filteredDevice *FilteredDevice
|
filteredDevice *FilteredDevice
|
||||||
nsTun *nbnetstack.NetStackTun
|
nsTun *nbnetstack.NetStackTun
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
configurer WGConfigurer
|
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 {
|
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.filteredDevice = newDeviceFilter(tunIface)
|
||||||
t.net = net
|
t.net = net
|
||||||
|
|
||||||
t.device = device.NewDevice(
|
t.device = wgbackend.NewDevice(
|
||||||
t.filteredDevice,
|
t.filteredDevice,
|
||||||
t.bind,
|
t.bind,
|
||||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||||
)
|
)
|
||||||
|
|
||||||
t.configurer = configurer.NewUSPConfigurerNoUAPI(t.device, t.name, t.bind.ActivityRecorder())
|
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
|
// Device returns the wireguard device
|
||||||
func (t *TunNetstackDevice) Device() *device.Device {
|
func (t *TunNetstackDevice) Device() *wgbackend.Device {
|
||||||
return t.device
|
return t.device
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunNetstackDevice) GetNet() *netstack.Net {
|
func (t *TunNetstackDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return t.net
|
return t.net
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
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/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TunDevice struct {
|
type TunDevice struct {
|
||||||
@@ -24,7 +22,7 @@ type TunDevice struct {
|
|||||||
mtu uint16
|
mtu uint16
|
||||||
iceBind *bind.ICEBind
|
iceBind *bind.ICEBind
|
||||||
|
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
filteredDevice *FilteredDevice
|
filteredDevice *FilteredDevice
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
@@ -45,7 +43,7 @@ func NewTunDevice(name string, address wgaddr.Address, port int, key string, mtu
|
|||||||
|
|
||||||
func (t *TunDevice) Create() (WGConfigurer, error) {
|
func (t *TunDevice) Create() (WGConfigurer, error) {
|
||||||
log.Info("create tun interface")
|
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 {
|
if err != nil {
|
||||||
log.Debugf("failed to create tun interface (%s, %d): %s", t.name, int(t.mtu), err)
|
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)
|
return nil, fmt.Errorf("error creating tun device: %s", err)
|
||||||
@@ -53,10 +51,10 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
|||||||
t.filteredDevice = newDeviceFilter(tunIface)
|
t.filteredDevice = newDeviceFilter(tunIface)
|
||||||
|
|
||||||
// We need to create a wireguard-go device and listen to configuration requests
|
// We need to create a wireguard-go device and listen to configuration requests
|
||||||
t.device = device.NewDevice(
|
t.device = wgbackend.NewDevice(
|
||||||
t.filteredDevice,
|
t.filteredDevice,
|
||||||
t.iceBind,
|
t.iceBind,
|
||||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||||
)
|
)
|
||||||
|
|
||||||
err = t.assignAddr()
|
err = t.assignAddr()
|
||||||
@@ -132,7 +130,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Device returns the wireguard device
|
// Device returns the wireguard device
|
||||||
func (t *TunDevice) Device() *device.Device {
|
func (t *TunDevice) Device() *wgbackend.Device {
|
||||||
return t.device
|
return t.device
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +141,7 @@ func (t *TunDevice) assignAddr() error {
|
|||||||
return link.assignAddr(&t.address)
|
return link.assignAddr(&t.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunDevice) GetNet() *netstack.Net {
|
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,15 +6,13 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/windows"
|
"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"
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultWindowsGUIDSTring = "{f2f29e61-d91f-4d76-8151-119b20c4bdeb}"
|
const defaultWindowsGUIDSTring = "{f2f29e61-d91f-4d76-8151-119b20c4bdeb}"
|
||||||
@@ -27,8 +25,8 @@ type TunDevice struct {
|
|||||||
mtu uint16
|
mtu uint16
|
||||||
iceBind *bind.ICEBind
|
iceBind *bind.ICEBind
|
||||||
|
|
||||||
device *device.Device
|
device *wgbackend.Device
|
||||||
nativeTunDevice *tun.NativeTun
|
nativeTunDevice *wgbackend.NativeTUN
|
||||||
filteredDevice *FilteredDevice
|
filteredDevice *FilteredDevice
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
configurer WGConfigurer
|
configurer WGConfigurer
|
||||||
@@ -60,18 +58,18 @@ func (t *TunDevice) Create() (WGConfigurer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Info("create tun interface")
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating tun device: %s", err)
|
return nil, fmt.Errorf("error creating tun device: %s", err)
|
||||||
}
|
}
|
||||||
t.nativeTunDevice = tunDevice.(*tun.NativeTun)
|
t.nativeTunDevice = tunDevice.(*wgbackend.NativeTUN)
|
||||||
t.filteredDevice = newDeviceFilter(tunDevice)
|
t.filteredDevice = newDeviceFilter(tunDevice)
|
||||||
|
|
||||||
// We need to create a wireguard-go device and listen to configuration requests
|
// We need to create a wireguard-go device and listen to configuration requests
|
||||||
t.device = device.NewDevice(
|
t.device = wgbackend.NewDevice(
|
||||||
t.filteredDevice,
|
t.filteredDevice,
|
||||||
t.iceBind,
|
t.iceBind,
|
||||||
device.NewLogger(wgLogLevel(), "[netbird] "),
|
wgbackend.NewLogger(wgLogLevel(), "[netbird] "),
|
||||||
)
|
)
|
||||||
|
|
||||||
luid := winipcfg.LUID(t.nativeTunDevice.LUID())
|
luid := winipcfg.LUID(t.nativeTunDevice.LUID())
|
||||||
@@ -172,7 +170,7 @@ func (t *TunDevice) FilteredDevice() *FilteredDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Device returns the wireguard device
|
// Device returns the wireguard device
|
||||||
func (t *TunDevice) Device() *device.Device {
|
func (t *TunDevice) Device() *wgbackend.Device {
|
||||||
return t.device
|
return t.device
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +207,7 @@ func (t *TunDevice) assignAddr() error {
|
|||||||
return luid.SetIPAddresses([]netip.Prefix{v4Prefix})
|
return luid.SetIPAddresses([]netip.Prefix{v4Prefix})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TunDevice) GetNet() *netstack.Net {
|
func (t *TunDevice) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
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
|
// closeAwareDevice wraps a tun.Device along with a flag
|
||||||
@@ -23,15 +24,15 @@ import (
|
|||||||
// goroutine is awaited and closed only once.
|
// goroutine is awaited and closed only once.
|
||||||
type closeAwareDevice struct {
|
type closeAwareDevice struct {
|
||||||
isClosed atomic.Bool
|
isClosed atomic.Bool
|
||||||
tun.Device
|
wgbackend.TUN
|
||||||
closeEventCh chan struct{}
|
closeEventCh chan struct{}
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClosableDevice(tunDevice tun.Device) *closeAwareDevice {
|
func newClosableDevice(tunDevice wgbackend.TUN) *closeAwareDevice {
|
||||||
return &closeAwareDevice{
|
return &closeAwareDevice{
|
||||||
Device: tunDevice,
|
TUN: tunDevice,
|
||||||
isClosed: atomic.Bool{},
|
isClosed: atomic.Bool{},
|
||||||
closeEventCh: make(chan struct{}),
|
closeEventCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
@@ -39,18 +40,18 @@ func newClosableDevice(tunDevice tun.Device) *closeAwareDevice {
|
|||||||
|
|
||||||
// redirectEvents redirects the Events() method of the underlying tun.Device
|
// redirectEvents redirects the Events() method of the underlying tun.Device
|
||||||
// to the given channel (RenewableTUN's events channel).
|
// 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)
|
c.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer c.wg.Done()
|
defer c.wg.Done()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ev, ok := <-c.Device.Events():
|
case ev, ok := <-c.TUN.Events():
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev == tun.EventDown {
|
if ev == wgbackend.TUNEventDown {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ func (c *closeAwareDevice) Close() (err error) {
|
|||||||
c.closeOnce.Do(func() {
|
c.closeOnce.Do(func() {
|
||||||
c.isClosed.Store(true)
|
c.isClosed.Store(true)
|
||||||
close(c.closeEventCh)
|
close(c.closeEventCh)
|
||||||
err = c.Device.Close()
|
err = c.TUN.Close()
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ type RenewableTUN struct {
|
|||||||
devices []*closeAwareDevice
|
devices []*closeAwareDevice
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
cond *sync.Cond
|
cond *sync.Cond
|
||||||
events chan tun.Event
|
events chan wgbackend.TUNEvent
|
||||||
closed atomic.Bool
|
closed atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ func NewRenewableTUN() *RenewableTUN {
|
|||||||
r := &RenewableTUN{
|
r := &RenewableTUN{
|
||||||
devices: make([]*closeAwareDevice, 0),
|
devices: make([]*closeAwareDevice, 0),
|
||||||
mu: sync.Mutex{},
|
mu: sync.Mutex{},
|
||||||
events: make(chan tun.Event, 16),
|
events: make(chan wgbackend.TUNEvent, 16),
|
||||||
}
|
}
|
||||||
r.cond = sync.NewCond(&r.mu)
|
r.cond = sync.NewCond(&r.mu)
|
||||||
return r
|
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
|
// Events returns a channel that is fed events from the underlying tun.Device's events channel
|
||||||
// once it is added.
|
// once it is added.
|
||||||
func (r *RenewableTUN) Events() <-chan tun.Event {
|
func (r *RenewableTUN) Events() <-chan wgbackend.TUNEvent {
|
||||||
return r.events
|
return r.events
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,7 +260,7 @@ func (r *RenewableTUN) BatchSize() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RenewableTUN) AddDevice(device tun.Device) {
|
func (r *RenewableTUN) AddDevice(device wgbackend.TUN) {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
if r.closed.Load() {
|
if r.closed.Load() {
|
||||||
r.mu.Unlock()
|
r.mu.Unlock()
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package device
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/device"
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
func wgLogLevel() int {
|
func wgLogLevel() int {
|
||||||
if os.Getenv("NB_WG_DEBUG") == "true" {
|
if os.Getenv("NB_WG_DEBUG") == "true" {
|
||||||
return device.LogLevelVerbose
|
return wgbackend.LogLevelVerbose
|
||||||
} else {
|
} else {
|
||||||
return device.LogLevelSilent
|
return wgbackend.LogLevelSilent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
package iface
|
package iface
|
||||||
|
|
||||||
import (
|
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/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WGTunDevice interface {
|
type WGTunDevice interface {
|
||||||
@@ -19,8 +16,8 @@ type WGTunDevice interface {
|
|||||||
DeviceName() string
|
DeviceName() string
|
||||||
Close() error
|
Close() error
|
||||||
FilteredDevice() *device.FilteredDevice
|
FilteredDevice() *device.FilteredDevice
|
||||||
Device() *wgdevice.Device
|
Device() *wgbackend.Device
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
RenewTun(fd int) error
|
RenewTun(fd int) error
|
||||||
GetICEBind() device.EndpointManager
|
GetICEBind() device.EndpointManager
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,17 +10,15 @@ import (
|
|||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/pion/transport/v3"
|
"github.com/pion/transport/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/errors"
|
"github.com/netbirdio/netbird/client/errors"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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/client/iface/wgproxy"
|
||||||
"github.com/netbirdio/netbird/monotime"
|
"github.com/netbirdio/netbird/monotime"
|
||||||
)
|
)
|
||||||
@@ -271,7 +269,7 @@ func (w *WGIface) GetDevice() *device.FilteredDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetWGDevice returns the WireGuard device
|
// GetWGDevice returns the WireGuard device
|
||||||
func (w *WGIface) GetWGDevice() *wgdevice.Device {
|
func (w *WGIface) GetWGDevice() *wgbackend.Device {
|
||||||
return w.tun.Device()
|
return w.tun.Device()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +342,7 @@ func (w *WGIface) waitUntilRemoved() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetNet returns the netstack.Net for the netstack device
|
// GetNet returns the netstack.Net for the netstack device
|
||||||
func (w *WGIface) GetNet() *netstack.Net {
|
func (w *WGIface) GetNet() *wgbackend.NetstackNet {
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
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/device"
|
||||||
|
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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/client/iface/wgproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,14 +33,14 @@ func (f *fakeTunDevice) Create() (device.WGConfigurer, error) {
|
|||||||
func (f *fakeTunDevice) Up() (*udpmux.UniversalUDPMuxDefault, error) {
|
func (f *fakeTunDevice) Up() (*udpmux.UniversalUDPMuxDefault, error) {
|
||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
func (f *fakeTunDevice) UpdateAddr(wgaddr.Address) error { return nil }
|
func (f *fakeTunDevice) UpdateAddr(wgaddr.Address) error { return nil }
|
||||||
func (f *fakeTunDevice) WgAddress() wgaddr.Address { return wgaddr.Address{} }
|
func (f *fakeTunDevice) WgAddress() wgaddr.Address { return wgaddr.Address{} }
|
||||||
func (f *fakeTunDevice) MTU() uint16 { return DefaultMTU }
|
func (f *fakeTunDevice) MTU() uint16 { return DefaultMTU }
|
||||||
func (f *fakeTunDevice) DeviceName() string { return "nb-close-test" }
|
func (f *fakeTunDevice) DeviceName() string { return "nb-close-test" }
|
||||||
func (f *fakeTunDevice) FilteredDevice() *device.FilteredDevice { return nil }
|
func (f *fakeTunDevice) FilteredDevice() *device.FilteredDevice { return nil }
|
||||||
func (f *fakeTunDevice) Device() *wgdevice.Device { return nil }
|
func (f *fakeTunDevice) Device() *wgbackend.Device { return nil }
|
||||||
func (f *fakeTunDevice) GetNet() *netstack.Net { return nil }
|
func (f *fakeTunDevice) GetNet() *wgbackend.NetstackNet { return nil }
|
||||||
func (f *fakeTunDevice) GetICEBind() device.EndpointManager { return nil }
|
func (f *fakeTunDevice) GetICEBind() device.EndpointManager { return nil }
|
||||||
|
|
||||||
func (f *fakeTunDevice) Close() error {
|
func (f *fakeTunDevice) Close() error {
|
||||||
close(f.closeStarted)
|
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
|
// WGIface.GetDevice() which needs the same mutex. The fix is to drop
|
||||||
// the lock before tun.Close() returns control.
|
// the lock before tun.Close() returns control.
|
||||||
func TestWGIface_CloseReleasesMutexBeforeTunClose(t *testing.T) {
|
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{
|
tun := &fakeTunDevice{
|
||||||
closeStarted: make(chan struct{}),
|
closeStarted: make(chan struct{}),
|
||||||
unblockClose: make(chan struct{}),
|
unblockClose: make(chan struct{}),
|
||||||
@@ -105,7 +108,10 @@ func TestWGIface_CloseReleasesMutexBeforeTunClose(t *testing.T) {
|
|||||||
|
|
||||||
close(tun.unblockClose)
|
close(tun.unblockClose)
|
||||||
select {
|
select {
|
||||||
case <-closeDone:
|
case err := <-closeDone:
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("WGIface.Close() returned an error: %v", err)
|
||||||
|
}
|
||||||
case <-time.After(2 * time.Second):
|
case <-time.After(2 * time.Second):
|
||||||
t.Fatal("WGIface.Close() never returned after the tun was unblocked")
|
t.Fatal("WGIface.Close() never returned after the tun was unblocked")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Code generated by MockGen. DO NOT EDIT.
|
// 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 is a generated GoMock package.
|
||||||
package mocks
|
package mocks
|
||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
os "os"
|
os "os"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
tun "github.com/netbirdio/wireguard-go/tun"
|
||||||
gomock "go.uber.org/mock/gomock"
|
gomock "go.uber.org/mock/gomock"
|
||||||
tun "golang.zx2c4.com/wireguard/tun"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockDevice is a mock of Device interface.
|
// MockDevice is a mock of Device interface.
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Dialer interface {
|
type Dialer interface {
|
||||||
@@ -13,10 +14,10 @@ type Dialer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NSDialer struct {
|
type NSDialer struct {
|
||||||
net *netstack.Net
|
net *wgbackend.NetstackNet
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNSDialer(net *netstack.Net) *NSDialer {
|
func NewNSDialer(net *wgbackend.NetstackNet) *NSDialer {
|
||||||
return &NSDialer{
|
return &NSDialer{
|
||||||
net: net,
|
net: net,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
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"
|
const EnvSkipProxy = "NB_NETSTACK_SKIP_PROXY"
|
||||||
@@ -19,7 +19,7 @@ type NetStackTun struct { //nolint:revive
|
|||||||
listenAddress string
|
listenAddress string
|
||||||
|
|
||||||
proxy *Proxy
|
proxy *Proxy
|
||||||
tundev tun.Device
|
tundev wgbackend.TUN
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNetStackTun(listenAddress string, addresses []netip.Addr, dnsAddress netip.Addr, mtu int) *NetStackTun {
|
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) {
|
func (t *NetStackTun) Create() (wgbackend.TUN, *wgbackend.NetstackNet, error) {
|
||||||
nsTunDev, tunNet, err := netstack.CreateNetTUN(
|
nsTunDev, tunNet, err := wgbackend.CreateNetTUN(
|
||||||
t.addresses,
|
t.addresses,
|
||||||
[]netip.Addr{t.dnsAddress},
|
[]netip.Addr{t.dnsAddress},
|
||||||
t.mtu)
|
t.mtu)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
"github.com/pion/logging"
|
"github.com/pion/logging"
|
||||||
"github.com/pion/stun/v3"
|
"github.com/pion/stun/v3"
|
||||||
"github.com/pion/transport/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
|
Section -MainProgram
|
||||||
${INSTALL_TYPE}
|
${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
|
# SetOverwrite ifnewer
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
!ifndef ARCH
|
!ifndef ARCH
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import (
|
|||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
gomock "go.uber.org/mock/gomock"
|
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/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockIFaceMapper is a mock of IFaceMapper interface.
|
// MockIFaceMapper is a mock of IFaceMapper interface.
|
||||||
@@ -108,10 +108,10 @@ func (mr *MockIFaceMapperMockRecorder) GetDevice() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetWGDevice mocks base method.
|
// GetWGDevice mocks base method.
|
||||||
func (m *MockIFaceMapper) GetWGDevice() *wgdevice.Device {
|
func (m *MockIFaceMapper) GetWGDevice() *wgbackend.Device {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetWGDevice")
|
ret := m.ctrl.Call(m, "GetWGDevice")
|
||||||
ret0, _ := ret[0].(*wgdevice.Device)
|
ret0, _ := ret[0].(*wgbackend.Device)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ The IP addresses in the interfaces file are anonymized using the same process as
|
|||||||
Configuration
|
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:
|
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
|
- ManagementURL
|
||||||
- AdminURL
|
|
||||||
- NATExternalIPs
|
- NATExternalIPs
|
||||||
- CustomDNSAddress
|
- CustomDNSAddress
|
||||||
|
|
||||||
@@ -603,9 +602,6 @@ func (g *BundleGenerator) addConfig() error {
|
|||||||
if g.internalConfig.ManagementURL != nil {
|
if g.internalConfig.ManagementURL != nil {
|
||||||
configContent.WriteString(fmt.Sprintf("ManagementURL: %s\n", g.anonymizer.AnonymizeURI(g.internalConfig.ManagementURL.String())))
|
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)))
|
configContent.WriteString(fmt.Sprintf("NATExternalIPs: %v\n", anonymizeNATExternalIPs(g.internalConfig.NATExternalIPs, g.anonymizer)))
|
||||||
if g.internalConfig.CustomDNSAddress != "" {
|
if g.internalConfig.CustomDNSAddress != "" {
|
||||||
configContent.WriteString(fmt.Sprintf("CustomDNSAddress: %s\n", g.anonymizer.AnonymizeString(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 {
|
if g.internalConfig.ManagementURL != nil {
|
||||||
configContent.WriteString(fmt.Sprintf("ManagementURL: %s\n", g.internalConfig.ManagementURL.String()))
|
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))
|
configContent.WriteString(fmt.Sprintf("NATExternalIPs: %v\n", g.internalConfig.NATExternalIPs))
|
||||||
if g.internalConfig.CustomDNSAddress != "" {
|
if g.internalConfig.CustomDNSAddress != "" {
|
||||||
configContent.WriteString(fmt.Sprintf("CustomDNSAddress: %s\n", 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")
|
mURL, _ := url.Parse("https://api.example.com:443")
|
||||||
aURL, _ := url.Parse("https://admin.example.com:443")
|
|
||||||
bTrue := true
|
bTrue := true
|
||||||
iVal := 42
|
iVal := 42
|
||||||
cfg := &profilemanager.Config{
|
cfg := &profilemanager.Config{
|
||||||
PrivateKey: "priv",
|
PrivateKey: "priv",
|
||||||
PreSharedKey: "psk",
|
PreSharedKey: "psk",
|
||||||
ManagementURL: mURL,
|
ManagementURL: mURL,
|
||||||
AdminURL: aURL,
|
|
||||||
WgIface: "wt0",
|
WgIface: "wt0",
|
||||||
WgPort: 51820,
|
WgPort: 51820,
|
||||||
NetworkMonitor: &bTrue,
|
NetworkMonitor: &bTrue,
|
||||||
@@ -947,7 +945,7 @@ func TestAddConfig_AllFieldsCovered(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderAddConfigSpecific renders the fields handled by the anonymize/non-anonymize
|
// 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
|
// addCommonConfigFields covers the rest. Keeping this in the test mirrors the
|
||||||
// production shape without needing to write an actual zip.
|
// production shape without needing to write an actual zip.
|
||||||
func renderAddConfigSpecific(g *BundleGenerator) string {
|
func renderAddConfigSpecific(g *BundleGenerator) string {
|
||||||
@@ -956,9 +954,6 @@ func renderAddConfigSpecific(g *BundleGenerator) string {
|
|||||||
if g.internalConfig.ManagementURL != nil {
|
if g.internalConfig.ManagementURL != nil {
|
||||||
sb.WriteString("ManagementURL: " + g.anonymizer.AnonymizeURI(g.internalConfig.ManagementURL.String()) + "\n")
|
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")
|
sb.WriteString("NATExternalIPs: x\n")
|
||||||
if g.internalConfig.CustomDNSAddress != "" {
|
if g.internalConfig.CustomDNSAddress != "" {
|
||||||
sb.WriteString("CustomDNSAddress: " + g.anonymizer.AnonymizeString(g.internalConfig.CustomDNSAddress) + "\n")
|
sb.WriteString("CustomDNSAddress: " + g.anonymizer.AnonymizeString(g.internalConfig.CustomDNSAddress) + "\n")
|
||||||
@@ -967,9 +962,6 @@ func renderAddConfigSpecific(g *BundleGenerator) string {
|
|||||||
if g.internalConfig.ManagementURL != nil {
|
if g.internalConfig.ManagementURL != nil {
|
||||||
sb.WriteString("ManagementURL: " + g.internalConfig.ManagementURL.String() + "\n")
|
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")
|
sb.WriteString("NATExternalIPs: x\n")
|
||||||
if g.internalConfig.CustomDNSAddress != "" {
|
if g.internalConfig.CustomDNSAddress != "" {
|
||||||
sb.WriteString("CustomDNSAddress: " + g.internalConfig.CustomDNSAddress + "\n")
|
sb.WriteString("CustomDNSAddress: " + g.internalConfig.CustomDNSAddress + "\n")
|
||||||
|
|||||||
@@ -35,11 +35,7 @@ func parseBackupResolvConf() (*resolvConf, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseResolvConfFile(resolvConfFile string) (*resolvConf, error) {
|
func parseResolvConfFile(resolvConfFile string) (*resolvConf, error) {
|
||||||
rconf := &resolvConf{
|
rconf := newResolvConf()
|
||||||
searchDomains: make([]string, 0),
|
|
||||||
nameServers: make([]netip.Addr, 0),
|
|
||||||
others: make([]string, 0),
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Open(resolvConfFile)
|
file, err := os.Open(resolvConfFile)
|
||||||
if err != nil {
|
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 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 {
|
if len(cur) == 0 {
|
||||||
return rconf, fmt.Errorf("file is empty")
|
return rconf, fmt.Errorf("file is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, line := range strings.Split(string(cur), "\n") {
|
for _, line := range strings.Split(string(cur), "\n") {
|
||||||
line = strings.TrimSpace(line)
|
parseResolvConfLine(rconf, 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rconf, nil
|
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
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"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 {
|
type repair struct {
|
||||||
operationFile string
|
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 {
|
if f.inotify != nil {
|
||||||
return
|
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)
|
log.Errorf("failed to start inotify watcher for resolv.conf: %s", err)
|
||||||
return
|
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.inotify = inotify
|
||||||
|
|
||||||
f.inotifyWg.Add(1)
|
f.inotifyWg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer f.inotifyWg.Done()
|
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)
|
// A change that landed before the watch was armed produced no event.
|
||||||
|
lastWritten := f.checkAndRepair(nbSearchDomains, nbNameserverIP, written, stateManager)
|
||||||
rConf, err := parseResolvConfFile(f.operationFile)
|
for {
|
||||||
if err != nil {
|
select {
|
||||||
log.Warnf("failed to parse resolv conf: %s", err)
|
case event, ok := <-inotify.Events:
|
||||||
continue
|
if !ok {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
log.Debugf("check resolv.conf parameters: %s", rConf)
|
if !f.isEventRelevant(event) {
|
||||||
if !isNbParamsMissing(nbSearchDomains, nbNameserverIP, rConf) {
|
continue
|
||||||
log.Tracef("resolv.conf still correct, skip the update")
|
}
|
||||||
continue
|
case err, ok := <-inotify.Errors:
|
||||||
}
|
if !ok {
|
||||||
log.Info("broken params in resolv.conf, repairing it...")
|
return
|
||||||
|
}
|
||||||
err = f.inotify.Remove(f.watchDir)
|
// fsnotify stops delivering events until an error is received, and an
|
||||||
if err != nil {
|
// error such as a queue overflow means events were dropped.
|
||||||
log.Errorf("failed to rm inotify watch for resolv.conf: %s", err)
|
log.Warnf("resolv.conf inotify error, checking the file: %v", 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
|
|
||||||
}
|
}
|
||||||
|
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 {
|
if err != nil {
|
||||||
log.Errorf("failed to add inotify watch for resolv.conf: %s", err)
|
log.Warnf("failed to read resolv.conf: %s", err)
|
||||||
return
|
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() {
|
func (f *repair) stopWatchFileChanges() {
|
||||||
|
|||||||
@@ -4,12 +4,19 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"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/client/internal/statemanager"
|
||||||
"github.com/netbirdio/netbird/util"
|
"github.com/netbirdio/netbird/util"
|
||||||
)
|
)
|
||||||
@@ -106,14 +113,14 @@ nameserver 8.8.8.8`,
|
|||||||
|
|
||||||
var changed bool
|
var changed bool
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
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
|
changed = true
|
||||||
cancel()
|
cancel()
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newRepair(operationFile, updateFn)
|
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)
|
err = os.WriteFile(operationFile, []byte(tt.touchedConfContent), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -153,14 +160,14 @@ searchdomain netbird.cloud something`
|
|||||||
|
|
||||||
var changed bool
|
var changed bool
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
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
|
changed = true
|
||||||
cancel()
|
cancel()
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
r := newRepair(tmpLink, updateFn)
|
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)
|
err = os.WriteFile(tmpLink, []byte(modifyContent), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -175,3 +182,149 @@ searchdomain netbird.cloud something`
|
|||||||
t.Errorf("unexpected result: want: %v, got: %v", true, false)
|
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()
|
f.repair.stopWatchFileChanges()
|
||||||
|
|
||||||
err = f.updateConfig(nbSearchDomains, f.nbNameserverIP, resolvConf, stateManager)
|
written, err := f.updateConfig(nbSearchDomains, f.nbNameserverIP, resolvConf, stateManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
f.repair.watchFileChanges(nbSearchDomains, f.nbNameserverIP, stateManager)
|
f.repair.watchFileChanges(nbSearchDomains, f.nbNameserverIP, written, stateManager)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ func (f *fileConfigurator) getOriginalNameservers() []netip.Addr {
|
|||||||
return f.originalNameservers
|
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)
|
searchDomainList := mergeSearchDomains(nbSearchDomains, cfg.searchDomains)
|
||||||
|
|
||||||
buf := prepareResolvConfContent(
|
buf := prepareResolvConfContent(
|
||||||
@@ -90,7 +90,7 @@ func (f *fileConfigurator) updateConfig(nbSearchDomains []string, nbNameserverIP
|
|||||||
if restoreErr != nil {
|
if restoreErr != nil {
|
||||||
log.Errorf("attempt to restore default file failed with error: %s", err)
|
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)
|
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)
|
log.Errorf("failed to create unclean shutdown resolv.conf backup: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fileConfigurator) restoreHostDNS() error {
|
func (f *fileConfigurator) restoreHostDNS() error {
|
||||||
|
|||||||
@@ -7,14 +7,15 @@ import (
|
|||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type responseWriter struct {
|
type responseWriter struct {
|
||||||
local net.Addr
|
local net.Addr
|
||||||
remote net.Addr
|
remote net.Addr
|
||||||
packet gopacket.Packet
|
packet gopacket.Packet
|
||||||
device tun.Device
|
device wgbackend.TUN
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr returns the net.Addr of the server
|
// LocalAddr returns the net.Addr of the server
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/firewall/uspfilter"
|
"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/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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/local"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns/test"
|
"github.com/netbirdio/netbird/client/internal/dns/test"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns/types"
|
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||||
@@ -83,7 +83,7 @@ func (w *mocWGIface) GetStats(_ string) (configurer.WGStats, error) {
|
|||||||
return configurer.WGStats{}, nil
|
return configurer.WGStats{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *mocWGIface) GetNet() *netstack.Net {
|
func (w *mocWGIface) GetNet() *wgbackend.NetstackNet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ func (s *ServiceViaMemory) filterDNSTraffic() error {
|
|||||||
if s.tcpDNS == nil {
|
if s.tcpDNS == nil {
|
||||||
if dev := s.wgInterface.GetDevice(); dev != nil {
|
if dev := s.wgInterface.GetDevice(); dev != nil {
|
||||||
// MTU only affects TCP segment sizing; DNS messages are small so this has no practical impact.
|
// 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{
|
writer := &responseWriter{
|
||||||
remote: remoteAddrFromPacket(packet),
|
remote: remoteAddrFromPacket(packet),
|
||||||
packet: packet,
|
packet: packet,
|
||||||
device: dev.Device,
|
device: dev.TUN,
|
||||||
}
|
}
|
||||||
go s.dnsMux.ServeDNS(writer, msg)
|
go s.dnsMux.ServeDNS(writer, msg)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
|
||||||
"gvisor.dev/gvisor/pkg/buffer"
|
"gvisor.dev/gvisor/pkg/buffer"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip"
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
||||||
@@ -21,6 +20,8 @@ import (
|
|||||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
|
||||||
"gvisor.dev/gvisor/pkg/waiter"
|
"gvisor.dev/gvisor/pkg/waiter"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -38,7 +39,7 @@ type tcpDNSServer struct {
|
|||||||
s *stack.Stack
|
s *stack.Stack
|
||||||
ep *dnsEndpoint
|
ep *dnsEndpoint
|
||||||
mux *dns.ServeMux
|
mux *dns.ServeMux
|
||||||
tunDev tun.Device
|
tunDev wgbackend.TUN
|
||||||
ip netip.Addr
|
ip netip.Addr
|
||||||
port uint16
|
port uint16
|
||||||
mtu uint16
|
mtu uint16
|
||||||
@@ -49,7 +50,7 @@ type tcpDNSServer struct {
|
|||||||
timer *time.Timer
|
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{
|
return &tcpDNSServer{
|
||||||
mux: mux,
|
mux: mux,
|
||||||
tunDev: tunDev,
|
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.
|
// dnsEndpoint implements stack.LinkEndpoint for writing packets back via the tun device.
|
||||||
type dnsEndpoint struct {
|
type dnsEndpoint struct {
|
||||||
dispatcher stack.NetworkDispatcher
|
dispatcher stack.NetworkDispatcher
|
||||||
tunDev tun.Device
|
tunDev wgbackend.TUN
|
||||||
mtu atomic.Uint32
|
mtu atomic.Uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ import (
|
|||||||
|
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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/resutil"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns/types"
|
"github.com/netbirdio/netbird/client/internal/dns/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"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.
|
// ExchangeWithNetstack performs a DNS exchange using netstack for dialing.
|
||||||
// This is needed when netstack is enabled to reach peer IPs through the tunnel.
|
// 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 request came in over TCP, go straight to TCP upstream
|
||||||
if dnsProtocolFromContext(ctx) == protoTCP {
|
if dnsProtocolFromContext(ctx) == protoTCP {
|
||||||
rm, err := netstackExchange(ctx, nsNet, r, upstream, 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
|
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)
|
conn, err := nsNet.DialContext(ctx, network, upstream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("with %s: %w", network, err)
|
return nil, fmt.Errorf("with %s: %w", network, err)
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
"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/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/shared/management/domain"
|
"github.com/netbirdio/netbird/shared/management/domain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type upstreamResolver struct {
|
type upstreamResolver struct {
|
||||||
*upstreamResolverBase
|
*upstreamResolverBase
|
||||||
nsNet *netstack.Net
|
nsNet *wgbackend.NetstackNet
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUpstreamResolver(
|
func newUpstreamResolver(
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns/test"
|
"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) IsUserspaceBind() bool { return false }
|
||||||
func (m *mockNetstackProvider) GetFilter() device.PacketFilter { return nil }
|
func (m *mockNetstackProvider) GetFilter() device.PacketFilter { return nil }
|
||||||
func (m *mockNetstackProvider) GetDevice() *device.FilteredDevice { 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) {
|
func (m *mockNetstackProvider) GetInterfaceGUIDString() (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WGIface defines subset methods of interface required for manager
|
// WGIface defines subset methods of interface required for manager
|
||||||
@@ -19,5 +18,5 @@ type WGIface interface {
|
|||||||
IsUserspaceBind() bool
|
IsUserspaceBind() bool
|
||||||
GetFilter() device.PacketFilter
|
GetFilter() device.PacketFilter
|
||||||
GetDevice() *device.FilteredDevice
|
GetDevice() *device.FilteredDevice
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WGIface defines subset methods of interface required for manager
|
// WGIface defines subset methods of interface required for manager
|
||||||
@@ -14,6 +13,6 @@ type WGIface interface {
|
|||||||
IsUserspaceBind() bool
|
IsUserspaceBind() bool
|
||||||
GetFilter() device.PacketFilter
|
GetFilter() device.PacketFilter
|
||||||
GetDevice() *device.FilteredDevice
|
GetDevice() *device.FilteredDevice
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
GetInterfaceGUIDString() (string, error)
|
GetInterfaceGUIDString() (string, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import (
|
|||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
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/dns/resutil"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/route"
|
"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 {
|
func (f *DNSForwarder) Listen(entries []*ForwarderEntry) error {
|
||||||
var netstackNet *netstack.Net
|
var netstackNet *wgbackend.NetstackNet
|
||||||
if f.wgIface != nil {
|
if f.wgIface != nil {
|
||||||
netstackNet = f.wgIface.GetNet()
|
netstackNet = f.wgIface.GetNet()
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ func (f *DNSForwarder) Listen(entries []*ForwarderEntry) error {
|
|||||||
return <-errCh
|
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 {
|
if netstackNet != nil {
|
||||||
return netstackNet.ListenUDPAddrPort(f.listenAddress)
|
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))
|
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 {
|
if netstackNet != nil {
|
||||||
return netstackNet.ListenTCPAddrPort(f.listenAddress)
|
return netstackNet.ListenTCPAddrPort(f.listenAddress)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
nftypes "github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
@@ -28,7 +28,7 @@ const (
|
|||||||
|
|
||||||
// wgIface defines the interface for WireGuard interface operations needed by the DNS forwarder.
|
// wgIface defines the interface for WireGuard interface operations needed by the DNS forwarder.
|
||||||
type wgIface interface {
|
type wgIface interface {
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
Address() wgaddr.Address
|
Address() wgaddr.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
"github.com/pion/stun/v3"
|
"github.com/pion/stun/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/anonymize"
|
"github.com/netbirdio/netbird/client/anonymize"
|
||||||
@@ -37,6 +35,7 @@ import (
|
|||||||
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
nbnetstack "github.com/netbirdio/netbird/client/iface/netstack"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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/acl"
|
||||||
"github.com/netbirdio/netbird/client/internal/certproof"
|
"github.com/netbirdio/netbird/client/internal/certproof"
|
||||||
"github.com/netbirdio/netbird/client/internal/debug"
|
"github.com/netbirdio/netbird/client/internal/debug"
|
||||||
@@ -254,7 +253,7 @@ type Engine struct {
|
|||||||
// wgInterface. Reaching the device through wgInterface requires
|
// wgInterface. Reaching the device through wgInterface requires
|
||||||
// syncMsgMux, which handleSync holds while it adds and removes peers;
|
// syncMsgMux, which handleSync holds while it adds and removes peers;
|
||||||
// SetPerformance must stay reachable exactly when that work is stuck.
|
// SetPerformance must stay reachable exactly when that work is stuck.
|
||||||
wgDevice atomic.Pointer[wgdevice.Device]
|
wgDevice atomic.Pointer[wgbackend.Device]
|
||||||
|
|
||||||
udpMux *udpmux.UniversalUDPMuxDefault
|
udpMux *udpmux.UniversalUDPMuxDefault
|
||||||
|
|
||||||
@@ -2788,7 +2787,7 @@ func (e *Engine) stopDNSForwarder() {
|
|||||||
e.dnsForwardMgr = nil
|
e.dnsForwardMgr = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Engine) GetNet() (*netstack.Net, error) {
|
func (e *Engine) GetNet() (*wgbackend.NetstackNet, error) {
|
||||||
e.syncMsgMux.Lock()
|
e.syncMsgMux.Lock()
|
||||||
intf := e.wgInterface
|
intf := e.wgInterface
|
||||||
e.syncMsgMux.Unlock()
|
e.syncMsgMux.Unlock()
|
||||||
|
|||||||
@@ -14,10 +14,9 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"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/internal/stdnet"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
@@ -61,11 +60,11 @@ type MockWGIface struct {
|
|||||||
SetFilterFunc func(filter device.PacketFilter) error
|
SetFilterFunc func(filter device.PacketFilter) error
|
||||||
GetFilterFunc func() device.PacketFilter
|
GetFilterFunc func() device.PacketFilter
|
||||||
GetDeviceFunc func() *device.FilteredDevice
|
GetDeviceFunc func() *device.FilteredDevice
|
||||||
GetWGDeviceFunc func() *wgdevice.Device
|
GetWGDeviceFunc func() *wgbackend.Device
|
||||||
GetStatsFunc func() (map[string]configurer.WGStats, error)
|
GetStatsFunc func() (map[string]configurer.WGStats, error)
|
||||||
GetInterfaceGUIDStringFunc func() (string, error)
|
GetInterfaceGUIDStringFunc func() (string, error)
|
||||||
GetProxyFunc func() wgproxy.Proxy
|
GetProxyFunc func() wgproxy.Proxy
|
||||||
GetNetFunc func() *netstack.Net
|
GetNetFunc func() *wgbackend.NetstackNet
|
||||||
LastActivitiesFunc func() map[string]monotime.Time
|
LastActivitiesFunc func() map[string]monotime.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +148,7 @@ func (m *MockWGIface) GetDevice() *device.FilteredDevice {
|
|||||||
return m.GetDeviceFunc()
|
return m.GetDeviceFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockWGIface) GetWGDevice() *wgdevice.Device {
|
func (m *MockWGIface) GetWGDevice() *wgbackend.Device {
|
||||||
return m.GetWGDeviceFunc()
|
return m.GetWGDeviceFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +160,7 @@ func (m *MockWGIface) GetProxy() wgproxy.Proxy {
|
|||||||
return m.GetProxyFunc()
|
return m.GetProxyFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MockWGIface) GetNet() *netstack.Net {
|
func (m *MockWGIface) GetNet() *wgbackend.NetstackNet {
|
||||||
return m.GetNetFunc()
|
return m.GetNetFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
wgdevice "golang.zx2c4.com/wireguard/device"
|
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/udpmux"
|
"github.com/netbirdio/netbird/client/iface/udpmux"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"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/client/iface/wgproxy"
|
||||||
"github.com/netbirdio/netbird/monotime"
|
"github.com/netbirdio/netbird/monotime"
|
||||||
)
|
)
|
||||||
@@ -37,9 +36,9 @@ type wgIfaceBase interface {
|
|||||||
SetFilter(filter device.PacketFilter) error
|
SetFilter(filter device.PacketFilter) error
|
||||||
GetFilter() device.PacketFilter
|
GetFilter() device.PacketFilter
|
||||||
GetDevice() *device.FilteredDevice
|
GetDevice() *device.FilteredDevice
|
||||||
GetWGDevice() *wgdevice.Device
|
GetWGDevice() *wgbackend.Device
|
||||||
GetStats() (map[string]configurer.WGStats, error)
|
GetStats() (map[string]configurer.WGStats, error)
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
FullStats() (*configurer.Stats, error)
|
FullStats() (*configurer.Stats, error)
|
||||||
LastActivities() map[string]monotime.Time
|
LastActivities() map[string]monotime.Time
|
||||||
SetPresharedKey(peerKey string, psk wgtypes.Key, updateOnly bool) error
|
SetPresharedKey(peerKey string, psk wgtypes.Key, updateOnly bool) error
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
icemaker "github.com/netbirdio/netbird/client/internal/peer/ice"
|
icemaker "github.com/netbirdio/netbird/client/internal/peer/ice"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
"github.com/pion/logging"
|
"github.com/pion/logging"
|
||||||
"github.com/pion/randutil"
|
"github.com/pion/randutil"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package ice
|
package ice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/internal/stdnet"
|
"github.com/netbirdio/netbird/client/internal/stdnet"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package peer
|
package peer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/ice/v4"
|
"github.com/netbirdio/ice/v4"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ const (
|
|||||||
DefaultManagementURL = "https://api.netbird.io:443"
|
DefaultManagementURL = "https://api.netbird.io:443"
|
||||||
// oldDefaultManagementURL points to the NetBird's old cloud management endpoint
|
// oldDefaultManagementURL points to the NetBird's old cloud management endpoint
|
||||||
oldDefaultManagementURL = "https://api.wiretrustee.com:443"
|
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"
|
DefaultAdminURL = "https://app.netbird.io:443"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -60,7 +61,6 @@ var DefaultInterfaceBlacklist = []string{
|
|||||||
// ConfigInput carries configuration changes to the client
|
// ConfigInput carries configuration changes to the client
|
||||||
type ConfigInput struct {
|
type ConfigInput struct {
|
||||||
ManagementURL string
|
ManagementURL string
|
||||||
AdminURL string
|
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
StateFilePath string
|
StateFilePath string
|
||||||
PreSharedKey *string
|
PreSharedKey *string
|
||||||
@@ -114,7 +114,6 @@ type Config struct {
|
|||||||
PrivateKey string
|
PrivateKey string
|
||||||
PreSharedKey string
|
PreSharedKey string
|
||||||
ManagementURL *url.URL
|
ManagementURL *url.URL
|
||||||
AdminURL *url.URL
|
|
||||||
WgIface string
|
WgIface string
|
||||||
WgPort int
|
WgPort int
|
||||||
NetworkMonitor *bool
|
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 {
|
if input.WireguardPort != nil && *input.WireguardPort != config.WgPort {
|
||||||
log.Infof("updating Wireguard port %d (old value %d)",
|
log.Infof("updating Wireguard port %d (old value %d)",
|
||||||
*input.WireguardPort, config.WgPort)
|
*input.WireguardPort, config.WgPort)
|
||||||
@@ -1027,8 +1003,7 @@ func ParseServiceURL(serviceName, serviceURL string) (*url.URL, error) {
|
|||||||
// matches only another nil one.
|
// matches only another nil one.
|
||||||
//
|
//
|
||||||
// The path plays no part: a management URL is dialed, and only its host and
|
// 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
|
// port are. util.SameServiceURL is this comparison plus the path.
|
||||||
// what SameServiceURLIncludingPath needs and delegates to.
|
|
||||||
func SameServiceURL(a, b *url.URL) bool {
|
func SameServiceURL(a, b *url.URL) bool {
|
||||||
if a == nil || b == nil {
|
if a == nil || b == nil {
|
||||||
return a == b
|
return a == b
|
||||||
@@ -1039,25 +1014,6 @@ func SameServiceURL(a, b *url.URL) bool {
|
|||||||
util.ServiceURLPort(a) == util.ServiceURLPort(b)
|
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) {
|
func parseURL(serviceName, serviceURL string) (*url.URL, error) {
|
||||||
parsedMgmtURL, err := url.ParseRequestURI(serviceURL)
|
parsedMgmtURL, err := url.ParseRequestURI(serviceURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -36,17 +36,14 @@ func TestGetConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, config.ManagementURL.String(), DefaultManagementURL)
|
assert.Equal(t, config.ManagementURL.String(), DefaultManagementURL)
|
||||||
assert.Equal(t, config.AdminURL.String(), DefaultAdminURL)
|
|
||||||
|
|
||||||
managementURL := "https://test.management.url:33071"
|
managementURL := "https://test.management.url:33071"
|
||||||
adminURL := "https://app.admin.url:443"
|
|
||||||
path := filepath.Join(t.TempDir(), "config.json")
|
path := filepath.Join(t.TempDir(), "config.json")
|
||||||
preSharedKey := "preSharedKey"
|
preSharedKey := "preSharedKey"
|
||||||
|
|
||||||
// case 2: new config has to be generated
|
// case 2: new config has to be generated
|
||||||
config, err = UpdateOrCreateConfig(ConfigInput{
|
config, err = UpdateOrCreateConfig(ConfigInput{
|
||||||
ManagementURL: managementURL,
|
ManagementURL: managementURL,
|
||||||
AdminURL: adminURL,
|
|
||||||
ConfigPath: path,
|
ConfigPath: path,
|
||||||
PreSharedKey: &preSharedKey,
|
PreSharedKey: &preSharedKey,
|
||||||
})
|
})
|
||||||
@@ -64,7 +61,6 @@ func TestGetConfig(t *testing.T) {
|
|||||||
// case 3: existing config -> fetch it
|
// case 3: existing config -> fetch it
|
||||||
config, err = UpdateOrCreateConfig(ConfigInput{
|
config, err = UpdateOrCreateConfig(ConfigInput{
|
||||||
ManagementURL: managementURL,
|
ManagementURL: managementURL,
|
||||||
AdminURL: adminURL,
|
|
||||||
ConfigPath: path,
|
ConfigPath: path,
|
||||||
PreSharedKey: &preSharedKey,
|
PreSharedKey: &preSharedKey,
|
||||||
})
|
})
|
||||||
@@ -79,7 +75,6 @@ func TestGetConfig(t *testing.T) {
|
|||||||
newManagementURL := "https://test.newManagement.url:33071"
|
newManagementURL := "https://test.newManagement.url:33071"
|
||||||
config, err = UpdateOrCreateConfig(ConfigInput{
|
config, err = UpdateOrCreateConfig(ConfigInput{
|
||||||
ManagementURL: newManagementURL,
|
ManagementURL: newManagementURL,
|
||||||
AdminURL: adminURL,
|
|
||||||
ConfigPath: path,
|
ConfigPath: path,
|
||||||
PreSharedKey: &preSharedKey,
|
PreSharedKey: &preSharedKey,
|
||||||
})
|
})
|
||||||
@@ -164,7 +159,6 @@ func TestNewProfileDefaults(t *testing.T) {
|
|||||||
require.NoError(t, err, "should create new config")
|
require.NoError(t, err, "should create new config")
|
||||||
|
|
||||||
assert.Equal(t, DefaultManagementURL, config.ManagementURL.String(), "ManagementURL should have default")
|
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.PrivateKey, "PrivateKey should be generated")
|
||||||
assert.NotEmpty(t, config.SSHKey, "SSHKey should be generated")
|
assert.NotEmpty(t, config.SSHKey, "SSHKey should be generated")
|
||||||
assert.Equal(t, iface.WgInterfaceDefault, config.WgIface, "WgIface should have default")
|
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)
|
require.NotEmpty(t, cfg.SSHKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The admin panel is opened, not dialed, so its path identifies it. Comparing
|
// Profiles written before the admin URL was dropped still carry an AdminURL key.
|
||||||
// it as a bare endpoint left a custom panel URL unable to change.
|
// It must not break loading, and the next write must drop it.
|
||||||
func TestAdminURLPathIsPartOfTheIdentity(t *testing.T) {
|
func TestLegacyAdminURLIsIgnored(t *testing.T) {
|
||||||
path := filepath.Join(t.TempDir(), "panel.json")
|
path := filepath.Join(t.TempDir(), "legacy.json")
|
||||||
_, err := UpdateOrCreateConfig(ConfigInput{
|
_, err := UpdateOrCreateConfig(ConfigInput{ConfigPath: path})
|
||||||
ConfigPath: path,
|
|
||||||
AdminURL: "https://app.example.com/netbird",
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cfg, err := GetExistingConfig(path)
|
raw, err := os.ReadFile(path)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "https://app.example.com:443/netbird", cfg.AdminURL.String())
|
var stored map[string]json.RawMessage
|
||||||
|
require.NoError(t, json.Unmarshal(raw, &stored))
|
||||||
// Equivalent spellings of the same panel are still not a change.
|
stored["AdminURL"] = json.RawMessage(`{"Scheme":"https","Host":"panel.example.com:443","Path":"/netbird"}`)
|
||||||
for _, same := range []string{
|
rewritten, err := json.Marshal(stored)
|
||||||
"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"})
|
|
||||||
require.NoError(t, err)
|
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.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,
|
// unsetOnDisk rewrites the stored config so the named fields carry a JSON null,
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wgIfaceBase interface {
|
type wgIfaceBase interface {
|
||||||
@@ -20,5 +19,5 @@ type wgIfaceBase interface {
|
|||||||
IsUserspaceBind() bool
|
IsUserspaceBind() bool
|
||||||
GetFilter() device.PacketFilter
|
GetFilter() device.PacketFilter
|
||||||
GetDevice() *device.FilteredDevice
|
GetDevice() *device.FilteredDevice
|
||||||
GetNet() *netstack.Net
|
GetNet() *wgbackend.NetstackNet
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager/refcounter"
|
"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) IsUserspaceBind() bool { return false }
|
||||||
func (m *reconcileWGMock) GetFilter() device.PacketFilter { return nil }
|
func (m *reconcileWGMock) GetFilter() device.PacketFilter { return nil }
|
||||||
func (m *reconcileWGMock) GetDevice() *device.FilteredDevice { 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
|
// 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.
|
// 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
|
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) {
|
func (p *Preferences) GetAdminURL() (string, error) {
|
||||||
if p.configInput.AdminURL != "" {
|
return profilemanager.DefaultAdminURL, nil
|
||||||
return p.configInput.AdminURL, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := profilemanager.ReadConfigOrDefault(p.configInput.ConfigPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return cfg.AdminURL.String(), err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAdminURL store the given url and wait for commit
|
// SetAdminURL is a no-op kept for API compatibility.
|
||||||
func (p *Preferences) SetAdminURL(url string) {
|
//
|
||||||
p.configInput.AdminURL = url
|
// 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
|
// HasPreSharedKey reports whether a pre-shared key is staged, persisted, or
|
||||||
// enforced by MDM; the key itself is never handed to the native layer.
|
// 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")
|
stateFile := filepath.Join(t.TempDir(), "state.json")
|
||||||
p := NewPreferences(cfgFile, stateFile)
|
p := NewPreferences(cfgFile, stateFile)
|
||||||
|
|
||||||
|
// The admin URL is deprecated: setting it is a no-op.
|
||||||
p.SetAdminURL(exampleString)
|
p.SetAdminURL(exampleString)
|
||||||
resp, err := p.GetAdminURL()
|
resp, err := p.GetAdminURL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to read admin url: %s", err)
|
t.Fatalf("failed to read admin url: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp != exampleString {
|
if resp != profilemanager.DefaultAdminURL {
|
||||||
t.Errorf("unexpected admin url: %s", resp)
|
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)
|
t.Fatalf("failed to read admin url: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp != exampleURL {
|
if resp != profilemanager.DefaultAdminURL {
|
||||||
t.Errorf("unexpected admin url: %s", resp)
|
t.Errorf("unexpected admin url: %s", resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -595,9 +595,6 @@ func (s *Server) setConfigInputFromRequest(msg *proto.SetConfigRequest) (profile
|
|||||||
if msg.ManagementUrl != "" {
|
if msg.ManagementUrl != "" {
|
||||||
config.ManagementURL = msg.ManagementUrl
|
config.ManagementURL = msg.ManagementUrl
|
||||||
}
|
}
|
||||||
if msg.AdminURL != "" {
|
|
||||||
config.AdminURL = msg.AdminURL
|
|
||||||
}
|
|
||||||
if msg.InterfaceName != nil {
|
if msg.InterfaceName != nil {
|
||||||
config.InterfaceName = msg.InterfaceName
|
config.InterfaceName = msg.InterfaceName
|
||||||
}
|
}
|
||||||
@@ -2413,7 +2410,6 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p
|
|||||||
// overlay (Loader lives outside profilemanager).
|
// overlay (Loader lives outside profilemanager).
|
||||||
cfg.ApplyMDMPolicy(s.mdmLoader.Load())
|
cfg.ApplyMDMPolicy(s.mdmLoader.Load())
|
||||||
managementURL := cfg.ManagementURL
|
managementURL := cfg.ManagementURL
|
||||||
adminURL := cfg.AdminURL
|
|
||||||
|
|
||||||
var preSharedKey = cfg.PreSharedKey
|
var preSharedKey = cfg.PreSharedKey
|
||||||
if preSharedKey != "" {
|
if preSharedKey != "" {
|
||||||
@@ -2469,7 +2465,6 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p
|
|||||||
return &proto.GetConfigResponse{
|
return &proto.GetConfigResponse{
|
||||||
ManagementUrl: managementURL.String(),
|
ManagementUrl: managementURL.String(),
|
||||||
PreSharedKey: preSharedKey,
|
PreSharedKey: preSharedKey,
|
||||||
AdminURL: adminURL.String(),
|
|
||||||
InterfaceName: cfg.WgIface,
|
InterfaceName: cfg.WgIface,
|
||||||
WireguardPort: int64(cfg.WgPort),
|
WireguardPort: int64(cfg.WgPort),
|
||||||
Mtu: int64(cfg.MTU),
|
Mtu: int64(cfg.MTU),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -129,7 +130,10 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Equal(t, "https://new-api.netbird.io:443", cfg.ManagementURL.String())
|
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, rosenpassEnabled, cfg.RosenpassEnabled)
|
||||||
require.Equal(t, rosenpassPermissive, cfg.RosenpassPermissive)
|
require.Equal(t, rosenpassPermissive, cfg.RosenpassPermissive)
|
||||||
require.NotNil(t, cfg.ServerSSHAllowed)
|
require.NotNil(t, cfg.ServerSSHAllowed)
|
||||||
@@ -182,11 +186,11 @@ func verifyAllFieldsCovered(t *testing.T, req *proto.SetConfigRequest) {
|
|||||||
"CleanNATExternalIPs": true, // control flag for clearing
|
"CleanNATExternalIPs": true, // control flag for clearing
|
||||||
"CleanDNSLabels": true, // control flag for clearing
|
"CleanDNSLabels": true, // control flag for clearing
|
||||||
"LazyConnectionEnabled": true, // deprecated: proto field retained for compat, no longer applied
|
"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{
|
expectedFields := map[string]bool{
|
||||||
"ManagementUrl": true,
|
"ManagementUrl": true,
|
||||||
"AdminURL": true,
|
|
||||||
"RosenpassEnabled": true,
|
"RosenpassEnabled": true,
|
||||||
"RosenpassPermissive": true,
|
"RosenpassPermissive": true,
|
||||||
"ServerSSHAllowed": 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.
|
// This map must be updated when adding new config-related CLI flags.
|
||||||
flagToField := map[string]string{
|
flagToField := map[string]string{
|
||||||
"management-url": "ManagementUrl",
|
"management-url": "ManagementUrl",
|
||||||
"admin-url": "AdminURL",
|
|
||||||
"enable-rosenpass": "RosenpassEnabled",
|
"enable-rosenpass": "RosenpassEnabled",
|
||||||
"rosenpass-permissive": "RosenpassPermissive",
|
"rosenpass-permissive": "RosenpassPermissive",
|
||||||
"allow-server-ssh": "ServerSSHAllowed",
|
"allow-server-ssh": "ServerSSHAllowed",
|
||||||
@@ -286,6 +289,7 @@ func TestCLIFlags_MappedToSetConfig(t *testing.T) {
|
|||||||
fieldsWithoutCLIFlags := map[string]bool{
|
fieldsWithoutCLIFlags := map[string]bool{
|
||||||
"DisableNotifications": true, // Only settable via UI
|
"DisableNotifications": true, // Only settable via UI
|
||||||
"LazyConnectionEnabled": true, // deprecated: no longer settable (managed by server + NB_LAZY_CONN)
|
"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.
|
// 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():
|
case <-ctx.Done():
|
||||||
_ = session.Signal(ssh.SIGTERM)
|
_ = session.Signal(ssh.SIGTERM)
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case err := <-done:
|
||||||
|
log.Debugf("session ended after SIGTERM: %v", err)
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
@@ -205,7 +206,8 @@ func (c *Client) ExecuteCommandWithPTY(ctx context.Context, command string) erro
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
_ = session.Signal(ssh.SIGTERM)
|
_ = session.Signal(ssh.SIGTERM)
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case err := <-done:
|
||||||
|
log.Debugf("session ended after SIGTERM: %v", err)
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
cryptossh "golang.org/x/crypto/ssh"
|
cryptossh "golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
"golang.zx2c4.com/wireguard/tun/netstack"
|
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
"github.com/netbirdio/netbird/client/iface/wgaddr"
|
||||||
|
"github.com/netbirdio/netbird/client/iface/wgbackend"
|
||||||
sshauth "github.com/netbirdio/netbird/client/ssh/auth"
|
sshauth "github.com/netbirdio/netbird/client/ssh/auth"
|
||||||
"github.com/netbirdio/netbird/client/ssh/detection"
|
"github.com/netbirdio/netbird/client/ssh/detection"
|
||||||
"github.com/netbirdio/netbird/shared/auth"
|
"github.com/netbirdio/netbird/shared/auth"
|
||||||
@@ -167,7 +167,7 @@ type Server struct {
|
|||||||
allowSFTP bool
|
allowSFTP bool
|
||||||
jwtEnabled bool
|
jwtEnabled bool
|
||||||
|
|
||||||
netstackNet *netstack.Net
|
netstackNet *wgbackend.NetstackNet
|
||||||
|
|
||||||
wgAddress wgaddr.Address
|
wgAddress wgaddr.Address
|
||||||
|
|
||||||
@@ -445,7 +445,7 @@ func (s *Server) buildSessionInfo(state *sessionState) SessionInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetNetstackNet sets the netstack network for userspace networking
|
// 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()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
s.netstackNet = net
|
s.netstackNet = net
|
||||||
|
|||||||
@@ -8,5 +8,6 @@
|
|||||||
"arrowParens": "always",
|
"arrowParens": "always",
|
||||||
"endOfLine": "lf",
|
"endOfLine": "lf",
|
||||||
"plugins": ["prettier-plugin-tailwindcss"],
|
"plugins": ["prettier-plugin-tailwindcss"],
|
||||||
|
"tailwindStylesheet": "./src/globals.css",
|
||||||
"tailwindFunctions": ["cn", "clsx", "cva", "tw"]
|
"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
|
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`.
|
**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):
|
`Config` (read-only mirror, all required):
|
||||||
```ts
|
```ts
|
||||||
{ managementUrl, adminUrl, configFile, logFile, preSharedKey, interfaceName: string;
|
{ managementUrl, configFile, logFile, preSharedKey, interfaceName: string;
|
||||||
wireguardPort, mtu, sshJwtCacheTtl: number;
|
wireguardPort, mtu, sshJwtCacheTtl: number;
|
||||||
disableAutoConnect, serverSshAllowed,
|
disableAutoConnect, serverSshAllowed,
|
||||||
rosenpassEnabled, rosenpassPermissive,
|
rosenpassEnabled, rosenpassPermissive,
|
||||||
@@ -254,7 +254,7 @@ The tray also reads a tray-only synthetic `"Error"` for icon purposes; the front
|
|||||||
disableSshAuth: boolean; }
|
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 }`.
|
`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