Browse Source

Merge pull request #1460 from gravitl/feature_v0.14.7_ipchecker

move client public ip check to use server
Matthew R Kasun 3 years ago
parent
commit
a529222bff

+ 0 - 2
controllers/config/dnsconfig/netmaker.hosts

@@ -1,2 +0,0 @@
-10.0.0.1         testnode.skynet
-10.0.0.2         myhost.skynet

+ 1 - 0
controllers/controller.go

@@ -24,6 +24,7 @@ var HttpHandlers = []interface{}{
 	fileHandlers,
 	serverHandlers,
 	extClientHandlers,
+	ipHandlers,
 }
 
 // HandleRESTRequests - handles the rest requests

+ 72 - 0
controllers/ipservice.go

@@ -0,0 +1,72 @@
+package controller
+
+import (
+	"fmt"
+	"net"
+	"net/http"
+	"strings"
+
+	"github.com/gorilla/mux"
+)
+
+func ipHandlers(r *mux.Router) {
+	r.HandleFunc("/api/getip", http.HandlerFunc(getPublicIP)).Methods("GET")
+}
+
+func getPublicIP(w http.ResponseWriter, r *http.Request) {
+	r.Header.Set("Connection", "close")
+	ip, err := parseIP(r)
+	if err != nil {
+		w.WriteHeader(400)
+		if ip != "" {
+			w.Write([]byte("ip is invalid: " + ip))
+			return
+		} else {
+			w.Write([]byte("no ip found"))
+			return
+		}
+	} else {
+		if err != nil {
+			fmt.Println(err)
+		}
+	}
+	w.WriteHeader(200)
+	w.Write([]byte(ip))
+}
+
+func parseIP(r *http.Request) (string, error) {
+	// Get Public IP from header
+	ip := r.Header.Get("X-REAL-IP")
+	ipnet := net.ParseIP(ip)
+	if ipnet != nil && !ipIsPrivate(ipnet) {
+		return ip, nil
+	}
+
+	// If above fails, get Public IP from other header instead
+	forwardips := r.Header.Get("X-FORWARDED-FOR")
+	iplist := strings.Split(forwardips, ",")
+	for _, ip := range iplist {
+		ipnet := net.ParseIP(ip)
+		if ipnet != nil && !ipIsPrivate(ipnet) {
+			return ip, nil
+		}
+	}
+
+	// If above also fails, get Public IP from Remote Address of request
+	ip, _, err := net.SplitHostPort(r.RemoteAddr)
+	if err != nil {
+		return "", err
+	}
+	ipnet = net.ParseIP(ip)
+	if ipnet != nil {
+		if ipIsPrivate(ipnet) {
+			return ip, fmt.Errorf("ip is a private address")
+		}
+		return ip, nil
+	}
+	return "", fmt.Errorf("no ip found")
+}
+
+func ipIsPrivate(ipnet net.IP) bool {
+	return ipnet.IsPrivate() || ipnet.IsLoopback()
+}

+ 1 - 1
netclient/functions/join.go

@@ -85,7 +85,7 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 		if cfg.Node.IsLocal == "yes" && cfg.Node.LocalAddress != "" {
 			cfg.Node.Endpoint = cfg.Node.LocalAddress
 		} else {
-			cfg.Node.Endpoint, err = ncutils.GetPublicIP()
+			cfg.Node.Endpoint, err = ncutils.GetPublicIP(cfg.Server.API)
 		}
 		if err != nil || cfg.Node.Endpoint == "" {
 			logger.Log(0, "network:", cfg.Network, "error setting cfg.Node.Endpoint.")

+ 1 - 1
netclient/functions/mqpublish.go

@@ -56,7 +56,7 @@ func checkin() {
 			nodeCfg.Node.FirewallInUse = models.FIREWALL_IPTABLES
 		}
 		if nodeCfg.Node.IsStatic != "yes" {
-			extIP, err := ncutils.GetPublicIP()
+			extIP, err := ncutils.GetPublicIP(nodeCfg.Server.API)
 			if err != nil {
 				logger.Log(1, "error encountered checking public ip addresses: ", err.Error())
 			}

+ 6 - 2
netclient/ncutils/netclientutils.go

@@ -137,9 +137,9 @@ func IsEmptyRecord(err error) bool {
 }
 
 // GetPublicIP - gets public ip
-func GetPublicIP() (string, error) {
+func GetPublicIP(api string) (string, error) {
 
-	iplist := []string{"https://ip.server.gravitl.com", "https://ifconfig.me", "https://api.ipify.org", "https://ipinfo.io/ip"}
+	iplist := []string{"https://ip.client.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)
@@ -147,6 +147,10 @@ func GetPublicIP() (string, error) {
 		// prepend the user-specified service so it's checked first
 		iplist = append([]string{ipService}, iplist...)
 	}
+	if api != "" {
+		api = "https://" + api + "/api/getip"
+		iplist = append([]string{api}, iplist...)
+	}
 
 	endpoint := ""
 	var err error

+ 4 - 4
servercfg/serverconf.go

@@ -430,20 +430,20 @@ func GetPublicIP() (string, error) {
 	iplist := []string{"https://ip.server.gravitl.com", "https://ifconfig.me", "https://api.ipify.org", "https://ipinfo.io/ip"}
 	publicIpService := os.Getenv("PUBLIC_IP_SERVICE")
 	if publicIpService != "" {
-		logger.Log(3, "User (environment variable) provided public IP service is", publicIpService)
+		logger.Log(4, "User (environment variable) provided public IP service is", publicIpService)
 
 		// prepend the user-specified service so it's checked first
 		iplist = append([]string{publicIpService}, iplist...)
 	} else if config.Config.Server.PublicIPService != "" {
 		publicIpService = config.Config.Server.PublicIPService
-		logger.Log(3, "User (config file) provided public IP service is", publicIpService)
+		logger.Log(4, "User (config file) provided public IP service is", publicIpService)
 
 		// prepend the user-specified service so it's checked first
 		iplist = append([]string{publicIpService}, iplist...)
 	}
 
 	for _, ipserver := range iplist {
-		logger.Log(3, "Running public IP check with service", ipserver)
+		logger.Log(4, "Running public IP check with service", ipserver)
 		client := &http.Client{
 			Timeout: time.Second * 10,
 		}
@@ -458,7 +458,7 @@ func GetPublicIP() (string, error) {
 				continue
 			}
 			endpoint = string(bodyBytes)
-			logger.Log(3, "Public IP address is", endpoint)
+			logger.Log(4, "Public IP address is", endpoint)
 			break
 		}
 	}