diff --git a/client/cmd/root.go b/client/cmd/root.go index a9fc9bc60a6..17ba8906544 100644 --- a/client/cmd/root.go +++ b/client/cmd/root.go @@ -15,6 +15,7 @@ import ( "time" "github.com/cenkalti/backoff/v4" + "github.com/netbirdio/netbird/iface" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -48,6 +49,8 @@ var ( preSharedKey string natExternalIPs []string customDNSAddress string + wgIface string + wgPort int rootCmd = &cobra.Command{ Use: "netbird", Short: "", @@ -116,6 +119,11 @@ func init() { `An empty string "" clears the previous configuration. `+ `E.g. --dns-resolver-address 127.0.0.1:5053 or --dns-resolver-address ""`, ) + upCmd.PersistentFlags().StringVar(&wgIface, "wg-iface", iface.WgInterfaceDefault, + `WireGuard interface name to use for Netbird client instance. `+ + `MacOS restricts the tun interface name to utun[0-9]+ pattern. e.g., utun100`) + upCmd.PersistentFlags().IntVar(&wgPort, "wg-port", iface.DefaultWgPort, "WireGuard port number to use for Netbird client instance") + } // SetupCloseHandler handles SIGTERM signal and exits with success diff --git a/client/cmd/up.go b/client/cmd/up.go index 4aa3f421cb1..c183f275443 100644 --- a/client/cmd/up.go +++ b/client/cmd/up.go @@ -3,6 +3,10 @@ package cmd import ( "context" "fmt" + "net" + "net/netip" + "strings" + "github.com/netbirdio/netbird/client/internal" "github.com/netbirdio/netbird/client/proto" nbStatus "github.com/netbirdio/netbird/client/status" @@ -11,9 +15,6 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc/codes" gstatus "google.golang.org/grpc/status" - "net" - "net/netip" - "strings" ) const ( @@ -77,6 +78,8 @@ func runInForegroundMode(ctx context.Context, cmd *cobra.Command) error { PreSharedKey: &preSharedKey, NATExternalIPs: natExternalIPs, CustomDNSAddress: customDNSAddressConverted, + WgIface: wgIface, + WgPort: wgPort, }) if err != nil { return fmt.Errorf("get config file: %v", err) diff --git a/client/internal/config.go b/client/internal/config.go index d5dbb7ad57f..8d87871f3f1 100644 --- a/client/internal/config.go +++ b/client/internal/config.go @@ -11,6 +11,7 @@ import ( mgm "github.com/netbirdio/netbird/management/client" "github.com/netbirdio/netbird/util" log "github.com/sirupsen/logrus" + "golang.org/x/exp/slices" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -21,7 +22,7 @@ import ( // NB: hardcoded from github.com/netbirdio/netbird/management/cmd to avoid import const ManagementLegacyPort = 33073 -var defaultInterfaceBlacklist = []string{iface.WgInterfaceDefault, "wt", "utun", "tun0", "zt", "ZeroTier", "wg", "ts", +var defaultInterfaceBlacklist = []string{"wt", "utun", "tun0", "zt", "ZeroTier", "wg", "ts", "Tailscale", "tailscale", "docker", "veth", "br-"} var managementURLDefault *url.URL @@ -46,6 +47,8 @@ type ConfigInput struct { PreSharedKey *string NATExternalIPs []string CustomDNSAddress []byte + WgIface string + WgPort int } // Config Configuration type @@ -99,6 +102,7 @@ func createNewConfig(input ConfigInput) (*Config, error) { NATExternalIPs: input.NATExternalIPs, CustomDNSAddress: string(input.CustomDNSAddress), } + if input.ManagementURL != "" { URL, err := ParseURL("Management URL", input.ManagementURL) if err != nil { @@ -121,7 +125,15 @@ func createNewConfig(input ConfigInput) (*Config, error) { config.AdminURL = newURL } - config.IFaceBlackList = defaultInterfaceBlacklist + if input.WgIface != "" { + config.WgIface = input.WgIface + } + + if input.WgPort != 0 { + config.WgPort = input.WgPort + } + + config.IFaceBlackList = append([]string{input.WgIface}, defaultInterfaceBlacklist...) err = util.WriteJson(input.ConfigPath, config) if err != nil { @@ -203,6 +215,17 @@ func ReadConfig(input ConfigInput) (*Config, error) { config.WgPort = iface.DefaultWgPort refresh = true } + + if input.WgIface == "" { + config.WgIface = iface.WgInterfaceDefault + refresh = true + } + + if !slices.Contains(config.IFaceBlackList, config.WgIface) { + config.IFaceBlackList = append([]string{config.WgIface}, config.IFaceBlackList...) + refresh = true + } + if input.NATExternalIPs != nil && len(config.NATExternalIPs) != len(input.NATExternalIPs) { config.NATExternalIPs = input.NATExternalIPs refresh = true diff --git a/client/internal/engine.go b/client/internal/engine.go index 0594082e37c..4698d5fe7f7 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -45,7 +45,10 @@ var ErrResetConnection = fmt.Errorf("reset connection") // EngineConfig is a config for the Engine type EngineConfig struct { - WgPort int + // WgPort is a port number Wireguard listens on + WgPort int + + // WgIfaceName is a Wireguard interface name to use WgIfaceName string // WgAddr is a Wireguard local address (Netbird Network IP) diff --git a/go.mod b/go.mod index d83f7cd0779..e833aac5363 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( go.opentelemetry.io/otel/exporters/prometheus v0.33.0 go.opentelemetry.io/otel/metric v0.33.0 go.opentelemetry.io/otel/sdk/metric v0.33.0 + golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf golang.org/x/net v0.0.0-20220630215102-69896b714898 golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 ) @@ -111,7 +112,6 @@ require ( go.opentelemetry.io/otel v1.11.1 // indirect go.opentelemetry.io/otel/sdk v1.11.1 // indirect go.opentelemetry.io/otel/trace v1.11.1 // indirect - golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf // indirect golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect