diff --git a/client/cmd/flags.go b/client/cmd/flags.go new file mode 100644 index 000000000..f8219bee9 --- /dev/null +++ b/client/cmd/flags.go @@ -0,0 +1,210 @@ +package cmd + +import ( + "fmt" + "time" + + "github.com/netbirdio/netbird/client/iface" + "github.com/netbirdio/netbird/client/internal" + "github.com/netbirdio/netbird/management/domain" + "github.com/spf13/cobra" +) + +// SharedFlags contains all configuration flags that are common between up and set commands +type SharedFlags struct { + // Network configuration + InterfaceName string + WireguardPort uint16 + NATExternalIPs []string + CustomDNSAddress string + ExtraIFaceBlackList []string + DNSLabels []string + DNSRouteInterval time.Duration + + // Feature flags + RosenpassEnabled bool + RosenpassPermissive bool + ServerSSHAllowed bool + AutoConnectDisabled bool + NetworkMonitor bool + LazyConnEnabled bool + + // System flags + DisableClientRoutes bool + DisableServerRoutes bool + DisableDNS bool + DisableFirewall bool + BlockLANAccess bool + BlockInbound bool + + // Login-specific (only for up command) + NoBrowser bool +} + +// AddSharedFlags adds all shared configuration flags to the given command +func AddSharedFlags(cmd *cobra.Command, flags *SharedFlags) { + // Network configuration flags + cmd.PersistentFlags().StringVar(&flags.InterfaceName, interfaceNameFlag, iface.WgInterfaceDefault, + "Wireguard interface name") + cmd.PersistentFlags().Uint16Var(&flags.WireguardPort, wireguardPortFlag, iface.DefaultWgPort, + "Wireguard interface listening port") + cmd.PersistentFlags().StringSliceVar(&flags.NATExternalIPs, externalIPMapFlag, nil, + `Sets external IPs maps between local addresses and interfaces. `+ + `You can specify a comma-separated list with a single IP and IP/IP or IP/Interface Name. `+ + `An empty string "" clears the previous configuration. `+ + `E.g. --external-ip-map 12.34.56.78/10.0.0.1 or --external-ip-map 12.34.56.200,12.34.56.78/10.0.0.1,12.34.56.80/eth1 `+ + `or --external-ip-map ""`) + cmd.PersistentFlags().StringVar(&flags.CustomDNSAddress, dnsResolverAddress, "", + `Sets a custom address for NetBird's local DNS resolver. `+ + `If set, the agent won't attempt to discover the best ip and port to listen on. `+ + `An empty string "" clears the previous configuration. `+ + `E.g. --dns-resolver-address 127.0.0.1:5053 or --dns-resolver-address ""`) + cmd.PersistentFlags().StringSliceVar(&flags.ExtraIFaceBlackList, extraIFaceBlackListFlag, nil, + "Extra list of default interfaces to ignore for listening") + cmd.PersistentFlags().StringSliceVar(&flags.DNSLabels, dnsLabelsFlag, nil, + `Sets DNS labels. `+ + `You can specify a comma-separated list of up to 32 labels. `+ + `An empty string "" clears the previous configuration. `+ + `E.g. --extra-dns-labels vpc1 or --extra-dns-labels vpc1,mgmt1 `+ + `or --extra-dns-labels ""`) + cmd.PersistentFlags().DurationVar(&flags.DNSRouteInterval, dnsRouteIntervalFlag, time.Minute, + "DNS route update interval") + + // Feature flags + cmd.PersistentFlags().BoolVar(&flags.RosenpassEnabled, enableRosenpassFlag, false, + "[Experimental] Enable Rosenpass feature. If enabled, the connection will be post-quantum secured via Rosenpass.") + cmd.PersistentFlags().BoolVar(&flags.RosenpassPermissive, rosenpassPermissiveFlag, false, + "[Experimental] Enable Rosenpass in permissive mode to allow this peer to accept WireGuard connections without requiring Rosenpass functionality from peers that do not have Rosenpass enabled.") + cmd.PersistentFlags().BoolVar(&flags.ServerSSHAllowed, serverSSHAllowedFlag, false, + "Allow SSH server on peer. If enabled, the SSH server will be permitted") + cmd.PersistentFlags().BoolVar(&flags.AutoConnectDisabled, disableAutoConnectFlag, false, + "Disables auto-connect feature. If enabled, then the client won't connect automatically when the service starts.") + cmd.PersistentFlags().BoolVarP(&flags.NetworkMonitor, networkMonitorFlag, "N", networkMonitor, + `Manage network monitoring. Defaults to true on Windows and macOS, false on Linux and FreeBSD. `+ + `E.g. --network-monitor=false to disable or --network-monitor=true to enable.`) + cmd.PersistentFlags().BoolVar(&flags.LazyConnEnabled, enableLazyConnectionFlag, false, + "[Experimental] Enable the lazy connection feature. If enabled, the client will establish connections on-demand.") + + // System flags (from system.go) + cmd.PersistentFlags().BoolVar(&flags.DisableClientRoutes, disableClientRoutesFlag, false, + "Disable client routes. If enabled, the client won't process client routes received from the management service.") + cmd.PersistentFlags().BoolVar(&flags.DisableServerRoutes, disableServerRoutesFlag, false, + "Disable server routes. If enabled, the client won't act as a router for server routes received from the management service.") + cmd.PersistentFlags().BoolVar(&flags.DisableDNS, disableDNSFlag, false, + "Disable DNS. If enabled, the client won't configure DNS settings.") + cmd.PersistentFlags().BoolVar(&flags.DisableFirewall, disableFirewallFlag, false, + "Disable firewall configuration. If enabled, the client won't modify firewall rules.") + cmd.PersistentFlags().BoolVar(&flags.BlockLANAccess, blockLANAccessFlag, false, + "Block access to local networks (LAN) when using this peer as a router or exit node") + cmd.PersistentFlags().BoolVar(&flags.BlockInbound, blockInboundFlag, false, + "Block inbound connections. If enabled, the client will not allow any inbound connections to the local machine nor routed networks.\n"+ + "This overrides any policies received from the management service.") +} + +// AddUpOnlyFlags adds flags that are specific to the up command +func AddUpOnlyFlags(cmd *cobra.Command, flags *SharedFlags) { + cmd.PersistentFlags().BoolVar(&flags.NoBrowser, noBrowserFlag, false, noBrowserDesc) +} + +// BuildConfigInput creates an internal.ConfigInput from SharedFlags with Changed() checks +func BuildConfigInput(cmd *cobra.Command, flags *SharedFlags, customDNSAddressConverted []byte) (*internal.ConfigInput, error) { + ic := internal.ConfigInput{ + ManagementURL: managementURL, + AdminURL: adminURL, + ConfigPath: configPath, + CustomDNSAddress: customDNSAddressConverted, + } + + // Handle PreSharedKey from root command + if rootCmd.PersistentFlags().Changed(preSharedKeyFlag) { + ic.PreSharedKey = &preSharedKey + } + + if cmd.Flag(enableRosenpassFlag).Changed { + ic.RosenpassEnabled = &flags.RosenpassEnabled + } + + if cmd.Flag(rosenpassPermissiveFlag).Changed { + ic.RosenpassPermissive = &flags.RosenpassPermissive + } + + if cmd.Flag(serverSSHAllowedFlag).Changed { + ic.ServerSSHAllowed = &flags.ServerSSHAllowed + } + + if cmd.Flag(interfaceNameFlag).Changed { + if err := parseInterfaceName(flags.InterfaceName); err != nil { + return nil, err + } + ic.InterfaceName = &flags.InterfaceName + } + + if cmd.Flag(wireguardPortFlag).Changed { + p := int(flags.WireguardPort) + ic.WireguardPort = &p + } + + if cmd.Flag(networkMonitorFlag).Changed { + ic.NetworkMonitor = &flags.NetworkMonitor + } + + if cmd.Flag(disableAutoConnectFlag).Changed { + ic.DisableAutoConnect = &flags.AutoConnectDisabled + + if flags.AutoConnectDisabled { + cmd.Println("Autoconnect has been disabled. The client won't connect automatically when the service starts.") + } else { + cmd.Println("Autoconnect has been enabled. The client will connect automatically when the service starts.") + } + } + + if cmd.Flag(dnsRouteIntervalFlag).Changed { + ic.DNSRouteInterval = &flags.DNSRouteInterval + } + + if cmd.Flag(disableClientRoutesFlag).Changed { + ic.DisableClientRoutes = &flags.DisableClientRoutes + } + + if cmd.Flag(disableServerRoutesFlag).Changed { + ic.DisableServerRoutes = &flags.DisableServerRoutes + } + + if cmd.Flag(disableDNSFlag).Changed { + ic.DisableDNS = &flags.DisableDNS + } + + if cmd.Flag(disableFirewallFlag).Changed { + ic.DisableFirewall = &flags.DisableFirewall + } + + if cmd.Flag(blockLANAccessFlag).Changed { + ic.BlockLANAccess = &flags.BlockLANAccess + } + + if cmd.Flag(blockInboundFlag).Changed { + ic.BlockInbound = &flags.BlockInbound + } + + if cmd.Flag(enableLazyConnectionFlag).Changed { + ic.LazyConnectionEnabled = &flags.LazyConnEnabled + } + + if cmd.Flag(externalIPMapFlag).Changed { + ic.NATExternalIPs = flags.NATExternalIPs + } + + if cmd.Flag(extraIFaceBlackListFlag).Changed { + ic.ExtraIFaceBlackList = flags.ExtraIFaceBlackList + } + + if cmd.Flag(dnsLabelsFlag).Changed { + var err error + ic.DNSLabels, err = domain.FromStringList(flags.DNSLabels) + if err != nil { + return nil, fmt.Errorf("invalid DNS labels: %v", err) + } + } + + return &ic, nil +} diff --git a/client/cmd/root.go b/client/cmd/root.go index 16e445f4d..5a9a49325 100644 --- a/client/cmd/root.go +++ b/client/cmd/root.go @@ -149,6 +149,7 @@ func init() { rootCmd.AddCommand(loginCmd) rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(sshCmd) + rootCmd.AddCommand(setCmd) rootCmd.AddCommand(networksCMD) rootCmd.AddCommand(forwardingRulesCmd) rootCmd.AddCommand(debugCmd) @@ -167,24 +168,6 @@ func init() { debugCmd.AddCommand(forCmd) debugCmd.AddCommand(persistenceCmd) - upCmd.PersistentFlags().StringSliceVar(&natExternalIPs, externalIPMapFlag, nil, - `Sets external IPs maps between local addresses and interfaces.`+ - `You can specify a comma-separated list with a single IP and IP/IP or IP/Interface Name. `+ - `An empty string "" clears the previous configuration. `+ - `E.g. --external-ip-map 12.34.56.78/10.0.0.1 or --external-ip-map 12.34.56.200,12.34.56.78/10.0.0.1,12.34.56.80/eth1 `+ - `or --external-ip-map ""`, - ) - upCmd.PersistentFlags().StringVar(&customDNSAddress, dnsResolverAddress, "", - `Sets a custom address for NetBird's local DNS resolver. `+ - `If set, the agent won't attempt to discover the best ip and port to listen on. `+ - `An empty string "" clears the previous configuration. `+ - `E.g. --dns-resolver-address 127.0.0.1:5053 or --dns-resolver-address ""`, - ) - upCmd.PersistentFlags().BoolVar(&rosenpassEnabled, enableRosenpassFlag, false, "[Experimental] Enable Rosenpass feature. If enabled, the connection will be post-quantum secured via Rosenpass.") - upCmd.PersistentFlags().BoolVar(&rosenpassPermissive, rosenpassPermissiveFlag, false, "[Experimental] Enable Rosenpass in permissive mode to allow this peer to accept WireGuard connections without requiring Rosenpass functionality from peers that do not have Rosenpass enabled.") - upCmd.PersistentFlags().BoolVar(&serverSSHAllowed, serverSSHAllowedFlag, false, "Allow SSH server on peer. If enabled, the SSH server will be permitted") - upCmd.PersistentFlags().BoolVar(&autoConnectDisabled, disableAutoConnectFlag, false, "Disables auto-connect feature. If enabled, then the client won't connect automatically when the service starts.") - upCmd.PersistentFlags().BoolVar(&lazyConnEnabled, enableLazyConnectionFlag, false, "[Experimental] Enable the lazy connection feature. If enabled, the client will establish connections on-demand.") debugCmd.PersistentFlags().BoolVarP(&debugSystemInfoFlag, systemInfoFlag, "S", true, "Adds system information to the debug bundle") debugCmd.PersistentFlags().BoolVarP(&debugUploadBundle, uploadBundle, "U", false, fmt.Sprintf("Uploads the debug bundle to a server from URL defined by %s", uploadBundleURL)) diff --git a/client/cmd/set.go b/client/cmd/set.go new file mode 100644 index 000000000..62de5d503 --- /dev/null +++ b/client/cmd/set.go @@ -0,0 +1,161 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "google.golang.org/protobuf/types/known/durationpb" + + "github.com/netbirdio/netbird/client/proto" +) + +var ( + setFlags = &SharedFlags{} + + setCmd = &cobra.Command{ + Use: "set", + Short: "Update NetBird client configuration", + Long: `Update NetBird client configuration without connecting. Uses the same flags as 'netbird up' but only updates the configuration file.`, + RunE: setFunc, + } +) + +func init() { + // Add all shared flags to the set command + AddSharedFlags(setCmd, setFlags) + // Note: We don't add up-only flags like --no-browser to set command +} + +func setFunc(cmd *cobra.Command, _ []string) error { + SetFlagsFromEnvVars(rootCmd) + SetFlagsFromEnvVars(cmd) + + cmd.SetOut(cmd.OutOrStdout()) + + // Validate inputs (reuse validation logic from up.go) + if err := validateNATExternalIPs(setFlags.NATExternalIPs); err != nil { + return err + } + + if cmd.Flag(dnsLabelsFlag).Changed { + if _, err := validateDnsLabels(setFlags.DNSLabels); err != nil { + return err + } + } + + var customDNSAddressConverted []byte + if cmd.Flag(dnsResolverAddress).Changed { + var err error + customDNSAddressConverted, err = parseCustomDNSAddress(cmd.Flag(dnsResolverAddress).Changed) + if err != nil { + return err + } + } + + // Connect to daemon + ctx := cmd.Context() + conn, err := DialClientGRPCServer(ctx, daemonAddr) + if err != nil { + return fmt.Errorf("connect to daemon: %w", err) + } + defer func() { + if closeErr := conn.Close(); closeErr != nil { + fmt.Printf("Warning: failed to close connection: %v\n", closeErr) + } + }() + + client := proto.NewDaemonServiceClient(conn) + req := &proto.SetConfigRequest{} + + // Set fields based on changed flags + if cmd.Flag(enableRosenpassFlag).Changed { + req.RosenpassEnabled = &setFlags.RosenpassEnabled + } + + if cmd.Flag(rosenpassPermissiveFlag).Changed { + req.RosenpassPermissive = &setFlags.RosenpassPermissive + } + + if cmd.Flag(serverSSHAllowedFlag).Changed { + req.ServerSSHAllowed = &setFlags.ServerSSHAllowed + } + + if cmd.Flag(disableAutoConnectFlag).Changed { + req.DisableAutoConnect = &setFlags.AutoConnectDisabled + } + + if cmd.Flag(networkMonitorFlag).Changed { + req.NetworkMonitor = &setFlags.NetworkMonitor + } + + if cmd.Flag(interfaceNameFlag).Changed { + if err := parseInterfaceName(setFlags.InterfaceName); err != nil { + return err + } + req.InterfaceName = &setFlags.InterfaceName + } + + if cmd.Flag(wireguardPortFlag).Changed { + port := int64(setFlags.WireguardPort) + req.WireguardPort = &port + } + + if cmd.Flag(dnsResolverAddress).Changed { + customAddr := string(customDNSAddressConverted) + req.CustomDNSAddress = &customAddr + } + + if cmd.Flag(extraIFaceBlackListFlag).Changed { + req.ExtraIFaceBlacklist = setFlags.ExtraIFaceBlackList + } + + if cmd.Flag(dnsLabelsFlag).Changed { + req.DnsLabels = setFlags.DNSLabels + req.CleanDNSLabels = &[]bool{setFlags.DNSLabels != nil && len(setFlags.DNSLabels) == 0}[0] + } + + if cmd.Flag(externalIPMapFlag).Changed { + req.NatExternalIPs = setFlags.NATExternalIPs + req.CleanNATExternalIPs = &[]bool{setFlags.NATExternalIPs != nil && len(setFlags.NATExternalIPs) == 0}[0] + } + + if cmd.Flag(dnsRouteIntervalFlag).Changed { + req.DnsRouteInterval = durationpb.New(setFlags.DNSRouteInterval) + } + + if cmd.Flag(disableClientRoutesFlag).Changed { + req.DisableClientRoutes = &setFlags.DisableClientRoutes + } + + if cmd.Flag(disableServerRoutesFlag).Changed { + req.DisableServerRoutes = &setFlags.DisableServerRoutes + } + + if cmd.Flag(disableDNSFlag).Changed { + req.DisableDns = &setFlags.DisableDNS + } + + if cmd.Flag(disableFirewallFlag).Changed { + req.DisableFirewall = &setFlags.DisableFirewall + } + + if cmd.Flag(blockLANAccessFlag).Changed { + req.BlockLanAccess = &setFlags.BlockLANAccess + } + + if cmd.Flag(blockInboundFlag).Changed { + req.BlockInbound = &setFlags.BlockInbound + } + + if cmd.Flag(enableLazyConnectionFlag).Changed { + req.LazyConnectionEnabled = &setFlags.LazyConnEnabled + } + + // Send the request + if _, err := client.SetConfig(ctx, req); err != nil { + return fmt.Errorf("update configuration: %w", err) + } + + cmd.Println("Configuration updated successfully") + return nil +} diff --git a/client/cmd/set_test.go b/client/cmd/set_test.go new file mode 100644 index 000000000..7abd02b68 --- /dev/null +++ b/client/cmd/set_test.go @@ -0,0 +1,110 @@ +package cmd + +import ( + "testing" + + "github.com/spf13/cobra" +) + +func TestParseBoolArg(t *testing.T) { + tests := []struct { + input string + expected bool + hasError bool + }{ + {"true", true, false}, + {"True", true, false}, + {"1", true, false}, + {"yes", true, false}, + {"on", true, false}, + {"false", false, false}, + {"False", false, false}, + {"0", false, false}, + {"no", false, false}, + {"off", false, false}, + {"invalid", false, true}, + {"maybe", false, true}, + {"", false, true}, + } + + for _, test := range tests { + t.Run(test.input, func(t *testing.T) { + result, err := parseBoolArg(test.input) + + if test.hasError { + if err == nil { + t.Errorf("Expected error for input %q, but got none", test.input) + } + } else { + if err != nil { + t.Errorf("Unexpected error for input %q: %v", test.input, err) + } + if result != test.expected { + t.Errorf("For input %q, expected %v but got %v", test.input, test.expected, result) + } + } + }) + } +} + +func TestSetCommandStructure(t *testing.T) { + // Test that the set command has the expected subcommands + expectedSubcommands := []string{ + "autoconnect", + "ssh-server", + "network-monitor", + "rosenpass", + "dns", + "dns-interval", + } + + actualSubcommands := make([]string, 0, len(setCmd.Commands())) + for _, cmd := range setCmd.Commands() { + actualSubcommands = append(actualSubcommands, cmd.Name()) + } + + if len(actualSubcommands) != len(expectedSubcommands) { + t.Errorf("Expected %d subcommands, got %d", len(expectedSubcommands), len(actualSubcommands)) + } + + for _, expected := range expectedSubcommands { + found := false + for _, actual := range actualSubcommands { + if actual == expected { + found = true + break + } + } + if !found { + t.Errorf("Expected subcommand %q not found", expected) + } + } +} + +func TestSetCommandUsage(t *testing.T) { + if setCmd.Use != "set" { + t.Errorf("Expected command use to be 'set', got %q", setCmd.Use) + } + + if setCmd.Short != "Set NetBird client configuration" { + t.Errorf("Expected short description to be 'Set NetBird client configuration', got %q", setCmd.Short) + } +} + +func TestSubcommandArgRequirements(t *testing.T) { + // Test that all subcommands except dns-interval require exactly 1 argument + subcommands := []*cobra.Command{ + setAutoconnectCmd, + setSSHServerCmd, + setNetworkMonitorCmd, + setRosenpassCmd, + setDNSCmd, + setDNSIntervalCmd, + } + + for _, cmd := range subcommands { + if cmd.Args == nil { + t.Errorf("Command %q should have Args validation", cmd.Name()) + } + } +} \ No newline at end of file diff --git a/client/cmd/system.go b/client/cmd/system.go index f63432401..fa9d7e02f 100644 --- a/client/cmd/system.go +++ b/client/cmd/system.go @@ -19,24 +19,3 @@ var ( blockInbound bool ) -func init() { - // Add system flags to upCmd - upCmd.PersistentFlags().BoolVar(&disableClientRoutes, disableClientRoutesFlag, false, - "Disable client routes. If enabled, the client won't process client routes received from the management service.") - - upCmd.PersistentFlags().BoolVar(&disableServerRoutes, disableServerRoutesFlag, false, - "Disable server routes. If enabled, the client won't act as a router for server routes received from the management service.") - - upCmd.PersistentFlags().BoolVar(&disableDNS, disableDNSFlag, false, - "Disable DNS. If enabled, the client won't configure DNS settings.") - - upCmd.PersistentFlags().BoolVar(&disableFirewall, disableFirewallFlag, false, - "Disable firewall configuration. If enabled, the client won't modify firewall rules.") - - upCmd.PersistentFlags().BoolVar(&blockLANAccess, blockLANAccessFlag, false, - "Block access to local networks (LAN) when using this peer as a router or exit node") - - upCmd.PersistentFlags().BoolVar(&blockInbound, blockInboundFlag, false, - "Block inbound connections. If enabled, the client will not allow any inbound connections to the local machine nor routed networks.\n"+ - "This overrides any policies received from the management service.") -} diff --git a/client/cmd/up.go b/client/cmd/up.go index b9781c0df..3acea3731 100644 --- a/client/cmd/up.go +++ b/client/cmd/up.go @@ -7,7 +7,6 @@ import ( "net/netip" "runtime" "strings" - "time" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -15,7 +14,6 @@ import ( gstatus "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/durationpb" - "github.com/netbirdio/netbird/client/iface" "github.com/netbirdio/netbird/client/internal" "github.com/netbirdio/netbird/client/internal/peer" "github.com/netbirdio/netbird/client/proto" @@ -42,6 +40,7 @@ var ( dnsLabels []string dnsLabelsValidated domain.List noBrowser bool + upFlags = &SharedFlags{} upCmd = &cobra.Command{ Use: "up", @@ -51,26 +50,12 @@ var ( ) func init() { + // Add shared flags to up command + AddSharedFlags(upCmd, upFlags) + + // Add up-specific flags upCmd.PersistentFlags().BoolVarP(&foregroundMode, "foreground-mode", "F", false, "start service in foreground") - upCmd.PersistentFlags().StringVar(&interfaceName, interfaceNameFlag, iface.WgInterfaceDefault, "Wireguard interface name") - upCmd.PersistentFlags().Uint16Var(&wireguardPort, wireguardPortFlag, iface.DefaultWgPort, "Wireguard interface listening port") - upCmd.PersistentFlags().BoolVarP(&networkMonitor, networkMonitorFlag, "N", networkMonitor, - `Manage network monitoring. Defaults to true on Windows and macOS, false on Linux and FreeBSD. `+ - `E.g. --network-monitor=false to disable or --network-monitor=true to enable.`, - ) - upCmd.PersistentFlags().StringSliceVar(&extraIFaceBlackList, extraIFaceBlackListFlag, nil, "Extra list of default interfaces to ignore for listening") - upCmd.PersistentFlags().DurationVar(&dnsRouteInterval, dnsRouteIntervalFlag, time.Minute, "DNS route update interval") - - upCmd.PersistentFlags().StringSliceVar(&dnsLabels, dnsLabelsFlag, nil, - `Sets DNS labels`+ - `You can specify a comma-separated list of up to 32 labels. `+ - `An empty string "" clears the previous configuration. `+ - `E.g. --extra-dns-labels vpc1 or --extra-dns-labels vpc1,mgmt1 `+ - `or --extra-dns-labels ""`, - ) - - upCmd.PersistentFlags().BoolVar(&noBrowser, noBrowserFlag, false, noBrowserDesc) - + AddUpOnlyFlags(upCmd, upFlags) } func upFunc(cmd *cobra.Command, args []string) error { @@ -118,7 +103,16 @@ func runInForegroundMode(ctx context.Context, cmd *cobra.Command) error { return err } - ic, err := setupConfig(customDNSAddressConverted, cmd) + // Handle DNS labels validation and assignment to SharedFlags + if cmd.Flag(dnsLabelsFlag).Changed { + var err error + dnsLabelsValidated, err = validateDnsLabels(upFlags.DNSLabels) + if err != nil { + return err + } + } + + ic, err := BuildConfigInput(cmd, upFlags, customDNSAddressConverted) if err != nil { return fmt.Errorf("setup config: %v", err) } @@ -235,92 +229,6 @@ func runInDaemonMode(ctx context.Context, cmd *cobra.Command) error { return nil } -func setupConfig(customDNSAddressConverted []byte, cmd *cobra.Command) (*internal.ConfigInput, error) { - ic := internal.ConfigInput{ - ManagementURL: managementURL, - AdminURL: adminURL, - ConfigPath: configPath, - NATExternalIPs: natExternalIPs, - CustomDNSAddress: customDNSAddressConverted, - ExtraIFaceBlackList: extraIFaceBlackList, - DNSLabels: dnsLabelsValidated, - } - - if cmd.Flag(enableRosenpassFlag).Changed { - ic.RosenpassEnabled = &rosenpassEnabled - } - - if cmd.Flag(rosenpassPermissiveFlag).Changed { - ic.RosenpassPermissive = &rosenpassPermissive - } - - if cmd.Flag(serverSSHAllowedFlag).Changed { - ic.ServerSSHAllowed = &serverSSHAllowed - } - - if cmd.Flag(interfaceNameFlag).Changed { - if err := parseInterfaceName(interfaceName); err != nil { - return nil, err - } - ic.InterfaceName = &interfaceName - } - - if cmd.Flag(wireguardPortFlag).Changed { - p := int(wireguardPort) - ic.WireguardPort = &p - } - - if cmd.Flag(networkMonitorFlag).Changed { - ic.NetworkMonitor = &networkMonitor - } - - if rootCmd.PersistentFlags().Changed(preSharedKeyFlag) { - ic.PreSharedKey = &preSharedKey - } - - if cmd.Flag(disableAutoConnectFlag).Changed { - ic.DisableAutoConnect = &autoConnectDisabled - - if autoConnectDisabled { - cmd.Println("Autoconnect has been disabled. The client won't connect automatically when the service starts.") - } - - if !autoConnectDisabled { - cmd.Println("Autoconnect has been enabled. The client will connect automatically when the service starts.") - } - } - - if cmd.Flag(dnsRouteIntervalFlag).Changed { - ic.DNSRouteInterval = &dnsRouteInterval - } - - if cmd.Flag(disableClientRoutesFlag).Changed { - ic.DisableClientRoutes = &disableClientRoutes - } - if cmd.Flag(disableServerRoutesFlag).Changed { - ic.DisableServerRoutes = &disableServerRoutes - } - if cmd.Flag(disableDNSFlag).Changed { - ic.DisableDNS = &disableDNS - } - if cmd.Flag(disableFirewallFlag).Changed { - ic.DisableFirewall = &disableFirewall - } - - if cmd.Flag(blockLANAccessFlag).Changed { - ic.BlockLANAccess = &blockLANAccess - } - - if cmd.Flag(blockInboundFlag).Changed { - ic.BlockInbound = &blockInbound - } - - if cmd.Flag(enableLazyConnectionFlag).Changed { - ic.LazyConnectionEnabled = &lazyConnEnabled - } - return &ic, nil -} - func setupLoginRequest(providedSetupKey string, customDNSAddressConverted []byte, cmd *cobra.Command) (*proto.LoginRequest, error) { loginRequest := proto.LoginRequest{ SetupKey: providedSetupKey, diff --git a/client/proto/daemon.pb.go b/client/proto/daemon.pb.go index 202dc6f89..1a23bc426 100644 --- a/client/proto/daemon.pb.go +++ b/client/proto/daemon.pb.go @@ -3495,6 +3495,246 @@ func (x *GetEventsResponse) GetEvents() []*SystemEvent { return nil } +type SetConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RosenpassEnabled *bool `protobuf:"varint,1,opt,name=rosenpassEnabled,proto3,oneof" json:"rosenpassEnabled,omitempty"` + RosenpassPermissive *bool `protobuf:"varint,2,opt,name=rosenpassPermissive,proto3,oneof" json:"rosenpassPermissive,omitempty"` + ServerSSHAllowed *bool `protobuf:"varint,3,opt,name=serverSSHAllowed,proto3,oneof" json:"serverSSHAllowed,omitempty"` + DisableAutoConnect *bool `protobuf:"varint,4,opt,name=disableAutoConnect,proto3,oneof" json:"disableAutoConnect,omitempty"` + NetworkMonitor *bool `protobuf:"varint,5,opt,name=networkMonitor,proto3,oneof" json:"networkMonitor,omitempty"` + DnsRouteInterval *durationpb.Duration `protobuf:"bytes,6,opt,name=dnsRouteInterval,proto3,oneof" json:"dnsRouteInterval,omitempty"` + DisableClientRoutes *bool `protobuf:"varint,7,opt,name=disable_client_routes,json=disableClientRoutes,proto3,oneof" json:"disable_client_routes,omitempty"` + DisableServerRoutes *bool `protobuf:"varint,8,opt,name=disable_server_routes,json=disableServerRoutes,proto3,oneof" json:"disable_server_routes,omitempty"` + DisableDns *bool `protobuf:"varint,9,opt,name=disable_dns,json=disableDns,proto3,oneof" json:"disable_dns,omitempty"` + DisableFirewall *bool `protobuf:"varint,10,opt,name=disable_firewall,json=disableFirewall,proto3,oneof" json:"disable_firewall,omitempty"` + BlockLanAccess *bool `protobuf:"varint,11,opt,name=block_lan_access,json=blockLanAccess,proto3,oneof" json:"block_lan_access,omitempty"` + LazyConnectionEnabled *bool `protobuf:"varint,12,opt,name=lazyConnectionEnabled,proto3,oneof" json:"lazyConnectionEnabled,omitempty"` + BlockInbound *bool `protobuf:"varint,13,opt,name=block_inbound,json=blockInbound,proto3,oneof" json:"block_inbound,omitempty"` + InterfaceName *string `protobuf:"bytes,14,opt,name=interfaceName,proto3,oneof" json:"interfaceName,omitempty"` + WireguardPort *int64 `protobuf:"varint,15,opt,name=wireguardPort,proto3,oneof" json:"wireguardPort,omitempty"` + CustomDNSAddress *string `protobuf:"bytes,16,opt,name=customDNSAddress,proto3,oneof" json:"customDNSAddress,omitempty"` + ExtraIFaceBlacklist []string `protobuf:"bytes,17,rep,name=extraIFaceBlacklist,proto3" json:"extraIFaceBlacklist,omitempty"` + DnsLabels []string `protobuf:"bytes,18,rep,name=dns_labels,json=dnsLabels,proto3" json:"dns_labels,omitempty"` + CleanDNSLabels *bool `protobuf:"varint,19,opt,name=cleanDNSLabels,proto3,oneof" json:"cleanDNSLabels,omitempty"` + NatExternalIPs []string `protobuf:"bytes,20,rep,name=natExternalIPs,proto3" json:"natExternalIPs,omitempty"` + CleanNATExternalIPs *bool `protobuf:"varint,21,opt,name=cleanNATExternalIPs,proto3,oneof" json:"cleanNATExternalIPs,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SetConfigRequest) Reset() { + *x = SetConfigRequest{} + mi := &file_daemon_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetConfigRequest) ProtoMessage() {} + +func (x *SetConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[52] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetConfigRequest.ProtoReflect.Descriptor instead. +func (*SetConfigRequest) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{52} +} + +func (x *SetConfigRequest) GetRosenpassEnabled() bool { + if x != nil && x.RosenpassEnabled != nil { + return *x.RosenpassEnabled + } + return false +} + +func (x *SetConfigRequest) GetRosenpassPermissive() bool { + if x != nil && x.RosenpassPermissive != nil { + return *x.RosenpassPermissive + } + return false +} + +func (x *SetConfigRequest) GetServerSSHAllowed() bool { + if x != nil && x.ServerSSHAllowed != nil { + return *x.ServerSSHAllowed + } + return false +} + +func (x *SetConfigRequest) GetDisableAutoConnect() bool { + if x != nil && x.DisableAutoConnect != nil { + return *x.DisableAutoConnect + } + return false +} + +func (x *SetConfigRequest) GetNetworkMonitor() bool { + if x != nil && x.NetworkMonitor != nil { + return *x.NetworkMonitor + } + return false +} + +func (x *SetConfigRequest) GetDnsRouteInterval() *durationpb.Duration { + if x != nil { + return x.DnsRouteInterval + } + return nil +} + +func (x *SetConfigRequest) GetDisableClientRoutes() bool { + if x != nil && x.DisableClientRoutes != nil { + return *x.DisableClientRoutes + } + return false +} + +func (x *SetConfigRequest) GetDisableServerRoutes() bool { + if x != nil && x.DisableServerRoutes != nil { + return *x.DisableServerRoutes + } + return false +} + +func (x *SetConfigRequest) GetDisableDns() bool { + if x != nil && x.DisableDns != nil { + return *x.DisableDns + } + return false +} + +func (x *SetConfigRequest) GetDisableFirewall() bool { + if x != nil && x.DisableFirewall != nil { + return *x.DisableFirewall + } + return false +} + +func (x *SetConfigRequest) GetBlockLanAccess() bool { + if x != nil && x.BlockLanAccess != nil { + return *x.BlockLanAccess + } + return false +} + +func (x *SetConfigRequest) GetLazyConnectionEnabled() bool { + if x != nil && x.LazyConnectionEnabled != nil { + return *x.LazyConnectionEnabled + } + return false +} + +func (x *SetConfigRequest) GetBlockInbound() bool { + if x != nil && x.BlockInbound != nil { + return *x.BlockInbound + } + return false +} + +func (x *SetConfigRequest) GetInterfaceName() string { + if x != nil && x.InterfaceName != nil { + return *x.InterfaceName + } + return "" +} + +func (x *SetConfigRequest) GetWireguardPort() int64 { + if x != nil && x.WireguardPort != nil { + return *x.WireguardPort + } + return 0 +} + +func (x *SetConfigRequest) GetCustomDNSAddress() string { + if x != nil && x.CustomDNSAddress != nil { + return *x.CustomDNSAddress + } + return "" +} + +func (x *SetConfigRequest) GetExtraIFaceBlacklist() []string { + if x != nil { + return x.ExtraIFaceBlacklist + } + return nil +} + +func (x *SetConfigRequest) GetDnsLabels() []string { + if x != nil { + return x.DnsLabels + } + return nil +} + +func (x *SetConfigRequest) GetCleanDNSLabels() bool { + if x != nil && x.CleanDNSLabels != nil { + return *x.CleanDNSLabels + } + return false +} + +func (x *SetConfigRequest) GetNatExternalIPs() []string { + if x != nil { + return x.NatExternalIPs + } + return nil +} + +func (x *SetConfigRequest) GetCleanNATExternalIPs() bool { + if x != nil && x.CleanNATExternalIPs != nil { + return *x.CleanNATExternalIPs + } + return false +} + +type SetConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SetConfigResponse) Reset() { + *x = SetConfigResponse{} + mi := &file_daemon_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetConfigResponse) ProtoMessage() {} + +func (x *SetConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_daemon_proto_msgTypes[53] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetConfigResponse.ProtoReflect.Descriptor instead. +func (*SetConfigResponse) Descriptor() ([]byte, []int) { + return file_daemon_proto_rawDescGZIP(), []int{53} +} + type PortInfo_Range struct { state protoimpl.MessageState `protogen:"open.v1"` Start uint32 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` @@ -3505,7 +3745,7 @@ type PortInfo_Range struct { func (x *PortInfo_Range) Reset() { *x = PortInfo_Range{} - mi := &file_daemon_proto_msgTypes[53] + mi := &file_daemon_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3517,7 +3757,7 @@ func (x *PortInfo_Range) String() string { func (*PortInfo_Range) ProtoMessage() {} func (x *PortInfo_Range) ProtoReflect() protoreflect.Message { - mi := &file_daemon_proto_msgTypes[53] + mi := &file_daemon_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3844,7 +4084,52 @@ const file_daemon_proto_rawDesc = "" + "\x06SYSTEM\x10\x04\"\x12\n" + "\x10GetEventsRequest\"@\n" + "\x11GetEventsResponse\x12+\n" + - "\x06events\x18\x01 \x03(\v2\x13.daemon.SystemEventR\x06events*b\n" + + "\x06events\x18\x01 \x03(\v2\x13.daemon.SystemEventR\x06events\"\x98\v\n" + + "\x10SetConfigRequest\x12/\n" + + "\x10rosenpassEnabled\x18\x01 \x01(\bH\x00R\x10rosenpassEnabled\x88\x01\x01\x125\n" + + "\x13rosenpassPermissive\x18\x02 \x01(\bH\x01R\x13rosenpassPermissive\x88\x01\x01\x12/\n" + + "\x10serverSSHAllowed\x18\x03 \x01(\bH\x02R\x10serverSSHAllowed\x88\x01\x01\x123\n" + + "\x12disableAutoConnect\x18\x04 \x01(\bH\x03R\x12disableAutoConnect\x88\x01\x01\x12+\n" + + "\x0enetworkMonitor\x18\x05 \x01(\bH\x04R\x0enetworkMonitor\x88\x01\x01\x12J\n" + + "\x10dnsRouteInterval\x18\x06 \x01(\v2\x19.google.protobuf.DurationH\x05R\x10dnsRouteInterval\x88\x01\x01\x127\n" + + "\x15disable_client_routes\x18\a \x01(\bH\x06R\x13disableClientRoutes\x88\x01\x01\x127\n" + + "\x15disable_server_routes\x18\b \x01(\bH\aR\x13disableServerRoutes\x88\x01\x01\x12$\n" + + "\vdisable_dns\x18\t \x01(\bH\bR\n" + + "disableDns\x88\x01\x01\x12.\n" + + "\x10disable_firewall\x18\n" + + " \x01(\bH\tR\x0fdisableFirewall\x88\x01\x01\x12-\n" + + "\x10block_lan_access\x18\v \x01(\bH\n" + + "R\x0eblockLanAccess\x88\x01\x01\x129\n" + + "\x15lazyConnectionEnabled\x18\f \x01(\bH\vR\x15lazyConnectionEnabled\x88\x01\x01\x12(\n" + + "\rblock_inbound\x18\r \x01(\bH\fR\fblockInbound\x88\x01\x01\x12)\n" + + "\rinterfaceName\x18\x0e \x01(\tH\rR\rinterfaceName\x88\x01\x01\x12)\n" + + "\rwireguardPort\x18\x0f \x01(\x03H\x0eR\rwireguardPort\x88\x01\x01\x12/\n" + + "\x10customDNSAddress\x18\x10 \x01(\tH\x0fR\x10customDNSAddress\x88\x01\x01\x120\n" + + "\x13extraIFaceBlacklist\x18\x11 \x03(\tR\x13extraIFaceBlacklist\x12\x1d\n" + + "\n" + + "dns_labels\x18\x12 \x03(\tR\tdnsLabels\x12+\n" + + "\x0ecleanDNSLabels\x18\x13 \x01(\bH\x10R\x0ecleanDNSLabels\x88\x01\x01\x12&\n" + + "\x0enatExternalIPs\x18\x14 \x03(\tR\x0enatExternalIPs\x125\n" + + "\x13cleanNATExternalIPs\x18\x15 \x01(\bH\x11R\x13cleanNATExternalIPs\x88\x01\x01B\x13\n" + + "\x11_rosenpassEnabledB\x16\n" + + "\x14_rosenpassPermissiveB\x13\n" + + "\x11_serverSSHAllowedB\x15\n" + + "\x13_disableAutoConnectB\x11\n" + + "\x0f_networkMonitorB\x13\n" + + "\x11_dnsRouteIntervalB\x18\n" + + "\x16_disable_client_routesB\x18\n" + + "\x16_disable_server_routesB\x0e\n" + + "\f_disable_dnsB\x13\n" + + "\x11_disable_firewallB\x13\n" + + "\x11_block_lan_accessB\x18\n" + + "\x16_lazyConnectionEnabledB\x10\n" + + "\x0e_block_inboundB\x10\n" + + "\x0e_interfaceNameB\x10\n" + + "\x0e_wireguardPortB\x13\n" + + "\x11_customDNSAddressB\x11\n" + + "\x0f_cleanDNSLabelsB\x16\n" + + "\x14_cleanNATExternalIPs\"\x13\n" + + "\x11SetConfigResponse*b\n" + "\bLogLevel\x12\v\n" + "\aUNKNOWN\x10\x00\x12\t\n" + "\x05PANIC\x10\x01\x12\t\n" + @@ -3853,7 +4138,7 @@ const file_daemon_proto_rawDesc = "" + "\x04WARN\x10\x04\x12\b\n" + "\x04INFO\x10\x05\x12\t\n" + "\x05DEBUG\x10\x06\x12\t\n" + - "\x05TRACE\x10\a2\xb3\v\n" + + "\x05TRACE\x10\a2\xf7\v\n" + "\rDaemonService\x126\n" + "\x05Login\x12\x14.daemon.LoginRequest\x1a\x15.daemon.LoginResponse\"\x00\x12K\n" + "\fWaitSSOLogin\x12\x1b.daemon.WaitSSOLoginRequest\x1a\x1c.daemon.WaitSSOLoginResponse\"\x00\x12-\n" + @@ -3876,7 +4161,8 @@ const file_daemon_proto_rawDesc = "" + "\x18SetNetworkMapPersistence\x12'.daemon.SetNetworkMapPersistenceRequest\x1a(.daemon.SetNetworkMapPersistenceResponse\"\x00\x12H\n" + "\vTracePacket\x12\x1a.daemon.TracePacketRequest\x1a\x1b.daemon.TracePacketResponse\"\x00\x12D\n" + "\x0fSubscribeEvents\x12\x18.daemon.SubscribeRequest\x1a\x13.daemon.SystemEvent\"\x000\x01\x12B\n" + - "\tGetEvents\x12\x18.daemon.GetEventsRequest\x1a\x19.daemon.GetEventsResponse\"\x00B\bZ\x06/protob\x06proto3" + "\tGetEvents\x12\x18.daemon.GetEventsRequest\x1a\x19.daemon.GetEventsResponse\"\x00\x12B\n" + + "\tSetConfig\x12\x18.daemon.SetConfigRequest\x1a\x19.daemon.SetConfigResponse\"\x00B\bZ\x06/protob\x06proto3" var ( file_daemon_proto_rawDescOnce sync.Once @@ -3891,7 +4177,7 @@ func file_daemon_proto_rawDescGZIP() []byte { } var file_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 55) +var file_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 57) var file_daemon_proto_goTypes = []any{ (LogLevel)(0), // 0: daemon.LogLevel (SystemEvent_Severity)(0), // 1: daemon.SystemEvent.Severity @@ -3948,18 +4234,20 @@ var file_daemon_proto_goTypes = []any{ (*SystemEvent)(nil), // 52: daemon.SystemEvent (*GetEventsRequest)(nil), // 53: daemon.GetEventsRequest (*GetEventsResponse)(nil), // 54: daemon.GetEventsResponse - nil, // 55: daemon.Network.ResolvedIPsEntry - (*PortInfo_Range)(nil), // 56: daemon.PortInfo.Range - nil, // 57: daemon.SystemEvent.MetadataEntry - (*durationpb.Duration)(nil), // 58: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 59: google.protobuf.Timestamp + (*SetConfigRequest)(nil), // 55: daemon.SetConfigRequest + (*SetConfigResponse)(nil), // 56: daemon.SetConfigResponse + nil, // 57: daemon.Network.ResolvedIPsEntry + (*PortInfo_Range)(nil), // 58: daemon.PortInfo.Range + nil, // 59: daemon.SystemEvent.MetadataEntry + (*durationpb.Duration)(nil), // 60: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 61: google.protobuf.Timestamp } var file_daemon_proto_depIdxs = []int32{ - 58, // 0: daemon.LoginRequest.dnsRouteInterval:type_name -> google.protobuf.Duration + 60, // 0: daemon.LoginRequest.dnsRouteInterval:type_name -> google.protobuf.Duration 22, // 1: daemon.StatusResponse.fullStatus:type_name -> daemon.FullStatus - 59, // 2: daemon.PeerState.connStatusUpdate:type_name -> google.protobuf.Timestamp - 59, // 3: daemon.PeerState.lastWireguardHandshake:type_name -> google.protobuf.Timestamp - 58, // 4: daemon.PeerState.latency:type_name -> google.protobuf.Duration + 61, // 2: daemon.PeerState.connStatusUpdate:type_name -> google.protobuf.Timestamp + 61, // 3: daemon.PeerState.lastWireguardHandshake:type_name -> google.protobuf.Timestamp + 60, // 4: daemon.PeerState.latency:type_name -> google.protobuf.Duration 19, // 5: daemon.FullStatus.managementState:type_name -> daemon.ManagementState 18, // 6: daemon.FullStatus.signalState:type_name -> daemon.SignalState 17, // 7: daemon.FullStatus.localPeerState:type_name -> daemon.LocalPeerState @@ -3968,8 +4256,8 @@ var file_daemon_proto_depIdxs = []int32{ 21, // 10: daemon.FullStatus.dns_servers:type_name -> daemon.NSGroupState 52, // 11: daemon.FullStatus.events:type_name -> daemon.SystemEvent 28, // 12: daemon.ListNetworksResponse.routes:type_name -> daemon.Network - 55, // 13: daemon.Network.resolvedIPs:type_name -> daemon.Network.ResolvedIPsEntry - 56, // 14: daemon.PortInfo.range:type_name -> daemon.PortInfo.Range + 57, // 13: daemon.Network.resolvedIPs:type_name -> daemon.Network.ResolvedIPsEntry + 58, // 14: daemon.PortInfo.range:type_name -> daemon.PortInfo.Range 29, // 15: daemon.ForwardingRule.destinationPort:type_name -> daemon.PortInfo 29, // 16: daemon.ForwardingRule.translatedPort:type_name -> daemon.PortInfo 30, // 17: daemon.ForwardingRulesResponse.rules:type_name -> daemon.ForwardingRule @@ -3980,55 +4268,58 @@ var file_daemon_proto_depIdxs = []int32{ 49, // 22: daemon.TracePacketResponse.stages:type_name -> daemon.TraceStage 1, // 23: daemon.SystemEvent.severity:type_name -> daemon.SystemEvent.Severity 2, // 24: daemon.SystemEvent.category:type_name -> daemon.SystemEvent.Category - 59, // 25: daemon.SystemEvent.timestamp:type_name -> google.protobuf.Timestamp - 57, // 26: daemon.SystemEvent.metadata:type_name -> daemon.SystemEvent.MetadataEntry + 61, // 25: daemon.SystemEvent.timestamp:type_name -> google.protobuf.Timestamp + 59, // 26: daemon.SystemEvent.metadata:type_name -> daemon.SystemEvent.MetadataEntry 52, // 27: daemon.GetEventsResponse.events:type_name -> daemon.SystemEvent - 27, // 28: daemon.Network.ResolvedIPsEntry.value:type_name -> daemon.IPList - 4, // 29: daemon.DaemonService.Login:input_type -> daemon.LoginRequest - 6, // 30: daemon.DaemonService.WaitSSOLogin:input_type -> daemon.WaitSSOLoginRequest - 8, // 31: daemon.DaemonService.Up:input_type -> daemon.UpRequest - 10, // 32: daemon.DaemonService.Status:input_type -> daemon.StatusRequest - 12, // 33: daemon.DaemonService.Down:input_type -> daemon.DownRequest - 14, // 34: daemon.DaemonService.GetConfig:input_type -> daemon.GetConfigRequest - 23, // 35: daemon.DaemonService.ListNetworks:input_type -> daemon.ListNetworksRequest - 25, // 36: daemon.DaemonService.SelectNetworks:input_type -> daemon.SelectNetworksRequest - 25, // 37: daemon.DaemonService.DeselectNetworks:input_type -> daemon.SelectNetworksRequest - 3, // 38: daemon.DaemonService.ForwardingRules:input_type -> daemon.EmptyRequest - 32, // 39: daemon.DaemonService.DebugBundle:input_type -> daemon.DebugBundleRequest - 34, // 40: daemon.DaemonService.GetLogLevel:input_type -> daemon.GetLogLevelRequest - 36, // 41: daemon.DaemonService.SetLogLevel:input_type -> daemon.SetLogLevelRequest - 39, // 42: daemon.DaemonService.ListStates:input_type -> daemon.ListStatesRequest - 41, // 43: daemon.DaemonService.CleanState:input_type -> daemon.CleanStateRequest - 43, // 44: daemon.DaemonService.DeleteState:input_type -> daemon.DeleteStateRequest - 45, // 45: daemon.DaemonService.SetNetworkMapPersistence:input_type -> daemon.SetNetworkMapPersistenceRequest - 48, // 46: daemon.DaemonService.TracePacket:input_type -> daemon.TracePacketRequest - 51, // 47: daemon.DaemonService.SubscribeEvents:input_type -> daemon.SubscribeRequest - 53, // 48: daemon.DaemonService.GetEvents:input_type -> daemon.GetEventsRequest - 5, // 49: daemon.DaemonService.Login:output_type -> daemon.LoginResponse - 7, // 50: daemon.DaemonService.WaitSSOLogin:output_type -> daemon.WaitSSOLoginResponse - 9, // 51: daemon.DaemonService.Up:output_type -> daemon.UpResponse - 11, // 52: daemon.DaemonService.Status:output_type -> daemon.StatusResponse - 13, // 53: daemon.DaemonService.Down:output_type -> daemon.DownResponse - 15, // 54: daemon.DaemonService.GetConfig:output_type -> daemon.GetConfigResponse - 24, // 55: daemon.DaemonService.ListNetworks:output_type -> daemon.ListNetworksResponse - 26, // 56: daemon.DaemonService.SelectNetworks:output_type -> daemon.SelectNetworksResponse - 26, // 57: daemon.DaemonService.DeselectNetworks:output_type -> daemon.SelectNetworksResponse - 31, // 58: daemon.DaemonService.ForwardingRules:output_type -> daemon.ForwardingRulesResponse - 33, // 59: daemon.DaemonService.DebugBundle:output_type -> daemon.DebugBundleResponse - 35, // 60: daemon.DaemonService.GetLogLevel:output_type -> daemon.GetLogLevelResponse - 37, // 61: daemon.DaemonService.SetLogLevel:output_type -> daemon.SetLogLevelResponse - 40, // 62: daemon.DaemonService.ListStates:output_type -> daemon.ListStatesResponse - 42, // 63: daemon.DaemonService.CleanState:output_type -> daemon.CleanStateResponse - 44, // 64: daemon.DaemonService.DeleteState:output_type -> daemon.DeleteStateResponse - 46, // 65: daemon.DaemonService.SetNetworkMapPersistence:output_type -> daemon.SetNetworkMapPersistenceResponse - 50, // 66: daemon.DaemonService.TracePacket:output_type -> daemon.TracePacketResponse - 52, // 67: daemon.DaemonService.SubscribeEvents:output_type -> daemon.SystemEvent - 54, // 68: daemon.DaemonService.GetEvents:output_type -> daemon.GetEventsResponse - 49, // [49:69] is the sub-list for method output_type - 29, // [29:49] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 60, // 28: daemon.SetConfigRequest.dnsRouteInterval:type_name -> google.protobuf.Duration + 27, // 29: daemon.Network.ResolvedIPsEntry.value:type_name -> daemon.IPList + 4, // 30: daemon.DaemonService.Login:input_type -> daemon.LoginRequest + 6, // 31: daemon.DaemonService.WaitSSOLogin:input_type -> daemon.WaitSSOLoginRequest + 8, // 32: daemon.DaemonService.Up:input_type -> daemon.UpRequest + 10, // 33: daemon.DaemonService.Status:input_type -> daemon.StatusRequest + 12, // 34: daemon.DaemonService.Down:input_type -> daemon.DownRequest + 14, // 35: daemon.DaemonService.GetConfig:input_type -> daemon.GetConfigRequest + 23, // 36: daemon.DaemonService.ListNetworks:input_type -> daemon.ListNetworksRequest + 25, // 37: daemon.DaemonService.SelectNetworks:input_type -> daemon.SelectNetworksRequest + 25, // 38: daemon.DaemonService.DeselectNetworks:input_type -> daemon.SelectNetworksRequest + 3, // 39: daemon.DaemonService.ForwardingRules:input_type -> daemon.EmptyRequest + 32, // 40: daemon.DaemonService.DebugBundle:input_type -> daemon.DebugBundleRequest + 34, // 41: daemon.DaemonService.GetLogLevel:input_type -> daemon.GetLogLevelRequest + 36, // 42: daemon.DaemonService.SetLogLevel:input_type -> daemon.SetLogLevelRequest + 39, // 43: daemon.DaemonService.ListStates:input_type -> daemon.ListStatesRequest + 41, // 44: daemon.DaemonService.CleanState:input_type -> daemon.CleanStateRequest + 43, // 45: daemon.DaemonService.DeleteState:input_type -> daemon.DeleteStateRequest + 45, // 46: daemon.DaemonService.SetNetworkMapPersistence:input_type -> daemon.SetNetworkMapPersistenceRequest + 48, // 47: daemon.DaemonService.TracePacket:input_type -> daemon.TracePacketRequest + 51, // 48: daemon.DaemonService.SubscribeEvents:input_type -> daemon.SubscribeRequest + 53, // 49: daemon.DaemonService.GetEvents:input_type -> daemon.GetEventsRequest + 55, // 50: daemon.DaemonService.SetConfig:input_type -> daemon.SetConfigRequest + 5, // 51: daemon.DaemonService.Login:output_type -> daemon.LoginResponse + 7, // 52: daemon.DaemonService.WaitSSOLogin:output_type -> daemon.WaitSSOLoginResponse + 9, // 53: daemon.DaemonService.Up:output_type -> daemon.UpResponse + 11, // 54: daemon.DaemonService.Status:output_type -> daemon.StatusResponse + 13, // 55: daemon.DaemonService.Down:output_type -> daemon.DownResponse + 15, // 56: daemon.DaemonService.GetConfig:output_type -> daemon.GetConfigResponse + 24, // 57: daemon.DaemonService.ListNetworks:output_type -> daemon.ListNetworksResponse + 26, // 58: daemon.DaemonService.SelectNetworks:output_type -> daemon.SelectNetworksResponse + 26, // 59: daemon.DaemonService.DeselectNetworks:output_type -> daemon.SelectNetworksResponse + 31, // 60: daemon.DaemonService.ForwardingRules:output_type -> daemon.ForwardingRulesResponse + 33, // 61: daemon.DaemonService.DebugBundle:output_type -> daemon.DebugBundleResponse + 35, // 62: daemon.DaemonService.GetLogLevel:output_type -> daemon.GetLogLevelResponse + 37, // 63: daemon.DaemonService.SetLogLevel:output_type -> daemon.SetLogLevelResponse + 40, // 64: daemon.DaemonService.ListStates:output_type -> daemon.ListStatesResponse + 42, // 65: daemon.DaemonService.CleanState:output_type -> daemon.CleanStateResponse + 44, // 66: daemon.DaemonService.DeleteState:output_type -> daemon.DeleteStateResponse + 46, // 67: daemon.DaemonService.SetNetworkMapPersistence:output_type -> daemon.SetNetworkMapPersistenceResponse + 50, // 68: daemon.DaemonService.TracePacket:output_type -> daemon.TracePacketResponse + 52, // 69: daemon.DaemonService.SubscribeEvents:output_type -> daemon.SystemEvent + 54, // 70: daemon.DaemonService.GetEvents:output_type -> daemon.GetEventsResponse + 56, // 71: daemon.DaemonService.SetConfig:output_type -> daemon.SetConfigResponse + 51, // [51:72] is the sub-list for method output_type + 30, // [30:51] is the sub-list for method input_type + 30, // [30:30] is the sub-list for extension type_name + 30, // [30:30] is the sub-list for extension extendee + 0, // [0:30] is the sub-list for field type_name } func init() { file_daemon_proto_init() } @@ -4043,13 +4334,14 @@ func file_daemon_proto_init() { } file_daemon_proto_msgTypes[45].OneofWrappers = []any{} file_daemon_proto_msgTypes[46].OneofWrappers = []any{} + file_daemon_proto_msgTypes[52].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_daemon_proto_rawDesc), len(file_daemon_proto_rawDesc)), NumEnums: 3, - NumMessages: 55, + NumMessages: 57, NumExtensions: 0, NumServices: 1, }, diff --git a/client/proto/daemon.proto b/client/proto/daemon.proto index f488e69e7..57490df24 100644 --- a/client/proto/daemon.proto +++ b/client/proto/daemon.proto @@ -67,6 +67,9 @@ service DaemonService { rpc SubscribeEvents(SubscribeRequest) returns (stream SystemEvent) {} rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {} + + // SetConfig updates daemon configuration without reconnecting + rpc SetConfig(SetConfigRequest) returns (SetConfigResponse) {} } @@ -496,3 +499,29 @@ message GetEventsRequest {} message GetEventsResponse { repeated SystemEvent events = 1; } + +message SetConfigRequest { + optional bool rosenpassEnabled = 1; + optional bool rosenpassPermissive = 2; + optional bool serverSSHAllowed = 3; + optional bool disableAutoConnect = 4; + optional bool networkMonitor = 5; + optional google.protobuf.Duration dnsRouteInterval = 6; + optional bool disable_client_routes = 7; + optional bool disable_server_routes = 8; + optional bool disable_dns = 9; + optional bool disable_firewall = 10; + optional bool block_lan_access = 11; + optional bool lazyConnectionEnabled = 12; + optional bool block_inbound = 13; + optional string interfaceName = 14; + optional int64 wireguardPort = 15; + optional string customDNSAddress = 16; + repeated string extraIFaceBlacklist = 17; + repeated string dns_labels = 18; + optional bool cleanDNSLabels = 19; + repeated string natExternalIPs = 20; + optional bool cleanNATExternalIPs = 21; +} + +message SetConfigResponse {} diff --git a/client/proto/daemon_grpc.pb.go b/client/proto/daemon_grpc.pb.go index e0612a6d1..7b36245b2 100644 --- a/client/proto/daemon_grpc.pb.go +++ b/client/proto/daemon_grpc.pb.go @@ -1,8 +1,4 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.29.3 -// source: daemon.proto package proto @@ -15,31 +11,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - DaemonService_Login_FullMethodName = "/daemon.DaemonService/Login" - DaemonService_WaitSSOLogin_FullMethodName = "/daemon.DaemonService/WaitSSOLogin" - DaemonService_Up_FullMethodName = "/daemon.DaemonService/Up" - DaemonService_Status_FullMethodName = "/daemon.DaemonService/Status" - DaemonService_Down_FullMethodName = "/daemon.DaemonService/Down" - DaemonService_GetConfig_FullMethodName = "/daemon.DaemonService/GetConfig" - DaemonService_ListNetworks_FullMethodName = "/daemon.DaemonService/ListNetworks" - DaemonService_SelectNetworks_FullMethodName = "/daemon.DaemonService/SelectNetworks" - DaemonService_DeselectNetworks_FullMethodName = "/daemon.DaemonService/DeselectNetworks" - DaemonService_ForwardingRules_FullMethodName = "/daemon.DaemonService/ForwardingRules" - DaemonService_DebugBundle_FullMethodName = "/daemon.DaemonService/DebugBundle" - DaemonService_GetLogLevel_FullMethodName = "/daemon.DaemonService/GetLogLevel" - DaemonService_SetLogLevel_FullMethodName = "/daemon.DaemonService/SetLogLevel" - DaemonService_ListStates_FullMethodName = "/daemon.DaemonService/ListStates" - DaemonService_CleanState_FullMethodName = "/daemon.DaemonService/CleanState" - DaemonService_DeleteState_FullMethodName = "/daemon.DaemonService/DeleteState" - DaemonService_SetNetworkMapPersistence_FullMethodName = "/daemon.DaemonService/SetNetworkMapPersistence" - DaemonService_TracePacket_FullMethodName = "/daemon.DaemonService/TracePacket" - DaemonService_SubscribeEvents_FullMethodName = "/daemon.DaemonService/SubscribeEvents" - DaemonService_GetEvents_FullMethodName = "/daemon.DaemonService/GetEvents" -) +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 // DaemonServiceClient is the client API for DaemonService service. // @@ -80,8 +53,10 @@ type DaemonServiceClient interface { // SetNetworkMapPersistence enables or disables network map persistence SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error) TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) - SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SystemEvent], error) + SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) + // SetConfig updates daemon configuration without reconnecting + SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) } type daemonServiceClient struct { @@ -93,9 +68,8 @@ func NewDaemonServiceClient(cc grpc.ClientConnInterface) DaemonServiceClient { } func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(LoginResponse) - err := c.cc.Invoke(ctx, DaemonService_Login_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/Login", in, out, opts...) if err != nil { return nil, err } @@ -103,9 +77,8 @@ func (c *daemonServiceClient) Login(ctx context.Context, in *LoginRequest, opts } func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLoginRequest, opts ...grpc.CallOption) (*WaitSSOLoginResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(WaitSSOLoginResponse) - err := c.cc.Invoke(ctx, DaemonService_WaitSSOLogin_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/WaitSSOLogin", in, out, opts...) if err != nil { return nil, err } @@ -113,9 +86,8 @@ func (c *daemonServiceClient) WaitSSOLogin(ctx context.Context, in *WaitSSOLogin } func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grpc.CallOption) (*UpResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(UpResponse) - err := c.cc.Invoke(ctx, DaemonService_Up_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/Up", in, out, opts...) if err != nil { return nil, err } @@ -123,9 +95,8 @@ func (c *daemonServiceClient) Up(ctx context.Context, in *UpRequest, opts ...grp } func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(StatusResponse) - err := c.cc.Invoke(ctx, DaemonService_Status_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/Status", in, out, opts...) if err != nil { return nil, err } @@ -133,9 +104,8 @@ func (c *daemonServiceClient) Status(ctx context.Context, in *StatusRequest, opt } func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts ...grpc.CallOption) (*DownResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(DownResponse) - err := c.cc.Invoke(ctx, DaemonService_Down_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/Down", in, out, opts...) if err != nil { return nil, err } @@ -143,9 +113,8 @@ func (c *daemonServiceClient) Down(ctx context.Context, in *DownRequest, opts .. } func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetConfigResponse) - err := c.cc.Invoke(ctx, DaemonService_GetConfig_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetConfig", in, out, opts...) if err != nil { return nil, err } @@ -153,9 +122,8 @@ func (c *daemonServiceClient) GetConfig(ctx context.Context, in *GetConfigReques } func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworksRequest, opts ...grpc.CallOption) (*ListNetworksResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListNetworksResponse) - err := c.cc.Invoke(ctx, DaemonService_ListNetworks_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/ListNetworks", in, out, opts...) if err != nil { return nil, err } @@ -163,9 +131,8 @@ func (c *daemonServiceClient) ListNetworks(ctx context.Context, in *ListNetworks } func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SelectNetworksResponse) - err := c.cc.Invoke(ctx, DaemonService_SelectNetworks_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/SelectNetworks", in, out, opts...) if err != nil { return nil, err } @@ -173,9 +140,8 @@ func (c *daemonServiceClient) SelectNetworks(ctx context.Context, in *SelectNetw } func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SelectNetworksResponse) - err := c.cc.Invoke(ctx, DaemonService_DeselectNetworks_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/DeselectNetworks", in, out, opts...) if err != nil { return nil, err } @@ -183,9 +149,8 @@ func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNe } func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ForwardingRulesResponse) - err := c.cc.Invoke(ctx, DaemonService_ForwardingRules_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/ForwardingRules", in, out, opts...) if err != nil { return nil, err } @@ -193,9 +158,8 @@ func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequ } func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(DebugBundleResponse) - err := c.cc.Invoke(ctx, DaemonService_DebugBundle_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/DebugBundle", in, out, opts...) if err != nil { return nil, err } @@ -203,9 +167,8 @@ func (c *daemonServiceClient) DebugBundle(ctx context.Context, in *DebugBundleRe } func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRequest, opts ...grpc.CallOption) (*GetLogLevelResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetLogLevelResponse) - err := c.cc.Invoke(ctx, DaemonService_GetLogLevel_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetLogLevel", in, out, opts...) if err != nil { return nil, err } @@ -213,9 +176,8 @@ func (c *daemonServiceClient) GetLogLevel(ctx context.Context, in *GetLogLevelRe } func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRequest, opts ...grpc.CallOption) (*SetLogLevelResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetLogLevelResponse) - err := c.cc.Invoke(ctx, DaemonService_SetLogLevel_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetLogLevel", in, out, opts...) if err != nil { return nil, err } @@ -223,9 +185,8 @@ func (c *daemonServiceClient) SetLogLevel(ctx context.Context, in *SetLogLevelRe } func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequest, opts ...grpc.CallOption) (*ListStatesResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListStatesResponse) - err := c.cc.Invoke(ctx, DaemonService_ListStates_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/ListStates", in, out, opts...) if err != nil { return nil, err } @@ -233,9 +194,8 @@ func (c *daemonServiceClient) ListStates(ctx context.Context, in *ListStatesRequ } func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequest, opts ...grpc.CallOption) (*CleanStateResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CleanStateResponse) - err := c.cc.Invoke(ctx, DaemonService_CleanState_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/CleanState", in, out, opts...) if err != nil { return nil, err } @@ -243,9 +203,8 @@ func (c *daemonServiceClient) CleanState(ctx context.Context, in *CleanStateRequ } func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRequest, opts ...grpc.CallOption) (*DeleteStateResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(DeleteStateResponse) - err := c.cc.Invoke(ctx, DaemonService_DeleteState_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/DeleteState", in, out, opts...) if err != nil { return nil, err } @@ -253,9 +212,8 @@ func (c *daemonServiceClient) DeleteState(ctx context.Context, in *DeleteStateRe } func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in *SetNetworkMapPersistenceRequest, opts ...grpc.CallOption) (*SetNetworkMapPersistenceResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetNetworkMapPersistenceResponse) - err := c.cc.Invoke(ctx, DaemonService_SetNetworkMapPersistence_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetNetworkMapPersistence", in, out, opts...) if err != nil { return nil, err } @@ -263,22 +221,20 @@ func (c *daemonServiceClient) SetNetworkMapPersistence(ctx context.Context, in * } func (c *daemonServiceClient) TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(TracePacketResponse) - err := c.cc.Invoke(ctx, DaemonService_TracePacket_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/TracePacket", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[SystemEvent], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &DaemonService_ServiceDesc.Streams[0], DaemonService_SubscribeEvents_FullMethodName, cOpts...) +func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error) { + stream, err := c.cc.NewStream(ctx, &DaemonService_ServiceDesc.Streams[0], "/daemon.DaemonService/SubscribeEvents", opts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[SubscribeRequest, SystemEvent]{ClientStream: stream} + x := &daemonServiceSubscribeEventsClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -288,13 +244,35 @@ func (c *daemonServiceClient) SubscribeEvents(ctx context.Context, in *Subscribe return x, nil } -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type DaemonService_SubscribeEventsClient = grpc.ServerStreamingClient[SystemEvent] +type DaemonService_SubscribeEventsClient interface { + Recv() (*SystemEvent, error) + grpc.ClientStream +} + +type daemonServiceSubscribeEventsClient struct { + grpc.ClientStream +} + +func (x *daemonServiceSubscribeEventsClient) Recv() (*SystemEvent, error) { + m := new(SystemEvent) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetEventsResponse) - err := c.cc.Invoke(ctx, DaemonService_GetEvents_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/GetEvents", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *daemonServiceClient) SetConfig(ctx context.Context, in *SetConfigRequest, opts ...grpc.CallOption) (*SetConfigResponse, error) { + out := new(SetConfigResponse) + err := c.cc.Invoke(ctx, "/daemon.DaemonService/SetConfig", in, out, opts...) if err != nil { return nil, err } @@ -303,7 +281,7 @@ func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsReques // DaemonServiceServer is the server API for DaemonService service. // All implementations must embed UnimplementedDaemonServiceServer -// for forward compatibility. +// for forward compatibility type DaemonServiceServer interface { // Login uses setup key to prepare configuration for the daemon. Login(context.Context, *LoginRequest) (*LoginResponse, error) @@ -340,17 +318,16 @@ type DaemonServiceServer interface { // SetNetworkMapPersistence enables or disables network map persistence SetNetworkMapPersistence(context.Context, *SetNetworkMapPersistenceRequest) (*SetNetworkMapPersistenceResponse, error) TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) - SubscribeEvents(*SubscribeRequest, grpc.ServerStreamingServer[SystemEvent]) error + SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) + // SetConfig updates daemon configuration without reconnecting + SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) mustEmbedUnimplementedDaemonServiceServer() } -// UnimplementedDaemonServiceServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedDaemonServiceServer struct{} +// UnimplementedDaemonServiceServer must be embedded to have forward compatible implementations. +type UnimplementedDaemonServiceServer struct { +} func (UnimplementedDaemonServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") @@ -406,14 +383,16 @@ func (UnimplementedDaemonServiceServer) SetNetworkMapPersistence(context.Context func (UnimplementedDaemonServiceServer) TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method TracePacket not implemented") } -func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, grpc.ServerStreamingServer[SystemEvent]) error { +func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error { return status.Errorf(codes.Unimplemented, "method SubscribeEvents not implemented") } func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented") } +func (UnimplementedDaemonServiceServer) SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetConfig not implemented") +} func (UnimplementedDaemonServiceServer) mustEmbedUnimplementedDaemonServiceServer() {} -func (UnimplementedDaemonServiceServer) testEmbeddedByValue() {} // UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to DaemonServiceServer will @@ -423,13 +402,6 @@ type UnsafeDaemonServiceServer interface { } func RegisterDaemonServiceServer(s grpc.ServiceRegistrar, srv DaemonServiceServer) { - // If the following call pancis, it indicates UnimplementedDaemonServiceServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } s.RegisterService(&DaemonService_ServiceDesc, srv) } @@ -443,7 +415,7 @@ func _DaemonService_Login_Handler(srv interface{}, ctx context.Context, dec func } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_Login_FullMethodName, + FullMethod: "/daemon.DaemonService/Login", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).Login(ctx, req.(*LoginRequest)) @@ -461,7 +433,7 @@ func _DaemonService_WaitSSOLogin_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_WaitSSOLogin_FullMethodName, + FullMethod: "/daemon.DaemonService/WaitSSOLogin", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).WaitSSOLogin(ctx, req.(*WaitSSOLoginRequest)) @@ -479,7 +451,7 @@ func _DaemonService_Up_Handler(srv interface{}, ctx context.Context, dec func(in } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_Up_FullMethodName, + FullMethod: "/daemon.DaemonService/Up", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).Up(ctx, req.(*UpRequest)) @@ -497,7 +469,7 @@ func _DaemonService_Status_Handler(srv interface{}, ctx context.Context, dec fun } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_Status_FullMethodName, + FullMethod: "/daemon.DaemonService/Status", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).Status(ctx, req.(*StatusRequest)) @@ -515,7 +487,7 @@ func _DaemonService_Down_Handler(srv interface{}, ctx context.Context, dec func( } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_Down_FullMethodName, + FullMethod: "/daemon.DaemonService/Down", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).Down(ctx, req.(*DownRequest)) @@ -533,7 +505,7 @@ func _DaemonService_GetConfig_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_GetConfig_FullMethodName, + FullMethod: "/daemon.DaemonService/GetConfig", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).GetConfig(ctx, req.(*GetConfigRequest)) @@ -551,7 +523,7 @@ func _DaemonService_ListNetworks_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_ListNetworks_FullMethodName, + FullMethod: "/daemon.DaemonService/ListNetworks", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).ListNetworks(ctx, req.(*ListNetworksRequest)) @@ -569,7 +541,7 @@ func _DaemonService_SelectNetworks_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_SelectNetworks_FullMethodName, + FullMethod: "/daemon.DaemonService/SelectNetworks", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).SelectNetworks(ctx, req.(*SelectNetworksRequest)) @@ -587,7 +559,7 @@ func _DaemonService_DeselectNetworks_Handler(srv interface{}, ctx context.Contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_DeselectNetworks_FullMethodName, + FullMethod: "/daemon.DaemonService/DeselectNetworks", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).DeselectNetworks(ctx, req.(*SelectNetworksRequest)) @@ -605,7 +577,7 @@ func _DaemonService_ForwardingRules_Handler(srv interface{}, ctx context.Context } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_ForwardingRules_FullMethodName, + FullMethod: "/daemon.DaemonService/ForwardingRules", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).ForwardingRules(ctx, req.(*EmptyRequest)) @@ -623,7 +595,7 @@ func _DaemonService_DebugBundle_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_DebugBundle_FullMethodName, + FullMethod: "/daemon.DaemonService/DebugBundle", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).DebugBundle(ctx, req.(*DebugBundleRequest)) @@ -641,7 +613,7 @@ func _DaemonService_GetLogLevel_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_GetLogLevel_FullMethodName, + FullMethod: "/daemon.DaemonService/GetLogLevel", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).GetLogLevel(ctx, req.(*GetLogLevelRequest)) @@ -659,7 +631,7 @@ func _DaemonService_SetLogLevel_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_SetLogLevel_FullMethodName, + FullMethod: "/daemon.DaemonService/SetLogLevel", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).SetLogLevel(ctx, req.(*SetLogLevelRequest)) @@ -677,7 +649,7 @@ func _DaemonService_ListStates_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_ListStates_FullMethodName, + FullMethod: "/daemon.DaemonService/ListStates", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).ListStates(ctx, req.(*ListStatesRequest)) @@ -695,7 +667,7 @@ func _DaemonService_CleanState_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_CleanState_FullMethodName, + FullMethod: "/daemon.DaemonService/CleanState", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).CleanState(ctx, req.(*CleanStateRequest)) @@ -713,7 +685,7 @@ func _DaemonService_DeleteState_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_DeleteState_FullMethodName, + FullMethod: "/daemon.DaemonService/DeleteState", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).DeleteState(ctx, req.(*DeleteStateRequest)) @@ -731,7 +703,7 @@ func _DaemonService_SetNetworkMapPersistence_Handler(srv interface{}, ctx contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_SetNetworkMapPersistence_FullMethodName, + FullMethod: "/daemon.DaemonService/SetNetworkMapPersistence", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).SetNetworkMapPersistence(ctx, req.(*SetNetworkMapPersistenceRequest)) @@ -749,7 +721,7 @@ func _DaemonService_TracePacket_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_TracePacket_FullMethodName, + FullMethod: "/daemon.DaemonService/TracePacket", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).TracePacket(ctx, req.(*TracePacketRequest)) @@ -762,11 +734,21 @@ func _DaemonService_SubscribeEvents_Handler(srv interface{}, stream grpc.ServerS if err := stream.RecvMsg(m); err != nil { return err } - return srv.(DaemonServiceServer).SubscribeEvents(m, &grpc.GenericServerStream[SubscribeRequest, SystemEvent]{ServerStream: stream}) + return srv.(DaemonServiceServer).SubscribeEvents(m, &daemonServiceSubscribeEventsServer{stream}) } -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type DaemonService_SubscribeEventsServer = grpc.ServerStreamingServer[SystemEvent] +type DaemonService_SubscribeEventsServer interface { + Send(*SystemEvent) error + grpc.ServerStream +} + +type daemonServiceSubscribeEventsServer struct { + grpc.ServerStream +} + +func (x *daemonServiceSubscribeEventsServer) Send(m *SystemEvent) error { + return x.ServerStream.SendMsg(m) +} func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetEventsRequest) @@ -778,7 +760,7 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: DaemonService_GetEvents_FullMethodName, + FullMethod: "/daemon.DaemonService/GetEvents", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(DaemonServiceServer).GetEvents(ctx, req.(*GetEventsRequest)) @@ -786,6 +768,24 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _DaemonService_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DaemonServiceServer).SetConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/daemon.DaemonService/SetConfig", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DaemonServiceServer).SetConfig(ctx, req.(*SetConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + // DaemonService_ServiceDesc is the grpc.ServiceDesc for DaemonService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -869,6 +869,10 @@ var DaemonService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetEvents", Handler: _DaemonService_GetEvents_Handler, }, + { + MethodName: "SetConfig", + Handler: _DaemonService_SetConfig_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/client/server/server.go b/client/server/server.go index e3ce1a2b4..cc859a000 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -799,6 +799,133 @@ func (s *Server) GetConfig(_ context.Context, _ *proto.GetConfigRequest) (*proto }, nil } +// SetConfig updates daemon configuration without reconnecting +func (s *Server) SetConfig(ctx context.Context, req *proto.SetConfigRequest) (*proto.SetConfigResponse, error) { + s.mutex.Lock() + defer s.mutex.Unlock() + + if s.config == nil { + return nil, gstatus.Errorf(codes.FailedPrecondition, "daemon is not configured") + } + + configChanged := false + + if req.RosenpassEnabled != nil && s.config.RosenpassEnabled != *req.RosenpassEnabled { + s.config.RosenpassEnabled = *req.RosenpassEnabled + configChanged = true + } + + if req.RosenpassPermissive != nil && s.config.RosenpassPermissive != *req.RosenpassPermissive { + s.config.RosenpassPermissive = *req.RosenpassPermissive + configChanged = true + } + + if req.ServerSSHAllowed != nil && s.config.ServerSSHAllowed != nil && *s.config.ServerSSHAllowed != *req.ServerSSHAllowed { + *s.config.ServerSSHAllowed = *req.ServerSSHAllowed + configChanged = true + } + + if req.DisableAutoConnect != nil && s.config.DisableAutoConnect != *req.DisableAutoConnect { + s.config.DisableAutoConnect = *req.DisableAutoConnect + configChanged = true + } + + if req.NetworkMonitor != nil && s.config.NetworkMonitor != nil && *s.config.NetworkMonitor != *req.NetworkMonitor { + *s.config.NetworkMonitor = *req.NetworkMonitor + configChanged = true + } + + if req.DnsRouteInterval != nil { + duration := req.DnsRouteInterval.AsDuration() + if s.config.DNSRouteInterval != duration { + s.config.DNSRouteInterval = duration + configChanged = true + } + } + + if req.DisableClientRoutes != nil && s.config.DisableClientRoutes != *req.DisableClientRoutes { + s.config.DisableClientRoutes = *req.DisableClientRoutes + configChanged = true + } + + if req.DisableServerRoutes != nil && s.config.DisableServerRoutes != *req.DisableServerRoutes { + s.config.DisableServerRoutes = *req.DisableServerRoutes + configChanged = true + } + + if req.DisableDns != nil && s.config.DisableDNS != *req.DisableDns { + s.config.DisableDNS = *req.DisableDns + configChanged = true + } + + if req.DisableFirewall != nil && s.config.DisableFirewall != *req.DisableFirewall { + s.config.DisableFirewall = *req.DisableFirewall + configChanged = true + } + + if req.BlockLanAccess != nil && s.config.BlockLANAccess != *req.BlockLanAccess { + s.config.BlockLANAccess = *req.BlockLanAccess + configChanged = true + } + + if req.LazyConnectionEnabled != nil && s.config.LazyConnectionEnabled != *req.LazyConnectionEnabled { + s.config.LazyConnectionEnabled = *req.LazyConnectionEnabled + configChanged = true + } + + if req.BlockInbound != nil && s.config.BlockInbound != *req.BlockInbound { + s.config.BlockInbound = *req.BlockInbound + configChanged = true + } + + if req.InterfaceName != nil && s.config.WgIface != *req.InterfaceName { + s.config.WgIface = *req.InterfaceName + configChanged = true + } + + if req.WireguardPort != nil && s.config.WgPort != int(*req.WireguardPort) { + s.config.WgPort = int(*req.WireguardPort) + configChanged = true + } + + if req.CustomDNSAddress != nil && s.config.CustomDNSAddress != *req.CustomDNSAddress { + s.config.CustomDNSAddress = *req.CustomDNSAddress + configChanged = true + } + + if len(req.ExtraIFaceBlacklist) > 0 { + s.config.IFaceBlackList = req.ExtraIFaceBlacklist + configChanged = true + } + + if len(req.DnsLabels) > 0 || (req.CleanDNSLabels != nil && *req.CleanDNSLabels) { + if req.CleanDNSLabels != nil && *req.CleanDNSLabels { + s.config.DNSLabels = domain.List{} + } else { + var err error + s.config.DNSLabels, err = domain.FromStringList(req.DnsLabels) + if err != nil { + return nil, gstatus.Errorf(codes.InvalidArgument, "invalid DNS labels: %v", err) + } + } + configChanged = true + } + + if len(req.NatExternalIPs) > 0 || (req.CleanNATExternalIPs != nil && *req.CleanNATExternalIPs) { + s.config.NATExternalIPs = req.NatExternalIPs + configChanged = true + } + + if configChanged { + if err := internal.WriteOutConfig(s.latestConfigInput.ConfigPath, s.config); err != nil { + return nil, gstatus.Errorf(codes.Internal, "write config: %v", err) + } + log.Debug("Configuration updated successfully") + } + + return &proto.SetConfigResponse{}, nil +} + func (s *Server) onSessionExpire() { if runtime.GOOS != "windows" { isUIActive := internal.CheckUIApp()