package controller import ( "fmt" "net" "net/http" "strings" "github.com/gorilla/mux" "github.com/gravitl/netmaker/netclient/ncutils" ) func ipHandlers(r *mux.Router) { r.HandleFunc("/api/getip", http.HandlerFunc(getPublicIP)).Methods(http.MethodGet) } // swagger:route GET /api/getip ipservice getPublicIP // // Get the current public IP address. // // Schemes: https // // Security: // oauth // // Responses: // 200: byteArrayResponse func getPublicIP(w http.ResponseWriter, r *http.Request) { r.Header.Set("Connection", "close") ip, err := parseIP(r) if err != nil { w.WriteHeader(400) switch { case ip != "": _, _ = w.Write([]byte("ip is invalid: " + ip)) case ip == "": _, _ = w.Write([]byte("no ip found")) default: fmt.Println(err) } return } 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 && !ncutils.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 && !ncutils.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 ncutils.IpIsPrivate(ipnet) { return ip, fmt.Errorf("ip is a private address") } return ip, nil } return "", fmt.Errorf("no ip found") }