diff --git a/netclient/cli_options/flags.go b/netclient/cli_options/flags.go index 9830e281..50ec8725 100644 --- a/netclient/cli_options/flags.go +++ b/netclient/cli_options/flags.go @@ -66,6 +66,13 @@ func GetFlags(hostname string) []cli.Flag { Value: "", Usage: "Identifiable name for machine within Netmaker network.", }, + &cli.StringFlag{ + Name: "publicipservice", + Aliases: []string{"ip-service"}, + EnvVars: []string{"NETCLIENT_IP_SERVICE"}, + Value: "", + Usage: "The service to call to obtain the public IP of the machine that is running netclient.", + }, &cli.StringFlag{ Name: "name", EnvVars: []string{"NETCLIENT_NAME"}, diff --git a/netclient/config/config.go b/netclient/config/config.go index d5e6e6ed..0bf5ef80 100644 --- a/netclient/config/config.go +++ b/netclient/config/config.go @@ -12,6 +12,7 @@ import ( "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/global_settings" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/urfave/cli/v2" "gopkg.in/yaml.v3" @@ -30,6 +31,7 @@ type ClientConfig struct { Daemon string `yaml:"daemon"` OperatingSystem string `yaml:"operatingsystem"` AccessKey string `yaml:"accesskey"` + PublicIPService string `yaml:"publicipservice"` } // RegisterRequest - struct for registation with netmaker server @@ -231,6 +233,10 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) { cfg.Server.CoreDNSAddr = c.String("corednsaddr") cfg.Server.API = c.String("apiserver") } + cfg.PublicIPService = c.String("publicipservice") + // populate the map as we're not running as a daemon so won't be building the map otherwise + // (and the map will be used by GetPublicIP()). + global_settings.PublicIPServices[cfg.Network] = cfg.PublicIPService cfg.Node.Name = c.String("name") cfg.Node.Interface = c.String("interface") cfg.Node.Password = c.String("password") diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go index ee71bbc1..1d277402 100644 --- a/netclient/functions/daemon.go +++ b/netclient/functions/daemon.go @@ -22,6 +22,7 @@ import ( "github.com/gravitl/netmaker/netclient/auth" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/daemon" + "github.com/gravitl/netmaker/netclient/global_settings" "github.com/gravitl/netmaker/netclient/local" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/wireguard" @@ -96,6 +97,10 @@ func startGoRoutines(wg *sync.WaitGroup) context.CancelFunc { if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, ncutils.GetNetclientPathSpecific()+cfg.Node.Interface+".conf"); err != nil { logger.Log(0, "failed to start ", cfg.Node.Interface, "wg interface", err.Error()) } + if cfg.PublicIPService != "" { + global_settings.PublicIPServices[network] = cfg.PublicIPService + } + server := cfg.Server.Server if !serverSet[server] { // == subscribe to all nodes for each on machine == diff --git a/netclient/global_settings/globalsettings.go b/netclient/global_settings/globalsettings.go new file mode 100644 index 00000000..192c884f --- /dev/null +++ b/netclient/global_settings/globalsettings.go @@ -0,0 +1,6 @@ +package global_settings + +// globalsettings - settings that are global in nature. Avoids circular dependencies between config loading and usage. + +// PublicIPServices - the list of user-specified IP services to use to obtain the node's public IP +var PublicIPServices map[string]string = make(map[string]string) diff --git a/netclient/ncutils/netclientutils.go b/netclient/ncutils/netclientutils.go index cbe39a00..2833d22b 100644 --- a/netclient/ncutils/netclientutils.go +++ b/netclient/ncutils/netclientutils.go @@ -22,6 +22,7 @@ import ( "github.com/c-robinson/iplib" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/global_settings" ) var ( @@ -128,10 +129,19 @@ func IsEmptyRecord(err error) bool { // GetPublicIP - gets public ip func GetPublicIP() (string, error) { - iplist := []string{"https://ip.client.gravitl.com", "https://ifconfig.me", "https://api.ipify.org", "https://ipinfo.io/ip"} + iplist := []string{"https://ip.server.gravitl.com", "https://ifconfig.me", "https://api.ipify.org", "https://ipinfo.io/ip"} + + for network, ipService := range global_settings.PublicIPServices { + logger.Log(3, "User provided public IP service defined for network", network, "is", ipService) + + // prepend the user-specified service so it's checked first + iplist = append([]string{ipService}, iplist...) + } + endpoint := "" var err error for _, ipserver := range iplist { + logger.Log(3, "Running public IP check with service", ipserver) client := &http.Client{ Timeout: time.Second * 10, } @@ -146,6 +156,7 @@ func GetPublicIP() (string, error) { continue } endpoint = string(bodyBytes) + logger.Log(3, "Public IP address is", endpoint) break } }