├── .gitmodules ├── versioninfo.json ├── .gitattributes ├── infrastructure_files ├── artifacts │ └── .gitkeep └── observability │ └── grafana │ └── dashboards │ ├── .gitignore │ └── readme.md ├── .dockerignore-client ├── relay ├── protocol │ └── protocol.go ├── Dockerfile ├── main.go ├── server │ └── listener │ │ └── listener.go ├── cmd │ └── pprof.go ├── doc.go └── testec2 │ └── start_msg.go ├── shared ├── relay │ ├── tls │ │ ├── alpn.go │ │ ├── server_prod.go │ │ ├── client_prod.go │ │ └── client_dev.go │ ├── auth │ │ ├── go.sum │ │ ├── allow │ │ │ └── allow_all.go │ │ ├── hmac │ │ │ ├── doc.go │ │ │ ├── v2 │ │ │ │ ├── algo.go │ │ │ │ └── token.go │ │ │ └── validator.go │ │ ├── doc.go │ │ └── validator.go │ ├── client │ │ ├── dialer │ │ │ ├── net │ │ │ │ └── err.go │ │ │ └── ws │ │ │ │ ├── dialopts_js.go │ │ │ │ ├── dialopts_generic.go │ │ │ │ └── addr.go │ │ ├── addr.go │ │ ├── dialers_js.go │ │ ├── doc.go │ │ ├── dialers_generic.go │ │ └── picker_test.go │ ├── constants.go │ ├── messages │ │ ├── doc.go │ │ ├── address │ │ │ └── address.go │ │ └── id.go │ └── healthcheck │ │ └── env.go ├── management │ ├── operations │ │ └── operation.go │ ├── http │ │ └── api │ │ │ ├── cfg.yaml │ │ │ └── generate.sh │ ├── proto │ │ ├── go.sum │ │ └── generate.sh │ └── client │ │ ├── go.sum │ │ ├── rest │ │ └── events.go │ │ └── common │ │ └── types.go ├── context │ └── keys.go ├── signal │ ├── proto │ │ ├── go.sum │ │ ├── constants.go │ │ └── generate.sh │ └── client │ │ └── client_suite_test.go └── auth │ └── user.go ├── client ├── internal │ ├── dns │ │ ├── types │ │ │ └── types.go │ │ ├── server_js.go │ │ ├── server_android.go │ │ ├── server_windows.go │ │ ├── server_ios.go │ │ ├── server_darwin.go │ │ ├── server_unix.go │ │ ├── unclean_shutdown_mobile.go │ │ ├── service.go │ │ ├── unclean_shutdown_js.go │ │ ├── systemd_freebsd.go │ │ ├── wgiface_windows.go │ │ ├── server_export_test.go │ │ ├── consts.go │ │ ├── wgiface.go │ │ ├── server_export.go │ │ ├── unclean_shutdown_windows.go │ │ ├── host_android.go │ │ ├── unclean_shutdown_darwin.go │ │ └── test │ │ │ └── mock.go │ ├── peer │ │ ├── id │ │ │ └── connid.go │ │ ├── ice │ │ │ ├── StunTurn_test.go │ │ │ ├── stdnet.go │ │ │ ├── stdnet_android.go │ │ │ ├── StunTurn.go │ │ │ └── config.go │ │ ├── listener.go │ │ ├── env.go │ │ ├── nilcheck.go │ │ ├── guard │ │ │ └── env.go │ │ ├── conntype │ │ │ └── priority.go │ │ ├── conn_status_test.go │ │ ├── iface.go │ │ ├── conn_status.go │ │ └── error_test.go │ ├── updatemanager │ │ ├── installer │ │ │ ├── log.go │ │ │ ├── binary_nowindows.go │ │ │ ├── repourl_dev.go │ │ │ ├── repourl_prod.go │ │ │ ├── installer_log_darwin.go │ │ │ ├── binary_windows.go │ │ │ ├── types.go │ │ │ ├── installer_log_windows.go │ │ │ ├── procattr_windows.go │ │ │ ├── procattr_darwin.go │ │ │ └── types_darwin.go │ │ ├── reposign │ │ │ ├── embed_dev.go │ │ │ ├── embed_prod.go │ │ │ ├── certs │ │ │ │ └── root-pub.pem │ │ │ ├── certsdev │ │ │ │ └── root-pub.pem │ │ │ └── signature.go │ │ └── update.go │ ├── ebpf │ │ ├── ebpf │ │ │ ├── bpf_bpfeb.o │ │ │ ├── bpf_bpfel.o │ │ │ └── src │ │ │ │ └── readme.md │ │ ├── manager │ │ │ └── manager.go │ │ ├── instantiater_nonlinux.go │ │ └── instantiater_linux.go │ ├── iface.go │ ├── iface_windows.go │ ├── debug │ │ ├── debug_nonunix.go │ │ ├── debug_mobile.go │ │ ├── debug_nondarwin.go │ │ ├── debug_nonlinux.go │ │ ├── debug_unix.go │ │ └── debug_nonmobile.go │ ├── templates │ │ └── embed.go │ ├── lazyconn │ │ ├── activity │ │ │ ├── listen_ip.go │ │ │ └── listen_ip_linux.go │ │ ├── peercfg.go │ │ ├── inactivity │ │ │ └── ticker.go │ │ ├── wgiface.go │ │ ├── env.go │ │ └── support_test.go │ ├── routemanager │ │ ├── iface │ │ │ ├── iface_windows.go │ │ │ ├── iface.go │ │ │ └── iface_common.go │ │ ├── systemops │ │ │ ├── flush_nonbsd.go │ │ │ └── state.go │ │ ├── dynamic │ │ │ └── route_generic.go │ │ ├── vars │ │ │ └── vars.go │ │ ├── refcounter │ │ │ └── types.go │ │ ├── util │ │ │ └── ip.go │ │ └── state.go │ ├── auth │ │ └── pkce_flow_other.go │ ├── sleep │ │ ├── detector_notsupported.go │ │ └── service.go │ ├── engine_stdnet_android.go │ ├── engine_stdnet.go │ ├── listener │ │ └── network_change.go │ ├── profilemanager │ │ └── error.go │ ├── netflow │ │ └── conntrack │ │ │ └── conntrack_nonlinux.go │ ├── acl │ │ └── mocks │ │ │ └── README.md │ ├── networkmonitor │ │ ├── check_change_js.go │ │ ├── monitor_mobile.go │ │ └── check_change_bsd.go │ ├── stdnet │ │ ├── discover.go │ │ ├── listener.go │ │ ├── discover_pion.go │ │ └── dialer.go │ ├── engine_js.go │ ├── engine_generic.go │ └── mobile_dependency.go ├── ui │ ├── Netbird.icns │ ├── build │ │ ├── banner.bmp │ │ ├── build-ui-linux.sh │ │ └── netbird.desktop │ ├── assets │ │ ├── connected.png │ │ ├── netbird.ico │ │ ├── netbird.png │ │ ├── disconnected.png │ │ ├── netbird-disconnected.ico │ │ ├── netbird-disconnected.png │ │ ├── netbird-systemtray-error.ico │ │ ├── netbird-systemtray-error.png │ │ ├── netbird-systemtray-connected.ico │ │ ├── netbird-systemtray-connected.png │ │ ├── netbird-systemtray-connecting.ico │ │ ├── netbird-systemtray-connecting.png │ │ ├── netbird-systemtray-error-dark.ico │ │ ├── netbird-systemtray-error-dark.png │ │ ├── netbird-systemtray-disconnected.ico │ │ ├── netbird-systemtray-disconnected.png │ │ ├── netbird-systemtray-error-macos.png │ │ ├── netbird-systemtray-connected-dark.ico │ │ ├── netbird-systemtray-connected-dark.png │ │ ├── netbird-systemtray-connected-macos.png │ │ ├── netbird-systemtray-connecting-dark.ico │ │ ├── netbird-systemtray-connecting-dark.png │ │ ├── netbird-systemtray-connecting-macos.png │ │ ├── netbird-systemtray-update-connected.ico │ │ ├── netbird-systemtray-update-connected.png │ │ ├── netbird-systemtray-disconnected-macos.png │ │ ├── netbird-systemtray-update-disconnected.ico │ │ ├── netbird-systemtray-update-disconnected.png │ │ ├── netbird-systemtray-update-connected-dark.ico │ │ ├── netbird-systemtray-update-connected-dark.png │ │ ├── netbird-systemtray-update-connected-macos.png │ │ ├── netbird-systemtray-update-disconnected-dark.ico │ │ ├── netbird-systemtray-update-disconnected-dark.png │ │ └── netbird-systemtray-update-disconnected-macos.png │ ├── font_linux.go │ ├── update_notwindows.go │ ├── desktop │ │ └── desktop.go │ ├── font_darwin.go │ ├── process │ │ ├── process_windows.go │ │ ├── process_nonwindows.go │ │ └── process.go │ ├── quickactions_assets.go │ ├── manifest.xml │ └── font_bsd.go ├── iface │ ├── bind │ │ ├── recv_msg.go │ │ ├── error.go │ │ ├── endpoint.go │ │ ├── control.go │ │ └── activity_test.go │ ├── configurer │ │ ├── err.go │ │ ├── name_darwin.go │ │ ├── wgstats.go │ │ ├── name.go │ │ ├── uapi_windows.go │ │ ├── uapi_js.go │ │ ├── wgshow.go │ │ ├── common.go │ │ └── uapi.go │ ├── iface_destroy_js.go │ ├── device │ │ ├── windows_guid.go │ │ ├── args.go │ │ ├── device_netstack_generic.go │ │ ├── kernel_module.go │ │ ├── wg_log.go │ │ ├── adapter.go │ │ ├── endpoint_manager.go │ │ ├── device_netstack_android.go │ │ ├── kernel_module_freebsd.go │ │ ├── device_netstack_test.go │ │ └── interface.go │ ├── freebsd │ │ └── errors.go │ ├── udpmux │ │ ├── mux_ios.go │ │ └── mux_generic.go │ ├── iface_destroy_mobile.go │ ├── netstack │ │ ├── env_js.go │ │ └── dialer.go │ ├── mocks │ │ └── README.md │ ├── iface_guid_windows.go │ ├── iface_destroy_bsd.go │ ├── bufsize │ │ └── bufsize.go │ ├── iface_destroy_linux.go │ ├── wgproxy │ │ ├── listener │ │ │ └── listener.go │ │ ├── factory_usp.go │ │ └── ebpf │ │ │ └── portlookup.go │ ├── wgaddr │ │ └── address.go │ ├── device.go │ ├── device_android.go │ ├── iface_create.go │ └── iface_create_android.go ├── net │ ├── dialer_init_android.go │ ├── dialer_init_windows.go │ ├── dialer_init_generic.go │ ├── listener_init_generic.go │ ├── listen_ios.go │ ├── listener_init_android.go │ ├── listener_listen_ios.go │ ├── dialer_init_linux.go │ ├── dial_ios.go │ ├── listener_init_linux.go │ ├── listener_init_windows.go │ ├── dialer.go │ ├── listener.go │ ├── env_generic.go │ └── env_android.go ├── server │ ├── panic_generic.go │ ├── state_generic.go │ ├── log.go │ ├── state_linux.go │ └── updateresult.go ├── android │ ├── gomobile.go │ ├── platform_files.go │ ├── peer_routes.go │ ├── exec.go │ ├── networks.go │ ├── dns_list_test.go │ └── env_list.go ├── ssh │ ├── server │ │ ├── user_utils_js.go │ │ ├── userswitching_js.go │ │ ├── sftp_js.go │ │ └── session_handlers_js.go │ └── config │ │ └── shutdown_state.go ├── main.go ├── ios │ └── NetBirdSDK │ │ ├── gomobile.go │ │ ├── logger.go │ │ └── env_list.go ├── cmd │ ├── update.go │ ├── debug_js.go │ ├── status_test.go │ ├── version.go │ ├── signer │ │ └── main.go │ └── pprof.go ├── resources.rc ├── system │ ├── sysinfo_linux.go │ ├── detect_platform │ │ ├── kube.go │ │ └── openstack.go │ ├── detect_cloud │ │ ├── vultr.go │ │ ├── alibabacloud.go │ │ ├── digitalocean.go │ │ ├── gcp.go │ │ └── azure.go │ ├── info_darwin_test.go │ ├── info_windows_test.go │ ├── static_info.go │ └── static_info_update.go ├── firewall │ ├── iptables │ │ └── rule.go │ ├── nftables │ │ └── rule_linux.go │ ├── uspfilter │ │ └── common │ │ │ └── iface.go │ ├── iface.go │ └── manager │ │ ├── routerpair.go │ │ ├── protocol.go │ │ └── forward_rule.go ├── grpc │ └── dialer_js.go ├── configs │ └── configs.go ├── proto │ └── generate.sh ├── manifest.xml └── errors │ └── errors.go ├── management ├── internals │ ├── controllers │ │ └── network_map │ │ │ ├── network_map.go │ │ │ ├── update_message.go │ │ │ ├── controller │ │ │ └── metrics.go │ │ │ └── update_channel.go │ └── modules │ │ └── peers │ │ └── ephemeral │ │ └── interface.go ├── server │ ├── testdata │ │ ├── geonames_20240305.db │ │ └── GeoLite2-City_20240305.mmdb │ ├── http │ │ └── configs │ │ │ └── auth.go │ ├── permissions │ │ ├── operations │ │ │ └── operation.go │ │ └── roles │ │ │ ├── owner.go │ │ │ ├── user.go │ │ │ ├── auditor.go │ │ │ ├── admin.go │ │ │ └── role_permissions.go │ ├── types │ │ ├── store.go │ │ ├── dns_settings.go │ │ └── resource.go │ ├── context │ │ └── keys.go │ ├── account │ │ └── request_buffer.go │ ├── users │ │ └── user.go │ ├── resource.go │ ├── integrations │ │ └── extra_settings │ │ │ └── manager.go │ ├── auth │ │ └── test_data │ │ │ ├── sample_key.pub │ │ │ └── jwks.json │ ├── testutil │ │ └── store_ios.go │ └── integration_reference │ │ └── integration_reference.go ├── Dockerfile ├── Dockerfile.debug ├── main.go └── cmd │ └── defaults.go ├── docs └── media │ ├── logo.png │ ├── peerA.gif │ ├── peerB.gif │ └── logo-full.png ├── .github ├── FUNDING.yml ├── workflows │ ├── git-town.yml │ ├── forum.yml │ ├── sync-main.yml │ ├── update-docs.yml │ └── sync-tag.yml └── ISSUE_TEMPLATE │ └── feature_request.md ├── release_files ├── systemd │ └── env ├── darwin-ui-uninstaller.sh ├── ui-post-install.sh └── darwin_pkg │ └── preinstall ├── encryption ├── testprotos │ ├── generate.sh │ └── testproto.proto ├── encryption_suite_test.go └── cert.go ├── version ├── url.go ├── url_linux.go ├── url_freebsd.go ├── version.go ├── url_windows.go └── url_darwin.go ├── AUTHORS ├── .editorconfig ├── formatter ├── hook │ ├── keys.go │ ├── additional_empty.go │ └── additional_goroutine.go ├── levels │ └── levels.go ├── syslog │ └── formatter_test.go └── txt │ ├── formatter.go │ ├── formatter_test.go │ └── format.go ├── util ├── permission.go ├── util_js.go ├── syslog_windows.go ├── membership_unix.go ├── util_suite_test.go ├── runtime.go ├── membership_windows.go ├── syslog_nonwindows.go ├── wsproxy │ └── constants.go ├── retry.go ├── duration.go └── embeddedroots │ └── isrg-root-x2.pem ├── upload-server ├── Dockerfile ├── main.go └── types │ └── upload.go ├── LICENSES └── REUSE.toml ├── signal ├── Dockerfile └── main.go ├── sharedsock ├── stun_filter_nolinux.go ├── filter.go └── sock_nolinux.go ├── .githooks └── pre-push ├── monotime └── time_test.go ├── .devcontainer ├── devcontainer.json └── Dockerfile ├── flow └── proto │ └── generate.sh ├── route └── hauniqueid.go ├── SECURITY.md ├── base62 └── base62_test.go └── .git-branches.toml /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /versioninfo.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.go text eol=lf 2 | -------------------------------------------------------------------------------- /infrastructure_files/artifacts/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore-client: -------------------------------------------------------------------------------- 1 | * 2 | !client/netbird-entrypoint.sh 3 | !netbird 4 | -------------------------------------------------------------------------------- /relay/protocol/protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | type Protocol string 4 | -------------------------------------------------------------------------------- /shared/relay/tls/alpn.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | const NBalpn = "nb-quic" 4 | -------------------------------------------------------------------------------- /client/internal/dns/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type HandlerID string 4 | -------------------------------------------------------------------------------- /management/internals/controllers/network_map/network_map.go: -------------------------------------------------------------------------------- 1 | package network_map 2 | -------------------------------------------------------------------------------- /docs/media/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/docs/media/logo.png -------------------------------------------------------------------------------- /docs/media/peerA.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/docs/media/peerA.gif -------------------------------------------------------------------------------- /docs/media/peerB.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/docs/media/peerB.gif -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [netbirdio] 4 | -------------------------------------------------------------------------------- /client/ui/Netbird.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/Netbird.icns -------------------------------------------------------------------------------- /release_files/systemd/env: -------------------------------------------------------------------------------- 1 | # Extra flags you might want to pass to the daemon 2 | FLAGS="" 3 | 4 | -------------------------------------------------------------------------------- /docs/media/logo-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/docs/media/logo-full.png -------------------------------------------------------------------------------- /client/ui/build/banner.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/build/banner.bmp -------------------------------------------------------------------------------- /encryption/testprotos/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | protoc -I testprotos/ testprotos/testproto.proto --go_out=. -------------------------------------------------------------------------------- /client/internal/peer/id/connid.go: -------------------------------------------------------------------------------- 1 | package id 2 | 3 | import "unsafe" 4 | 5 | type ConnID unsafe.Pointer 6 | -------------------------------------------------------------------------------- /client/ui/assets/connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/connected.png -------------------------------------------------------------------------------- /client/ui/assets/netbird.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird.png -------------------------------------------------------------------------------- /shared/relay/auth/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= 2 | -------------------------------------------------------------------------------- /version/url.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | const ( 4 | downloadURL = "https://app.netbird.io/install" 5 | ) 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Mikhail Bragin (https://github.com/braginini) 2 | Maycon Santos (https://github.com/mlsmaycon) 3 | NetBird GmbH 4 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/log.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | const ( 4 | LogFile = "installer.log" 5 | ) 6 | -------------------------------------------------------------------------------- /client/ui/assets/disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/disconnected.png -------------------------------------------------------------------------------- /client/internal/ebpf/ebpf/bpf_bpfeb.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/internal/ebpf/ebpf/bpf_bpfeb.o -------------------------------------------------------------------------------- /client/internal/ebpf/ebpf/bpf_bpfel.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/internal/ebpf/ebpf/bpf_bpfel.o -------------------------------------------------------------------------------- /client/iface/bind/recv_msg.go: -------------------------------------------------------------------------------- 1 | package bind 2 | 3 | type recvMessage struct { 4 | Endpoint *Endpoint 5 | Buffer []byte 6 | } 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.go] 8 | indent_style = tab 9 | -------------------------------------------------------------------------------- /client/iface/configurer/err.go: -------------------------------------------------------------------------------- 1 | package configurer 2 | 3 | import "errors" 4 | 5 | var ErrPeerNotFound = errors.New("peer not found") 6 | -------------------------------------------------------------------------------- /client/net/dialer_init_android.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | func (d *Dialer) init() { 4 | d.Dialer.Control = ControlProtectSocket 5 | } 6 | -------------------------------------------------------------------------------- /client/net/dialer_init_windows.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | func (d *Dialer) init() { 4 | d.Dialer.Control = applyUnicastIFToSocket 5 | } 6 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-disconnected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-disconnected.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-disconnected.png -------------------------------------------------------------------------------- /client/server/panic_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package server 4 | 5 | func handlePanicLog() error { 6 | return nil 7 | } 8 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-error.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-error.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-error.png -------------------------------------------------------------------------------- /formatter/hook/keys.go: -------------------------------------------------------------------------------- 1 | package hook 2 | 3 | const ( 4 | EntryKeySource = "source" 5 | EntryKeyGoroutineID = "goroutine_id" 6 | ) 7 | -------------------------------------------------------------------------------- /formatter/levels/levels.go: -------------------------------------------------------------------------------- 1 | package levels 2 | 3 | var ValidLevelDesc = []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"} 4 | -------------------------------------------------------------------------------- /util/permission.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package util 4 | 5 | func EnforcePermission(dirPath string) error { 6 | return nil 7 | } 8 | -------------------------------------------------------------------------------- /management/server/testdata/geonames_20240305.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/management/server/testdata/geonames_20240305.db -------------------------------------------------------------------------------- /client/iface/iface_destroy_js.go: -------------------------------------------------------------------------------- 1 | package iface 2 | 3 | // Destroy is a no-op on WASM 4 | func (w *WGIface) Destroy() error { 5 | return nil 6 | } 7 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connected.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connected.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connecting.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connecting.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connecting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connecting.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-error-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-error-dark.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-error-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-error-dark.png -------------------------------------------------------------------------------- /shared/management/operations/operation.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | // Operation represents a permission operation type 4 | type Operation string 5 | -------------------------------------------------------------------------------- /upload-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/distroless/base:debug 2 | ENTRYPOINT [ "/go/bin/netbird-upload" ] 3 | COPY netbird-upload /go/bin/netbird-upload 4 | -------------------------------------------------------------------------------- /client/internal/iface.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package internal 5 | 6 | type WGIface interface { 7 | wgIfaceBase 8 | } 9 | -------------------------------------------------------------------------------- /client/internal/iface_windows.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type WGIface interface { 4 | wgIfaceBase 5 | GetInterfaceGUIDString() (string, error) 6 | } 7 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-disconnected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-disconnected.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-disconnected.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-error-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-error-macos.png -------------------------------------------------------------------------------- /shared/relay/client/dialer/net/err.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrClosedByServer = errors.New("closed by server") 7 | ) 8 | -------------------------------------------------------------------------------- /client/iface/bind/error.go: -------------------------------------------------------------------------------- 1 | package bind 2 | 3 | import "fmt" 4 | 5 | var ( 6 | ErrUDPMUXNotSupported = fmt.Errorf("UDPMUX is not supported in WASM") 7 | ) 8 | -------------------------------------------------------------------------------- /client/internal/debug/debug_nonunix.go: -------------------------------------------------------------------------------- 1 | //go:build !unix 2 | 3 | package debug 4 | 5 | func (g *BundleGenerator) addDNSInfo() error { 6 | return nil 7 | } 8 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connected-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connected-dark.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connected-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connected-dark.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connected-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connected-macos.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connecting-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connecting-dark.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connecting-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connecting-dark.png -------------------------------------------------------------------------------- /management/server/testdata/GeoLite2-City_20240305.mmdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/management/server/testdata/GeoLite2-City_20240305.mmdb -------------------------------------------------------------------------------- /version/url_linux.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | // DownloadUrl return with the proper download link 4 | func DownloadUrl() string { 5 | return downloadURL 6 | } 7 | -------------------------------------------------------------------------------- /LICENSES/REUSE.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | default_license = "BSD-3-Clause" 3 | 4 | [[files]] 5 | paths = ["management/", "signal/", "relay/"] 6 | license = "AGPL-3.0-only" 7 | -------------------------------------------------------------------------------- /client/internal/dns/server_js.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | func (s *DefaultServer) initialize() (hostManager, error) { 4 | return &noopHostConfigurator{}, nil 5 | } 6 | -------------------------------------------------------------------------------- /client/internal/templates/embed.go: -------------------------------------------------------------------------------- 1 | package templates 2 | 3 | import ( 4 | _ "embed" 5 | ) 6 | 7 | //go:embed pkce-auth-msg.html 8 | var PKCEAuthMsgTmpl string 9 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-connecting-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-connecting-macos.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-connected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-connected.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-connected.png -------------------------------------------------------------------------------- /version/url_freebsd.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | // DownloadUrl return with the proper download link 4 | func DownloadUrl() string { 5 | return downloadURL 6 | } 7 | -------------------------------------------------------------------------------- /client/iface/device/windows_guid.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | // CustomWindowsGUIDString is a custom GUID string for the interface 4 | var CustomWindowsGUIDString string 5 | -------------------------------------------------------------------------------- /client/internal/dns/server_android.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | func (s *DefaultServer) initialize() (manager hostManager, err error) { 4 | return newHostManager() 5 | } 6 | -------------------------------------------------------------------------------- /client/internal/dns/server_windows.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | func (s *DefaultServer) initialize() (hostManager, error) { 4 | return newHostManager(s.wgInterface) 5 | } 6 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-disconnected-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-disconnected-macos.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-disconnected.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-disconnected.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-disconnected.png -------------------------------------------------------------------------------- /client/ui/font_linux.go: -------------------------------------------------------------------------------- 1 | //go:build !386 2 | 3 | package main 4 | 5 | func (s *serviceClient) setDefaultFonts() { 6 | //TODO: Linux Multiple Language Support 7 | } 8 | -------------------------------------------------------------------------------- /relay/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/distroless/base:debug 2 | ENTRYPOINT [ "/go/bin/netbird-relay" ] 3 | ENV NB_LOG_FILE=console 4 | COPY netbird-relay /go/bin/netbird-relay 5 | -------------------------------------------------------------------------------- /shared/relay/constants.go: -------------------------------------------------------------------------------- 1 | package relay 2 | 3 | const ( 4 | // WebSocketURLPath is the path for the websocket relay connection 5 | WebSocketURLPath = "/relay" 6 | ) 7 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-connected-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-connected-dark.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-connected-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-connected-dark.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-connected-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-connected-macos.png -------------------------------------------------------------------------------- /client/ui/build/build-ui-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apt update 3 | sudo apt remove gir1.2-appindicator3-0.1 4 | sudo apt install -y libayatana-appindicator3-dev 5 | go build -------------------------------------------------------------------------------- /client/ui/update_notwindows.go: -------------------------------------------------------------------------------- 1 | //go:build !windows && !(linux && 386) 2 | 3 | package main 4 | 5 | func killParentUIProcess() { 6 | // No-op on non-Windows platforms 7 | } 8 | -------------------------------------------------------------------------------- /client/internal/dns/server_ios.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | func (s *DefaultServer) initialize() (manager hostManager, err error) { 4 | return newHostManager(s.iosDnsManager) 5 | } 6 | -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-disconnected-dark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-disconnected-dark.ico -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-disconnected-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-disconnected-dark.png -------------------------------------------------------------------------------- /client/ui/assets/netbird-systemtray-update-disconnected-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netbirdio/netbird/HEAD/client/ui/assets/netbird-systemtray-update-disconnected-macos.png -------------------------------------------------------------------------------- /client/iface/device/args.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | type MobileIFaceArguments struct { 4 | TunAdapter TunAdapter // only for Android 5 | TunFd int // only for iOS 6 | } 7 | -------------------------------------------------------------------------------- /client/net/dialer_init_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !windows 2 | 3 | package net 4 | 5 | func (d *Dialer) init() { 6 | // implemented on Linux, Android, and Windows only 7 | } 8 | -------------------------------------------------------------------------------- /encryption/testprotos/testproto.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "/testprotos"; 4 | 5 | package testprotos; 6 | 7 | message TestMessage { 8 | string body = 1; 9 | } -------------------------------------------------------------------------------- /shared/context/keys.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | const ( 4 | RequestIDKey = "requestID" 5 | AccountIDKey = "accountID" 6 | UserIDKey = "userID" 7 | PeerIDKey = "peerID" 8 | ) 9 | -------------------------------------------------------------------------------- /signal/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/distroless/base:debug 2 | ENTRYPOINT [ "/go/bin/netbird-signal","run" ] 3 | CMD ["--log-file", "console"] 4 | COPY netbird-signal /go/bin/netbird-signal 5 | -------------------------------------------------------------------------------- /util/util_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package util 4 | 5 | // IsAdmin returns false for WASM as there's no admin concept in browser 6 | func IsAdmin() bool { 7 | return false 8 | } 9 | -------------------------------------------------------------------------------- /client/iface/device/device_netstack_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package device 4 | 5 | func (t *TunNetstackDevice) Create() (WGConfigurer, error) { 6 | return t.create() 7 | } 8 | -------------------------------------------------------------------------------- /client/internal/dns/server_darwin.go: -------------------------------------------------------------------------------- 1 | //go:build !ios 2 | 3 | package dns 4 | 5 | func (s *DefaultServer) initialize() (manager hostManager, err error) { 6 | return newHostManager() 7 | } 8 | -------------------------------------------------------------------------------- /infrastructure_files/observability/grafana/dashboards/.gitignore: -------------------------------------------------------------------------------- 1 | # Some files eg. management.json are being ignored by root .gitignore. Need to un-ignore all json dashboards here. 2 | !*.json -------------------------------------------------------------------------------- /shared/management/http/api/cfg.yaml: -------------------------------------------------------------------------------- 1 | package: api 2 | generate: 3 | models: true 4 | embedded-spec: false 5 | output: types.gen.go 6 | compatibility: 7 | always-prefix-enum-values: true -------------------------------------------------------------------------------- /util/syslog_windows.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | func AddSyslogHook() { 4 | // The syslog package is not available for Windows. This adapter is needed 5 | // to handle windows build. 6 | } 7 | -------------------------------------------------------------------------------- /client/internal/lazyconn/activity/listen_ip.go: -------------------------------------------------------------------------------- 1 | //go:build !linux || android 2 | 3 | package activity 4 | 5 | import "net" 6 | 7 | var ( 8 | listenIP = net.IP{127, 0, 0, 1} 9 | ) 10 | -------------------------------------------------------------------------------- /client/net/listener_init_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !windows 2 | 3 | package net 4 | 5 | func (l *ListenerConfig) init() { 6 | // implemented on Linux, Android, and Windows only 7 | } 8 | -------------------------------------------------------------------------------- /client/android/gomobile.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import _ "golang.org/x/mobile/bind" 4 | 5 | // to keep our CI/CD that checks go.mod and go.sum files happy, we need to import the package above 6 | -------------------------------------------------------------------------------- /client/iface/configurer/name_darwin.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | 3 | package configurer 4 | 5 | // WgInterfaceDefault is a default interface name of Netbird 6 | const WgInterfaceDefault = "utun100" 7 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/binary_nowindows.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package installer 4 | 5 | func UpdaterBinaryNameWithoutExtension() string { 6 | return updaterBinary 7 | } 8 | -------------------------------------------------------------------------------- /client/ui/build/netbird.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Netbird 3 | Exec=/usr/bin/netbird-ui 4 | Icon=netbird 5 | Type=Application 6 | Terminal=false 7 | Categories=Utility; 8 | Keywords=netbird; 9 | -------------------------------------------------------------------------------- /client/iface/configurer/wgstats.go: -------------------------------------------------------------------------------- 1 | package configurer 2 | 3 | import "time" 4 | 5 | type WGStats struct { 6 | LastHandshake time.Time 7 | TxBytes int64 8 | RxBytes int64 9 | } 10 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/repourl_dev.go: -------------------------------------------------------------------------------- 1 | //go:build devartifactsign 2 | 3 | package installer 4 | 5 | const ( 6 | DefaultSigningKeysBaseURL = "http://192.168.0.10:9089/signrepo" 7 | ) 8 | -------------------------------------------------------------------------------- /client/iface/freebsd/errors.go: -------------------------------------------------------------------------------- 1 | package freebsd 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrDoesNotExist = errors.New("does not exist") 7 | ErrNameDoesNotMatch = errors.New("name does not match") 8 | ) 9 | -------------------------------------------------------------------------------- /client/iface/udpmux/mux_ios.go: -------------------------------------------------------------------------------- 1 | //go:build ios 2 | 3 | package udpmux 4 | 5 | func (m *SingleSocketUDPMux) notifyAddressRemoval(addr string) { 6 | // iOS doesn't support nbnet hooks, so this is a no-op 7 | } 8 | -------------------------------------------------------------------------------- /client/ssh/server/user_utils_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package server 4 | 5 | // validateUsername is not supported on JS/WASM 6 | func validateUsername(_ string) error { 7 | return errNotSupported 8 | } 9 | -------------------------------------------------------------------------------- /client/ssh/server/userswitching_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package server 4 | 5 | // enableUserSwitching is not supported on JS/WASM 6 | func enableUserSwitching() error { 7 | return errNotSupported 8 | } 9 | -------------------------------------------------------------------------------- /shared/signal/proto/go.sum: -------------------------------------------------------------------------------- 1 | google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= 2 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 3 | -------------------------------------------------------------------------------- /shared/management/proto/go.sum: -------------------------------------------------------------------------------- 1 | google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= 2 | google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= 3 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/repourl_prod.go: -------------------------------------------------------------------------------- 1 | //go:build !devartifactsign 2 | 3 | package installer 4 | 5 | const ( 6 | DefaultSigningKeysBaseURL = "https://publickeys.netbird.io/artifact-signatures" 7 | ) 8 | -------------------------------------------------------------------------------- /signal/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/signal/cmd" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | if err := cmd.Execute(); err != nil { 10 | os.Exit(1) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /client/iface/configurer/name.go: -------------------------------------------------------------------------------- 1 | //go:build linux || windows || freebsd || js || wasip1 2 | 3 | package configurer 4 | 5 | // WgInterfaceDefault is a default interface name of Netbird 6 | const WgInterfaceDefault = "wt0" 7 | -------------------------------------------------------------------------------- /client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/netbirdio/netbird/client/cmd" 7 | ) 8 | 9 | func main() { 10 | if err := cmd.Execute(); err != nil { 11 | os.Exit(1) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/iface/iface_destroy_mobile.go: -------------------------------------------------------------------------------- 1 | //go:build android || (ios && !darwin) 2 | 3 | package iface 4 | 5 | import "errors" 6 | 7 | func (w *WGIface) Destroy() error { 8 | return errors.New("not supported on mobile") 9 | } 10 | -------------------------------------------------------------------------------- /client/internal/dns/server_unix.go: -------------------------------------------------------------------------------- 1 | //go:build (linux && !android) || freebsd 2 | 3 | package dns 4 | 5 | func (s *DefaultServer) initialize() (manager hostManager, err error) { 6 | return newHostManager(s.wgInterface.Name()) 7 | } 8 | -------------------------------------------------------------------------------- /client/ios/NetBirdSDK/gomobile.go: -------------------------------------------------------------------------------- 1 | //go:build ios 2 | 3 | package NetBirdSDK 4 | 5 | import _ "golang.org/x/mobile/bind" 6 | 7 | // to keep our CI/CD that checks go.mod and go.sum files happy, we need to import the package above 8 | -------------------------------------------------------------------------------- /client/internal/routemanager/iface/iface_windows.go: -------------------------------------------------------------------------------- 1 | package iface 2 | 3 | // WGIface defines subset methods of interface required for router 4 | type WGIface interface { 5 | wgIfaceBase 6 | GetInterfaceGUIDString() (string, error) 7 | } 8 | -------------------------------------------------------------------------------- /client/net/listen_ios.go: -------------------------------------------------------------------------------- 1 | //go:build ios 2 | 3 | package net 4 | 5 | import ( 6 | "net" 7 | ) 8 | 9 | func ListenUDP(network string, laddr *net.UDPAddr) (*net.UDPConn, error) { 10 | return net.ListenUDP(network, laddr) 11 | } 12 | -------------------------------------------------------------------------------- /shared/signal/proto/constants.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | // protocol constants, field names that can be used by both client and server 4 | const HeaderId = "x-wiretrustee-peer-id" 5 | const HeaderRegistered = "x-wiretrustee-peer-registered" 6 | -------------------------------------------------------------------------------- /client/cmd/update.go: -------------------------------------------------------------------------------- 1 | //go:build !windows && !darwin 2 | 3 | package cmd 4 | 5 | import ( 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var updateCmd *cobra.Command 10 | 11 | func isUpdateBinary() bool { 12 | return false 13 | } 14 | -------------------------------------------------------------------------------- /client/internal/auth/pkce_flow_other.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package auth 4 | 5 | // getSystemExcludedPortRanges returns nil on non-Windows platforms. 6 | func getSystemExcludedPortRanges() []excludedPortRange { 7 | return nil 8 | } 9 | -------------------------------------------------------------------------------- /client/internal/lazyconn/activity/listen_ip_linux.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package activity 4 | 5 | import "net" 6 | 7 | var ( 8 | // use this ip to avoid eBPF proxy congestion 9 | listenIP = net.IP{127, 0, 1, 1} 10 | ) 11 | -------------------------------------------------------------------------------- /client/internal/updatemanager/reposign/embed_dev.go: -------------------------------------------------------------------------------- 1 | //go:build devartifactsign 2 | 3 | package reposign 4 | 5 | import "embed" 6 | 7 | //go:embed certsdev 8 | var embeddedCerts embed.FS 9 | 10 | const embeddedCertsDir = "certsdev" 11 | -------------------------------------------------------------------------------- /client/internal/updatemanager/reposign/embed_prod.go: -------------------------------------------------------------------------------- 1 | //go:build !devartifactsign 2 | 3 | package reposign 4 | 5 | import "embed" 6 | 7 | //go:embed certs 8 | var embeddedCerts embed.FS 9 | 10 | const embeddedCertsDir = "certs" 11 | -------------------------------------------------------------------------------- /client/net/listener_init_android.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | // init configures the net.ListenerConfig Control function to set the fwmark on the socket 4 | func (l *ListenerConfig) init() { 5 | l.ListenConfig.Control = ControlProtectSocket 6 | } 7 | -------------------------------------------------------------------------------- /util/membership_unix.go: -------------------------------------------------------------------------------- 1 | //go:build linux || darwin || freebsd 2 | 3 | package util 4 | 5 | import ( 6 | "os" 7 | ) 8 | 9 | // IsAdmin returns true if user is root 10 | func IsAdmin() bool { 11 | return os.Geteuid() == 0 12 | } 13 | -------------------------------------------------------------------------------- /client/internal/routemanager/iface/iface.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package iface 5 | 6 | // WGIface defines subset methods of interface required for router 7 | type WGIface interface { 8 | wgIfaceBase 9 | } 10 | -------------------------------------------------------------------------------- /client/internal/sleep/detector_notsupported.go: -------------------------------------------------------------------------------- 1 | //go:build !darwin || ios 2 | 3 | package sleep 4 | 5 | import "fmt" 6 | 7 | func NewDetector() (detector, error) { 8 | return nil, fmt.Errorf("sleep not supported on this platform") 9 | } 10 | -------------------------------------------------------------------------------- /management/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | RUN apt update && apt install -y ca-certificates && rm -fr /var/cache/apt 3 | ENTRYPOINT [ "/go/bin/netbird-mgmt","management"] 4 | CMD ["--log-file", "console"] 5 | COPY netbird-mgmt /go/bin/netbird-mgmt 6 | -------------------------------------------------------------------------------- /client/cmd/debug_js.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import "context" 4 | 5 | // SetupDebugHandler is a no-op for WASM 6 | func SetupDebugHandler(context.Context, interface{}, interface{}, interface{}, string) { 7 | // Debug handler not needed for WASM 8 | } 9 | -------------------------------------------------------------------------------- /client/iface/device/kernel_module.go: -------------------------------------------------------------------------------- 1 | //go:build (!linux && !freebsd) || android 2 | 3 | package device 4 | 5 | // WireGuardModuleIsLoaded check if we can load WireGuard mod (linux only) 6 | func WireGuardModuleIsLoaded() bool { 7 | return false 8 | } 9 | -------------------------------------------------------------------------------- /client/internal/debug/debug_mobile.go: -------------------------------------------------------------------------------- 1 | //go:build ios || android 2 | 3 | package debug 4 | 5 | func (g *BundleGenerator) addRoutes() error { 6 | return nil 7 | } 8 | 9 | func (g *BundleGenerator) addDNSInfo() error { 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /management/internals/controllers/network_map/update_message.go: -------------------------------------------------------------------------------- 1 | package network_map 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/shared/management/proto" 5 | ) 6 | 7 | type UpdateMessage struct { 8 | Update *proto.SyncResponse 9 | } 10 | -------------------------------------------------------------------------------- /client/iface/configurer/uapi_windows.go: -------------------------------------------------------------------------------- 1 | package configurer 2 | 3 | import ( 4 | "net" 5 | 6 | "golang.zx2c4.com/wireguard/ipc" 7 | ) 8 | 9 | func openUAPI(deviceName string) (net.Listener, error) { 10 | return ipc.UAPIListen(deviceName) 11 | } 12 | -------------------------------------------------------------------------------- /shared/relay/client/addr.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | type RelayAddr struct { 4 | addr string 5 | } 6 | 7 | func (a RelayAddr) Network() string { 8 | return "relay" 9 | } 10 | 11 | func (a RelayAddr) String() string { 12 | return a.addr 13 | } 14 | -------------------------------------------------------------------------------- /client/ui/desktop/desktop.go: -------------------------------------------------------------------------------- 1 | package desktop 2 | 3 | import "github.com/netbirdio/netbird/version" 4 | 5 | // GetUIUserAgent returns the Desktop ui user agent 6 | func GetUIUserAgent() string { 7 | return "netbird-desktop-ui/" + version.NetbirdVersion() 8 | } 9 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/installer_log_darwin.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "path/filepath" 5 | ) 6 | 7 | func (u *Installer) LogFiles() []string { 8 | return []string{ 9 | filepath.Join(u.tempDir, LogFile), 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /management/server/http/configs/auth.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | // AuthCfg contains parameters for authentication middleware 4 | type AuthCfg struct { 5 | Issuer string 6 | Audience string 7 | UserIDClaim string 8 | KeysLocation string 9 | } 10 | -------------------------------------------------------------------------------- /management/server/permissions/operations/operation.go: -------------------------------------------------------------------------------- 1 | package operations 2 | 3 | type Operation string 4 | 5 | const ( 6 | Create Operation = "create" 7 | Read Operation = "read" 8 | Update Operation = "update" 9 | Delete Operation = "delete" 10 | ) 11 | -------------------------------------------------------------------------------- /sharedsock/stun_filter_nolinux.go: -------------------------------------------------------------------------------- 1 | //go:build !linux 2 | 3 | package sharedsock 4 | 5 | // NewIncomingSTUNFilter is a noop method just because we do not support BPF filters on other platforms than Linux 6 | func NewIncomingSTUNFilter() BPFFilter { 7 | return nil 8 | } 9 | -------------------------------------------------------------------------------- /.githooks/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Running pre-push hook..." 4 | if ! make lint; then 5 | echo "" 6 | echo "Hint: To push without verification, run:" 7 | echo " git push --no-verify" 8 | exit 1 9 | fi 10 | 11 | echo "All checks passed!" 12 | -------------------------------------------------------------------------------- /management/Dockerfile.debug: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | RUN apt update && apt install -y ca-certificates && rm -fr /var/cache/apt 3 | ENTRYPOINT [ "/go/bin/netbird-mgmt","management","--log-level","debug"] 4 | CMD ["--log-file", "console"] 5 | COPY netbird-mgmt /go/bin/netbird-mgmt 6 | -------------------------------------------------------------------------------- /client/net/listener_listen_ios.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | // WrapPacketConn on iOS just returns the original connection since iOS handles its own networking 8 | func WrapPacketConn(conn *net.UDPConn) *net.UDPConn { 9 | return conn 10 | } 11 | -------------------------------------------------------------------------------- /formatter/hook/additional_empty.go: -------------------------------------------------------------------------------- 1 | //go:build !loggoroutine 2 | 3 | package hook 4 | 5 | import log "github.com/sirupsen/logrus" 6 | 7 | func additionalEntries(_ *log.Entry) { 8 | // This function is empty and is used to demonstrate the use of additional hooks. 9 | } 10 | -------------------------------------------------------------------------------- /management/server/types/store.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type Engine string 4 | 5 | const ( 6 | PostgresStoreEngine Engine = "postgres" 7 | FileStoreEngine Engine = "jsonfile" 8 | SqliteStoreEngine Engine = "sqlite" 9 | MysqlStoreEngine Engine = "mysql" 10 | ) 11 | -------------------------------------------------------------------------------- /shared/relay/client/dialer/ws/dialopts_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package ws 4 | 5 | import "github.com/coder/websocket" 6 | 7 | func createDialOptions() *websocket.DialOptions { 8 | // WASM version doesn't support HTTPClient 9 | return &websocket.DialOptions{} 10 | } 11 | -------------------------------------------------------------------------------- /util/util_suite_test.go: -------------------------------------------------------------------------------- 1 | package util_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestManagement(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Util Service Suite") 13 | } 14 | -------------------------------------------------------------------------------- /relay/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | 6 | "github.com/netbirdio/netbird/relay/cmd" 7 | ) 8 | 9 | func main() { 10 | if err := cmd.Execute(); err != nil { 11 | log.Fatalf("failed to execute command: %v", err) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /shared/relay/client/dialer/ws/dialopts_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !js 2 | 3 | package ws 4 | 5 | import "github.com/coder/websocket" 6 | 7 | func createDialOptions() *websocket.DialOptions { 8 | return &websocket.DialOptions{ 9 | HTTPClient: httpClientNbDialer(), 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /shared/signal/client/client_suite_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestSignal(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Signal Suite") 13 | } 14 | -------------------------------------------------------------------------------- /client/internal/routemanager/systemops/flush_nonbsd.go: -------------------------------------------------------------------------------- 1 | //go:build !((darwin && !ios) || dragonfly || freebsd || netbsd || openbsd) 2 | 3 | package systemops 4 | 5 | // FlushMarkedRoutes is a no-op on non-BSD platforms. 6 | func (r *SysOps) FlushMarkedRoutes() error { 7 | return nil 8 | } 9 | -------------------------------------------------------------------------------- /client/resources.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #pragma code_page(65001) // UTF-8 4 | 5 | #define STRINGIZE(x) #x 6 | #define EXPAND(x) STRINGIZE(x) 7 | CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml 8 | 7 ICON ui/assets/netbird.ico 9 | wintun.dll RCDATA wintun.dll 10 | -------------------------------------------------------------------------------- /shared/relay/messages/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package messages provides the message types that are used to communicate between the relay and the client. 3 | This package is used to determine the type of message that is being sent and received between the relay and the client. 4 | */ 5 | package messages 6 | -------------------------------------------------------------------------------- /client/internal/engine_stdnet_android.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "github.com/netbirdio/netbird/client/internal/stdnet" 4 | 5 | func (e *Engine) newStdNet() (*stdnet.Net, error) { 6 | return stdnet.NewNetWithDiscover(e.clientCtx, e.mobileDep.IFaceDiscover, e.config.IFaceBlackList) 7 | } 8 | -------------------------------------------------------------------------------- /client/internal/dns/unclean_shutdown_mobile.go: -------------------------------------------------------------------------------- 1 | //go:build ios || android 2 | 3 | package dns 4 | 5 | type ShutdownState struct { 6 | } 7 | 8 | func (s *ShutdownState) Name() string { 9 | return "dns_state" 10 | } 11 | 12 | func (s *ShutdownState) Cleanup() error { 13 | return nil 14 | } 15 | -------------------------------------------------------------------------------- /client/internal/engine_stdnet.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package internal 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/client/internal/stdnet" 7 | ) 8 | 9 | func (e *Engine) newStdNet() (*stdnet.Net, error) { 10 | return stdnet.NewNet(e.clientCtx, e.config.IFaceBlackList) 11 | } 12 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/binary_windows.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "path/filepath" 5 | "strings" 6 | ) 7 | 8 | func UpdaterBinaryNameWithoutExtension() string { 9 | ext := filepath.Ext(updaterBinary) 10 | return strings.TrimSuffix(updaterBinary, ext) 11 | } 12 | -------------------------------------------------------------------------------- /formatter/hook/additional_goroutine.go: -------------------------------------------------------------------------------- 1 | //go:build loggoroutine 2 | 3 | package hook 4 | 5 | import ( 6 | "github.com/petermattis/goid" 7 | log "github.com/sirupsen/logrus" 8 | ) 9 | 10 | func additionalEntries(entry *log.Entry) { 11 | entry.Data[EntryKeyGoroutineID] = goid.Get() 12 | } 13 | -------------------------------------------------------------------------------- /management/server/context/keys.go: -------------------------------------------------------------------------------- 1 | package context 2 | 3 | import "github.com/netbirdio/netbird/shared/context" 4 | 5 | const ( 6 | RequestIDKey = context.RequestIDKey 7 | AccountIDKey = context.AccountIDKey 8 | UserIDKey = context.UserIDKey 9 | PeerIDKey = context.PeerIDKey 10 | ) 11 | -------------------------------------------------------------------------------- /util/runtime.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "runtime" 4 | 5 | func GetCallerName() string { 6 | pc, _, _, ok := runtime.Caller(2) 7 | if !ok { 8 | return "unknown" 9 | } 10 | fn := runtime.FuncForPC(pc) 11 | if fn == nil { 12 | return "unknown" 13 | } 14 | return fn.Name() 15 | } 16 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/types.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | type Type struct { 4 | name string 5 | downloadable bool 6 | } 7 | 8 | func (t Type) String() string { 9 | return t.name 10 | } 11 | 12 | func (t Type) Downloadable() bool { 13 | return t.downloadable 14 | } 15 | -------------------------------------------------------------------------------- /client/system/sysinfo_linux.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | // SysInfo used to moc out the sysinfo getter 4 | type SysInfo struct { 5 | ChassisSerial string 6 | ProductSerial string 7 | BoardSerial string 8 | 9 | ProductName string 10 | BoardName string 11 | ProductVendor string 12 | } 13 | -------------------------------------------------------------------------------- /encryption/encryption_suite_test.go: -------------------------------------------------------------------------------- 1 | package encryption_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestManagement(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Management Service Suite") 13 | } 14 | -------------------------------------------------------------------------------- /shared/management/client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 2 | golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= 3 | google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= 4 | -------------------------------------------------------------------------------- /client/iface/netstack/env_js.go: -------------------------------------------------------------------------------- 1 | package netstack 2 | 3 | const EnvUseNetstackMode = "NB_USE_NETSTACK_MODE" 4 | 5 | // IsEnabled always returns true for js since it's the only mode available 6 | func IsEnabled() bool { 7 | return true 8 | } 9 | 10 | func ListenAddr() string { 11 | return "" 12 | } 13 | -------------------------------------------------------------------------------- /client/internal/listener/network_change.go: -------------------------------------------------------------------------------- 1 | package listener 2 | 3 | // NetworkChangeListener is a callback interface for mobile system 4 | type NetworkChangeListener interface { 5 | // OnNetworkChanged invoke when network settings has been changed 6 | OnNetworkChanged(string) 7 | SetInterfaceIP(string) 8 | } 9 | -------------------------------------------------------------------------------- /client/internal/peer/ice/StunTurn_test.go: -------------------------------------------------------------------------------- 1 | package ice 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestStunTurn_LoadEmpty(t *testing.T) { 8 | var stStunTurn StunTurn 9 | got := stStunTurn.Load() 10 | if len(got) != 0 { 11 | t.Errorf("StunTurn.Load() = %v, want %v", got, nil) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/installer_log_windows.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "path/filepath" 5 | ) 6 | 7 | func (u *Installer) LogFiles() []string { 8 | return []string{ 9 | filepath.Join(u.tempDir, msiLogFile), 10 | filepath.Join(u.tempDir, LogFile), 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /client/iface/device/wg_log.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "os" 5 | 6 | "golang.zx2c4.com/wireguard/device" 7 | ) 8 | 9 | func wgLogLevel() int { 10 | if os.Getenv("NB_WG_DEBUG") == "true" { 11 | return device.LogLevelVerbose 12 | } else { 13 | return device.LogLevelSilent 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /client/internal/profilemanager/error.go: -------------------------------------------------------------------------------- 1 | package profilemanager 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrProfileNotFound = errors.New("profile not found") 7 | ErrProfileAlreadyExists = errors.New("profile already exists") 8 | ErrNoActiveProfile = errors.New("no active profile set") 9 | ) 10 | -------------------------------------------------------------------------------- /client/ssh/server/sftp_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package server 4 | 5 | import ( 6 | "os/user" 7 | ) 8 | 9 | // parseUserCredentials is not supported on JS/WASM 10 | func (s *Server) parseUserCredentials(_ *user.User) (uint32, uint32, []uint32, error) { 11 | return 0, 0, nil, errNotSupported 12 | } 13 | -------------------------------------------------------------------------------- /management/server/account/request_buffer.go: -------------------------------------------------------------------------------- 1 | package account 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/netbirdio/netbird/management/server/types" 7 | ) 8 | 9 | type RequestBuffer interface { 10 | GetAccountWithBackpressure(ctx context.Context, accountID string) (*types.Account, error) 11 | } 12 | -------------------------------------------------------------------------------- /client/ios/NetBirdSDK/logger.go: -------------------------------------------------------------------------------- 1 | //go:build ios 2 | 3 | package NetBirdSDK 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/util" 7 | ) 8 | 9 | // InitializeLog initializes the log file. 10 | func InitializeLog(logLevel string, filePath string) error { 11 | return util.InitLog(logLevel, filePath) 12 | } 13 | -------------------------------------------------------------------------------- /shared/relay/client/dialer/ws/addr.go: -------------------------------------------------------------------------------- 1 | package ws 2 | 3 | const ( 4 | Network = "ws" 5 | ) 6 | 7 | type WebsocketAddr struct { 8 | addr string 9 | } 10 | 11 | func (a WebsocketAddr) Network() string { 12 | return Network 13 | } 14 | 15 | func (a WebsocketAddr) String() string { 16 | return a.addr 17 | } 18 | -------------------------------------------------------------------------------- /client/internal/netflow/conntrack/conntrack_nonlinux.go: -------------------------------------------------------------------------------- 1 | //go:build !linux || android 2 | 3 | package conntrack 4 | 5 | import nftypes "github.com/netbirdio/netbird/client/internal/netflow/types" 6 | 7 | func New(flowLogger nftypes.FlowLogger, iface nftypes.IFaceMapper) nftypes.ConnTracker { 8 | return nil 9 | } 10 | -------------------------------------------------------------------------------- /client/internal/peer/listener.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | // Listener is a callback type about the NetBird network connection state 4 | type Listener interface { 5 | OnConnected() 6 | OnDisconnected() 7 | OnConnecting() 8 | OnDisconnecting() 9 | OnAddressChanged(string, string) 10 | OnPeersListChanged(int) 11 | } 12 | -------------------------------------------------------------------------------- /relay/server/listener/listener.go: -------------------------------------------------------------------------------- 1 | package listener 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | "github.com/netbirdio/netbird/relay/protocol" 8 | ) 9 | 10 | type Listener interface { 11 | Listen(func(conn net.Conn)) error 12 | Shutdown(ctx context.Context) error 13 | Protocol() protocol.Protocol 14 | } 15 | -------------------------------------------------------------------------------- /client/internal/updatemanager/update.go: -------------------------------------------------------------------------------- 1 | package updatemanager 2 | 3 | import v "github.com/hashicorp/go-version" 4 | 5 | type UpdateInterface interface { 6 | StopWatch() 7 | SetDaemonVersion(newVersion string) bool 8 | SetOnUpdateListener(updateFn func()) 9 | LatestVersion() *v.Version 10 | StartFetcher() 11 | } 12 | -------------------------------------------------------------------------------- /util/membership_windows.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "golang.zx2c4.com/wireguard/windows/elevate" 4 | 5 | // IsAdmin returns true if user has admin privileges 6 | func IsAdmin() bool { 7 | adminDesktop, err := elevate.IsAdminDesktop() 8 | if err == nil && adminDesktop { 9 | return true 10 | } 11 | return false 12 | } 13 | -------------------------------------------------------------------------------- /client/cmd/status_test.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestParsingOfIP(t *testing.T) { 10 | InterfaceIP := "192.168.178.123/16" 11 | 12 | parsedIP := parseInterfaceIP(InterfaceIP) 13 | 14 | assert.Equal(t, "192.168.178.123\n", parsedIP) 15 | } 16 | -------------------------------------------------------------------------------- /client/iface/device/adapter.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | // TunAdapter is an interface for create tun device from external service 4 | type TunAdapter interface { 5 | ConfigureInterface(address string, mtu int, dns string, searchDomains string, routes string) (int, error) 6 | UpdateAddr(address string) error 7 | ProtectSocket(fd int32) bool 8 | } 9 | -------------------------------------------------------------------------------- /client/iface/mocks/README.md: -------------------------------------------------------------------------------- 1 | ## Mocks 2 | 3 | To generate (or refresh) mocks from iface package interfaces please install [mockgen](https://github.com/golang/mock). 4 | Run this command to update PacketFilter mock: 5 | ```bash 6 | mockgen -destination iface/mocks/filter.go -package mocks github.com/netbirdio/netbird/iface PacketFilter 7 | ``` 8 | -------------------------------------------------------------------------------- /client/internal/ebpf/manager/manager.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | // Manager is used to load multiple eBPF programs. E.g., current DNS programs and WireGuard proxy 4 | type Manager interface { 5 | LoadDNSFwd(ip string, dnsPort int) error 6 | FreeDNSFwd() error 7 | LoadWgProxy(proxyPort, wgPort int) error 8 | FreeWGProxy() error 9 | } 10 | -------------------------------------------------------------------------------- /client/net/dialer_init_linux.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package net 4 | 5 | import "syscall" 6 | 7 | // init configures the net.Dialer Control function to set the fwmark on the socket 8 | func (d *Dialer) init() { 9 | d.Dialer.Control = func(_, _ string, c syscall.RawConn) error { 10 | return setRawSocketMark(c) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /shared/relay/auth/allow/allow_all.go: -------------------------------------------------------------------------------- 1 | package allow 2 | 3 | // Auth is a Validator that allows all connections. 4 | // Used this for testing purposes only. 5 | type Auth struct { 6 | } 7 | 8 | func (a *Auth) Validate(any) error { 9 | return nil 10 | } 11 | 12 | func (a *Auth) ValidateHelloMsgType(any) error { 13 | return nil 14 | } 15 | -------------------------------------------------------------------------------- /client/internal/routemanager/dynamic/route_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !ios 2 | 3 | package dynamic 4 | 5 | import ( 6 | "net" 7 | 8 | "github.com/netbirdio/netbird/shared/management/domain" 9 | ) 10 | 11 | func (r *Route) getIPsFromResolver(domain domain.Domain) ([]net.IP, error) { 12 | return net.LookupIP(domain.PunycodeString()) 13 | } 14 | -------------------------------------------------------------------------------- /client/internal/acl/mocks/README.md: -------------------------------------------------------------------------------- 1 | ## Mocks 2 | 3 | To generate (or refresh) mocks from acl package please install [mockgen](https://github.com/golang/mock). 4 | Run this command from the `./client/internal/acl` folder to update iface mapper interface mock: 5 | ```bash 6 | mockgen -destination mocks/iface_mapper.go -package mocks . IFaceMapper 7 | ``` 8 | -------------------------------------------------------------------------------- /client/internal/ebpf/instantiater_nonlinux.go: -------------------------------------------------------------------------------- 1 | //go:build !linux || android 2 | 3 | package ebpf 4 | 5 | import "github.com/netbirdio/netbird/client/internal/ebpf/manager" 6 | 7 | // GetEbpfManagerInstance return error because ebpf is not supported on all os 8 | func GetEbpfManagerInstance() manager.Manager { 9 | panic("unsupported os") 10 | } 11 | -------------------------------------------------------------------------------- /client/internal/peer/env.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | import ( 4 | "os" 5 | "runtime" 6 | "strings" 7 | ) 8 | 9 | const ( 10 | EnvKeyNBForceRelay = "NB_FORCE_RELAY" 11 | ) 12 | 13 | func isForceRelayed() bool { 14 | if runtime.GOOS == "js" { 15 | return true 16 | } 17 | return strings.EqualFold(os.Getenv(EnvKeyNBForceRelay), "true") 18 | } 19 | -------------------------------------------------------------------------------- /client/android/platform_files.go: -------------------------------------------------------------------------------- 1 | //go:build android 2 | 3 | package android 4 | 5 | // PlatformFiles groups paths to files used internally by the engine that can't be created/modified 6 | // at their default locations due to android OS restrictions. 7 | type PlatformFiles interface { 8 | ConfigurationFilePath() string 9 | StateFilePath() string 10 | } 11 | -------------------------------------------------------------------------------- /client/iface/iface_guid_windows.go: -------------------------------------------------------------------------------- 1 | package iface 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/client/iface/device" 5 | ) 6 | 7 | // GetInterfaceGUIDString returns an interface GUID. This is useful on Windows only 8 | func (w *WGIface) GetInterfaceGUIDString() (string, error) { 9 | return w.tun.(*device.TunDevice).GetInterfaceGUIDString() 10 | } 11 | -------------------------------------------------------------------------------- /client/internal/lazyconn/peercfg.go: -------------------------------------------------------------------------------- 1 | package lazyconn 2 | 3 | import ( 4 | "net/netip" 5 | 6 | log "github.com/sirupsen/logrus" 7 | 8 | "github.com/netbirdio/netbird/client/internal/peer/id" 9 | ) 10 | 11 | type PeerConfig struct { 12 | PublicKey string 13 | AllowedIPs []netip.Prefix 14 | PeerConnID id.ConnID 15 | Log *log.Entry 16 | } 17 | -------------------------------------------------------------------------------- /client/net/dial_ios.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | func DialUDP(network string, laddr, raddr *net.UDPAddr) (*net.UDPConn, error) { 8 | return net.DialUDP(network, laddr, raddr) 9 | } 10 | 11 | func DialTCP(network string, laddr, raddr *net.TCPAddr) (*net.TCPConn, error) { 12 | return net.DialTCP(network, laddr, raddr) 13 | } 14 | -------------------------------------------------------------------------------- /client/internal/networkmonitor/check_change_js.go: -------------------------------------------------------------------------------- 1 | package networkmonitor 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/netbirdio/netbird/client/internal/routemanager/systemops" 7 | ) 8 | 9 | func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) error { 10 | // No-op for WASM - network changes don't apply 11 | return nil 12 | } 13 | -------------------------------------------------------------------------------- /client/internal/peer/ice/stdnet.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package ice 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/netbirdio/netbird/client/internal/stdnet" 9 | ) 10 | 11 | func newStdNet(ctx context.Context, _ stdnet.ExternalIFaceDiscover, ifaceBlacklist []string) (*stdnet.Net, error) { 12 | return stdnet.NewNet(ctx, ifaceBlacklist) 13 | } 14 | -------------------------------------------------------------------------------- /client/iface/bind/endpoint.go: -------------------------------------------------------------------------------- 1 | package bind 2 | 3 | import ( 4 | "net" 5 | 6 | wgConn "golang.zx2c4.com/wireguard/conn" 7 | ) 8 | 9 | type Endpoint = wgConn.StdNetEndpoint 10 | 11 | func EndpointToUDPAddr(e Endpoint) *net.UDPAddr { 12 | return &net.UDPAddr{ 13 | IP: e.Addr().AsSlice(), 14 | Port: int(e.Port()), 15 | Zone: e.Addr().Zone(), 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /monotime/time_test.go: -------------------------------------------------------------------------------- 1 | package monotime 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func BenchmarkMonotimeNow(b *testing.B) { 9 | b.ReportAllocs() 10 | for i := 0; i < b.N; i++ { 11 | _ = Now() 12 | } 13 | } 14 | 15 | func BenchmarkTimeNow(b *testing.B) { 16 | b.ReportAllocs() 17 | for i := 0; i < b.N; i++ { 18 | _ = time.Now() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sharedsock/filter.go: -------------------------------------------------------------------------------- 1 | package sharedsock 2 | 3 | import "golang.org/x/net/bpf" 4 | 5 | // BPFFilter is a generic filter that provides ipv4 and ipv6 BPF instructions 6 | type BPFFilter interface { 7 | // GetInstructions returns raw BPF instructions for ipv4 and ipv6 8 | GetInstructions(port uint32) (ipv4 []bpf.RawInstruction, ipv6 []bpf.RawInstruction, err error) 9 | } 10 | -------------------------------------------------------------------------------- /client/internal/dns/service.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "net/netip" 5 | 6 | "github.com/miekg/dns" 7 | ) 8 | 9 | const ( 10 | DefaultPort = 53 11 | ) 12 | 13 | type service interface { 14 | Listen() error 15 | Stop() 16 | RegisterMux(domain string, handler dns.Handler) 17 | DeregisterMux(key string) 18 | RuntimePort() int 19 | RuntimeIP() netip.Addr 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/peer/ice/stdnet_android.go: -------------------------------------------------------------------------------- 1 | package ice 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/netbirdio/netbird/client/internal/stdnet" 7 | ) 8 | 9 | func newStdNet(ctx context.Context, iFaceDiscover stdnet.ExternalIFaceDiscover, ifaceBlacklist []string) (*stdnet.Net, error) { 10 | return stdnet.NewNetWithDiscover(ctx, iFaceDiscover, ifaceBlacklist) 11 | } 12 | -------------------------------------------------------------------------------- /client/internal/updatemanager/reposign/certs/root-pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ROOT PUBLIC KEY----- 2 | eyJLZXkiOiJoaGIxdGRDSEZNMFBuQWp1b2w2cXJ1QXRFbWFFSlg1QjFsZUNxWmpn 3 | V1pvPSIsIk1ldGFkYXRhIjp7ImlkIjoiOWE0OTg2NmI2MzE2MjNiNCIsImNyZWF0 4 | ZWRfYXQiOiIyMDI1LTExLTI0VDE3OjE1OjI4LjYyNzE3MzE3MVoiLCJleHBpcmVz 5 | X2F0IjoiMjAzNS0xMS0yMlQxNzoxNToyOC42MjcxNzMxNzFaIn19 6 | -----END ROOT PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /client/net/listener_init_linux.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package net 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | // init configures the net.ListenerConfig Control function to set the fwmark on the socket 10 | func (l *ListenerConfig) init() { 11 | l.ListenConfig.Control = func(_, _ string, c syscall.RawConn) error { 12 | return setRawSocketMark(c) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /client/firewall/iptables/rule.go: -------------------------------------------------------------------------------- 1 | package iptables 2 | 3 | // Rule to handle management of rules 4 | type Rule struct { 5 | ruleID string 6 | ipsetName string 7 | 8 | specs []string 9 | mangleSpecs []string 10 | ip string 11 | chain string 12 | } 13 | 14 | // GetRuleID returns the rule id 15 | func (r *Rule) ID() string { 16 | return r.ruleID 17 | } 18 | -------------------------------------------------------------------------------- /client/internal/updatemanager/reposign/certsdev/root-pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ROOT PUBLIC KEY----- 2 | eyJLZXkiOiJyTDByVTN2MEFOZUNmbDZraitiUUd3TE1waU5CaUJLdVBWSnZtQzgr 3 | ZS84PSIsIk1ldGFkYXRhIjp7ImlkIjoiMTBkNjQyZTY2N2FmMDNkNCIsImNyZWF0 4 | ZWRfYXQiOiIyMDI1LTExLTIwVDE3OjI5OjI5LjE4MDk0NjMxNloiLCJleHBpcmVz 5 | X2F0IjoiMjAyNi0xMS0yMFQxNzoyOToyOS4xODA5NDYzMTZaIn19 6 | -----END ROOT PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /management/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | // nolint:gosec 7 | _ "net/http/pprof" 8 | "os" 9 | 10 | "github.com/netbirdio/netbird/management/cmd" 11 | ) 12 | 13 | func main() { 14 | go func() { 15 | log.Println(http.ListenAndServe("localhost:6060", nil)) 16 | }() 17 | if err := cmd.Execute(); err != nil { 18 | os.Exit(1) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /management/server/users/user.go: -------------------------------------------------------------------------------- 1 | package users 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/permissions/roles" 5 | "github.com/netbirdio/netbird/management/server/types" 6 | ) 7 | 8 | // Wrapped UserInfo with Role Permissions 9 | type UserInfoWithPermissions struct { 10 | *types.UserInfo 11 | 12 | Permissions roles.Permissions 13 | Restricted bool 14 | } 15 | -------------------------------------------------------------------------------- /shared/relay/client/dialers_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package client 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/shared/relay/client/dialer" 7 | "github.com/netbirdio/netbird/shared/relay/client/dialer/ws" 8 | ) 9 | 10 | func (c *Client) getDialers() []dialer.DialeFn { 11 | // JS/WASM build only uses WebSocket transport 12 | return []dialer.DialeFn{ws.Dialer{}} 13 | } 14 | -------------------------------------------------------------------------------- /client/system/detect_platform/kube.go: -------------------------------------------------------------------------------- 1 | package detect_platform 2 | 3 | import ( 4 | "context" 5 | "os" 6 | ) 7 | 8 | func detectContainer(ctx context.Context) string { 9 | if _, exists := os.LookupEnv("KUBERNETES_SERVICE_HOST"); exists { 10 | return "Kubernetes" 11 | } 12 | 13 | if _, err := os.Stat("/.dockerenv"); err == nil { 14 | return "Docker" 15 | } 16 | return "" 17 | } 18 | -------------------------------------------------------------------------------- /client/iface/device/endpoint_manager.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "net" 5 | "net/netip" 6 | ) 7 | 8 | // EndpointManager manages fake IP to connection mappings for userspace bind implementations. 9 | // Implemented by bind.ICEBind and bind.RelayBindJS. 10 | type EndpointManager interface { 11 | SetEndpoint(fakeIP netip.Addr, conn net.Conn) 12 | RemoveEndpoint(fakeIP netip.Addr) 13 | } 14 | -------------------------------------------------------------------------------- /client/internal/dns/unclean_shutdown_js.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type ShutdownState struct{} 8 | 9 | func (s *ShutdownState) Name() string { 10 | return "dns_state" 11 | } 12 | 13 | func (s *ShutdownState) Cleanup() error { 14 | return nil 15 | } 16 | 17 | func (s *ShutdownState) RestoreUncleanShutdownConfigs(context.Context) error { 18 | return nil 19 | } 20 | -------------------------------------------------------------------------------- /sharedsock/sock_nolinux.go: -------------------------------------------------------------------------------- 1 | //go:build !linux || android 2 | 3 | package sharedsock 4 | 5 | import ( 6 | "fmt" 7 | "net" 8 | "runtime" 9 | ) 10 | 11 | // Listen is not supported on other platforms then Linux 12 | func Listen(port int, filter BPFFilter, mtu uint16) (net.PacketConn, error) { 13 | return nil, fmt.Errorf("not supported OS %s. SharedSocket is only supported on Linux", runtime.GOOS) 14 | } 15 | -------------------------------------------------------------------------------- /release_files/darwin-ui-uninstaller.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PATH=$PATH:/usr/local/bin 4 | 5 | # check if netbird is installed 6 | NB_BIN=$(which netbird) 7 | if [ -z "$NB_BIN" ] 8 | then 9 | exit 0 10 | fi 11 | # start netbird daemon service 12 | echo "netbird daemon service still running. You can uninstall it by running: " 13 | echo "sudo netbird service stop" 14 | echo "sudo netbird service uninstall" 15 | -------------------------------------------------------------------------------- /client/internal/peer/nilcheck.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | import ( 4 | "net" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func remoteConnNil(log *log.Entry, conn net.Conn) bool { 10 | if conn == nil { 11 | log.Errorf("ice conn is nil") 12 | return true 13 | } 14 | 15 | if conn.RemoteAddr() == nil { 16 | log.Errorf("ICE remote address is nil") 17 | return true 18 | } 19 | 20 | return false 21 | } 22 | -------------------------------------------------------------------------------- /management/internals/controllers/network_map/controller/metrics.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/telemetry" 5 | ) 6 | 7 | type metrics struct { 8 | *telemetry.UpdateChannelMetrics 9 | } 10 | 11 | func newMetrics(updateChannelMetrics *telemetry.UpdateChannelMetrics) (*metrics, error) { 12 | return &metrics{ 13 | updateChannelMetrics, 14 | }, nil 15 | } 16 | -------------------------------------------------------------------------------- /management/server/resource.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | type ResourceType string 4 | 5 | const ( 6 | // nolint 7 | hostType ResourceType = "Host" 8 | //nolint 9 | subnetType ResourceType = "Subnet" 10 | // nolint 11 | domainType ResourceType = "Domain" 12 | ) 13 | 14 | func (p ResourceType) String() string { 15 | return string(p) 16 | } 17 | 18 | type Resource struct { 19 | Type ResourceType 20 | ID string 21 | } 22 | -------------------------------------------------------------------------------- /shared/relay/auth/hmac/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | This package uses a similar HMAC method for authentication with the TURN server. The Management server provides the 3 | tokens for the peers. The peers manage these tokens in the token store. The token store is a simple thread safe store 4 | that keeps the tokens in memory. These tokens are used to authenticate the peers with the Relay server in the hello 5 | message. 6 | */ 7 | 8 | package hmac 9 | -------------------------------------------------------------------------------- /client/android/peer_routes.go: -------------------------------------------------------------------------------- 1 | //go:build android 2 | 3 | package android 4 | 5 | import "fmt" 6 | 7 | type PeerRoutes struct { 8 | routes []string 9 | } 10 | 11 | func (p *PeerRoutes) Get(i int) (string, error) { 12 | if i < 0 || i >= len(p.routes) { 13 | return "", fmt.Errorf("%d is out of range", i) 14 | } 15 | return p.routes[i], nil 16 | } 17 | 18 | func (p *PeerRoutes) Size() int { 19 | return len(p.routes) 20 | } 21 | -------------------------------------------------------------------------------- /shared/relay/tls/server_prod.go: -------------------------------------------------------------------------------- 1 | //go:build !devcert 2 | 3 | package tls 4 | 5 | import ( 6 | "crypto/tls" 7 | "fmt" 8 | ) 9 | 10 | func ServerQUICTLSConfig(originTLSCfg *tls.Config) (*tls.Config, error) { 11 | if originTLSCfg == nil { 12 | return nil, fmt.Errorf("valid TLS config is required for QUIC listener") 13 | } 14 | cfg := originTLSCfg.Clone() 15 | cfg.NextProtos = []string{NBalpn} 16 | return cfg, nil 17 | } 18 | -------------------------------------------------------------------------------- /client/cmd/version.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/netbirdio/netbird/version" 7 | ) 8 | 9 | var ( 10 | versionCmd = &cobra.Command{ 11 | Use: "version", 12 | Short: "Print the NetBird's client application version", 13 | Run: func(cmd *cobra.Command, args []string) { 14 | cmd.SetOut(cmd.OutOrStdout()) 15 | cmd.Println(version.NetbirdVersion()) 16 | }, 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /client/ui/font_darwin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | const defaultFontPath = "/Library/Fonts/Arial Unicode.ttf" 10 | 11 | func (s *serviceClient) setDefaultFonts() { 12 | if _, err := os.Stat(defaultFontPath); err != nil { 13 | log.Errorf("Failed to find default font file: %v", err) 14 | return 15 | } 16 | 17 | os.Setenv("FYNE_FONT", defaultFontPath) 18 | } 19 | -------------------------------------------------------------------------------- /management/server/integrations/extra_settings/manager.go: -------------------------------------------------------------------------------- 1 | package extra_settings 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/netbirdio/netbird/management/server/types" 7 | ) 8 | 9 | type Manager interface { 10 | GetExtraSettings(ctx context.Context, accountID string) (*types.ExtraSettings, error) 11 | UpdateExtraSettings(ctx context.Context, accountID, userID string, extraSettings *types.ExtraSettings) (bool, error) 12 | } 13 | -------------------------------------------------------------------------------- /client/iface/iface_destroy_bsd.go: -------------------------------------------------------------------------------- 1 | //go:build darwin || dragonfly || freebsd || netbsd || openbsd 2 | 3 | package iface 4 | 5 | import ( 6 | "fmt" 7 | "os/exec" 8 | ) 9 | 10 | func (w *WGIface) Destroy() error { 11 | out, err := exec.Command("ifconfig", w.Name(), "destroy").CombinedOutput() 12 | if err != nil { 13 | return fmt.Errorf("failed to remove interface %s: %w - %s", w.Name(), err, out) 14 | } 15 | 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /client/internal/debug/debug_nondarwin.go: -------------------------------------------------------------------------------- 1 | //go:build unix && !darwin && !android 2 | 3 | package debug 4 | 5 | import ( 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | // addDNSInfo collects and adds DNS configuration information to the archive 10 | func (g *BundleGenerator) addDNSInfo() error { 11 | if err := g.addResolvConf(); err != nil { 12 | log.Errorf("failed to add resolv.conf: %v", err) 13 | } 14 | 15 | return nil 16 | } 17 | -------------------------------------------------------------------------------- /client/internal/peer/ice/StunTurn.go: -------------------------------------------------------------------------------- 1 | package ice 2 | 3 | import ( 4 | "sync/atomic" 5 | 6 | "github.com/pion/stun/v3" 7 | ) 8 | 9 | type StunTurn atomic.Value 10 | 11 | func (s *StunTurn) Load() []*stun.URI { 12 | v := (*atomic.Value)(s).Load() 13 | if v == nil { 14 | return nil 15 | } 16 | 17 | return v.([]*stun.URI) 18 | } 19 | 20 | func (s *StunTurn) Store(value []*stun.URI) { 21 | (*atomic.Value)(s).Store(value) 22 | } 23 | -------------------------------------------------------------------------------- /release_files/ui-post-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Check if netbird-ui is running 4 | if pgrep -x -f /usr/bin/netbird-ui >/dev/null 2>&1; 5 | then 6 | runner=$(ps --no-headers -o '%U' -p $(pgrep -x -f /usr/bin/netbird-ui) | sed 's/^[ \t]*//;s/[ \t]*$//') 7 | # Only re-run if it was already running 8 | pkill -x -f /usr/bin/netbird-ui >/dev/null 2>&1 9 | su -l - "$runner" -c 'nohup /usr/bin/netbird-ui > /dev/null 2>&1 &' 10 | fi 11 | -------------------------------------------------------------------------------- /client/internal/routemanager/vars/vars.go: -------------------------------------------------------------------------------- 1 | package vars 2 | 3 | import ( 4 | "errors" 5 | "net/netip" 6 | ) 7 | 8 | const MinRangeBits = 7 9 | 10 | var ( 11 | ErrRouteNotFound = errors.New("route not found") 12 | ErrRouteNotAllowed = errors.New("route not allowed") 13 | 14 | Defaultv4 = netip.PrefixFrom(netip.IPv4Unspecified(), 0) 15 | Defaultv6 = netip.PrefixFrom(netip.IPv6Unspecified(), 0) 16 | 17 | ExitNodeCIDR = "0.0.0.0/0" 18 | ) 19 | -------------------------------------------------------------------------------- /client/net/listener_init_windows.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | func (l *ListenerConfig) init() { 4 | // TODO: this will select a single source interface, but for UDP we can have various source interfaces and IP addresses. 5 | // For now we stick to the one that matches the request IP address, which can be the unspecified IP. In this case 6 | // the interface will be selected that serves the default route. 7 | l.ListenConfig.Control = applyUnicastIFToSocket 8 | } 9 | -------------------------------------------------------------------------------- /client/firewall/nftables/rule_linux.go: -------------------------------------------------------------------------------- 1 | package nftables 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/google/nftables" 7 | ) 8 | 9 | // Rule to handle management of rules 10 | type Rule struct { 11 | nftRule *nftables.Rule 12 | mangleRule *nftables.Rule 13 | nftSet *nftables.Set 14 | ruleID string 15 | ip net.IP 16 | } 17 | 18 | // GetRuleID returns the rule id 19 | func (r *Rule) ID() string { 20 | return r.ruleID 21 | } 22 | -------------------------------------------------------------------------------- /client/iface/bufsize/bufsize.go: -------------------------------------------------------------------------------- 1 | package bufsize 2 | 3 | const ( 4 | // WGBufferOverhead represents the additional buffer space needed beyond MTU 5 | // for WireGuard packet encapsulation (WG header + UDP + IP + safety margin) 6 | // Original hardcoded buffers were 1500, default MTU is 1280, so overhead = 220 7 | // TODO: Calculate this properly based on actual protocol overhead instead of using hardcoded difference 8 | WGBufferOverhead = 220 9 | ) 10 | -------------------------------------------------------------------------------- /.github/workflows/git-town.yml: -------------------------------------------------------------------------------- 1 | name: Git Town 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - '**' 7 | 8 | jobs: 9 | git-town: 10 | name: Display the branch stack 11 | runs-on: ubuntu-latest 12 | 13 | permissions: 14 | contents: read 15 | pull-requests: write 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - uses: git-town/action@v1.2.1 20 | with: 21 | skip-single-stacks: true 22 | -------------------------------------------------------------------------------- /client/internal/stdnet/discover.go: -------------------------------------------------------------------------------- 1 | package stdnet 2 | 3 | import "github.com/pion/transport/v3" 4 | 5 | // ExternalIFaceDiscover provide an option for external services (mobile) 6 | // to collect network interface information 7 | type ExternalIFaceDiscover interface { 8 | // IFaces return with the description of the interfaces 9 | IFaces() (string, error) 10 | } 11 | 12 | type iFaceDiscover interface { 13 | iFaces() ([]*transport.Interface, error) 14 | } 15 | -------------------------------------------------------------------------------- /util/syslog_nonwindows.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package util 5 | 6 | import ( 7 | "log/syslog" 8 | 9 | log "github.com/sirupsen/logrus" 10 | lSyslog "github.com/sirupsen/logrus/hooks/syslog" 11 | ) 12 | 13 | func AddSyslogHook() { 14 | hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "") 15 | 16 | if err != nil { 17 | log.Errorf("Failed creating syslog hook: %s", err) 18 | } 19 | log.AddHook(hook) 20 | } 21 | -------------------------------------------------------------------------------- /shared/management/http/api/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! which realpath > /dev/null 2>&1 5 | then 6 | echo realpath is not installed 7 | echo run: brew install coreutils 8 | exit 1 9 | fi 10 | 11 | old_pwd=$(pwd) 12 | script_path=$(dirname $(realpath "$0")) 13 | cd "$script_path" 14 | go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@4a1477f6a8ba6ca8115cc23bb2fb67f0b9fca18e 15 | oapi-codegen --config cfg.yaml openapi.yml 16 | cd "$old_pwd" -------------------------------------------------------------------------------- /client/iface/device/device_netstack_android.go: -------------------------------------------------------------------------------- 1 | //go:build android 2 | 3 | package device 4 | 5 | import "fmt" 6 | 7 | func (t *TunNetstackDevice) Create(routes []string, dns string, searchDomains []string) (WGConfigurer, error) { 8 | return t.create() 9 | } 10 | 11 | func (t *TunNetstackDevice) RenewTun(fd int) error { 12 | // Doesn't make sense in Android for Netstack. 13 | return fmt.Errorf("this function has not been implemented in Netstack for Android") 14 | } 15 | -------------------------------------------------------------------------------- /client/iface/configurer/uapi_js.go: -------------------------------------------------------------------------------- 1 | package configurer 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | type noopListener struct{} 8 | 9 | func (n *noopListener) Accept() (net.Conn, error) { 10 | return nil, net.ErrClosed 11 | } 12 | 13 | func (n *noopListener) Close() error { 14 | return nil 15 | } 16 | 17 | func (n *noopListener) Addr() net.Addr { 18 | return nil 19 | } 20 | 21 | func openUAPI(deviceName string) (net.Listener, error) { 22 | return &noopListener{}, nil 23 | } 24 | -------------------------------------------------------------------------------- /client/iface/configurer/wgshow.go: -------------------------------------------------------------------------------- 1 | package configurer 2 | 3 | import ( 4 | "net" 5 | "time" 6 | ) 7 | 8 | type Peer struct { 9 | PublicKey string 10 | Endpoint net.UDPAddr 11 | AllowedIPs []net.IPNet 12 | TxBytes int64 13 | RxBytes int64 14 | LastHandshake time.Time 15 | PresharedKey bool 16 | } 17 | 18 | type Stats struct { 19 | DeviceName string 20 | PublicKey string 21 | ListenPort int 22 | FWMark int 23 | Peers []Peer 24 | } 25 | -------------------------------------------------------------------------------- /management/server/permissions/roles/owner.go: -------------------------------------------------------------------------------- 1 | package roles 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/permissions/operations" 5 | "github.com/netbirdio/netbird/management/server/types" 6 | ) 7 | 8 | var Owner = RolePermissions{ 9 | Role: types.UserRoleOwner, 10 | AutoAllowNew: map[operations.Operation]bool{ 11 | operations.Read: true, 12 | operations.Create: true, 13 | operations.Update: true, 14 | operations.Delete: true, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /client/internal/lazyconn/inactivity/ticker.go: -------------------------------------------------------------------------------- 1 | package inactivity 2 | 3 | import "time" 4 | 5 | var newTicker = func(d time.Duration) Ticker { 6 | return &realTicker{t: time.NewTicker(d)} 7 | } 8 | 9 | type Ticker interface { 10 | C() <-chan time.Time 11 | Stop() 12 | } 13 | 14 | type realTicker struct { 15 | t *time.Ticker 16 | } 17 | 18 | func (r *realTicker) C() <-chan time.Time { 19 | return r.t.C 20 | } 21 | 22 | func (r *realTicker) Stop() { 23 | r.t.Stop() 24 | } 25 | -------------------------------------------------------------------------------- /management/server/permissions/roles/user.go: -------------------------------------------------------------------------------- 1 | package roles 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/permissions/operations" 5 | "github.com/netbirdio/netbird/management/server/types" 6 | ) 7 | 8 | var User = RolePermissions{ 9 | Role: types.UserRoleUser, 10 | AutoAllowNew: map[operations.Operation]bool{ 11 | operations.Read: false, 12 | operations.Create: false, 13 | operations.Update: false, 14 | operations.Delete: false, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /client/internal/dns/systemd_freebsd.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | var errNotImplemented = errors.New("not implemented") 9 | 10 | func newSystemdDbusConfigurator(string) (restoreHostManager, error) { 11 | return nil, fmt.Errorf("systemd dns management: %w on freebsd", errNotImplemented) 12 | } 13 | 14 | func isSystemdResolvedRunning() bool { 15 | return false 16 | } 17 | 18 | func isSystemdResolveConfMode() bool { 19 | return false 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/routemanager/refcounter/types.go: -------------------------------------------------------------------------------- 1 | package refcounter 2 | 3 | import "net/netip" 4 | 5 | // RouteRefCounter is a Counter for Route, it doesn't take any input on Increment and doesn't use any output on Decrement 6 | type RouteRefCounter = Counter[netip.Prefix, struct{}, struct{}] 7 | 8 | // AllowedIPsRefCounter is a Counter for AllowedIPs, it takes a peer key on Increment and passes it back to Decrement 9 | type AllowedIPsRefCounter = Counter[netip.Prefix, string, string] 10 | -------------------------------------------------------------------------------- /management/internals/modules/peers/ephemeral/interface.go: -------------------------------------------------------------------------------- 1 | package ephemeral 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | nbpeer "github.com/netbirdio/netbird/management/server/peer" 8 | ) 9 | 10 | const ( 11 | EphemeralLifeTime = 10 * time.Minute 12 | ) 13 | 14 | type Manager interface { 15 | LoadInitialPeers(ctx context.Context) 16 | Stop() 17 | OnPeerConnected(ctx context.Context, peer *nbpeer.Peer) 18 | OnPeerDisconnected(ctx context.Context, peer *nbpeer.Peer) 19 | } 20 | -------------------------------------------------------------------------------- /management/server/permissions/roles/auditor.go: -------------------------------------------------------------------------------- 1 | package roles 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/permissions/operations" 5 | "github.com/netbirdio/netbird/management/server/types" 6 | ) 7 | 8 | var Auditor = RolePermissions{ 9 | Role: types.UserRoleAuditor, 10 | AutoAllowNew: map[operations.Operation]bool{ 11 | operations.Read: true, 12 | operations.Create: false, 13 | operations.Update: false, 14 | operations.Delete: false, 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NetBird", 3 | "build": { 4 | "context": "..", 5 | "dockerfile": "Dockerfile" 6 | }, 7 | "features": { 8 | "ghcr.io/devcontainers/features/docker-in-docker:2": {}, 9 | "ghcr.io/devcontainers/features/go:1": { 10 | "version": "1.23" 11 | } 12 | }, 13 | "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", 14 | "capAdd": [ 15 | "NET_ADMIN", 16 | "SYS_ADMIN", 17 | "SYS_RESOURCE" 18 | ], 19 | "privileged": true 20 | } -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/procattr_windows.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "os/exec" 5 | "syscall" 6 | ) 7 | 8 | // setUpdaterProcAttr configures the updater process to run detached from the parent, 9 | // making it independent of the parent daemon process. 10 | func setUpdaterProcAttr(cmd *exec.Cmd) { 11 | cmd.SysProcAttr = &syscall.SysProcAttr{ 12 | CreationFlags: syscall.CREATE_NEW_PROCESS_GROUP | 0x00000008, // 0x00000008 is DETACHED_PROCESS 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /client/internal/peer/guard/env.go: -------------------------------------------------------------------------------- 1 | package guard 2 | 3 | import ( 4 | "os" 5 | "strconv" 6 | "time" 7 | ) 8 | 9 | const ( 10 | envICEMonitorPeriod = "NB_ICE_MONITOR_PERIOD" 11 | ) 12 | 13 | func GetICEMonitorPeriod() time.Duration { 14 | if envVal := os.Getenv(envICEMonitorPeriod); envVal != "" { 15 | if seconds, err := strconv.Atoi(envVal); err == nil && seconds > 0 { 16 | return time.Duration(seconds) * time.Second 17 | } 18 | } 19 | return defaultCandidatesMonitorPeriod 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/routemanager/util/ip.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/netip" 7 | ) 8 | 9 | // GetPrefixFromIP returns a netip.Prefix from a net.IP address. 10 | func GetPrefixFromIP(ip net.IP) (netip.Prefix, error) { 11 | addr, ok := netip.AddrFromSlice(ip) 12 | if !ok { 13 | return netip.Prefix{}, fmt.Errorf("parse IP address: %s", ip) 14 | } 15 | 16 | addr = addr.Unmap() 17 | prefix := netip.PrefixFrom(addr, addr.BitLen()) 18 | return prefix, nil 19 | } 20 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/procattr_darwin.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "os/exec" 5 | "syscall" 6 | ) 7 | 8 | // setUpdaterProcAttr configures the updater process to run in a new session, 9 | // making it independent of the parent daemon process. This ensures the updater 10 | // survives when the daemon is stopped during the pkg installation. 11 | func setUpdaterProcAttr(cmd *exec.Cmd) { 12 | cmd.SysProcAttr = &syscall.SysProcAttr{ 13 | Setsid: true, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /encryption/cert.go: -------------------------------------------------------------------------------- 1 | package encryption 2 | 3 | import "crypto/tls" 4 | 5 | func LoadTLSConfig(certFile, keyFile string) (*tls.Config, error) { 6 | serverCert, err := tls.LoadX509KeyPair(certFile, keyFile) 7 | if err != nil { 8 | return nil, err 9 | } 10 | 11 | config := &tls.Config{ 12 | Certificates: []tls.Certificate{serverCert}, 13 | ClientAuth: tls.NoClientCert, 14 | NextProtos: []string{ 15 | "h2", "http/1.1", // enable HTTP/2 16 | }, 17 | } 18 | return config, nil 19 | } 20 | -------------------------------------------------------------------------------- /client/iface/bind/control.go: -------------------------------------------------------------------------------- 1 | package bind 2 | 3 | import ( 4 | wireguard "golang.zx2c4.com/wireguard/conn" 5 | 6 | nbnet "github.com/netbirdio/netbird/client/net" 7 | ) 8 | 9 | // TODO: This is most likely obsolete since the control fns should be called by the wrapped udpconn (ice_bind.go) 10 | func init() { 11 | listener := nbnet.NewListener() 12 | if listener.ListenConfig.Control != nil { 13 | *wireguard.ControlFns = append(*wireguard.ControlFns, listener.ListenConfig.Control) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /client/internal/dns/wgiface_windows.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/client/iface/device" 5 | "github.com/netbirdio/netbird/client/iface/wgaddr" 6 | ) 7 | 8 | // WGIface defines subset methods of interface required for manager 9 | type WGIface interface { 10 | Name() string 11 | Address() wgaddr.Address 12 | IsUserspaceBind() bool 13 | GetFilter() device.PacketFilter 14 | GetDevice() *device.FilteredDevice 15 | GetInterfaceGUIDString() (string, error) 16 | } 17 | -------------------------------------------------------------------------------- /flow/proto/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! which realpath > /dev/null 2>&1 5 | then 6 | echo realpath is not installed 7 | echo run: brew install coreutils 8 | exit 1 9 | fi 10 | 11 | old_pwd=$(pwd) 12 | script_path=$(dirname $(realpath "$0")) 13 | cd "$script_path" 14 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 15 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 16 | protoc -I ./ ./flow.proto --go_out=../ --go-grpc_out=../ 17 | cd "$old_pwd" 18 | -------------------------------------------------------------------------------- /client/cmd/signer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var rootCmd = &cobra.Command{ 10 | Use: "signer", 11 | Short: "A CLI tool for managing cryptographic keys and artifacts", 12 | Long: `signer is a command-line tool that helps you manage 13 | root keys, artifact keys, and revocation lists securely.`, 14 | } 15 | 16 | func main() { 17 | if err := rootCmd.Execute(); err != nil { 18 | rootCmd.Println(err) 19 | os.Exit(1) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /client/internal/dns/server_export_test.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGetServerDns(t *testing.T) { 8 | _, err := GetServerDns() 9 | if err == nil { 10 | t.Errorf("invalid dns server instance") 11 | } 12 | 13 | srv := &MockServer{} 14 | setServerDns(srv) 15 | 16 | srvB, err := GetServerDns() 17 | if err != nil { 18 | t.Errorf("invalid dns server instance: %s", err) 19 | } 20 | 21 | if srvB != srv { 22 | t.Errorf("mismatch dns instances") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/internal/dns/consts.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package dns 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/client/configs" 7 | "os" 8 | "path/filepath" 9 | ) 10 | 11 | var fileUncleanShutdownResolvConfLocation string 12 | 13 | func init() { 14 | fileUncleanShutdownResolvConfLocation = os.Getenv("NB_UNCLEAN_SHUTDOWN_RESOLV_FILE") 15 | if fileUncleanShutdownResolvConfLocation == "" { 16 | fileUncleanShutdownResolvConfLocation = filepath.Join(configs.StateDir, "resolv.conf") 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /management/server/auth/test_data/sample_key.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4f5wg5l2hKsTeNem/V41 3 | fGnJm6gOdrj8ym3rFkEU/wT8RDtnSgFEZOQpHEgQ7JL38xUfU0Y3g6aYw9QT0hJ7 4 | mCpz9Er5qLaMXJwZxzHzAahlfA0icqabvJOMvQtzD6uQv6wPEyZtDTWiQi9AXwBp 5 | HssPnpYGIn20ZZuNlX2BrClciHhCPUIIZOQn/MmqTD31jSyjoQoV7MhhMTATKJx2 6 | XrHhR+1DcKJzQBSTAGnpYVaqpsARap+nwRipr3nUTuxyGohBTSmjJ2usSeQXHI3b 7 | ODIRe1AuTyHceAbewn8b462yEWKARdpd9AjQW5SIVPfdsz5B6GlYQ5LdYKtznTuy 8 | 7wIDAQAB 9 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /shared/signal/proto/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! which realpath > /dev/null 2>&1 5 | then 6 | echo realpath is not installed 7 | echo run: brew install coreutils 8 | exit 1 9 | fi 10 | 11 | old_pwd=$(pwd) 12 | script_path=$(dirname $(realpath "$0")) 13 | cd "$script_path" 14 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 15 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 16 | protoc -I ./ ./signalexchange.proto --go_out=../ --go-grpc_out=../ 17 | cd "$old_pwd" -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "regexp" 5 | 6 | v "github.com/hashicorp/go-version" 7 | ) 8 | 9 | // will be replaced with the release version when using goreleaser 10 | var version = "development" 11 | 12 | var ( 13 | VersionRegexp = regexp.MustCompile("^" + v.VersionRegexpRaw + "$") 14 | SemverRegexp = regexp.MustCompile("^" + v.SemverRegexpRaw + "$") 15 | ) 16 | 17 | // NetbirdVersion returns the Netbird version 18 | func NetbirdVersion() string { 19 | return version 20 | } 21 | -------------------------------------------------------------------------------- /client/firewall/uspfilter/common/iface.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | wgdevice "golang.zx2c4.com/wireguard/device" 5 | 6 | "github.com/netbirdio/netbird/client/iface/device" 7 | "github.com/netbirdio/netbird/client/iface/wgaddr" 8 | ) 9 | 10 | // IFaceMapper defines subset methods of interface required for manager 11 | type IFaceMapper interface { 12 | SetFilter(device.PacketFilter) error 13 | Address() wgaddr.Address 14 | GetWGDevice() *wgdevice.Device 15 | GetDevice() *device.FilteredDevice 16 | } 17 | -------------------------------------------------------------------------------- /client/iface/configurer/common.go: -------------------------------------------------------------------------------- 1 | package configurer 2 | 3 | import ( 4 | "net" 5 | "net/netip" 6 | ) 7 | 8 | func prefixesToIPNets(prefixes []netip.Prefix) []net.IPNet { 9 | ipNets := make([]net.IPNet, len(prefixes)) 10 | for i, prefix := range prefixes { 11 | ipNets[i] = net.IPNet{ 12 | IP: prefix.Addr().AsSlice(), // Convert netip.Addr to net.IP 13 | Mask: net.CIDRMask(prefix.Bits(), prefix.Addr().BitLen()), // Create subnet mask 14 | } 15 | } 16 | return ipNets 17 | } 18 | -------------------------------------------------------------------------------- /shared/management/proto/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! which realpath > /dev/null 2>&1 5 | then 6 | echo realpath is not installed 7 | echo run: brew install coreutils 8 | exit 1 9 | fi 10 | 11 | old_pwd=$(pwd) 12 | script_path=$(dirname $(realpath "$0")) 13 | cd "$script_path" 14 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 15 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 16 | protoc -I ./ ./management.proto --go_out=../ --go-grpc_out=../ 17 | cd "$old_pwd" 18 | -------------------------------------------------------------------------------- /client/grpc/dialer_js.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "google.golang.org/grpc" 5 | 6 | "github.com/netbirdio/netbird/util/wsproxy/client" 7 | ) 8 | 9 | // WithCustomDialer returns a gRPC dial option that uses WebSocket transport for WASM/JS environments. 10 | // The component parameter specifies the WebSocket proxy component path (e.g., "/management", "/signal"). 11 | func WithCustomDialer(tlsEnabled bool, component string) grpc.DialOption { 12 | return client.WithWebSocketDialer(tlsEnabled, component) 13 | } 14 | -------------------------------------------------------------------------------- /client/system/detect_cloud/vultr.go: -------------------------------------------------------------------------------- 1 | package detect_cloud 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func detectVultr(ctx context.Context) string { 9 | req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/v1.json", nil) 10 | if err != nil { 11 | return "" 12 | } 13 | 14 | resp, err := hc.Do(req) 15 | if err != nil { 16 | return "" 17 | } 18 | defer resp.Body.Close() 19 | 20 | if resp.StatusCode == http.StatusOK { 21 | return "Vultr" 22 | } 23 | return "" 24 | } 25 | -------------------------------------------------------------------------------- /route/hauniqueid.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import "strings" 4 | 5 | const haSeparator = "|" 6 | 7 | // HAUniqueID is a unique identifier that is used to group high availability routes. 8 | type HAUniqueID string 9 | 10 | func (id HAUniqueID) String() string { 11 | return string(id) 12 | } 13 | 14 | // NetID returns the NetID from the HAUniqueID 15 | func (id HAUniqueID) NetID() NetID { 16 | if i := strings.LastIndex(string(id), haSeparator); i != -1 { 17 | return NetID(id[:i]) 18 | } 19 | return NetID(id) 20 | } 21 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23-bullseye 2 | 3 | RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 4 | && apt-get -y install --no-install-recommends\ 5 | gettext-base=0.21-4 \ 6 | iptables=1.8.7-1 \ 7 | libgl1-mesa-dev=20.3.5-1 \ 8 | xorg-dev=1:7.7+22 \ 9 | libayatana-appindicator3-dev=0.5.5-2+deb11u2 \ 10 | && apt-get clean \ 11 | && rm -rf /var/lib/apt/lists/* \ 12 | && go install -v golang.org/x/tools/gopls@v0.18.1 13 | 14 | 15 | WORKDIR /app 16 | -------------------------------------------------------------------------------- /client/internal/dns/wgiface.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package dns 4 | 5 | import ( 6 | "net" 7 | 8 | "github.com/netbirdio/netbird/client/iface/device" 9 | "github.com/netbirdio/netbird/client/iface/wgaddr" 10 | ) 11 | 12 | // WGIface defines subset methods of interface required for manager 13 | type WGIface interface { 14 | Name() string 15 | Address() wgaddr.Address 16 | ToInterface() *net.Interface 17 | IsUserspaceBind() bool 18 | GetFilter() device.PacketFilter 19 | GetDevice() *device.FilteredDevice 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/networkmonitor/monitor_mobile.go: -------------------------------------------------------------------------------- 1 | //go:build ios || android 2 | 3 | package networkmonitor 4 | 5 | import ( 6 | "context" 7 | "fmt" 8 | ) 9 | 10 | type NetworkMonitor struct { 11 | } 12 | 13 | // New creates a new network monitor. 14 | func New() *NetworkMonitor { 15 | return &NetworkMonitor{} 16 | } 17 | 18 | func (nw *NetworkMonitor) Listen(_ context.Context) error { 19 | return fmt.Errorf("network monitor not supported on mobile platforms") 20 | } 21 | 22 | func (nw *NetworkMonitor) Stop() { 23 | } 24 | -------------------------------------------------------------------------------- /management/internals/controllers/network_map/update_channel.go: -------------------------------------------------------------------------------- 1 | package network_map 2 | 3 | import "context" 4 | 5 | type PeersUpdateManager interface { 6 | SendUpdate(ctx context.Context, peerID string, update *UpdateMessage) 7 | CreateChannel(ctx context.Context, peerID string) chan *UpdateMessage 8 | CloseChannel(ctx context.Context, peerID string) 9 | CountStreams() int 10 | HasChannel(peerID string) bool 11 | CloseChannels(ctx context.Context, peerIDs []string) 12 | GetAllConnectedPeers() map[string]struct{} 13 | } 14 | -------------------------------------------------------------------------------- /client/iface/iface_destroy_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux && !android 2 | 3 | package iface 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/vishvananda/netlink" 9 | ) 10 | 11 | func (w *WGIface) Destroy() error { 12 | link, err := netlink.LinkByName(w.Name()) 13 | if err != nil { 14 | return fmt.Errorf("failed to get link by name %s: %w", w.Name(), err) 15 | } 16 | 17 | if err := netlink.LinkDel(link); err != nil { 18 | return fmt.Errorf("failed to delete link %s: %w", w.Name(), err) 19 | } 20 | 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /client/internal/debug/debug_nonlinux.go: -------------------------------------------------------------------------------- 1 | //go:build !linux || android 2 | 3 | package debug 4 | 5 | // collectFirewallRules returns nothing on non-linux systems 6 | func (g *BundleGenerator) addFirewallRules() error { 7 | return nil 8 | } 9 | 10 | func (g *BundleGenerator) trySystemdLogFallback() error { 11 | // Systemd is only available on Linux 12 | // TODO: Add BSD support 13 | return nil 14 | } 15 | 16 | func (g *BundleGenerator) addIPRules() error { 17 | // IP rules are only supported on Linux 18 | return nil 19 | } 20 | -------------------------------------------------------------------------------- /client/net/dialer.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | // Dialer extends the standard net.Dialer with the ability to execute hooks before 8 | // and after connections. This can be used to bypass the VPN for connections using this dialer. 9 | type Dialer struct { 10 | *net.Dialer 11 | } 12 | 13 | // NewDialer returns a customized net.Dialer with overridden Control method 14 | func NewDialer() *Dialer { 15 | dialer := &Dialer{ 16 | Dialer: &net.Dialer{}, 17 | } 18 | dialer.init() 19 | return dialer 20 | } 21 | -------------------------------------------------------------------------------- /shared/relay/messages/address/address.go: -------------------------------------------------------------------------------- 1 | // Deprecated: This package is deprecated and will be removed in a future release. 2 | package address 3 | 4 | import ( 5 | "bytes" 6 | "encoding/gob" 7 | "fmt" 8 | ) 9 | 10 | type Address struct { 11 | URL string 12 | } 13 | 14 | func (addr *Address) Marshal() ([]byte, error) { 15 | var buf bytes.Buffer 16 | enc := gob.NewEncoder(&buf) 17 | if err := enc.Encode(addr); err != nil { 18 | return nil, fmt.Errorf("encode Address: %w", err) 19 | } 20 | return buf.Bytes(), nil 21 | } 22 | -------------------------------------------------------------------------------- /client/net/listener.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | // ListenerConfig extends the standard net.ListenConfig with the ability to execute hooks before 8 | // responding via the socket and after closing. This can be used to bypass the VPN for listeners. 9 | type ListenerConfig struct { 10 | net.ListenConfig 11 | } 12 | 13 | // NewListener creates a new ListenerConfig instance. 14 | func NewListener() *ListenerConfig { 15 | listener := &ListenerConfig{} 16 | listener.init() 17 | 18 | return listener 19 | } 20 | -------------------------------------------------------------------------------- /client/configs/configs.go: -------------------------------------------------------------------------------- 1 | package configs 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "runtime" 7 | ) 8 | 9 | var StateDir string 10 | 11 | func init() { 12 | StateDir = os.Getenv("NB_STATE_DIR") 13 | if StateDir != "" { 14 | return 15 | } 16 | switch runtime.GOOS { 17 | case "windows": 18 | StateDir = filepath.Join(os.Getenv("PROGRAMDATA"), "Netbird") 19 | case "darwin", "linux": 20 | StateDir = "/var/lib/netbird" 21 | case "freebsd", "openbsd", "netbsd", "dragonfly": 22 | StateDir = "/var/db/netbird" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/proto/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if ! which realpath > /dev/null 2>&1 5 | then 6 | echo realpath is not installed 7 | echo run: brew install coreutils 8 | exit 1 9 | fi 10 | 11 | old_pwd=$(pwd) 12 | script_path=$(dirname $(realpath "$0")) 13 | cd "$script_path" 14 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.6 15 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1 16 | protoc -I ./ ./daemon.proto --go_out=../ --go-grpc_out=../ --experimental_allow_proto3_optional 17 | cd "$old_pwd" 18 | -------------------------------------------------------------------------------- /client/system/detect_cloud/alibabacloud.go: -------------------------------------------------------------------------------- 1 | package detect_cloud 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func detectAlibabaCloud(ctx context.Context) string { 9 | req, err := http.NewRequestWithContext(ctx, "GET", "http://100.100.100.200/latest/", nil) 10 | if err != nil { 11 | return "" 12 | } 13 | 14 | resp, err := hc.Do(req) 15 | if err != nil { 16 | return "" 17 | } 18 | defer resp.Body.Close() 19 | 20 | if resp.StatusCode == http.StatusOK { 21 | return "Alibaba Cloud" 22 | } 23 | return "" 24 | } 25 | -------------------------------------------------------------------------------- /client/system/detect_platform/openstack.go: -------------------------------------------------------------------------------- 1 | package detect_platform 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func detectOpenStack(ctx context.Context) string { 9 | req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/openstack", nil) 10 | if err != nil { 11 | return "" 12 | } 13 | 14 | resp, err := hc.Do(req) 15 | if err != nil { 16 | return "" 17 | } 18 | defer resp.Body.Close() 19 | 20 | if resp.StatusCode == http.StatusOK { 21 | return "OpenStack" 22 | } 23 | return "" 24 | } 25 | -------------------------------------------------------------------------------- /management/server/testutil/store_ios.go: -------------------------------------------------------------------------------- 1 | //go:build ios 2 | // +build ios 3 | 4 | package testutil 5 | 6 | func CreatePostgresTestContainer() (func(), string, error) { 7 | return func() { 8 | // Empty function for Postgres 9 | }, "", nil 10 | } 11 | 12 | func CreateMysqlTestContainer() (func(), string, error) { 13 | return func() { 14 | // Empty function for MySQL 15 | }, "", nil 16 | } 17 | 18 | func CreateRedisTestContainer() (func(), string, error) { 19 | return func() { 20 | // Empty function for Redis 21 | }, "", nil 22 | } 23 | -------------------------------------------------------------------------------- /client/system/detect_cloud/digitalocean.go: -------------------------------------------------------------------------------- 1 | package detect_cloud 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func detectDigitalOcean(ctx context.Context) string { 9 | req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/metadata/v1/", nil) 10 | if err != nil { 11 | return "" 12 | } 13 | 14 | resp, err := hc.Do(req) 15 | if err != nil { 16 | return "" 17 | } 18 | defer resp.Body.Close() 19 | 20 | if resp.StatusCode == http.StatusOK { 21 | return "Digital Ocean" 22 | } 23 | return "" 24 | } 25 | -------------------------------------------------------------------------------- /infrastructure_files/observability/grafana/dashboards/readme.md: -------------------------------------------------------------------------------- 1 | ## Dashboard variables 2 | 3 | 1. **datasource**: Select Prometheus server 4 | 2. **cluster**: Filter NetBird instances by cluster 5 | 3. **environment**: Filter by environment (dev, staging, UAT, prod) 6 | 4. **job**: Select target NetBird instance if multiple are running 7 | 5. **host**: Filter metrics by host 8 | 9 | 10 | NOTE: 11 | - Your installation may have a subset of these variables. 12 | - The dashboard expects `exported_endpoint` instead of `endpoint` in HTTP request metrics. -------------------------------------------------------------------------------- /client/firewall/iface.go: -------------------------------------------------------------------------------- 1 | package firewall 2 | 3 | import ( 4 | wgdevice "golang.zx2c4.com/wireguard/device" 5 | 6 | "github.com/netbirdio/netbird/client/iface/device" 7 | "github.com/netbirdio/netbird/client/iface/wgaddr" 8 | ) 9 | 10 | // IFaceMapper defines subset methods of interface required for manager 11 | type IFaceMapper interface { 12 | Name() string 13 | Address() wgaddr.Address 14 | IsUserspaceBind() bool 15 | SetFilter(device.PacketFilter) error 16 | GetDevice() *device.FilteredDevice 17 | GetWGDevice() *wgdevice.Device 18 | } 19 | -------------------------------------------------------------------------------- /upload-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/netbirdio/netbird/upload-server/server" 9 | "github.com/netbirdio/netbird/util" 10 | ) 11 | 12 | func main() { 13 | err := util.InitLog("info", util.LogConsole) 14 | if err != nil { 15 | log.Fatalf("Failed to initialize logger: %v", err) 16 | } 17 | 18 | srv := server.NewServer() 19 | if err = srv.Start(); err != nil && !errors.Is(err, http.ErrServerClosed) { 20 | log.Fatalf("Failed to start server: %v", err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/forum.yml: -------------------------------------------------------------------------------- 1 | name: Post release topic on Discourse 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | post: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: roots/discourse-topic-github-release-action@main 12 | with: 13 | discourse-api-key: ${{ secrets.DISCOURSE_RELEASES_API_KEY }} 14 | discourse-base-url: https://forum.netbird.io 15 | discourse-author-username: NetBird 16 | discourse-category: 17 17 | discourse-tags: 18 | releases 19 | -------------------------------------------------------------------------------- /upload-server/types/upload.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | const ( 4 | // ClientHeader is the header used to identify the client 5 | ClientHeader = "x-nb-client" 6 | // ClientHeaderValue is the value of the ClientHeader 7 | ClientHeaderValue = "netbird" 8 | // GetURLPath is the path for the GetURL request 9 | GetURLPath = "/upload-url" 10 | 11 | DefaultBundleURL = "https://upload.debug.netbird.io" + GetURLPath 12 | ) 13 | 14 | // GetURLResponse is the response for the GetURL request 15 | type GetURLResponse struct { 16 | URL string 17 | Key string 18 | } 19 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | NetBird's goal is to provide a secure network. If you find a vulnerability or bug, please report it by opening an issue [here](https://github.com/netbirdio/netbird/issues/new?assignees=&labels=&template=bug-issue-report.md&title=) or by contacting us by email. 4 | 5 | There has yet to be an official bug bounty program for the NetBird project. 6 | 7 | ## Supported Versions 8 | - We currently support only the latest version 9 | 10 | ## Reporting a Vulnerability 11 | 12 | Please report security issues to `security@netbird.io` 13 | -------------------------------------------------------------------------------- /client/firewall/manager/routerpair.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/route" 5 | ) 6 | 7 | type RouterPair struct { 8 | ID route.ID 9 | Source Network 10 | Destination Network 11 | Masquerade bool 12 | Inverse bool 13 | } 14 | 15 | func GetInversePair(pair RouterPair) RouterPair { 16 | return RouterPair{ 17 | ID: pair.ID, 18 | // invert Source/Destination 19 | Source: pair.Destination, 20 | Destination: pair.Source, 21 | Masquerade: pair.Masquerade, 22 | Inverse: true, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/internal/routemanager/state.go: -------------------------------------------------------------------------------- 1 | package routemanager 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/client/internal/routeselector" 5 | ) 6 | 7 | type SelectorState routeselector.RouteSelector 8 | 9 | func (s *SelectorState) Name() string { 10 | return "routeselector_state" 11 | } 12 | 13 | func (s *SelectorState) MarshalJSON() ([]byte, error) { 14 | return (*routeselector.RouteSelector)(s).MarshalJSON() 15 | } 16 | 17 | func (s *SelectorState) UnmarshalJSON(data []byte) error { 18 | return (*routeselector.RouteSelector)(s).UnmarshalJSON(data) 19 | } 20 | -------------------------------------------------------------------------------- /client/server/state_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !linux || android 2 | 3 | package server 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/client/internal/dns" 7 | "github.com/netbirdio/netbird/client/internal/routemanager/systemops" 8 | "github.com/netbirdio/netbird/client/internal/statemanager" 9 | "github.com/netbirdio/netbird/client/ssh/config" 10 | ) 11 | 12 | func registerStates(mgr *statemanager.Manager) { 13 | mgr.RegisterState(&dns.ShutdownState{}) 14 | mgr.RegisterState(&systemops.ShutdownState{}) 15 | mgr.RegisterState(&config.ShutdownState{}) 16 | } 17 | -------------------------------------------------------------------------------- /client/firewall/manager/protocol.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | // Protocol is the protocol of the port 4 | // todo Move Protocol and Port and RouterPair to the Firwall package or a separate package 5 | type Protocol string 6 | 7 | const ( 8 | // ProtocolTCP is the TCP protocol 9 | ProtocolTCP Protocol = "tcp" 10 | 11 | // ProtocolUDP is the UDP protocol 12 | ProtocolUDP Protocol = "udp" 13 | 14 | // ProtocolICMP is the ICMP protocol 15 | ProtocolICMP Protocol = "icmp" 16 | 17 | // ProtocolALL cover all supported protocols 18 | ProtocolALL Protocol = "all" 19 | ) 20 | -------------------------------------------------------------------------------- /client/internal/engine_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package internal 4 | 5 | import ( 6 | icemaker "github.com/netbirdio/netbird/client/internal/peer/ice" 7 | ) 8 | 9 | // createICEConfig creates ICE configuration for WASM environment. 10 | func (e *Engine) createICEConfig() icemaker.Config { 11 | cfg := icemaker.Config{ 12 | StunTurn: &e.stunTurn, 13 | InterfaceBlackList: e.config.IFaceBlackList, 14 | DisableIPv6Discovery: e.config.DisableIPv6Discovery, 15 | NATExternalIPs: e.parseNATExternalIPMappings(), 16 | } 17 | return cfg 18 | } 19 | -------------------------------------------------------------------------------- /client/system/detect_cloud/gcp.go: -------------------------------------------------------------------------------- 1 | package detect_cloud 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func detectGCP(ctx context.Context) string { 9 | req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254", nil) 10 | if err != nil { 11 | return "" 12 | } 13 | req.Header.Add("Metadata-Flavor", "Google") 14 | 15 | resp, err := hc.Do(req) 16 | if err != nil { 17 | return "" 18 | } 19 | defer resp.Body.Close() 20 | 21 | if resp.StatusCode == http.StatusOK { 22 | return "Google Cloud Platform" 23 | } 24 | return "" 25 | } 26 | -------------------------------------------------------------------------------- /client/system/info_darwin_test.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "testing" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func Test_sysInfoMac(t *testing.T) { 10 | t.Skip("skipping darwin test") 11 | serialNum, prodName, manufacturer := sysInfo() 12 | if serialNum == "" { 13 | t.Errorf("serialNum is empty") 14 | } 15 | 16 | if prodName == "" { 17 | t.Errorf("prodName is empty") 18 | } 19 | 20 | if manufacturer == "" { 21 | t.Errorf("manufacturer is empty") 22 | } 23 | log.Infof("Mac sys info: %s, %s, %s", serialNum, prodName, manufacturer) 24 | } 25 | -------------------------------------------------------------------------------- /base62/base62_test.go: -------------------------------------------------------------------------------- 1 | package base62 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestEncodeDecode(t *testing.T) { 8 | tests := []struct { 9 | num uint32 10 | }{ 11 | {0}, 12 | {1}, 13 | {42}, 14 | {12345}, 15 | {99999}, 16 | {123456789}, 17 | } 18 | 19 | for _, tt := range tests { 20 | encoded := Encode(tt.num) 21 | decoded, err := Decode(encoded) 22 | 23 | if err != nil { 24 | t.Errorf("Decode error: %v", err) 25 | } 26 | 27 | if decoded != tt.num { 28 | t.Errorf("Decode(%v) = %v, want %v", encoded, decoded, tt.num) 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /management/server/auth/test_data/jwks.json: -------------------------------------------------------------------------------- 1 | { 2 | "keys": [ 3 | { 4 | "kty": "RSA", 5 | "kid": "test-key", 6 | "use": "sig", 7 | "n": "4f5wg5l2hKsTeNem_V41fGnJm6gOdrj8ym3rFkEU_wT8RDtnSgFEZOQpHEgQ7JL38xUfU0Y3g6aYw9QT0hJ7mCpz9Er5qLaMXJwZxzHzAahlfA0icqabvJOMvQtzD6uQv6wPEyZtDTWiQi9AXwBpHssPnpYGIn20ZZuNlX2BrClciHhCPUIIZOQn_MmqTD31jSyjoQoV7MhhMTATKJx2XrHhR-1DcKJzQBSTAGnpYVaqpsARap-nwRipr3nUTuxyGohBTSmjJ2usSeQXHI3bODIRe1AuTyHceAbewn8b462yEWKARdpd9AjQW5SIVPfdsz5B6GlYQ5LdYKtznTuy7w", 8 | "e": "AQAB" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /client/system/detect_cloud/azure.go: -------------------------------------------------------------------------------- 1 | package detect_cloud 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | func detectAzure(ctx context.Context) string { 9 | req, err := http.NewRequestWithContext(ctx, "GET", "http://169.254.169.254/metadata/instance?api-version=2021-02-01", nil) 10 | if err != nil { 11 | return "" 12 | } 13 | req.Header.Set("Metadata", "true") 14 | 15 | resp, err := hc.Do(req) 16 | if err != nil { 17 | return "" 18 | } 19 | defer resp.Body.Close() 20 | 21 | if resp.StatusCode == http.StatusOK { 22 | return "Microsoft Azure" 23 | } 24 | return "" 25 | } 26 | -------------------------------------------------------------------------------- /client/ui/process/process_windows.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "os/user" 5 | 6 | "github.com/shirou/gopsutil/v3/process" 7 | log "github.com/sirupsen/logrus" 8 | ) 9 | 10 | func isProcessOwnedByCurrentUser(p *process.Process) bool { 11 | processUsername, err := p.Username() 12 | if err != nil { 13 | log.Errorf("get process username error: %v", err) 14 | return false 15 | } 16 | 17 | currUser, err := user.Current() 18 | if err != nil { 19 | log.Errorf("get current user error: %v", err) 20 | return false 21 | } 22 | 23 | return processUsername == currUser.Username 24 | } 25 | -------------------------------------------------------------------------------- /client/internal/lazyconn/wgiface.go: -------------------------------------------------------------------------------- 1 | package lazyconn 2 | 3 | import ( 4 | "net" 5 | "net/netip" 6 | "time" 7 | 8 | "golang.zx2c4.com/wireguard/wgctrl/wgtypes" 9 | 10 | "github.com/netbirdio/netbird/client/iface/wgaddr" 11 | "github.com/netbirdio/netbird/monotime" 12 | ) 13 | 14 | type WGIface interface { 15 | RemovePeer(peerKey string) error 16 | UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error 17 | IsUserspaceBind() bool 18 | Address() wgaddr.Address 19 | LastActivities() map[string]monotime.Time 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/peer/conntype/priority.go: -------------------------------------------------------------------------------- 1 | package conntype 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | None ConnPriority = 0 9 | Relay ConnPriority = 1 10 | ICETurn ConnPriority = 2 11 | ICEP2P ConnPriority = 3 12 | ) 13 | 14 | type ConnPriority int 15 | 16 | func (cp ConnPriority) String() string { 17 | switch cp { 18 | case None: 19 | return "None" 20 | case Relay: 21 | return "PriorityRelay" 22 | case ICETurn: 23 | return "PriorityICETurn" 24 | case ICEP2P: 25 | return "PriorityICEP2P" 26 | default: 27 | return fmt.Sprintf("ConnPriority(%d)", cp) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /client/internal/peer/ice/config.go: -------------------------------------------------------------------------------- 1 | package ice 2 | 3 | import ( 4 | "github.com/pion/ice/v4" 5 | ) 6 | 7 | type Config struct { 8 | // StunTurn is a list of STUN and TURN URLs 9 | StunTurn *StunTurn // []*stun.URI 10 | 11 | // InterfaceBlackList is a list of machine interfaces that should be filtered out by ICE Candidate gathering 12 | // (e.g. if eth0 is in the list, host candidate of this interface won't be used) 13 | InterfaceBlackList []string 14 | DisableIPv6Discovery bool 15 | 16 | UDPMux ice.UDPMux 17 | UDPMuxSrflx ice.UniversalUDPMux 18 | 19 | NATExternalIPs []string 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/routemanager/iface/iface_common.go: -------------------------------------------------------------------------------- 1 | package iface 2 | 3 | import ( 4 | "net" 5 | "net/netip" 6 | 7 | "github.com/netbirdio/netbird/client/iface/device" 8 | "github.com/netbirdio/netbird/client/iface/wgaddr" 9 | ) 10 | 11 | type wgIfaceBase interface { 12 | AddAllowedIP(peerKey string, allowedIP netip.Prefix) error 13 | RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error 14 | 15 | Name() string 16 | Address() wgaddr.Address 17 | ToInterface() *net.Interface 18 | IsUserspaceBind() bool 19 | GetFilter() device.PacketFilter 20 | GetDevice() *device.FilteredDevice 21 | } 22 | -------------------------------------------------------------------------------- /management/server/types/dns_settings.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // DNSSettings defines dns settings at the account level 4 | type DNSSettings struct { 5 | // DisabledManagementGroups groups whose DNS management is disabled 6 | DisabledManagementGroups []string `gorm:"serializer:json"` 7 | } 8 | 9 | // Copy returns a copy of the DNS settings 10 | func (d DNSSettings) Copy() DNSSettings { 11 | settings := DNSSettings{ 12 | DisabledManagementGroups: make([]string, len(d.DisabledManagementGroups)), 13 | } 14 | copy(settings.DisabledManagementGroups, d.DisabledManagementGroups) 15 | return settings 16 | } 17 | -------------------------------------------------------------------------------- /.git-branches.toml: -------------------------------------------------------------------------------- 1 | # More info around this file at https://www.git-town.com/configuration-file 2 | 3 | [branches] 4 | main = "main" 5 | perennials = [] 6 | perennial-regex = "" 7 | 8 | [create] 9 | new-branch-type = "feature" 10 | push-new-branches = false 11 | 12 | [hosting] 13 | dev-remote = "origin" 14 | # platform = "" 15 | # origin-hostname = "" 16 | 17 | [ship] 18 | delete-tracking-branch = false 19 | strategy = "squash-merge" 20 | 21 | [sync] 22 | feature-strategy = "merge" 23 | perennial-strategy = "rebase" 24 | prototype-strategy = "merge" 25 | push-hook = true 26 | tags = true 27 | upstream = false 28 | -------------------------------------------------------------------------------- /client/ui/process/process_nonwindows.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package process 4 | 5 | import ( 6 | "os" 7 | 8 | "github.com/shirou/gopsutil/v3/process" 9 | log "github.com/sirupsen/logrus" 10 | ) 11 | 12 | func isProcessOwnedByCurrentUser(p *process.Process) bool { 13 | currentUserID := os.Getuid() 14 | uids, err := p.Uids() 15 | if err != nil { 16 | log.Errorf("get process uids: %v", err) 17 | return false 18 | } 19 | for _, id := range uids { 20 | log.Debugf("checking process uid: %d", id) 21 | if int(id) == currentUserID { 22 | return true 23 | } 24 | } 25 | return false 26 | } 27 | -------------------------------------------------------------------------------- /client/internal/lazyconn/env.go: -------------------------------------------------------------------------------- 1 | package lazyconn 2 | 3 | import ( 4 | "os" 5 | "strconv" 6 | 7 | log "github.com/sirupsen/logrus" 8 | ) 9 | 10 | const ( 11 | EnvEnableLazyConn = "NB_ENABLE_EXPERIMENTAL_LAZY_CONN" 12 | EnvInactivityThreshold = "NB_LAZY_CONN_INACTIVITY_THRESHOLD" 13 | ) 14 | 15 | func IsLazyConnEnabledByEnv() bool { 16 | val := os.Getenv(EnvEnableLazyConn) 17 | if val == "" { 18 | return false 19 | } 20 | enabled, err := strconv.ParseBool(val) 21 | if err != nil { 22 | log.Warnf("failed to parse %s: %v", EnvEnableLazyConn, err) 23 | return false 24 | } 25 | return enabled 26 | } 27 | -------------------------------------------------------------------------------- /client/internal/ebpf/instantiater_linux.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package ebpf 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/client/internal/ebpf/ebpf" 7 | "github.com/netbirdio/netbird/client/internal/ebpf/manager" 8 | ) 9 | 10 | // GetEbpfManagerInstance is a wrapper function. This encapsulation is required because if the code import the internal 11 | // ebpf package the Go compiler will include the object files. But it is not supported on Android. It can cause instant 12 | // panic on older Android version. 13 | func GetEbpfManagerInstance() manager.Manager { 14 | return ebpf.GetEbpfManagerInstance() 15 | } 16 | -------------------------------------------------------------------------------- /client/iface/wgproxy/listener/listener.go: -------------------------------------------------------------------------------- 1 | package listener 2 | 3 | import "sync" 4 | 5 | type CloseListener struct { 6 | listener func() 7 | mu sync.Mutex 8 | } 9 | 10 | func NewCloseListener() *CloseListener { 11 | return &CloseListener{} 12 | } 13 | 14 | func (c *CloseListener) SetCloseListener(listener func()) { 15 | c.mu.Lock() 16 | defer c.mu.Unlock() 17 | 18 | c.listener = listener 19 | } 20 | 21 | func (c *CloseListener) Notify() { 22 | c.mu.Lock() 23 | 24 | if c.listener == nil { 25 | c.mu.Unlock() 26 | return 27 | } 28 | listener := c.listener 29 | c.mu.Unlock() 30 | 31 | listener() 32 | } 33 | -------------------------------------------------------------------------------- /shared/relay/tls/client_prod.go: -------------------------------------------------------------------------------- 1 | //go:build !devcert 2 | 3 | package tls 4 | 5 | import ( 6 | "crypto/tls" 7 | "crypto/x509" 8 | 9 | log "github.com/sirupsen/logrus" 10 | 11 | "github.com/netbirdio/netbird/util/embeddedroots" 12 | ) 13 | 14 | func ClientQUICTLSConfig() *tls.Config { 15 | certPool, err := x509.SystemCertPool() 16 | if err != nil || certPool == nil { 17 | log.Debugf("System cert pool not available; falling back to embedded cert, error: %v", err) 18 | certPool = embeddedroots.Get() 19 | } 20 | 21 | return &tls.Config{ 22 | NextProtos: []string{NBalpn}, 23 | RootCAs: certPool, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /util/wsproxy/constants.go: -------------------------------------------------------------------------------- 1 | package wsproxy 2 | 3 | import "errors" 4 | 5 | // ProxyPath is the base path where the WebSocket proxy is mounted on servers. 6 | const ProxyPath = "/ws-proxy" 7 | 8 | // Component paths that are appended to ProxyPath 9 | const ( 10 | ManagementComponent = "/management" 11 | SignalComponent = "/signal" 12 | FlowComponent = "/flow" 13 | ) 14 | 15 | // Common errors 16 | var ( 17 | ErrConnectionTimeout = errors.New("WebSocket connection timeout") 18 | ErrConnectionFailed = errors.New("WebSocket connection failed") 19 | ErrBackendUnavailable = errors.New("backend unavailable") 20 | ) 21 | -------------------------------------------------------------------------------- /client/internal/updatemanager/installer/types_darwin.go: -------------------------------------------------------------------------------- 1 | package installer 2 | 3 | import ( 4 | "context" 5 | "os/exec" 6 | ) 7 | 8 | var ( 9 | TypeHomebrew = Type{name: "Homebrew", downloadable: false} 10 | TypePKG = Type{name: "pkg", downloadable: true} 11 | ) 12 | 13 | func TypeOfInstaller(ctx context.Context) Type { 14 | cmd := exec.CommandContext(ctx, "pkgutil", "--pkg-info", "io.netbird.client") 15 | _, err := cmd.Output() 16 | if err != nil && cmd.ProcessState.ExitCode() == 1 { 17 | // Not installed using pkg file, thus installed using Homebrew 18 | 19 | return TypeHomebrew 20 | } 21 | return TypePKG 22 | } 23 | -------------------------------------------------------------------------------- /release_files/darwin_pkg/preinstall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | LOG_FILE=/var/log/netbird/client_pre_install.log 6 | AGENT=/usr/local/bin/netbird 7 | 8 | mkdir -p /var/log/netbird/ 9 | 10 | { 11 | # check if it was installed with brew 12 | brew list --formula | grep netbird 13 | if [ $? -eq 0 ] 14 | then 15 | echo "NetBird has been installed with Brew. Please use Brew to update the package." 16 | exit 1 17 | fi 18 | osascript -e 'quit app "Netbird"' || true 19 | $AGENT service stop || true 20 | 21 | echo "Preinstall complete" 22 | exit 0 # all good 23 | } &> $LOG_FILE 24 | 25 | -------------------------------------------------------------------------------- /client/internal/dns/server_export.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | var ( 9 | mutex sync.Mutex 10 | server Server 11 | ) 12 | 13 | // GetServerDns export the DNS server instance in static way. It used by the Mobile client 14 | func GetServerDns() (Server, error) { 15 | mutex.Lock() 16 | if server == nil { 17 | mutex.Unlock() 18 | return nil, fmt.Errorf("DNS server not instantiated yet") 19 | } 20 | s := server 21 | mutex.Unlock() 22 | return s, nil 23 | } 24 | 25 | func setServerDns(newServerServer Server) { 26 | mutex.Lock() 27 | server = newServerServer 28 | defer mutex.Unlock() 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/sync-main.yml: -------------------------------------------------------------------------------- 1 | name: sync main 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || github.actor_id }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | trigger_sync_main: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Trigger main branch sync 17 | uses: benc-uk/workflow-dispatch@v1 18 | with: 19 | workflow: sync-main.yml 20 | repo: ${{ secrets.UPSTREAM_REPO }} 21 | token: ${{ secrets.NC_GITHUB_TOKEN }} 22 | inputs: '{ "sha": "${{ github.sha }}" }' -------------------------------------------------------------------------------- /client/iface/configurer/uapi.go: -------------------------------------------------------------------------------- 1 | //go:build !windows && !js 2 | 3 | package configurer 4 | 5 | import ( 6 | "net" 7 | 8 | log "github.com/sirupsen/logrus" 9 | "golang.zx2c4.com/wireguard/ipc" 10 | ) 11 | 12 | func openUAPI(deviceName string) (net.Listener, error) { 13 | uapiSock, err := ipc.UAPIOpen(deviceName) 14 | if err != nil { 15 | log.Errorf("failed to open uapi socket: %v", err) 16 | return nil, err 17 | } 18 | 19 | listener, err := ipc.UAPIListen(deviceName, uapiSock) 20 | if err != nil { 21 | log.Errorf("failed to listen on uapi socket: %v", err) 22 | return nil, err 23 | } 24 | 25 | return listener, nil 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/update-docs.yml: -------------------------------------------------------------------------------- 1 | name: update docs 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | paths: 8 | - 'shared/management/http/api/openapi.yml' 9 | 10 | jobs: 11 | trigger_docs_api_update: 12 | runs-on: ubuntu-latest 13 | if: startsWith(github.ref, 'refs/tags/') 14 | steps: 15 | - name: Trigger API pages generation 16 | uses: benc-uk/workflow-dispatch@v1 17 | with: 18 | workflow: generate api pages 19 | repo: netbirdio/docs 20 | ref: "refs/heads/main" 21 | token: ${{ secrets.SIGN_GITHUB_TOKEN }} 22 | inputs: '{ "tag": "${{ github.ref }}" }' -------------------------------------------------------------------------------- /client/ssh/config/shutdown_state.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // ShutdownState represents SSH configuration state that needs to be cleaned up. 4 | type ShutdownState struct { 5 | SSHConfigDir string 6 | SSHConfigFile string 7 | } 8 | 9 | // Name returns the state name for the state manager. 10 | func (s *ShutdownState) Name() string { 11 | return "ssh_config_state" 12 | } 13 | 14 | // Cleanup removes SSH client configuration files. 15 | func (s *ShutdownState) Cleanup() error { 16 | manager := &Manager{ 17 | sshConfigDir: s.SSHConfigDir, 18 | sshConfigFile: s.SSHConfigFile, 19 | } 20 | 21 | return manager.RemoveSSHClientConfig() 22 | } 23 | -------------------------------------------------------------------------------- /client/internal/engine_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !js 2 | 3 | package internal 4 | 5 | import ( 6 | icemaker "github.com/netbirdio/netbird/client/internal/peer/ice" 7 | ) 8 | 9 | // createICEConfig creates ICE configuration for non-WASM environments 10 | func (e *Engine) createICEConfig() icemaker.Config { 11 | return icemaker.Config{ 12 | StunTurn: &e.stunTurn, 13 | InterfaceBlackList: e.config.IFaceBlackList, 14 | DisableIPv6Discovery: e.config.DisableIPv6Discovery, 15 | UDPMux: e.udpMux.SingleSocketUDPMux, 16 | UDPMuxSrflx: e.udpMux, 17 | NATExternalIPs: e.parseNATExternalIPMappings(), 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /management/server/integration_reference/integration_reference.go: -------------------------------------------------------------------------------- 1 | package integration_reference 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // IntegrationReference holds the reference to a particular integration 9 | type IntegrationReference struct { 10 | ID int 11 | IntegrationType string 12 | } 13 | 14 | func (ir IntegrationReference) String() string { 15 | return fmt.Sprintf("%s:%d", ir.IntegrationType, ir.ID) 16 | } 17 | 18 | func (ir IntegrationReference) CacheKey(path ...string) string { 19 | if len(path) == 0 { 20 | return ir.String() 21 | } 22 | return fmt.Sprintf("%s:%s", ir.String(), strings.Join(path, ":")) 23 | } 24 | -------------------------------------------------------------------------------- /.github/workflows/sync-tag.yml: -------------------------------------------------------------------------------- 1 | name: sync tag 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || github.actor_id }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | trigger_sync_tag: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Trigger release tag sync 17 | uses: benc-uk/workflow-dispatch@v1 18 | with: 19 | workflow: sync-tag.yml 20 | ref: main 21 | repo: ${{ secrets.UPSTREAM_REPO }} 22 | token: ${{ secrets.NC_GITHUB_TOKEN }} 23 | inputs: '{ "tag": "${{ github.ref_name }}" }' -------------------------------------------------------------------------------- /client/server/log.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/netbirdio/netbird/client/proto" 7 | ) 8 | 9 | func ParseLogLevel(level string) proto.LogLevel { 10 | switch strings.ToLower(level) { 11 | case "panic": 12 | return proto.LogLevel_PANIC 13 | case "fatal": 14 | return proto.LogLevel_FATAL 15 | case "error": 16 | return proto.LogLevel_ERROR 17 | case "warn": 18 | return proto.LogLevel_WARN 19 | case "info": 20 | return proto.LogLevel_INFO 21 | case "debug": 22 | return proto.LogLevel_DEBUG 23 | case "trace": 24 | return proto.LogLevel_TRACE 25 | default: 26 | return proto.LogLevel_UNKNOWN 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /client/system/info_windows_test.go: -------------------------------------------------------------------------------- 1 | package system 2 | 3 | import ( 4 | "testing" 5 | 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | func Test_sysInfo(t *testing.T) { 10 | serialNum, err := sysNumber() 11 | if err != nil { 12 | t.Errorf("failed to get system serial number: %s", err) 13 | } 14 | 15 | prodName, err := sysProductName() 16 | if err != nil { 17 | t.Errorf("failed to get system product name: %s", err) 18 | } 19 | 20 | manufacturer, err := sysManufacturer() 21 | if err != nil { 22 | t.Errorf("failed to get system manufacturer: %s", err) 23 | } 24 | log.Infof("Windows sys info: %s, %s, %s", serialNum, prodName, manufacturer) 25 | } 26 | -------------------------------------------------------------------------------- /client/internal/dns/unclean_shutdown_windows.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type ShutdownState struct { 8 | Guid string 9 | GPO bool 10 | NRPTEntryCount int 11 | } 12 | 13 | func (s *ShutdownState) Name() string { 14 | return "dns_state" 15 | } 16 | 17 | func (s *ShutdownState) Cleanup() error { 18 | manager := ®istryConfigurator{ 19 | guid: s.Guid, 20 | gpo: s.GPO, 21 | nrptEntryCount: s.NRPTEntryCount, 22 | } 23 | 24 | if err := manager.restoreUncleanShutdownDNS(); err != nil { 25 | return fmt.Errorf("restore unclean shutdown dns: %w", err) 26 | } 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /client/ui/quickactions_assets.go: -------------------------------------------------------------------------------- 1 | // auto-generated 2 | // Code generated by '$ fyne bundle'. DO NOT EDIT. 3 | 4 | package main 5 | 6 | import ( 7 | _ "embed" 8 | "fyne.io/fyne/v2" 9 | ) 10 | 11 | //go:embed assets/connected.png 12 | var resourceConnectedPngData []byte 13 | var resourceConnectedPng = &fyne.StaticResource{ 14 | StaticName: "assets/connected.png", 15 | StaticContent: resourceConnectedPngData, 16 | } 17 | 18 | //go:embed assets/disconnected.png 19 | var resourceDisconnectedPngData []byte 20 | var resourceDisconnectedPng = &fyne.StaticResource{ 21 | StaticName: "assets/disconnected.png", 22 | StaticContent: resourceDisconnectedPngData, 23 | } 24 | -------------------------------------------------------------------------------- /client/iface/udpmux/mux_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !ios 2 | 3 | package udpmux 4 | 5 | import ( 6 | nbnet "github.com/netbirdio/netbird/client/net" 7 | ) 8 | 9 | func (m *SingleSocketUDPMux) notifyAddressRemoval(addr string) { 10 | // Kernel mode: direct nbnet.PacketConn (SharedSocket wrapped with nbnet) 11 | if conn, ok := m.params.UDPConn.(*nbnet.PacketConn); ok { 12 | conn.RemoveAddress(addr) 13 | return 14 | } 15 | 16 | // Userspace mode: UDPConn wrapper around nbnet.PacketConn 17 | if wrapped, ok := m.params.UDPConn.(*UDPConn); ok { 18 | if conn, ok := wrapped.GetPacketConn().(*nbnet.PacketConn); ok { 19 | conn.RemoveAddress(addr) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /client/internal/dns/host_android.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/client/internal/statemanager" 5 | ) 6 | 7 | type androidHostManager struct { 8 | } 9 | 10 | func newHostManager() (*androidHostManager, error) { 11 | return &androidHostManager{}, nil 12 | } 13 | 14 | func (a androidHostManager) applyDNSConfig(HostDNSConfig, *statemanager.Manager) error { 15 | return nil 16 | } 17 | 18 | func (a androidHostManager) restoreHostDNS() error { 19 | return nil 20 | } 21 | 22 | func (a androidHostManager) supportCustomPort() bool { 23 | return false 24 | } 25 | 26 | func (a androidHostManager) string() string { 27 | return "none" 28 | } 29 | -------------------------------------------------------------------------------- /client/internal/stdnet/listener.go: -------------------------------------------------------------------------------- 1 | package stdnet 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | "github.com/pion/transport/v3" 8 | 9 | nbnet "github.com/netbirdio/netbird/client/net" 10 | ) 11 | 12 | // ListenPacket listens for incoming packets on the given network and address. 13 | func (n *Net) ListenPacket(network, address string) (net.PacketConn, error) { 14 | return nbnet.NewListener().ListenPacket(context.Background(), network, address) 15 | } 16 | 17 | // ListenUDP acts like ListenPacket for UDP networks. 18 | func (n *Net) ListenUDP(network string, locAddr *net.UDPAddr) (transport.UDPConn, error) { 19 | return nbnet.ListenUDP(network, locAddr) 20 | } 21 | -------------------------------------------------------------------------------- /client/internal/peer/conn_status_test.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestConnStatus_String(t *testing.T) { 10 | 11 | tables := []struct { 12 | name string 13 | status ConnStatus 14 | want string 15 | }{ 16 | {"StatusConnected", StatusConnected, "Connected"}, 17 | {"StatusIdle", StatusIdle, "Idle"}, 18 | {"StatusConnecting", StatusConnecting, "Connecting"}, 19 | } 20 | 21 | for _, table := range tables { 22 | t.Run(table.name, func(t *testing.T) { 23 | got := table.status.String() 24 | assert.Equal(t, got, table.want, "they should be equal") 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /client/iface/bind/activity_test.go: -------------------------------------------------------------------------------- 1 | package bind 2 | 3 | import ( 4 | "net/netip" 5 | "testing" 6 | "time" 7 | 8 | "github.com/netbirdio/netbird/monotime" 9 | ) 10 | 11 | func TestActivityRecorder_GetLastActivities(t *testing.T) { 12 | peer := "peer1" 13 | ar := NewActivityRecorder() 14 | ar.UpsertAddress("peer1", netip.MustParseAddrPort("192.168.0.5:51820")) 15 | activities := ar.GetLastActivities() 16 | 17 | p, ok := activities[peer] 18 | if !ok { 19 | t.Fatalf("Expected activity for peer %s, but got none", peer) 20 | } 21 | 22 | if monotime.Since(p) > 5*time.Second { 23 | t.Fatalf("Expected activity for peer %s to be recent, but got %v", peer, p) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/iface/wgproxy/factory_usp.go: -------------------------------------------------------------------------------- 1 | package wgproxy 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | 6 | proxyBind "github.com/netbirdio/netbird/client/iface/wgproxy/bind" 7 | ) 8 | 9 | type USPFactory struct { 10 | bind proxyBind.Bind 11 | mtu uint16 12 | } 13 | 14 | func NewUSPFactory(bind proxyBind.Bind, mtu uint16) *USPFactory { 15 | log.Infof("WireGuard Proxy Factory will produce bind proxy") 16 | f := &USPFactory{ 17 | bind: bind, 18 | mtu: mtu, 19 | } 20 | return f 21 | } 22 | 23 | func (w *USPFactory) GetProxy() Proxy { 24 | return proxyBind.NewProxyBind(w.bind, w.mtu) 25 | } 26 | 27 | func (w *USPFactory) Free() error { 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /client/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Netbird application 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /client/net/env_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !windows && !android 2 | 3 | package net 4 | 5 | // Init initializes the network environment (no-op on non-Linux/Windows platforms) 6 | func Init() { 7 | // No-op on non-Linux/Windows platforms 8 | } 9 | 10 | // AdvancedRouting returns false on non-Linux/Windows platforms 11 | func AdvancedRouting() bool { 12 | return false 13 | } 14 | 15 | // SetVPNInterfaceName is a no-op on non-Windows platforms 16 | func SetVPNInterfaceName(name string) { 17 | // No-op on non-Windows platforms 18 | } 19 | 20 | // GetVPNInterfaceName returns empty string on non-Windows platforms 21 | func GetVPNInterfaceName() string { 22 | return "" 23 | } 24 | -------------------------------------------------------------------------------- /client/ssh/server/session_handlers_js.go: -------------------------------------------------------------------------------- 1 | //go:build js 2 | 3 | package server 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/gliderlabs/ssh" 9 | log "github.com/sirupsen/logrus" 10 | ) 11 | 12 | // handlePty is not supported on JS/WASM 13 | func (s *Server) handlePty(logger *log.Entry, session ssh.Session, _ PrivilegeCheckResult, _ ssh.Pty, _ <-chan ssh.Window) bool { 14 | errorMsg := "PTY sessions are not supported on WASM/JS platform\n" 15 | if _, err := fmt.Fprint(session.Stderr(), errorMsg); err != nil { 16 | logger.Debugf(errWriteSession, err) 17 | } 18 | if err := session.Exit(1); err != nil { 19 | logSessionExitError(logger, err) 20 | } 21 | return false 22 | } 23 | -------------------------------------------------------------------------------- /client/cmd/pprof.go: -------------------------------------------------------------------------------- 1 | //go:build pprof 2 | // +build pprof 3 | 4 | package cmd 5 | 6 | import ( 7 | "net/http" 8 | _ "net/http/pprof" 9 | "os" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func init() { 15 | addr := pprofAddr() 16 | go pprof(addr) 17 | } 18 | 19 | func pprofAddr() string { 20 | listenAddr := os.Getenv("NB_PPROF_ADDR") 21 | if listenAddr == "" { 22 | return "localhost:6969" 23 | } 24 | 25 | return listenAddr 26 | } 27 | 28 | func pprof(listenAddr string) { 29 | log.Infof("listening pprof on: %s\n", listenAddr) 30 | if err := http.ListenAndServe(listenAddr, nil); err != nil { 31 | log.Fatalf("Failed to start pprof: %v", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /client/errors/errors.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/hashicorp/go-multierror" 8 | ) 9 | 10 | func formatError(es []error) string { 11 | if len(es) == 1 { 12 | return fmt.Sprintf("1 error occurred:\n\t* %s", es[0]) 13 | } 14 | 15 | points := make([]string, len(es)) 16 | for i, err := range es { 17 | points[i] = fmt.Sprintf("* %s", err) 18 | } 19 | 20 | return fmt.Sprintf( 21 | "%d errors occurred:\n\t%s", 22 | len(es), strings.Join(points, "\n\t")) 23 | } 24 | 25 | func FormatErrorOrNil(err *multierror.Error) error { 26 | if err != nil { 27 | err.ErrorFormat = formatError 28 | } 29 | return err.ErrorOrNil() 30 | } 31 | -------------------------------------------------------------------------------- /relay/cmd/pprof.go: -------------------------------------------------------------------------------- 1 | //go:build pprof 2 | // +build pprof 3 | 4 | package cmd 5 | 6 | import ( 7 | "net/http" 8 | _ "net/http/pprof" 9 | "os" 10 | 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func init() { 15 | addr := pprofAddr() 16 | go pprof(addr) 17 | } 18 | 19 | func pprofAddr() string { 20 | listenAddr := os.Getenv("NB_PPROF_ADDR") 21 | if listenAddr == "" { 22 | return "localhost:6969" 23 | } 24 | 25 | return listenAddr 26 | } 27 | 28 | func pprof(listenAddr string) { 29 | log.Infof("listening pprof on: %s\n", listenAddr) 30 | if err := http.ListenAndServe(listenAddr, nil); err != nil { 31 | log.Fatalf("Failed to start pprof: %v", err) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /client/ui/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | Netbird UI application 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /management/cmd/defaults.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | const ( 4 | defaultMgmtDataDir = "/var/lib/netbird/" 5 | defaultMgmtConfigDir = "/etc/netbird" 6 | defaultLogDir = "/var/log/netbird" 7 | 8 | oldDefaultMgmtDataDir = "/var/lib/wiretrustee/" 9 | oldDefaultMgmtConfigDir = "/etc/wiretrustee" 10 | oldDefaultLogDir = "/var/log/wiretrustee" 11 | 12 | defaultMgmtConfig = defaultMgmtConfigDir + "/management.json" 13 | defaultLogFile = defaultLogDir + "/management.log" 14 | oldDefaultMgmtConfig = oldDefaultMgmtConfigDir + "/management.json" 15 | oldDefaultLogFile = oldDefaultLogDir + "/management.log" 16 | 17 | defaultSingleAccModeDomain = "netbird.selfhosted" 18 | ) 19 | -------------------------------------------------------------------------------- /client/internal/debug/debug_unix.go: -------------------------------------------------------------------------------- 1 | //go:build unix && !android 2 | 3 | package debug 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | const resolvConfPath = "/etc/resolv.conf" 12 | 13 | func (g *BundleGenerator) addResolvConf() error { 14 | data, err := os.ReadFile(resolvConfPath) 15 | if err != nil { 16 | return fmt.Errorf("read %s: %w", resolvConfPath, err) 17 | } 18 | 19 | content := string(data) 20 | if g.anonymize { 21 | content = g.anonymizer.AnonymizeString(content) 22 | } 23 | 24 | if err := g.addFileToZip(strings.NewReader(content), "resolv.conf"); err != nil { 25 | return fmt.Errorf("add resolv.conf to zip: %w", err) 26 | } 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /client/iface/wgaddr/address.go: -------------------------------------------------------------------------------- 1 | package wgaddr 2 | 3 | import ( 4 | "fmt" 5 | "net/netip" 6 | ) 7 | 8 | // Address WireGuard parsed address 9 | type Address struct { 10 | IP netip.Addr 11 | Network netip.Prefix 12 | } 13 | 14 | // ParseWGAddress parse a string ("1.2.3.4/24") address to WG Address 15 | func ParseWGAddress(address string) (Address, error) { 16 | prefix, err := netip.ParsePrefix(address) 17 | if err != nil { 18 | return Address{}, err 19 | } 20 | return Address{ 21 | IP: prefix.Addr().Unmap(), 22 | Network: prefix.Masked(), 23 | }, nil 24 | } 25 | 26 | func (addr Address) String() string { 27 | return fmt.Sprintf("%s/%d", addr.IP.String(), addr.Network.Bits()) 28 | } 29 | -------------------------------------------------------------------------------- /client/internal/stdnet/discover_pion.go: -------------------------------------------------------------------------------- 1 | package stdnet 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/pion/transport/v3" 7 | ) 8 | 9 | type pionDiscover struct { 10 | } 11 | 12 | func (d pionDiscover) iFaces() ([]*transport.Interface, error) { 13 | ifs := []*transport.Interface{} 14 | 15 | oifs, err := net.Interfaces() 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | for _, oif := range oifs { 21 | ifc := transport.NewInterface(oif) 22 | 23 | addrs, err := oif.Addrs() 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | for _, addr := range addrs { 29 | ifc.AddAddress(addr) 30 | } 31 | 32 | ifs = append(ifs, ifc) 33 | } 34 | 35 | return ifs, nil 36 | } 37 | -------------------------------------------------------------------------------- /client/internal/updatemanager/reposign/signature.go: -------------------------------------------------------------------------------- 1 | package reposign 2 | 3 | import ( 4 | "encoding/json" 5 | "time" 6 | ) 7 | 8 | // Signature contains a signature with associated Metadata 9 | type Signature struct { 10 | Signature []byte `json:"signature"` 11 | Timestamp time.Time `json:"timestamp"` 12 | KeyID KeyID `json:"key_id"` 13 | Algorithm string `json:"algorithm"` // "ed25519" 14 | HashAlgo string `json:"hash_algo"` // "blake2s" or sha512 15 | } 16 | 17 | func ParseSignature(data []byte) (*Signature, error) { 18 | var signature Signature 19 | if err := json.Unmarshal(data, &signature); err != nil { 20 | return nil, err 21 | } 22 | 23 | return &signature, nil 24 | } 25 | -------------------------------------------------------------------------------- /client/iface/wgproxy/ebpf/portlookup.go: -------------------------------------------------------------------------------- 1 | package ebpf 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | var ( 9 | portRangeStart = 3128 10 | portRangeEnd = portRangeStart + 100 11 | ) 12 | 13 | type portLookup struct { 14 | } 15 | 16 | func (pl portLookup) searchFreePort() (int, error) { 17 | for i := portRangeStart; i <= portRangeEnd; i++ { 18 | if pl.tryToBind(i) == nil { 19 | return i, nil 20 | } 21 | } 22 | return 0, fmt.Errorf("failed to bind free port for eBPF proxy") 23 | } 24 | 25 | func (pl portLookup) tryToBind(port int) error { 26 | l, err := net.ListenPacket("udp", fmt.Sprintf(":%d", port)) 27 | if err != nil { 28 | return err 29 | } 30 | _ = l.Close() 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /client/internal/dns/unclean_shutdown_darwin.go: -------------------------------------------------------------------------------- 1 | //go:build !ios 2 | 3 | package dns 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | type ShutdownState struct { 10 | CreatedKeys []string 11 | } 12 | 13 | func (s *ShutdownState) Name() string { 14 | return "dns_state" 15 | } 16 | 17 | func (s *ShutdownState) Cleanup() error { 18 | manager, err := newHostManager() 19 | if err != nil { 20 | return fmt.Errorf("create host manager: %w", err) 21 | } 22 | 23 | for _, key := range s.CreatedKeys { 24 | manager.createdKeys[key] = struct{}{} 25 | } 26 | 27 | if err := manager.restoreUncleanShutdownDNS(); err != nil { 28 | return fmt.Errorf("restore unclean shutdown dns: %w", err) 29 | } 30 | 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /client/internal/peer/iface.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | import ( 4 | "net" 5 | "net/netip" 6 | "time" 7 | 8 | "golang.zx2c4.com/wireguard/wgctrl/wgtypes" 9 | 10 | "github.com/netbirdio/netbird/client/iface/configurer" 11 | "github.com/netbirdio/netbird/client/iface/wgaddr" 12 | "github.com/netbirdio/netbird/client/iface/wgproxy" 13 | ) 14 | 15 | type WGIface interface { 16 | UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error 17 | RemovePeer(peerKey string) error 18 | GetStats() (map[string]configurer.WGStats, error) 19 | GetProxy() wgproxy.Proxy 20 | Address() wgaddr.Address 21 | RemoveEndpointAddress(key string) error 22 | } 23 | -------------------------------------------------------------------------------- /shared/management/client/rest/events.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/netbirdio/netbird/shared/management/http/api" 7 | ) 8 | 9 | // EventsAPI APIs for Events, do not use directly 10 | type EventsAPI struct { 11 | c *Client 12 | } 13 | 14 | // List list all events 15 | // See more: https://docs.netbird.io/api/resources/events#list-all-events 16 | func (a *EventsAPI) List(ctx context.Context) ([]api.Event, error) { 17 | resp, err := a.c.NewRequest(ctx, "GET", "/api/events", nil, nil) 18 | if err != nil { 19 | return nil, err 20 | } 21 | if resp.Body != nil { 22 | defer resp.Body.Close() 23 | } 24 | ret, err := parseResponse[[]api.Event](resp) 25 | return ret, err 26 | } 27 | -------------------------------------------------------------------------------- /client/android/exec.go: -------------------------------------------------------------------------------- 1 | //go:build android 2 | 3 | package android 4 | 5 | import ( 6 | "fmt" 7 | _ "unsafe" 8 | ) 9 | 10 | // https://github.com/golang/go/pull/69543/commits/aad6b3b32c81795f86bc4a9e81aad94899daf520 11 | // In Android version 11 and earlier, pidfd-related system calls 12 | // are not allowed by the seccomp policy, which causes crashes due 13 | // to SIGSYS signals. 14 | 15 | //go:linkname checkPidfdOnce os.checkPidfdOnce 16 | var checkPidfdOnce func() error 17 | 18 | func execWorkaround(androidSDKVersion int) { 19 | if androidSDKVersion > 30 { // above Android 11 20 | return 21 | } 22 | 23 | checkPidfdOnce = func() error { 24 | return fmt.Errorf("unsupported Android version") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /shared/relay/auth/hmac/v2/algo.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import ( 4 | "crypto/sha256" 5 | "hash" 6 | ) 7 | 8 | const ( 9 | AuthAlgoUnknown AuthAlgo = iota 10 | AuthAlgoHMACSHA256 11 | ) 12 | 13 | type AuthAlgo uint8 14 | 15 | func (a AuthAlgo) String() string { 16 | switch a { 17 | case AuthAlgoHMACSHA256: 18 | return "HMAC-SHA256" 19 | default: 20 | return "Unknown" 21 | } 22 | } 23 | 24 | func (a AuthAlgo) New() func() hash.Hash { 25 | switch a { 26 | case AuthAlgoHMACSHA256: 27 | return sha256.New 28 | default: 29 | return nil 30 | } 31 | } 32 | 33 | func (a AuthAlgo) Size() int { 34 | switch a { 35 | case AuthAlgoHMACSHA256: 36 | return sha256.Size 37 | default: 38 | return 0 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /version/url_windows.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "golang.org/x/sys/windows/registry" 5 | "runtime" 6 | ) 7 | 8 | const ( 9 | urlWinExe = "https://pkgs.netbird.io/windows/x64" 10 | urlWinExeArm = "https://pkgs.netbird.io/windows/arm64" 11 | ) 12 | 13 | var regKeyAppPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Netbird" 14 | 15 | // DownloadUrl return with the proper download link 16 | func DownloadUrl() string { 17 | _, err := registry.OpenKey(registry.LOCAL_MACHINE, regKeyAppPath, registry.QUERY_VALUE) 18 | if err != nil { 19 | return downloadURL 20 | } 21 | 22 | url := urlWinExe 23 | if runtime.GOARCH == "arm64" { 24 | url = urlWinExeArm 25 | } 26 | 27 | return url 28 | } 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: ['feature-request'] 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /client/android/networks.go: -------------------------------------------------------------------------------- 1 | //go:build android 2 | 3 | package android 4 | 5 | type Network struct { 6 | Name string 7 | Network string 8 | Peer string 9 | Status string 10 | IsSelected bool 11 | Domains NetworkDomains 12 | } 13 | 14 | func (n Network) GetNetworkDomains() *NetworkDomains { 15 | return &n.Domains 16 | } 17 | 18 | type NetworkArray struct { 19 | items []Network 20 | } 21 | 22 | func (array *NetworkArray) Add(s Network) *NetworkArray { 23 | array.items = append(array.items, s) 24 | return array 25 | } 26 | 27 | func (array *NetworkArray) Get(i int) *Network { 28 | return &array.items[i] 29 | } 30 | 31 | func (array *NetworkArray) Size() int { 32 | return len(array.items) 33 | } 34 | -------------------------------------------------------------------------------- /client/net/env_android.go: -------------------------------------------------------------------------------- 1 | //go:build android 2 | 3 | package net 4 | 5 | // Init initializes the network environment for Android 6 | func Init() { 7 | // No initialization needed on Android 8 | } 9 | 10 | // AdvancedRouting reports whether routing loops can be avoided without using exclusion routes. 11 | // Always returns true on Android since we cannot handle routes dynamically. 12 | func AdvancedRouting() bool { 13 | return true 14 | } 15 | 16 | // SetVPNInterfaceName is a no-op on Android 17 | func SetVPNInterfaceName(name string) { 18 | // No-op on Android - not needed for Android VPN service 19 | } 20 | 21 | // GetVPNInterfaceName returns empty string on Android 22 | func GetVPNInterfaceName() string { 23 | return "" 24 | } 25 | -------------------------------------------------------------------------------- /shared/auth/user.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type UserAuth struct { 8 | // The account id the user is accessing 9 | AccountId string 10 | // The account domain 11 | Domain string 12 | // The account domain category, TBC values 13 | DomainCategory string 14 | // Indicates whether this user was invited, TBC logic 15 | Invited bool 16 | // Indicates whether this is a child account 17 | IsChild bool 18 | 19 | // The user id 20 | UserId string 21 | // Last login time for this user 22 | LastLogin time.Time 23 | // The Groups the user belongs to on this account 24 | Groups []string 25 | 26 | // Indicates whether this user has authenticated with a Personal Access Token 27 | IsPAT bool 28 | } 29 | -------------------------------------------------------------------------------- /shared/relay/healthcheck/env.go: -------------------------------------------------------------------------------- 1 | package healthcheck 2 | 3 | import ( 4 | "os" 5 | "strconv" 6 | 7 | log "github.com/sirupsen/logrus" 8 | ) 9 | 10 | const ( 11 | defaultAttemptThresholdEnv = "NB_RELAY_HC_ATTEMPT_THRESHOLD" 12 | ) 13 | 14 | func getAttemptThresholdFromEnv() int { 15 | if attemptThreshold := os.Getenv(defaultAttemptThresholdEnv); attemptThreshold != "" { 16 | threshold, err := strconv.ParseInt(attemptThreshold, 10, 64) 17 | if err != nil { 18 | log.Errorf("Failed to parse attempt threshold from environment variable \"%s\" should be an integer. Using default value", attemptThreshold) 19 | return defaultAttemptThreshold 20 | } 21 | return int(threshold) 22 | } 23 | return defaultAttemptThreshold 24 | } 25 | -------------------------------------------------------------------------------- /client/internal/debug/debug_nonmobile.go: -------------------------------------------------------------------------------- 1 | //go:build !ios && !android 2 | 3 | package debug 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | 9 | "github.com/netbirdio/netbird/client/internal/routemanager/systemops" 10 | ) 11 | 12 | func (g *BundleGenerator) addRoutes() error { 13 | detailedRoutes, err := systemops.GetDetailedRoutesFromTable() 14 | if err != nil { 15 | return fmt.Errorf("get detailed routes: %w", err) 16 | } 17 | 18 | routesContent := formatRoutesTable(detailedRoutes, g.anonymize, g.anonymizer) 19 | routesReader := strings.NewReader(routesContent) 20 | if err := g.addFileToZip(routesReader, "routes.txt"); err != nil { 21 | return fmt.Errorf("add routes file to zip: %w", err) 22 | } 23 | 24 | return nil 25 | } 26 | -------------------------------------------------------------------------------- /version/url_darwin.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "os/exec" 5 | "runtime" 6 | ) 7 | 8 | const ( 9 | urlMacIntel = "https://pkgs.netbird.io/macos/amd64" 10 | urlMacM1M2 = "https://pkgs.netbird.io/macos/arm64" 11 | ) 12 | 13 | // DownloadUrl return with the proper download link 14 | func DownloadUrl() string { 15 | cmd := exec.Command("brew", "list --formula | grep -i netbird") 16 | if err := cmd.Start(); err != nil { 17 | goto PKGINSTALL 18 | } 19 | 20 | if err := cmd.Wait(); err == nil { 21 | return downloadURL 22 | } 23 | 24 | PKGINSTALL: 25 | switch runtime.GOARCH { 26 | case "amd64": 27 | return urlMacIntel 28 | case "arm64": 29 | return urlMacM1M2 30 | default: 31 | return downloadURL 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /shared/relay/client/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package client contains the implementation of the Relay client. 3 | 4 | The Relay client is responsible for establishing a connection with the Relay server and sending and receiving messages, 5 | Keep persistent connection with the Relay server and handle the connection issues. 6 | It uses the WebSocket protocol for communication and optionally supports TLS (Transport Layer Security). 7 | 8 | If a peer wants to communicate with a peer on a different relay server, the manager will establish a new connection to 9 | the relay server. The connection with these relay servers will be closed if there is no active connection. The peers 10 | negotiate the common relay instance via signaling service. 11 | */ 12 | package client 13 | -------------------------------------------------------------------------------- /management/server/permissions/roles/admin.go: -------------------------------------------------------------------------------- 1 | package roles 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/permissions/modules" 5 | "github.com/netbirdio/netbird/management/server/permissions/operations" 6 | "github.com/netbirdio/netbird/management/server/types" 7 | ) 8 | 9 | var Admin = RolePermissions{ 10 | Role: types.UserRoleAdmin, 11 | AutoAllowNew: map[operations.Operation]bool{ 12 | operations.Read: true, 13 | operations.Create: true, 14 | operations.Update: true, 15 | operations.Delete: true, 16 | }, 17 | Permissions: Permissions{ 18 | modules.Accounts: { 19 | operations.Read: true, 20 | operations.Create: false, 21 | operations.Update: false, 22 | operations.Delete: false, 23 | }, 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /formatter/syslog/formatter_test.go: -------------------------------------------------------------------------------- 1 | package syslog 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/sirupsen/logrus" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestLogSyslogFormat(t *testing.T) { 12 | 13 | someEntry := &logrus.Entry{ 14 | Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, 15 | Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), 16 | Level: 3, 17 | Message: "Some Message", 18 | } 19 | 20 | formatter := NewSyslogFormatter() 21 | result, _ := formatter.Format(someEntry) 22 | 23 | parsedString := string(result) 24 | expectedString := "^\\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] Some Message\\s+$" 25 | assert.Regexp(t, expectedString, parsedString) 26 | } 27 | -------------------------------------------------------------------------------- /shared/relay/tls/client_dev.go: -------------------------------------------------------------------------------- 1 | //go:build devcert 2 | 3 | package tls 4 | 5 | import ( 6 | "crypto/tls" 7 | "crypto/x509" 8 | 9 | log "github.com/sirupsen/logrus" 10 | 11 | "github.com/netbirdio/netbird/util/embeddedroots" 12 | ) 13 | 14 | func ClientQUICTLSConfig() *tls.Config { 15 | certPool, err := x509.SystemCertPool() 16 | if err != nil || certPool == nil { 17 | log.Debugf("System cert pool not available; falling back to embedded cert, error: %v", err) 18 | certPool = embeddedroots.Get() 19 | } 20 | 21 | return &tls.Config{ 22 | InsecureSkipVerify: true, // Debug mode allows insecure connections 23 | NextProtos: []string{NBalpn}, // Ensure this matches the server's ALPN 24 | RootCAs: certPool, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /client/server/state_linux.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package server 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/client/firewall/iptables" 7 | "github.com/netbirdio/netbird/client/firewall/nftables" 8 | "github.com/netbirdio/netbird/client/internal/dns" 9 | "github.com/netbirdio/netbird/client/internal/routemanager/systemops" 10 | "github.com/netbirdio/netbird/client/internal/statemanager" 11 | "github.com/netbirdio/netbird/client/ssh/config" 12 | ) 13 | 14 | func registerStates(mgr *statemanager.Manager) { 15 | mgr.RegisterState(&dns.ShutdownState{}) 16 | mgr.RegisterState(&systemops.ShutdownState{}) 17 | mgr.RegisterState(&nftables.ShutdownState{}) 18 | mgr.RegisterState(&iptables.ShutdownState{}) 19 | mgr.RegisterState(&config.ShutdownState{}) 20 | } 21 | -------------------------------------------------------------------------------- /client/android/dns_list_test.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import "testing" 4 | 5 | func TestDNSList_Get(t *testing.T) { 6 | l := DNSList{} 7 | 8 | // Add a valid DNS address 9 | err := l.Add("8.8.8.8") 10 | if err != nil { 11 | t.Errorf("unexpected error: %s", err) 12 | } 13 | 14 | // Test getting valid index 15 | addr, err := l.Get(0) 16 | if err != nil { 17 | t.Errorf("invalid error: %s", err) 18 | } 19 | if addr != "8.8.8.8" { 20 | t.Errorf("expected 8.8.8.8, got %s", addr) 21 | } 22 | 23 | // Test negative index 24 | _, err = l.Get(-1) 25 | if err == nil { 26 | t.Errorf("expected error but got nil") 27 | } 28 | 29 | // Test out of bounds index 30 | _, err = l.Get(1) 31 | if err == nil { 32 | t.Errorf("expected error but got nil") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /client/iface/netstack/dialer.go: -------------------------------------------------------------------------------- 1 | package netstack 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | log "github.com/sirupsen/logrus" 8 | "golang.zx2c4.com/wireguard/tun/netstack" 9 | ) 10 | 11 | type Dialer interface { 12 | Dial(ctx context.Context, network, addr string) (net.Conn, error) 13 | } 14 | 15 | type NSDialer struct { 16 | net *netstack.Net 17 | } 18 | 19 | func NewNSDialer(net *netstack.Net) *NSDialer { 20 | return &NSDialer{ 21 | net: net, 22 | } 23 | } 24 | 25 | func (d *NSDialer) Dial(ctx context.Context, network, addr string) (net.Conn, error) { 26 | log.Debugf("dialing %s %s", network, addr) 27 | conn, err := d.net.Dial(network, addr) 28 | if err != nil { 29 | log.Debugf("failed to deal connection: %s", err) 30 | } 31 | return conn, err 32 | } 33 | -------------------------------------------------------------------------------- /formatter/txt/formatter.go: -------------------------------------------------------------------------------- 1 | package txt 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/sirupsen/logrus" 7 | 8 | "github.com/netbirdio/netbird/formatter/levels" 9 | ) 10 | 11 | // TextFormatter formats logs into text with included source code's path 12 | type TextFormatter struct { 13 | timestampFormat string 14 | levelDesc []string 15 | } 16 | 17 | // NewTextFormatter create new MyTextFormatter instance 18 | func NewTextFormatter() *TextFormatter { 19 | return &TextFormatter{ 20 | levelDesc: levels.ValidLevelDesc, 21 | timestampFormat: time.RFC3339, // or RFC3339 22 | } 23 | } 24 | 25 | func (f *TextFormatter) parseLevel(level logrus.Level) string { 26 | if len(f.levelDesc) < int(level) { 27 | return "" 28 | } 29 | 30 | return f.levelDesc[level] 31 | } 32 | -------------------------------------------------------------------------------- /client/iface/device.go: -------------------------------------------------------------------------------- 1 | //go:build !android 2 | 3 | package iface 4 | 5 | import ( 6 | "golang.zx2c4.com/wireguard/tun/netstack" 7 | 8 | wgdevice "golang.zx2c4.com/wireguard/device" 9 | 10 | "github.com/netbirdio/netbird/client/iface/device" 11 | "github.com/netbirdio/netbird/client/iface/udpmux" 12 | "github.com/netbirdio/netbird/client/iface/wgaddr" 13 | ) 14 | 15 | type WGTunDevice interface { 16 | Create() (device.WGConfigurer, error) 17 | Up() (*udpmux.UniversalUDPMuxDefault, error) 18 | UpdateAddr(address wgaddr.Address) error 19 | WgAddress() wgaddr.Address 20 | MTU() uint16 21 | DeviceName() string 22 | Close() error 23 | FilteredDevice() *device.FilteredDevice 24 | Device() *wgdevice.Device 25 | GetNet() *netstack.Net 26 | GetICEBind() device.EndpointManager 27 | } 28 | -------------------------------------------------------------------------------- /shared/relay/client/dialers_generic.go: -------------------------------------------------------------------------------- 1 | //go:build !js 2 | 3 | package client 4 | 5 | import ( 6 | "github.com/netbirdio/netbird/client/iface" 7 | "github.com/netbirdio/netbird/shared/relay/client/dialer" 8 | "github.com/netbirdio/netbird/shared/relay/client/dialer/quic" 9 | "github.com/netbirdio/netbird/shared/relay/client/dialer/ws" 10 | ) 11 | 12 | // getDialers returns the list of dialers to use for connecting to the relay server. 13 | func (c *Client) getDialers() []dialer.DialeFn { 14 | if c.mtu > 0 && c.mtu > iface.DefaultMTU { 15 | c.log.Infof("MTU %d exceeds default (%d), forcing WebSocket transport to avoid DATAGRAM frame size issues", c.mtu, iface.DefaultMTU) 16 | return []dialer.DialeFn{ws.Dialer{}} 17 | } 18 | return []dialer.DialeFn{quic.Dialer{}, ws.Dialer{}} 19 | } 20 | -------------------------------------------------------------------------------- /util/retry.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | // Retry retries a given toExec function calling onError on failed attempts 9 | // onError shouldn be a lightweight function and shouldn't be blocking 10 | func Retry(attempts int, sleep time.Duration, toExec func() error, onError func(e error)) error { 11 | if err := toExec(); err != nil { 12 | if s, ok := err.(stop); ok { 13 | return s.error 14 | } 15 | 16 | if attempts--; attempts > 0 { 17 | jitter := time.Duration(rand.Int63n(int64(sleep))) 18 | sleep += jitter / 2 19 | 20 | onError(err) 21 | time.Sleep(sleep) 22 | return Retry(attempts, 2*sleep, toExec, onError) 23 | } 24 | return err 25 | } 26 | 27 | return nil 28 | } 29 | 30 | type stop struct { 31 | error 32 | } 33 | -------------------------------------------------------------------------------- /relay/doc.go: -------------------------------------------------------------------------------- 1 | //Package main 2 | /* 3 | The `relay` package contains the implementation of the Relay server and client. The Relay server can be used to relay 4 | messages between peers on a single network channel. In this implementation the transport layer is the WebSocket 5 | protocol. 6 | 7 | Between the server and client communication has been design a custom protocol and message format. These messages are 8 | transported over the WebSocket connection. Optionally the server can use TLS to secure the communication. 9 | 10 | The service can support multiple Relay server instances. For this purpose the peers must know the server instance URL. 11 | This URL will be sent to the target peer to choose the common Relay server for the communication via Signal service. 12 | 13 | */ 14 | package main 15 | -------------------------------------------------------------------------------- /shared/relay/auth/hmac/validator.go: -------------------------------------------------------------------------------- 1 | package hmac 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | "time" 7 | 8 | log "github.com/sirupsen/logrus" 9 | ) 10 | 11 | type TimedHMACValidator struct { 12 | *TimedHMAC 13 | } 14 | 15 | func NewTimedHMACValidator(secret string, duration time.Duration) *TimedHMACValidator { 16 | ta := NewTimedHMAC(secret, duration) 17 | return &TimedHMACValidator{ 18 | ta, 19 | } 20 | } 21 | 22 | func (a *TimedHMACValidator) Validate(credentials any) error { 23 | b, ok := credentials.([]byte) 24 | if !ok { 25 | return fmt.Errorf("invalid credentials type") 26 | } 27 | c, err := unmarshalToken(b) 28 | if err != nil { 29 | log.Debugf("failed to unmarshal token: %s", err) 30 | return err 31 | } 32 | return a.TimedHMAC.Validate(sha256.New, c) 33 | } 34 | -------------------------------------------------------------------------------- /client/internal/ebpf/ebpf/src/readme.md: -------------------------------------------------------------------------------- 1 | # DNS forwarder 2 | 3 | The agent attach the XDP program to the lo device. We can not use fake address in eBPF because the 4 | traffic does not appear in the eBPF program. The program capture the traffic on wg_ip:53 and 5 | overwrite in it the destination port to 5053. 6 | 7 | # Debug 8 | 9 | The CONFIG_BPF_EVENTS kernel module is required for bpf_printk. 10 | Apply this code to use bpf_printk 11 | ``` 12 | #define bpf_printk(fmt, ...) \ 13 | ({ \ 14 | char ____fmt[] = fmt; \ 15 | bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \ 16 | }) 17 | ``` 18 | -------------------------------------------------------------------------------- /client/internal/sleep/service.go: -------------------------------------------------------------------------------- 1 | package sleep 2 | 3 | var ( 4 | EventTypeUnknown EventType = 0 5 | EventTypeSleep EventType = 1 6 | EventTypeWakeUp EventType = 2 7 | ) 8 | 9 | type EventType int 10 | 11 | type detector interface { 12 | Register(callback func(eventType EventType)) error 13 | Deregister() error 14 | } 15 | 16 | type Service struct { 17 | detector detector 18 | } 19 | 20 | func New() (*Service, error) { 21 | d, err := NewDetector() 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | return &Service{ 27 | detector: d, 28 | }, nil 29 | } 30 | 31 | func (s *Service) Register(callback func(eventType EventType)) error { 32 | return s.detector.Register(callback) 33 | } 34 | 35 | func (s *Service) Deregister() error { 36 | return s.detector.Deregister() 37 | } 38 | -------------------------------------------------------------------------------- /formatter/txt/formatter_test.go: -------------------------------------------------------------------------------- 1 | package txt 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/sirupsen/logrus" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestLogTextFormat(t *testing.T) { 12 | 13 | someEntry := &logrus.Entry{ 14 | Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, 15 | Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), 16 | Level: 3, 17 | Message: "Some Message", 18 | } 19 | 20 | formatter := NewTextFormatter() 21 | result, _ := formatter.Format(someEntry) 22 | 23 | parsedString := string(result) 24 | expectedString := "^2021-02-21T01:10:30Z WARN \\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] some/fancy/path.go:46: Some Message\\s+$" 25 | assert.Regexp(t, expectedString, parsedString) 26 | } 27 | -------------------------------------------------------------------------------- /client/system/static_info.go: -------------------------------------------------------------------------------- 1 | //go:build (linux && !android) || windows || (darwin && !ios) 2 | 3 | package system 4 | 5 | import ( 6 | "sync" 7 | ) 8 | 9 | var ( 10 | staticInfo StaticInfo 11 | once sync.Once 12 | ) 13 | 14 | // StaticInfo is an object that contains machine information that does not change 15 | type StaticInfo struct { 16 | SystemSerialNumber string 17 | SystemProductName string 18 | SystemManufacturer string 19 | Environment Environment 20 | 21 | // Windows specific fields 22 | OSName string 23 | OSVersion string 24 | BuildVersion string 25 | } 26 | 27 | func updateStaticInfo() { 28 | once.Do(func() { 29 | staticInfo = newStaticInfo() 30 | }) 31 | } 32 | 33 | func getStaticInfo() StaticInfo { 34 | updateStaticInfo() 35 | return staticInfo 36 | } 37 | -------------------------------------------------------------------------------- /management/server/permissions/roles/role_permissions.go: -------------------------------------------------------------------------------- 1 | package roles 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/management/server/permissions/modules" 5 | "github.com/netbirdio/netbird/management/server/permissions/operations" 6 | "github.com/netbirdio/netbird/management/server/types" 7 | ) 8 | 9 | type RolePermissions struct { 10 | Role types.UserRole 11 | Permissions Permissions 12 | AutoAllowNew map[operations.Operation]bool 13 | } 14 | 15 | type Permissions map[modules.Module]map[operations.Operation]bool 16 | 17 | var RolesMap = map[types.UserRole]RolePermissions{ 18 | types.UserRoleOwner: Owner, 19 | types.UserRoleAdmin: Admin, 20 | types.UserRoleUser: User, 21 | types.UserRoleAuditor: Auditor, 22 | types.UserRoleNetworkAdmin: NetworkAdmin, 23 | } 24 | -------------------------------------------------------------------------------- /shared/relay/client/picker_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestServerPicker_UnavailableServers(t *testing.T) { 11 | timeout := 5 * time.Second 12 | sp := ServerPicker{ 13 | TokenStore: nil, 14 | PeerID: "test", 15 | ConnectionTimeout: timeout, 16 | } 17 | sp.ServerURLs.Store([]string{"rel://dummy1", "rel://dummy2"}) 18 | 19 | ctx, cancel := context.WithTimeout(context.Background(), timeout+1) 20 | defer cancel() 21 | 22 | go func() { 23 | _, err := sp.PickServer(ctx) 24 | if err == nil { 25 | t.Error(err) 26 | } 27 | cancel() 28 | }() 29 | 30 | <-ctx.Done() 31 | if errors.Is(ctx.Err(), context.DeadlineExceeded) { 32 | t.Errorf("PickServer() took too long to complete") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /client/internal/stdnet/dialer.go: -------------------------------------------------------------------------------- 1 | package stdnet 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/pion/transport/v3" 7 | 8 | nbnet "github.com/netbirdio/netbird/client/net" 9 | ) 10 | 11 | // Dial connects to the address on the named network. 12 | func (n *Net) Dial(network, address string) (net.Conn, error) { 13 | return nbnet.NewDialer().Dial(network, address) 14 | } 15 | 16 | // DialUDP connects to the address on the named UDP network. 17 | func (n *Net) DialUDP(network string, laddr, raddr *net.UDPAddr) (transport.UDPConn, error) { 18 | return nbnet.DialUDP(network, laddr, raddr) 19 | } 20 | 21 | // DialTCP connects to the address on the named TCP network. 22 | func (n *Net) DialTCP(network string, laddr, raddr *net.TCPAddr) (transport.TCPConn, error) { 23 | return nbnet.DialTCP(network, laddr, raddr) 24 | } 25 | -------------------------------------------------------------------------------- /client/android/env_list.go: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | import "github.com/netbirdio/netbird/client/internal/peer" 4 | 5 | var ( 6 | // EnvKeyNBForceRelay Exported for Android java client 7 | EnvKeyNBForceRelay = peer.EnvKeyNBForceRelay 8 | ) 9 | 10 | // EnvList wraps a Go map for export to Java 11 | type EnvList struct { 12 | data map[string]string 13 | } 14 | 15 | // NewEnvList creates a new EnvList 16 | func NewEnvList() *EnvList { 17 | return &EnvList{data: make(map[string]string)} 18 | } 19 | 20 | // Put adds a key-value pair 21 | func (el *EnvList) Put(key, value string) { 22 | el.data[key] = value 23 | } 24 | 25 | // Get retrieves a value by key 26 | func (el *EnvList) Get(key string) string { 27 | return el.data[key] 28 | } 29 | 30 | func (el *EnvList) AllItems() map[string]string { 31 | return el.data 32 | } 33 | -------------------------------------------------------------------------------- /client/iface/device/kernel_module_freebsd.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | // WireGuardModuleIsLoaded check if kernel support wireguard 4 | func WireGuardModuleIsLoaded() bool { 5 | // Despite the fact FreeBSD natively support Wireguard (https://github.com/WireGuard/wireguard-freebsd) 6 | // we are currently do not use it, since it is required to add wireguard kernel support to 7 | // - https://github.com/netbirdio/netbird/tree/main/sharedsock 8 | // - https://github.com/mdlayher/socket 9 | // TODO: implement kernel space 10 | return false 11 | } 12 | 13 | // ModuleTunIsLoaded check if tun module exist, if is not attempt to load it 14 | func ModuleTunIsLoaded() bool { 15 | // Assume tun supported by freebsd kernel by default 16 | // TODO: implement check for module loaded in kernel or build-it 17 | return true 18 | } 19 | -------------------------------------------------------------------------------- /client/internal/lazyconn/support_test.go: -------------------------------------------------------------------------------- 1 | package lazyconn 2 | 3 | import "testing" 4 | 5 | func TestIsSupported(t *testing.T) { 6 | tests := []struct { 7 | version string 8 | want bool 9 | }{ 10 | {"development", true}, 11 | {"0.45.0", true}, 12 | {"v0.45.0", true}, 13 | {"0.45.1", true}, 14 | {"0.45.1-SNAPSHOT-559e6731", true}, 15 | {"v0.45.1-dev", true}, 16 | {"a7d5c522", false}, 17 | {"0.9.6", false}, 18 | {"0.9.6-SNAPSHOT", false}, 19 | {"0.9.6-SNAPSHOT-2033650", false}, 20 | {"meta_wt_version", false}, 21 | {"v0.31.1-dev", false}, 22 | {"", false}, 23 | } 24 | for _, tt := range tests { 25 | t.Run(tt.version, func(t *testing.T) { 26 | if got := IsSupported(tt.version); got != tt.want { 27 | t.Errorf("IsSupported() = %v, want %v", got, tt.want) 28 | } 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/internal/mobile_dependency.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "net/netip" 5 | 6 | "github.com/netbirdio/netbird/client/iface/device" 7 | "github.com/netbirdio/netbird/client/internal/dns" 8 | "github.com/netbirdio/netbird/client/internal/listener" 9 | "github.com/netbirdio/netbird/client/internal/stdnet" 10 | ) 11 | 12 | // MobileDependency collect all dependencies for mobile platform 13 | type MobileDependency struct { 14 | // Android only 15 | TunAdapter device.TunAdapter 16 | IFaceDiscover stdnet.ExternalIFaceDiscover 17 | NetworkChangeListener listener.NetworkChangeListener 18 | HostDNSAddresses []netip.AddrPort 19 | DnsReadyListener dns.ReadyListener 20 | 21 | // iOS only 22 | DnsManager dns.IosDnsManager 23 | FileDescriptor int32 24 | StateFilePath string 25 | } 26 | -------------------------------------------------------------------------------- /client/internal/networkmonitor/check_change_bsd.go: -------------------------------------------------------------------------------- 1 | //go:build dragonfly || freebsd || netbsd || openbsd 2 | 3 | package networkmonitor 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | 10 | log "github.com/sirupsen/logrus" 11 | "golang.org/x/sys/unix" 12 | 13 | "github.com/netbirdio/netbird/client/internal/routemanager/systemops" 14 | ) 15 | 16 | func checkChange(ctx context.Context, nexthopv4, nexthopv6 systemops.Nexthop) error { 17 | fd, err := prepareFd() 18 | if err != nil { 19 | return fmt.Errorf("open routing socket: %v", err) 20 | } 21 | 22 | defer func() { 23 | err := unix.Close(fd) 24 | if err != nil && !errors.Is(err, unix.EBADF) { 25 | log.Warnf("Network monitor: failed to close routing socket: %v", err) 26 | } 27 | }() 28 | 29 | return routeCheck(ctx, fd, nexthopv4, nexthopv6) 30 | } 31 | -------------------------------------------------------------------------------- /client/internal/peer/conn_status.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | ) 6 | 7 | const ( 8 | // StatusIdle indicate the peer is in disconnected state 9 | StatusIdle ConnStatus = iota 10 | // StatusConnecting indicate the peer is in connecting state 11 | StatusConnecting 12 | // StatusConnected indicate the peer is in connected state 13 | StatusConnected 14 | ) 15 | 16 | // ConnStatus describe the status of a peer's connection 17 | type ConnStatus int32 18 | 19 | func (s ConnStatus) String() string { 20 | switch s { 21 | case StatusConnecting: 22 | return "Connecting" 23 | case StatusConnected: 24 | return "Connected" 25 | case StatusIdle: 26 | return "Idle" 27 | default: 28 | log.Errorf("unknown status: %d", s) 29 | return "INVALID_PEER_CONNECTION_STATUS" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client/firewall/manager/forward_rule.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | import ( 4 | "fmt" 5 | "net/netip" 6 | ) 7 | 8 | // ForwardRule todo figure out better place to this to avoid circular imports 9 | type ForwardRule struct { 10 | Protocol Protocol 11 | DestinationPort Port 12 | TranslatedAddress netip.Addr 13 | TranslatedPort Port 14 | } 15 | 16 | func (r ForwardRule) ID() string { 17 | id := fmt.Sprintf("%s;%s;%s;%s", 18 | r.Protocol, 19 | r.DestinationPort.String(), 20 | r.TranslatedAddress.String(), 21 | r.TranslatedPort.String()) 22 | return id 23 | } 24 | 25 | func (r ForwardRule) String() string { 26 | return fmt.Sprintf("protocol: %s, destinationPort: %s, translatedAddress: %s, translatedPort: %s", r.Protocol, r.DestinationPort.String(), r.TranslatedAddress.String(), r.TranslatedPort.String()) 27 | } 28 | -------------------------------------------------------------------------------- /shared/management/client/common/types.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // LoginFlag introduces additional login flags to the PKCE authorization request. 4 | // 5 | // # Config Values 6 | // 7 | // | Value | Flag | OAuth Parameters | 8 | // |-------|----------------------|-----------------------------------------| 9 | // | 0 | LoginFlagPromptLogin | prompt=login | 10 | // | 1 | LoginFlagMaxAge0 | max_age=0 | 11 | type LoginFlag uint8 12 | 13 | const ( 14 | // LoginFlagPromptLogin adds prompt=login to the authorization request 15 | LoginFlagPromptLogin LoginFlag = iota 16 | // LoginFlagMaxAge0 adds max_age=0 to the authorization request 17 | LoginFlagMaxAge0 18 | // LoginFlagNone disables all login flags 19 | LoginFlagNone 20 | ) 21 | -------------------------------------------------------------------------------- /shared/relay/messages/id.go: -------------------------------------------------------------------------------- 1 | package messages 2 | 3 | import ( 4 | "crypto/sha256" 5 | "encoding/base64" 6 | "fmt" 7 | ) 8 | 9 | const ( 10 | prefixLength = 4 11 | peerIDSize = prefixLength + sha256.Size 12 | ) 13 | 14 | var ( 15 | prefix = []byte("sha-") // 4 bytes 16 | ) 17 | 18 | type PeerID [peerIDSize]byte 19 | 20 | func (p PeerID) String() string { 21 | return fmt.Sprintf("%s%s", p[:prefixLength], base64.StdEncoding.EncodeToString(p[prefixLength:])) 22 | } 23 | 24 | // HashID generates a sha256 hash from the peerID and returns the hash and the human-readable string 25 | func HashID(peerID string) PeerID { 26 | idHash := sha256.Sum256([]byte(peerID)) 27 | var prefixedHash [peerIDSize]byte 28 | copy(prefixedHash[:prefixLength], prefix) 29 | copy(prefixedHash[prefixLength:], idHash[:]) 30 | return prefixedHash 31 | } 32 | -------------------------------------------------------------------------------- /formatter/txt/format.go: -------------------------------------------------------------------------------- 1 | //go:build !loggoroutine 2 | 3 | package txt 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | 9 | "github.com/sirupsen/logrus" 10 | 11 | "github.com/netbirdio/netbird/formatter/hook" 12 | ) 13 | 14 | func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { 15 | var fields string 16 | keys := make([]string, 0, len(entry.Data)) 17 | for k, v := range entry.Data { 18 | if k == hook.EntryKeySource { 19 | continue 20 | } 21 | keys = append(keys, fmt.Sprintf("%s: %v", k, v)) 22 | } 23 | 24 | if len(keys) > 0 { 25 | fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) 26 | } 27 | 28 | level := f.parseLevel(entry.Level) 29 | 30 | return []byte(fmt.Sprintf("%s %s %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, fields, entry.Data[hook.EntryKeySource], entry.Message)), nil 31 | } 32 | -------------------------------------------------------------------------------- /client/iface/device_android.go: -------------------------------------------------------------------------------- 1 | package iface 2 | 3 | import ( 4 | wgdevice "golang.zx2c4.com/wireguard/device" 5 | 6 | "golang.zx2c4.com/wireguard/tun/netstack" 7 | 8 | "github.com/netbirdio/netbird/client/iface/device" 9 | "github.com/netbirdio/netbird/client/iface/udpmux" 10 | "github.com/netbirdio/netbird/client/iface/wgaddr" 11 | ) 12 | 13 | type WGTunDevice interface { 14 | Create(routes []string, dns string, searchDomains []string) (device.WGConfigurer, error) 15 | Up() (*udpmux.UniversalUDPMuxDefault, error) 16 | UpdateAddr(address wgaddr.Address) error 17 | WgAddress() wgaddr.Address 18 | MTU() uint16 19 | DeviceName() string 20 | Close() error 21 | FilteredDevice() *device.FilteredDevice 22 | Device() *wgdevice.Device 23 | GetNet() *netstack.Net 24 | RenewTun(fd int) error 25 | GetICEBind() device.EndpointManager 26 | } 27 | -------------------------------------------------------------------------------- /shared/relay/auth/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package auth manages the authentication process with the relay server. 3 | 4 | Key Components: 5 | 6 | Validator: The Validator interface defines the Validate method. Any type that provides this method can be used as a 7 | Validator. 8 | 9 | Methods: 10 | 11 | Validate(func() hash.Hash, any): This method is defined in the Validator interface and is used to validate the authentication. 12 | 13 | Usage: 14 | 15 | To create a new AllowAllAuth validator, simply instantiate it: 16 | 17 | validator := &allow.Auth{} 18 | 19 | To validate the authentication, use the Validate method: 20 | 21 | err := validator.Validate(sha256.New, any) 22 | 23 | This package provides a simple and effective way to manage authentication with the relay server, ensuring that the 24 | peers are authenticated properly. 25 | */ 26 | package auth 27 | -------------------------------------------------------------------------------- /client/iface/device/device_netstack_test.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "testing" 5 | 6 | "golang.zx2c4.com/wireguard/wgctrl/wgtypes" 7 | 8 | "github.com/netbirdio/netbird/client/iface/bind" 9 | "github.com/netbirdio/netbird/client/iface/netstack" 10 | "github.com/netbirdio/netbird/client/iface/wgaddr" 11 | ) 12 | 13 | func TestNewNetstackDevice(t *testing.T) { 14 | privateKey, _ := wgtypes.GeneratePrivateKey() 15 | wgAddress, _ := wgaddr.ParseWGAddress("1.2.3.4/24") 16 | 17 | relayBind := bind.NewRelayBindJS() 18 | nsTun := NewNetstackDevice("wtx", wgAddress, 1234, privateKey.String(), 1500, relayBind, netstack.ListenAddr()) 19 | 20 | cfgr, err := nsTun.Create() 21 | if err != nil { 22 | t.Fatalf("failed to create netstack device: %v", err) 23 | } 24 | if cfgr == nil { 25 | t.Fatal("expected non-nil configurer") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /client/internal/routemanager/systemops/state.go: -------------------------------------------------------------------------------- 1 | package systemops 2 | 3 | import ( 4 | "net/netip" 5 | 6 | "github.com/netbirdio/netbird/client/internal/routemanager/refcounter" 7 | ) 8 | 9 | type ShutdownState ExclusionCounter 10 | 11 | func (s *ShutdownState) Name() string { 12 | return "route_state" 13 | } 14 | 15 | func (s *ShutdownState) Cleanup() error { 16 | sysOps := New(nil, nil) 17 | sysOps.refCounter = refcounter.New[netip.Prefix, struct{}, Nexthop](nil, sysOps.removeFromRouteTable) 18 | sysOps.refCounter.LoadData((*ExclusionCounter)(s)) 19 | 20 | return sysOps.refCounter.Flush() 21 | } 22 | 23 | func (s *ShutdownState) MarshalJSON() ([]byte, error) { 24 | return (*ExclusionCounter)(s).MarshalJSON() 25 | } 26 | 27 | func (s *ShutdownState) UnmarshalJSON(data []byte) error { 28 | return (*ExclusionCounter)(s).UnmarshalJSON(data) 29 | } 30 | -------------------------------------------------------------------------------- /util/duration.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "time" 7 | ) 8 | 9 | // Duration is used strictly for JSON requests/responses due to duration marshalling issues 10 | type Duration struct { 11 | time.Duration 12 | } 13 | 14 | func (d Duration) MarshalJSON() ([]byte, error) { 15 | return json.Marshal(d.String()) 16 | } 17 | 18 | func (d *Duration) UnmarshalJSON(b []byte) error { 19 | var v interface{} 20 | if err := json.Unmarshal(b, &v); err != nil { 21 | return err 22 | } 23 | switch value := v.(type) { 24 | case float64: 25 | d.Duration = time.Duration(value) 26 | return nil 27 | case string: 28 | var err error 29 | d.Duration, err = time.ParseDuration(value) 30 | if err != nil { 31 | return err 32 | } 33 | return nil 34 | default: 35 | return errors.New("invalid duration") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /client/iface/iface_create.go: -------------------------------------------------------------------------------- 1 | //go:build (!android && !darwin) || ios 2 | 3 | package iface 4 | 5 | import "fmt" 6 | 7 | // Create creates a new Wireguard interface, sets a given IP and brings it up. 8 | // Will reuse an existing one. 9 | // this function is different on Android 10 | func (w *WGIface) Create() error { 11 | w.mu.Lock() 12 | defer w.mu.Unlock() 13 | 14 | cfgr, err := w.tun.Create() 15 | if err != nil { 16 | return err 17 | } 18 | 19 | w.configurer = cfgr 20 | return nil 21 | } 22 | 23 | // CreateOnAndroid this function make sense on mobile only 24 | func (w *WGIface) CreateOnAndroid([]string, string, []string) error { 25 | return fmt.Errorf("this function has not implemented on non mobile") 26 | } 27 | 28 | func (w *WGIface) RenewTun(fd int) error { 29 | return fmt.Errorf("this function has not been implemented on non-android") 30 | } 31 | -------------------------------------------------------------------------------- /client/server/updateresult.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | 6 | log "github.com/sirupsen/logrus" 7 | 8 | "github.com/netbirdio/netbird/client/internal/updatemanager/installer" 9 | "github.com/netbirdio/netbird/client/proto" 10 | ) 11 | 12 | func (s *Server) GetInstallerResult(ctx context.Context, _ *proto.InstallerResultRequest) (*proto.InstallerResultResponse, error) { 13 | inst := installer.New() 14 | dir := inst.TempDir() 15 | 16 | rh := installer.NewResultHandler(dir) 17 | result, err := rh.Watch(ctx) 18 | if err != nil { 19 | log.Errorf("failed to watch update result: %v", err) 20 | return &proto.InstallerResultResponse{ 21 | Success: false, 22 | ErrorMsg: err.Error(), 23 | }, nil 24 | } 25 | 26 | return &proto.InstallerResultResponse{ 27 | Success: result.Success, 28 | ErrorMsg: result.Error, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /management/server/types/resource.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "github.com/netbirdio/netbird/shared/management/http/api" 5 | ) 6 | 7 | type ResourceType string 8 | 9 | const ( 10 | ResourceTypePeer ResourceType = "peer" 11 | ResourceTypeDomain ResourceType = "domain" 12 | ResourceTypeHost ResourceType = "host" 13 | ResourceTypeSubnet ResourceType = "subnet" 14 | ) 15 | 16 | type Resource struct { 17 | ID string 18 | Type ResourceType 19 | } 20 | 21 | func (r *Resource) ToAPIResponse() *api.Resource { 22 | if r.ID == "" && r.Type == "" { 23 | return nil 24 | } 25 | 26 | return &api.Resource{ 27 | Id: r.ID, 28 | Type: api.ResourceType(r.Type), 29 | } 30 | } 31 | 32 | func (r *Resource) FromAPIRequest(req *api.Resource) { 33 | if req == nil { 34 | return 35 | } 36 | 37 | r.ID = req.Id 38 | r.Type = ResourceType(req.Type) 39 | } 40 | -------------------------------------------------------------------------------- /util/embeddedroots/isrg-root-x2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw 3 | CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg 4 | R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 5 | MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT 6 | ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw 7 | EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW 8 | +1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 9 | ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T 10 | AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI 11 | zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW 12 | tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 13 | /q4AaOeMSQ+2b1tbFfLn 14 | -----END CERTIFICATE----- 15 | -------------------------------------------------------------------------------- /client/ui/font_bsd.go: -------------------------------------------------------------------------------- 1 | //go:build freebsd || openbsd || netbsd || dragonfly 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | "runtime" 8 | 9 | log "github.com/sirupsen/logrus" 10 | ) 11 | 12 | func (s *serviceClient) setDefaultFonts() { 13 | paths := []string{ 14 | "/usr/local/share/fonts/TTF/DejaVuSans.ttf", 15 | "/usr/local/share/fonts/dejavu/DejaVuSans.ttf", 16 | "/usr/local/share/noto/NotoSans-Regular.ttf", 17 | "/usr/local/share/fonts/noto/NotoSans-Regular.ttf", 18 | "/usr/local/share/fonts/liberation-fonts-ttf/LiberationSans-Regular.ttf", 19 | } 20 | 21 | for _, fontPath := range paths { 22 | if _, err := os.Stat(fontPath); err == nil { 23 | os.Setenv("FYNE_FONT", fontPath) 24 | log.Debugf("Using font: %s", fontPath) 25 | return 26 | } 27 | } 28 | 29 | log.Errorf("Failed to find any suitable font files for %s", runtime.GOOS) 30 | } 31 | -------------------------------------------------------------------------------- /client/internal/dns/test/mock.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/miekg/dns" 7 | ) 8 | 9 | type MockResponseWriter struct { 10 | WriteMsgFunc func(m *dns.Msg) error 11 | } 12 | 13 | func (rw *MockResponseWriter) WriteMsg(m *dns.Msg) error { 14 | if rw.WriteMsgFunc != nil { 15 | return rw.WriteMsgFunc(m) 16 | } 17 | return nil 18 | } 19 | 20 | func (rw *MockResponseWriter) LocalAddr() net.Addr { return nil } 21 | func (rw *MockResponseWriter) RemoteAddr() net.Addr { return nil } 22 | func (rw *MockResponseWriter) Write([]byte) (int, error) { return 0, nil } 23 | func (rw *MockResponseWriter) Close() error { return nil } 24 | func (rw *MockResponseWriter) TsigStatus() error { return nil } 25 | func (rw *MockResponseWriter) TsigTimersOnly(bool) {} 26 | func (rw *MockResponseWriter) Hijack() {} 27 | -------------------------------------------------------------------------------- /client/internal/peer/error_test.go: -------------------------------------------------------------------------------- 1 | package peer 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestNewConnectionClosedError(t *testing.T) { 10 | err := NewConnectionClosedError("X") 11 | assert.Equal(t, &ConnectionClosedError{peer: "X"}, err) 12 | } 13 | 14 | func TestNewConnectionDisconnectedError(t *testing.T) { 15 | err := NewConnectionDisconnectedError("X") 16 | assert.Equal(t, &ConnectionDisconnectedError{peer: "X"}, err) 17 | } 18 | 19 | func TestNewConnectionTimeoutErrorC(t *testing.T) { 20 | err := NewConnectionTimeoutError("X", time.Second) 21 | assert.Equal(t, &ConnectionTimeoutError{peer: "X", timeout: time.Second}, err) 22 | } 23 | 24 | func TestNewConnectionAlreadyClosed(t *testing.T) { 25 | err := NewConnectionAlreadyClosed("X") 26 | assert.Equal(t, &ConnectionAlreadyClosedError{peer: "X"}, err) 27 | } 28 | -------------------------------------------------------------------------------- /client/system/static_info_update.go: -------------------------------------------------------------------------------- 1 | //go:build (linux && !android) || (darwin && !ios) 2 | 3 | package system 4 | 5 | import ( 6 | "context" 7 | "sync" 8 | "time" 9 | 10 | "github.com/netbirdio/netbird/client/system/detect_cloud" 11 | "github.com/netbirdio/netbird/client/system/detect_platform" 12 | ) 13 | 14 | func newStaticInfo() StaticInfo { 15 | si := StaticInfo{} 16 | 17 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 18 | defer cancel() 19 | wg := sync.WaitGroup{} 20 | wg.Add(3) 21 | go func() { 22 | si.SystemSerialNumber, si.SystemProductName, si.SystemManufacturer = sysInfo() 23 | wg.Done() 24 | }() 25 | go func() { 26 | si.Environment.Cloud = detect_cloud.Detect(ctx) 27 | wg.Done() 28 | }() 29 | go func() { 30 | si.Environment.Platform = detect_platform.Detect(ctx) 31 | wg.Done() 32 | }() 33 | wg.Wait() 34 | return si 35 | } 36 | -------------------------------------------------------------------------------- /relay/testec2/start_msg.go: -------------------------------------------------------------------------------- 1 | //go:build linux || darwin 2 | 3 | package main 4 | 5 | import ( 6 | "bytes" 7 | "encoding/gob" 8 | "time" 9 | 10 | log "github.com/sirupsen/logrus" 11 | ) 12 | 13 | type StartIndication struct { 14 | Started time.Time 15 | TransferSize int 16 | } 17 | 18 | func NewStartInidication(started time.Time, transferSize int) []byte { 19 | si := StartIndication{ 20 | Started: started, 21 | TransferSize: transferSize, 22 | } 23 | 24 | var data bytes.Buffer 25 | err := gob.NewEncoder(&data).Encode(si) 26 | if err != nil { 27 | log.Fatal("encode error:", err) 28 | } 29 | return data.Bytes() 30 | } 31 | 32 | func DecodeStartIndication(data []byte) StartIndication { 33 | var si StartIndication 34 | err := gob.NewDecoder(bytes.NewReader(data)).Decode(&si) 35 | if err != nil { 36 | log.Fatal("decode error:", err) 37 | } 38 | return si 39 | } 40 | -------------------------------------------------------------------------------- /client/iface/device/interface.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "net" 5 | "net/netip" 6 | "time" 7 | 8 | "golang.zx2c4.com/wireguard/wgctrl/wgtypes" 9 | 10 | "github.com/netbirdio/netbird/client/iface/configurer" 11 | "github.com/netbirdio/netbird/monotime" 12 | ) 13 | 14 | type WGConfigurer interface { 15 | ConfigureInterface(privateKey string, port int) error 16 | UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error 17 | RemovePeer(peerKey string) error 18 | AddAllowedIP(peerKey string, allowedIP netip.Prefix) error 19 | RemoveAllowedIP(peerKey string, allowedIP netip.Prefix) error 20 | Close() 21 | GetStats() (map[string]configurer.WGStats, error) 22 | FullStats() (*configurer.Stats, error) 23 | LastActivities() map[string]monotime.Time 24 | RemoveEndpointAddress(peerKey string) error 25 | } 26 | -------------------------------------------------------------------------------- /shared/relay/auth/validator.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "time" 5 | 6 | auth "github.com/netbirdio/netbird/shared/relay/auth/hmac" 7 | authv2 "github.com/netbirdio/netbird/shared/relay/auth/hmac/v2" 8 | ) 9 | 10 | type TimedHMACValidator struct { 11 | authenticatorV2 *authv2.Validator 12 | authenticator *auth.TimedHMACValidator 13 | } 14 | 15 | func NewTimedHMACValidator(secret []byte, duration time.Duration) *TimedHMACValidator { 16 | return &TimedHMACValidator{ 17 | authenticatorV2: authv2.NewValidator(secret), 18 | authenticator: auth.NewTimedHMACValidator(string(secret), duration), 19 | } 20 | } 21 | 22 | func (a *TimedHMACValidator) Validate(credentials any) error { 23 | return a.authenticatorV2.Validate(credentials) 24 | } 25 | 26 | func (a *TimedHMACValidator) ValidateHelloMsgType(credentials any) error { 27 | return a.authenticator.Validate(credentials) 28 | } 29 | -------------------------------------------------------------------------------- /client/ios/NetBirdSDK/env_list.go: -------------------------------------------------------------------------------- 1 | //go:build ios 2 | 3 | package NetBirdSDK 4 | 5 | import "github.com/netbirdio/netbird/client/internal/peer" 6 | 7 | // EnvList is an exported struct to be bound by gomobile 8 | type EnvList struct { 9 | data map[string]string 10 | } 11 | 12 | // NewEnvList creates a new EnvList 13 | func NewEnvList() *EnvList { 14 | return &EnvList{data: make(map[string]string)} 15 | } 16 | 17 | // Put adds a key-value pair 18 | func (el *EnvList) Put(key, value string) { 19 | el.data[key] = value 20 | } 21 | 22 | // Get retrieves a value by key 23 | func (el *EnvList) Get(key string) string { 24 | return el.data[key] 25 | } 26 | 27 | func (el *EnvList) AllItems() map[string]string { 28 | return el.data 29 | } 30 | 31 | // GetEnvKeyNBForceRelay Exports the environment variable for the iOS client 32 | func GetEnvKeyNBForceRelay() string { 33 | return peer.EnvKeyNBForceRelay 34 | } 35 | -------------------------------------------------------------------------------- /client/iface/iface_create_android.go: -------------------------------------------------------------------------------- 1 | package iface 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // CreateOnAndroid creates a new Wireguard interface, sets a given IP and brings it up. 8 | // Will reuse an existing one. 9 | // todo: review does this function really necessary or can we merge it with iOS 10 | func (w *WGIface) CreateOnAndroid(routes []string, dns string, searchDomains []string) error { 11 | w.mu.Lock() 12 | defer w.mu.Unlock() 13 | 14 | cfgr, err := w.tun.Create(routes, dns, searchDomains) 15 | if err != nil { 16 | return err 17 | } 18 | w.configurer = cfgr 19 | return nil 20 | } 21 | 22 | // Create this function make sense on mobile only 23 | func (w *WGIface) Create() error { 24 | return fmt.Errorf("this function has not implemented on this platform") 25 | } 26 | 27 | func (w *WGIface) RenewTun(fd int) error { 28 | w.mu.Lock() 29 | defer w.mu.Unlock() 30 | return w.tun.RenewTun(fd) 31 | } 32 | -------------------------------------------------------------------------------- /shared/relay/auth/hmac/v2/token.go: -------------------------------------------------------------------------------- 1 | package v2 2 | 3 | import "errors" 4 | 5 | type Token struct { 6 | AuthAlgo AuthAlgo 7 | Signature []byte 8 | Payload []byte 9 | } 10 | 11 | func (t *Token) Marshal() []byte { 12 | size := 1 + len(t.Signature) + len(t.Payload) 13 | 14 | buf := make([]byte, size) 15 | 16 | buf[0] = byte(t.AuthAlgo) 17 | copy(buf[1:], t.Signature) 18 | copy(buf[1+len(t.Signature):], t.Payload) 19 | 20 | return buf 21 | } 22 | 23 | func UnmarshalToken(data []byte) (*Token, error) { 24 | if len(data) == 0 { 25 | return nil, errors.New("invalid token data") 26 | } 27 | 28 | algo := AuthAlgo(data[0]) 29 | sigSize := algo.Size() 30 | if len(data) < 1+sigSize { 31 | return nil, errors.New("invalid token data: insufficient length") 32 | } 33 | 34 | return &Token{ 35 | AuthAlgo: algo, 36 | Signature: data[1 : 1+sigSize], 37 | Payload: data[1+sigSize:], 38 | }, nil 39 | } 40 | -------------------------------------------------------------------------------- /client/ui/process/process.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/shirou/gopsutil/v3/process" 9 | ) 10 | 11 | func IsAnotherProcessRunning() (int32, bool, error) { 12 | processes, err := process.Processes() 13 | if err != nil { 14 | return 0, false, err 15 | } 16 | 17 | pid := os.Getpid() 18 | processName := strings.ToLower(filepath.Base(os.Args[0])) 19 | 20 | for _, p := range processes { 21 | if int(p.Pid) == pid { 22 | continue 23 | } 24 | 25 | runningProcessPath, err := p.Exe() 26 | // most errors are related to short-lived processes 27 | if err != nil { 28 | continue 29 | } 30 | 31 | runningProcessName := strings.ToLower(filepath.Base(runningProcessPath)) 32 | if runningProcessName == processName && isProcessOwnedByCurrentUser(p) { 33 | return p.Pid, true, nil 34 | } 35 | } 36 | 37 | return 0, false, nil 38 | } 39 | --------------------------------------------------------------------------------