mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-22 10:16:38 +00:00
Compare commits
3 Commits
logs/peerl
...
set-cmd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0c3818e06 | ||
|
|
6922826919 | ||
|
|
56a1a75e3f |
210
client/cmd/flags.go
Normal file
210
client/cmd/flags.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -149,6 +149,7 @@ func init() {
|
|||||||
rootCmd.AddCommand(loginCmd)
|
rootCmd.AddCommand(loginCmd)
|
||||||
rootCmd.AddCommand(versionCmd)
|
rootCmd.AddCommand(versionCmd)
|
||||||
rootCmd.AddCommand(sshCmd)
|
rootCmd.AddCommand(sshCmd)
|
||||||
|
rootCmd.AddCommand(setCmd)
|
||||||
rootCmd.AddCommand(networksCMD)
|
rootCmd.AddCommand(networksCMD)
|
||||||
rootCmd.AddCommand(forwardingRulesCmd)
|
rootCmd.AddCommand(forwardingRulesCmd)
|
||||||
rootCmd.AddCommand(debugCmd)
|
rootCmd.AddCommand(debugCmd)
|
||||||
@@ -167,24 +168,6 @@ func init() {
|
|||||||
debugCmd.AddCommand(forCmd)
|
debugCmd.AddCommand(forCmd)
|
||||||
debugCmd.AddCommand(persistenceCmd)
|
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(&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))
|
debugCmd.PersistentFlags().BoolVarP(&debugUploadBundle, uploadBundle, "U", false, fmt.Sprintf("Uploads the debug bundle to a server from URL defined by %s", uploadBundleURL))
|
||||||
|
|||||||
161
client/cmd/set.go
Normal file
161
client/cmd/set.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
110
client/cmd/set_test.go
Normal file
110
client/cmd/set_test.go
Normal file
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -120,7 +120,7 @@ func getStatus(ctx context.Context) (*proto.StatusResponse, error) {
|
|||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
resp, err := proto.NewDaemonServiceClient(conn).Status(ctx, &proto.StatusRequest{GetFullPeerStatus: true})
|
resp, err := proto.NewDaemonServiceClient(conn).Status(ctx, &proto.StatusRequest{GetFullPeerStatus: true, ShouldRunProbes: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("status failed: %v", status.Convert(err).Message())
|
return nil, fmt.Errorf("status failed: %v", status.Convert(err).Message())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,24 +19,3 @@ var (
|
|||||||
blockInbound bool
|
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.")
|
|
||||||
}
|
|
||||||
|
|||||||
124
client/cmd/up.go
124
client/cmd/up.go
@@ -7,7 +7,6 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -15,7 +14,6 @@ import (
|
|||||||
gstatus "google.golang.org/grpc/status"
|
gstatus "google.golang.org/grpc/status"
|
||||||
"google.golang.org/protobuf/types/known/durationpb"
|
"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"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/proto"
|
"github.com/netbirdio/netbird/client/proto"
|
||||||
@@ -42,6 +40,7 @@ var (
|
|||||||
dnsLabels []string
|
dnsLabels []string
|
||||||
dnsLabelsValidated domain.List
|
dnsLabelsValidated domain.List
|
||||||
noBrowser bool
|
noBrowser bool
|
||||||
|
upFlags = &SharedFlags{}
|
||||||
|
|
||||||
upCmd = &cobra.Command{
|
upCmd = &cobra.Command{
|
||||||
Use: "up",
|
Use: "up",
|
||||||
@@ -51,26 +50,12 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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().BoolVarP(&foregroundMode, "foreground-mode", "F", false, "start service in foreground")
|
||||||
upCmd.PersistentFlags().StringVar(&interfaceName, interfaceNameFlag, iface.WgInterfaceDefault, "Wireguard interface name")
|
AddUpOnlyFlags(upCmd, upFlags)
|
||||||
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)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func upFunc(cmd *cobra.Command, args []string) error {
|
func upFunc(cmd *cobra.Command, args []string) error {
|
||||||
@@ -118,7 +103,16 @@ func runInForegroundMode(ctx context.Context, cmd *cobra.Command) error {
|
|||||||
return err
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("setup config: %v", err)
|
return fmt.Errorf("setup config: %v", err)
|
||||||
}
|
}
|
||||||
@@ -235,92 +229,6 @@ func runInDaemonMode(ctx context.Context, cmd *cobra.Command) error {
|
|||||||
return nil
|
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) {
|
func setupLoginRequest(providedSetupKey string, customDNSAddressConverted []byte, cmd *cobra.Command) (*proto.LoginRequest, error) {
|
||||||
loginRequest := proto.LoginRequest{
|
loginRequest := proto.LoginRequest{
|
||||||
SetupKey: providedSetupKey,
|
SetupKey: providedSetupKey,
|
||||||
|
|||||||
@@ -319,10 +319,6 @@ func (config *Config) apply(input ConfigInput) (updated bool, err error) {
|
|||||||
*input.WireguardPort, config.WgPort)
|
*input.WireguardPort, config.WgPort)
|
||||||
config.WgPort = *input.WireguardPort
|
config.WgPort = *input.WireguardPort
|
||||||
updated = true
|
updated = true
|
||||||
} else if config.WgPort == 0 {
|
|
||||||
config.WgPort = iface.DefaultWgPort
|
|
||||||
log.Infof("using default Wireguard port %d", config.WgPort)
|
|
||||||
updated = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.InterfaceName != nil && *input.InterfaceName != config.WgIface {
|
if input.InterfaceName != nil && *input.InterfaceName != config.WgIface {
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import (
|
|||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
gstatus "google.golang.org/grpc/status"
|
gstatus "google.golang.org/grpc/status"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns"
|
"github.com/netbirdio/netbird/client/internal/dns"
|
||||||
"github.com/netbirdio/netbird/client/internal/listener"
|
"github.com/netbirdio/netbird/client/internal/listener"
|
||||||
@@ -526,17 +525,13 @@ func statusRecorderToSignalConnStateNotifier(statusRecorder *peer.Status) signal
|
|||||||
|
|
||||||
// freePort attempts to determine if the provided port is available, if not it will ask the system for a free port.
|
// freePort attempts to determine if the provided port is available, if not it will ask the system for a free port.
|
||||||
func freePort(initPort int) (int, error) {
|
func freePort(initPort int) (int, error) {
|
||||||
addr := net.UDPAddr{}
|
addr := net.UDPAddr{Port: initPort}
|
||||||
if initPort == 0 {
|
|
||||||
initPort = iface.DefaultWgPort
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.Port = initPort
|
|
||||||
|
|
||||||
conn, err := net.ListenUDP("udp", &addr)
|
conn, err := net.ListenUDP("udp", &addr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
returnPort := conn.LocalAddr().(*net.UDPAddr).Port
|
||||||
closeConnWithLog(conn)
|
closeConnWithLog(conn)
|
||||||
return initPort, nil
|
return returnPort, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the port is already in use, ask the system for a free port
|
// if the port is already in use, ask the system for a free port
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ func Test_freePort(t *testing.T) {
|
|||||||
shouldMatch bool
|
shouldMatch bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "not provided, fallback to default",
|
name: "when port is 0 use random port",
|
||||||
port: 0,
|
port: 0,
|
||||||
want: 51820,
|
want: 0,
|
||||||
shouldMatch: true,
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "provided and available",
|
name: "provided and available",
|
||||||
@@ -31,7 +31,7 @@ func Test_freePort(t *testing.T) {
|
|||||||
shouldMatch: false,
|
shouldMatch: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c1, err := net.ListenUDP("udp", &net.UDPAddr{Port: 51830})
|
c1, err := net.ListenUDP("udp", &net.UDPAddr{Port: 0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("freePort error = %v", err)
|
t.Errorf("freePort error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,14 @@ func Test_freePort(t *testing.T) {
|
|||||||
_ = c1.Close()
|
_ = c1.Close()
|
||||||
}(c1)
|
}(c1)
|
||||||
|
|
||||||
|
if tests[1].port == c1.LocalAddr().(*net.UDPAddr).Port {
|
||||||
|
tests[1].port++
|
||||||
|
tests[1].want++
|
||||||
|
}
|
||||||
|
|
||||||
|
tests[2].port = c1.LocalAddr().(*net.UDPAddr).Port
|
||||||
|
tests[2].want = c1.LocalAddr().(*net.UDPAddr).Port
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -67,6 +67,9 @@ service DaemonService {
|
|||||||
rpc SubscribeEvents(SubscribeRequest) returns (stream SystemEvent) {}
|
rpc SubscribeEvents(SubscribeRequest) returns (stream SystemEvent) {}
|
||||||
|
|
||||||
rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {}
|
rpc GetEvents(GetEventsRequest) returns (GetEventsResponse) {}
|
||||||
|
|
||||||
|
// SetConfig updates daemon configuration without reconnecting
|
||||||
|
rpc SetConfig(SetConfigRequest) returns (SetConfigResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -158,6 +161,7 @@ message UpResponse {}
|
|||||||
|
|
||||||
message StatusRequest{
|
message StatusRequest{
|
||||||
bool getFullPeerStatus = 1;
|
bool getFullPeerStatus = 1;
|
||||||
|
bool shouldRunProbes = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message StatusResponse{
|
message StatusResponse{
|
||||||
@@ -495,3 +499,29 @@ message GetEventsRequest {}
|
|||||||
message GetEventsResponse {
|
message GetEventsResponse {
|
||||||
repeated SystemEvent events = 1;
|
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 {}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ type DaemonServiceClient interface {
|
|||||||
TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error)
|
TracePacket(ctx context.Context, in *TracePacketRequest, opts ...grpc.CallOption) (*TracePacketResponse, error)
|
||||||
SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error)
|
SubscribeEvents(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (DaemonService_SubscribeEventsClient, error)
|
||||||
GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, 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 {
|
type daemonServiceClient struct {
|
||||||
@@ -268,6 +270,15 @@ func (c *daemonServiceClient) GetEvents(ctx context.Context, in *GetEventsReques
|
|||||||
return out, nil
|
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
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DaemonServiceServer is the server API for DaemonService service.
|
// DaemonServiceServer is the server API for DaemonService service.
|
||||||
// All implementations must embed UnimplementedDaemonServiceServer
|
// All implementations must embed UnimplementedDaemonServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
@@ -309,6 +320,8 @@ type DaemonServiceServer interface {
|
|||||||
TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error)
|
TracePacket(context.Context, *TracePacketRequest) (*TracePacketResponse, error)
|
||||||
SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error
|
SubscribeEvents(*SubscribeRequest, DaemonService_SubscribeEventsServer) error
|
||||||
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
|
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
|
||||||
|
// SetConfig updates daemon configuration without reconnecting
|
||||||
|
SetConfig(context.Context, *SetConfigRequest) (*SetConfigResponse, error)
|
||||||
mustEmbedUnimplementedDaemonServiceServer()
|
mustEmbedUnimplementedDaemonServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,6 +389,9 @@ func (UnimplementedDaemonServiceServer) SubscribeEvents(*SubscribeRequest, Daemo
|
|||||||
func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
|
func (UnimplementedDaemonServiceServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
|
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) mustEmbedUnimplementedDaemonServiceServer() {}
|
||||||
|
|
||||||
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeDaemonServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
@@ -752,6 +768,24 @@ func _DaemonService_GetEvents_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
return interceptor(ctx, in, info, handler)
|
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.
|
// DaemonService_ServiceDesc is the grpc.ServiceDesc for DaemonService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@@ -835,6 +869,10 @@ var DaemonService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "GetEvents",
|
MethodName: "GetEvents",
|
||||||
Handler: _DaemonService_GetEvents_Handler,
|
Handler: _DaemonService_GetEvents_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SetConfig",
|
||||||
|
Handler: _DaemonService_SetConfig_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -707,7 +707,9 @@ func (s *Server) Status(
|
|||||||
s.statusRecorder.UpdateRosenpass(s.config.RosenpassEnabled, s.config.RosenpassPermissive)
|
s.statusRecorder.UpdateRosenpass(s.config.RosenpassEnabled, s.config.RosenpassPermissive)
|
||||||
|
|
||||||
if msg.GetFullPeerStatus {
|
if msg.GetFullPeerStatus {
|
||||||
s.runProbes()
|
if msg.ShouldRunProbes {
|
||||||
|
s.runProbes()
|
||||||
|
}
|
||||||
|
|
||||||
fullStatus := s.statusRecorder.GetFullStatus()
|
fullStatus := s.statusRecorder.GetFullStatus()
|
||||||
pbFullStatus := toProtoFullStatus(fullStatus)
|
pbFullStatus := toProtoFullStatus(fullStatus)
|
||||||
@@ -797,6 +799,133 @@ func (s *Server) GetConfig(_ context.Context, _ *proto.GetConfigRequest) (*proto
|
|||||||
}, nil
|
}, 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() {
|
func (s *Server) onSessionExpire() {
|
||||||
if runtime.GOOS != "windows" {
|
if runtime.GOOS != "windows" {
|
||||||
isUIActive := internal.CheckUIApp()
|
isUIActive := internal.CheckUIApp()
|
||||||
|
|||||||
Reference in New Issue
Block a user