Browse Source

dns server setup

afeiszli 4 years ago
parent
commit
2b77ae6723

+ 11 - 5
Dockerfile

@@ -1,6 +1,6 @@
 #first stage - builder
 #first stage - builder
 
 
-FROM golang:1.14-stretch as builder
+FROM golang:latest as builder
 
 
 COPY . /app
 COPY . /app
 
 
@@ -10,22 +10,28 @@ ENV GO111MODULE=auto
 
 
 RUN CGO_ENABLED=0 GOOS=linux go build -o app main.go
 RUN CGO_ENABLED=0 GOOS=linux go build -o app main.go
 
 
+WORKDIR /app/netclient
+
+ENV GO111MODULE=auto
+
+RUN CGO_ENABLED=0 GOOS=linux go build -o netclient main.go
 
 
 #second stage
 #second stage
 
 
-FROM alpine:latest
+FROM debian:latest
 
 
-WORKDIR /root/
+RUN apt-get update && apt-get -y install systemd procps
 
 
-RUN apk add --no-cache tzdata
+WORKDIR /root/
 
 
 COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
 COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
 
 
 COPY --from=builder /app .
 COPY --from=builder /app .
 COPY --from=builder /app/config config
 COPY --from=builder /app/config config
+COPY --from=builder /app/netclient netclient
 
 
 EXPOSE 8081
 EXPOSE 8081
 EXPOSE 50051
 EXPOSE 50051
 
 
-CMD ["./app", "--clientmode=off"]
+CMD ["./app"]
 
 

+ 1 - 1
controllers/dnsHttpController.go

@@ -441,7 +441,7 @@ func WriteHosts() error {
 	                }
 	                }
 		}
 		}
 	}
 	}
-	err = hostfile.SaveAs("./config/netmaker.hosts")
+	err = hostfile.SaveAs("./config/dnsconfig/netmaker.hosts")
 	return err
 	return err
 }
 }
 
 

+ 38 - 5
docker-compose.yml

@@ -1,5 +1,8 @@
-version: "3.3"
+version: "3.4"
 
 
+volumes:
+  dnsconfig:
+  driver: local
 services:
 services:
   mongodb:
   mongodb:
     image: mongo:4.2
     image: mongo:4.2
@@ -13,24 +16,54 @@ services:
       MONGO_INITDB_ROOT_USERNAME: mongoadmin
       MONGO_INITDB_ROOT_USERNAME: mongoadmin
       MONGO_INITDB_ROOT_PASSWORD: mongopass
       MONGO_INITDB_ROOT_PASSWORD: mongopass
   netmaker:
   netmaker:
+    privileged: true
     container_name: netmaker
     container_name: netmaker
+    build: netmaker
     depends_on:
     depends_on:
       - mongodb
       - mongodb
-    image: gravitl/netmaker:v0.2
+    image: gravitl/netmaker:v0.3
     ports:
     ports:
       - "8081:8081"
       - "8081:8081"
       - "50051:50051"
       - "50051:50051"
+    volumes:
+      - ./:/local
+      - /etc/netclient:/etc/netclient
+      - dnsconfig:/root/config/dnsconfig
+      - /usr/bin/wg:/usr/bin/wg:ro
+      - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
+      - /run/systemd/system:/run/systemd/system
+      - /etc/systemd/system:/etc/systemd/system
+      - /sys/fs/cgroup:/sys/fs/cgroup
     environment:
     environment:
-      MONGO_HOST: mongodb
+      MONGO_HOST: "127.0.0.1"
+      SERVER_DOMAIN: "3.236.149.180"
+    cap_add:
+      - NET_ADMIN
+      - SYS_MODULE
     restart: always
     restart: always
+    network_mode: host
   netmaker-ui:
   netmaker-ui:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.2
+    image: gravitl/netmaker-ui:v0.3
+    links:
+      - "netmaker:api"
     ports:
     ports:
       - "80:80"
       - "80:80"
     environment:
     environment:
-      BACKEND_URL: "http://localhost:8081"
+      BACKEND_URL: "http://3.236.149.180:8081"
+  coredns:
+    depends_on:
+      - netmaker 
+    image: coredns/coredns
+    command: -conf /root/dnsconfig/Corefile
+    container_name: coredns
+    restart: always
+    ports:
+      - "53:53/udp"
+    volumes:
+      - dnsconfig:/root/dnsconfig
 volumes:
 volumes:
   mongovol: {}
   mongovol: {}
+  dnsconfig: {}

+ 0 - 7
functions/helpers.go

@@ -49,11 +49,6 @@ func CreateServerToken(netID string) (string, error) {
 		privAddr = network.LocalRange
 		privAddr = network.LocalRange
 	}
 	}
 
 
-	fmt.Println("Token details:")
-	fmt.Println("    grpc address + port: " + address)
-	fmt.Println("                network: " + netID)
-	fmt.Println("          private range: " + privAddr)
-
 	accessstringdec := address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
 	accessstringdec := address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
 
 
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
@@ -131,8 +126,6 @@ func NetworkExists(name string) (bool, error) {
 		if err == mongo.ErrNoDocuments {
 		if err == mongo.ErrNoDocuments {
 			return false, nil
 			return false, nil
 		}
 		}
-		fmt.Println("Error Retrieving Group: " + name)
-		fmt.Println(err)
 	}
 	}
 	return true, err
 	return true, err
 }
 }

+ 53 - 0
functions/local.go

@@ -0,0 +1,53 @@
+package functions
+
+import (
+        "fmt"
+	"path/filepath"
+        "log"
+        "os"
+	"io/ioutil"
+)
+
+
+func FileExists(f string) bool {
+    info, err := os.Stat(f)
+    if os.IsNotExist(err) {
+        return false
+    }
+    return !info.IsDir()
+}
+
+func ConfigureDNS() error {
+	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
+	if err != nil {
+            return err
+	}
+	_, err = os.Stat(dir + "/config/dnsconfig")
+        if os.IsNotExist(err) {
+                os.Mkdir(dir +"/config/dnsconfig", 744)
+        } else if err != nil {
+                fmt.Println("couldnt find or create /config/dnsconfig")
+                return err
+        }
+
+	if !FileExists(dir + "/config/dnsconfig/Corefile") {
+
+		corefile := `. {
+    hosts /root/dnsconfig/netmaker.hosts {
+	fallthrough	
+    }
+    forward . 8.8.8.8 8.8.4.4
+    log
+}
+`
+		corebytes := []byte(corefile)
+
+		err = ioutil.WriteFile(dir + "/config/dnsconfig/Corefile", corebytes, 0644)
+		if err != nil {
+			log.Println(err)
+			log.Println("")
+			return err
+		}
+	}
+	return err
+}

+ 9 - 33
main.go

@@ -15,10 +15,7 @@ import (
     "go.mongodb.org/mongo-driver/bson"
     "go.mongodb.org/mongo-driver/bson"
     "fmt"
     "fmt"
     "time"
     "time"
-    "net/http"
     "strings"
     "strings"
-    "errors"
-    "io/ioutil"
     "os"
     "os"
     "os/exec"
     "os/exec"
     "net"
     "net"
@@ -39,10 +36,12 @@ var PortGRPC string
 func main() {
 func main() {
 
 
 
 
+	var dnsmode string
 	var clientmode string
 	var clientmode string
 	var defaultnet string
 	var defaultnet string
 	flag.StringVar(&clientmode, "clientmode", "on", "Have a client on the server")
 	flag.StringVar(&clientmode, "clientmode", "on", "Have a client on the server")
 	flag.StringVar(&defaultnet, "defaultnet", "on", "Create a default network")
 	flag.StringVar(&defaultnet, "defaultnet", "on", "Create a default network")
+	flag.StringVar(&dnsmode, "dnsmode", "on", "Add DNS settings")
 	flag.Parse()
 	flag.Parse()
 	if clientmode == "on" {
 	if clientmode == "on" {
 
 
@@ -77,6 +76,12 @@ func main() {
 		}
 		}
 	}
 	}
 	}
 	}
+	if dnsmode == "on" {
+		err := functions.ConfigureDNS()
+                if err != nil {
+                        fmt.Printf("Error setting DNS: %v", err)
+                }
+	}
 	var waitnetwork sync.WaitGroup
 	var waitnetwork sync.WaitGroup
 
 
 	if config.Config.Server.AgentBackend {
 	if config.Config.Server.AgentBackend {
@@ -116,7 +121,7 @@ func runGRPC(wg *sync.WaitGroup, installserver bool) {
 	PortGRPC = grpcport
 	PortGRPC = grpcport
 	if os.Getenv("BACKEND_URL") == ""  {
 	if os.Getenv("BACKEND_URL") == ""  {
 		if config.Config.Server.Host == "" {
 		if config.Config.Server.Host == "" {
-			ServerGRPC, _ = getPublicIP()
+			ServerGRPC, _ = serverctl.GetPublicIP()
 		} else {
 		} else {
 			ServerGRPC = config.Config.Server.Host
 			ServerGRPC = config.Config.Server.Host
 		}
 		}
@@ -281,35 +286,6 @@ func createDefaultNetwork() (bool, error) {
 
 
 }
 }
 
 
-
-func getPublicIP() (string, error) {
-
-        iplist := []string{"https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
-        endpoint := ""
-        var err error
-            for _, ipserver := range iplist {
-                resp, err := http.Get(ipserver)
-                if err != nil {
-                        continue
-                }
-                defer resp.Body.Close()
-                if resp.StatusCode == http.StatusOK {
-                        bodyBytes, err := ioutil.ReadAll(resp.Body)
-                        if err != nil {
-                                continue
-                        }
-                        endpoint = string(bodyBytes)
-                        break
-                }
-
-        }
-        if err == nil && endpoint == "" {
-                err =  errors.New("Public Address Not Found.")
-        }
-        return endpoint, err
-}
-
-
 func authServerUnaryInterceptor() grpc.ServerOption {
 func authServerUnaryInterceptor() grpc.ServerOption {
 	return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)
 	return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)
 }
 }

+ 5 - 1
netclient/functions/common.go

@@ -72,7 +72,7 @@ func GetFreePort(rangestart int32) (int32, error){
         return portno, err
         return portno, err
 }
 }
 
 
-func Install(accesskey string, password string, server string, network string, noauto bool, accesstoken string,  inputname string) error {
+func Install(accesskey string, password string, server string, network string, noauto bool, accesstoken string,  inputname string, pubip string) error {
 
 
 	tserver := ""
 	tserver := ""
 	tnetwork := ""
 	tnetwork := ""
@@ -252,6 +252,9 @@ func Install(accesskey string, password string, server string, network string, n
 	}
 	}
        fmt.Println("     Local Address: " + localaddress)
        fmt.Println("     Local Address: " + localaddress)
 
 
+        if pubip != "" && pubip != "nopubip" {
+                endpoint = pubip
+        } else {
         if nodecfg.Endpoint == "" {
         if nodecfg.Endpoint == "" {
 		if islocal && localaddress != "" {
 		if islocal && localaddress != "" {
 			endpoint = localaddress
 			endpoint = localaddress
@@ -269,6 +272,7 @@ func Install(accesskey string, password string, server string, network string, n
                 endpoint = nodecfg.Endpoint
                 endpoint = nodecfg.Endpoint
 		fmt.Println("Endpoint set in config. Setting to address: " + endpoint)
 		fmt.Println("Endpoint set in config. Setting to address: " + endpoint)
         }
         }
+	}
        fmt.Println("     Endpoint: " + endpoint)
        fmt.Println("     Endpoint: " + endpoint)
 
 
 
 

+ 20 - 28
netclient/functions/local.go

@@ -118,40 +118,32 @@ WantedBy=timers.target
                 return err
                 return err
         }
         }
 	}
 	}
-        sysExec, err := exec.LookPath("systemctl")
+        //sysExec, err := exec.LookPath("systemctl")
 
 
-        cmdSysEnableService := &exec.Cmd {
+        cmdSysEnableService := exec.Command("systemctl", "enable", "[email protected]")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "enable", "[email protected]" },
                 Args: []string{ sysExec, "enable", "[email protected]" },
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-	/*
-        cmdSysStartService := &exec.Cmd {
-                Path: sysExec,
-                Args: []string{ sysExec, "start", "[email protected]"},
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
-	*/
-        cmdSysDaemonReload := &exec.Cmd {
+        }*/
+        cmdSysDaemonReload := exec.Command("systemctl", "daemon-reload")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "daemon-reload"},
                 Args: []string{ sysExec, "daemon-reload"},
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysEnableTimer := &exec.Cmd {
+        }*/
+        cmdSysEnableTimer := exec.Command("systemctl", "enable", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "enable", "netclient-"+network+".timer" },
                 Args: []string{ sysExec, "enable", "netclient-"+network+".timer" },
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysStartTimer := &exec.Cmd {
+        }*/
+        cmdSysStartTimer := exec.Command("systemctl", "start", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
 		Args: []string{ sysExec, "start", "netclient-"+network+".timer"},
 		Args: []string{ sysExec, "start", "netclient-"+network+".timer"},
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
+        }*/
 
 
         err = cmdSysEnableService.Run()
         err = cmdSysEnableService.Run()
         if  err  !=  nil {
         if  err  !=  nil {
@@ -191,7 +183,7 @@ func isOnlyService(network string) (bool, error) {
 }
 }
 
 
 func RemoveSystemDServices(network string) error {
 func RemoveSystemDServices(network string) error {
-        sysExec, err := exec.LookPath("systemctl")
+        //sysExec, err := exec.LookPath("systemctl")
 
 
 
 
 	fullremove, err := isOnlyService(network)
 	fullremove, err := isOnlyService(network)
@@ -199,36 +191,36 @@ func RemoveSystemDServices(network string) error {
 		fmt.Println(err)
 		fmt.Println(err)
 	}
 	}
 
 
-        cmdSysDisableService := &exec.Cmd {
+	cmdSysDisableService := exec.Command("systemctl","disable","[email protected]")/* &exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "disable", "[email protected]"},
                 Args: []string{ sysExec, "disable", "[email protected]"},
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysDaemonReload := &exec.Cmd {
+        }*/
+        cmdSysDaemonReload := exec.Command("systemctl","daemon-reload")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "daemon-reload"},
                 Args: []string{ sysExec, "daemon-reload"},
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysResetFailed := &exec.Cmd {
+        }*/
+        cmdSysResetFailed := exec.Command("systemctl","reset-failed")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "reset-failed"},
                 Args: []string{ sysExec, "reset-failed"},
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysStopTimer := &exec.Cmd {
+        }*/
+        cmdSysStopTimer := exec.Command("systemctl", "stop", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "stop", "netclient-"+network+".timer" },
                 Args: []string{ sysExec, "stop", "netclient-"+network+".timer" },
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysDisableTimer := &exec.Cmd {
+        }*/
+        cmdSysDisableTimer :=  exec.Command("systemctl", "disable", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Path: sysExec,
                 Args: []string{ sysExec, "disable", "netclient-"+network+".timer"},
                 Args: []string{ sysExec, "disable", "netclient-"+network+".timer"},
                 Stdout: os.Stdout,
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
                 Stderr: os.Stdout,
-        }
+        }*/
 
 
         //err = cmdSysStopService.Run()
         //err = cmdSysStopService.Run()
         if  err  !=  nil {
         if  err  !=  nil {

+ 2 - 1
netclient/main.go

@@ -39,6 +39,7 @@ func main() {
 	tname := flag.String("name", "noname", "give the node a name at runtime")
 	tname := flag.String("name", "noname", "give the node a name at runtime")
 	tserver := flag.String("s", "localhost:50051", "The location (including port) of the remote gRPC server.")
 	tserver := flag.String("s", "localhost:50051", "The location (including port) of the remote gRPC server.")
 	tnetwork := flag.String("n", "nonetwork", "The node network you are attempting to join.")
 	tnetwork := flag.String("n", "nonetwork", "The node network you are attempting to join.")
+	tpublicip := flag.String("ip4", "nopubip", "The node network you are attempting to join.")
 	tnoauto := flag.Bool("na", false, "No auto mode. If true, netmclient will not be installed as a system service and you will have to retrieve updates manually via checkin command.")
 	tnoauto := flag.Bool("na", false, "No auto mode. If true, netmclient will not be installed as a system service and you will have to retrieve updates manually via checkin command.")
 	tnoforward := flag.Bool("nf", false, "No Forward mode. If true, netclient will not check for IP forwarding. This may break functionality")
 	tnoforward := flag.Bool("nf", false, "No Forward mode. If true, netclient will not check for IP forwarding. This may break functionality")
 	command := flag.String("c", "required", "The command to run")
 	command := flag.String("c", "required", "The command to run")
@@ -108,7 +109,7 @@ func main() {
 			}
 			}
 
 
 			fmt.Println("Beginning agent installation.")
 			fmt.Println("Beginning agent installation.")
-			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken, *tname)
+			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken, *tname, *tpublicip)
 			if err != nil {
 			if err != nil {
 				fmt.Println("Error encountered while installing.")
 				fmt.Println("Error encountered while installing.")
 				if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {
 				if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {

+ 3 - 2
scripts/netmaker-install-local.sh

@@ -13,6 +13,7 @@ sleep 10
 echo "Installing Netmaker API"
 echo "Installing Netmaker API"
 
 
 mkdir -p /etc/netmaker/config/environments
 mkdir -p /etc/netmaker/config/environments
+mkdir -p /etc/netmaker/config/dnsconfig
 cp ../netmaker /etc/netmaker/netmaker
 cp ../netmaker /etc/netmaker/netmaker
 chmod +x /etc/netmaker/netmaker
 chmod +x /etc/netmaker/netmaker
 
 
@@ -37,7 +38,7 @@ mongoconn:
   opts: '/?authSource=admin'
   opts: '/?authSource=admin'
 EOL
 EOL
 
 
-cat >/etc/netmaker/config/Corefile<<EOL
+cat >/etc/netmaker/config/dnsconfig/Corefile<<EOL
 . {
 . {
     hosts ./root/netmaker.hosts {
     hosts ./root/netmaker.hosts {
 	fallthrough	
 	fallthrough	
@@ -70,7 +71,7 @@ sudo docker pull gravitl/netmaker-ui:v0.3
 systemctl stop systemd-resolved
 systemctl stop systemd-resolved
 systemctl disable systemd-resolved
 systemctl disable systemd-resolved
 echo "Running CoreDNS"
 echo "Running CoreDNS"
-sudo docker run -d --name coredns --restart=always --volume=/etc/netmaker/config/:/root/ -p 53:53/udp coredns/coredns -conf /root/Corefile
+sudo docker run -d --name coredns --restart=always --volume=/etc/netmaker/config/dnsconfig/:/root/ -p 53:53/udp coredns/coredns -conf /root/Corefile
 
 
 echo "Running UI"
 echo "Running UI"
 sudo docker run -d --name netmaker-ui -p 80:80 -e BACKEND_URL="http://$SERVER_DOMAIN:8081" gravitl/netmaker-ui:v0.3
 sudo docker run -d --name netmaker-ui -p 80:80 -e BACKEND_URL="http://$SERVER_DOMAIN:8081" gravitl/netmaker-ui:v0.3

+ 1 - 0
scripts/uninstall-netmaker.sh

@@ -6,6 +6,7 @@ echo "Starting."
 sudo docker kill mongodb || true
 sudo docker kill mongodb || true
 sudo docker rm mongodb || true
 sudo docker rm mongodb || true
 sudo docker volume rm mongovol || true
 sudo docker volume rm mongovol || true
+sudo  docker volume rm `docker volume ls -q -f dangling=true` || true
 sudo docker kill coredns || true
 sudo docker kill coredns || true
 sudo docker rm coredns || true
 sudo docker rm coredns || true
 sudo docker kill netmaker-ui || true
 sudo docker kill netmaker-ui || true

+ 89 - 8
serverctl/serverctl.go

@@ -2,17 +2,50 @@ package serverctl
 
 
 import (
 import (
         "fmt"
         "fmt"
-  "github.com/gravitl/netmaker/functions"
+	"net/http"
+	"io/ioutil"
+	"github.com/gravitl/netmaker/functions"
 	"io"
 	"io"
 	"errors"
 	"errors"
-	"net/http"
         "os"
         "os"
         "os/exec"
         "os/exec"
 )
 )
 
 
+func GetPublicIP() (string, error) {
 
 
-func DownloadNetclient() error {
+        endpoint := ""
+        var err error
+
+        if os.Getenv("SERVER_DOMAIN") != ""  {
+                endpoint = os.Getenv("SERVER_DOMAIN")
+        } else {
+
+        iplist := []string{"https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
+        for _, ipserver := range iplist {
+                resp, err := http.Get(ipserver)
+                if err != nil {
+                        continue
+                }
+                defer resp.Body.Close()
+                if resp.StatusCode == http.StatusOK {
+                        bodyBytes, err := ioutil.ReadAll(resp.Body)
+                        if err != nil {
+                                continue
+                        }
+                        endpoint = string(bodyBytes)
+                        break
+                }
 
 
+        }
+        if err == nil && endpoint == "" {
+                err =  errors.New("Public Address Not Found.")
+        }
+        }
+        return endpoint, err
+}
+
+func DownloadNetclient() error {
+	/*
 	// Get the data
 	// Get the data
 	resp, err := http.Get("https://github.com/gravitl/netmaker/releases/download/latest/netclient")
 	resp, err := http.Get("https://github.com/gravitl/netmaker/releases/download/latest/netclient")
 	if err != nil {
 	if err != nil {
@@ -23,16 +56,58 @@ func DownloadNetclient() error {
 
 
 	// Create the file
 	// Create the file
 	out, err := os.Create("/etc/netclient/netclient")
 	out, err := os.Create("/etc/netclient/netclient")
+        */
+        if !FileExists("/etc/netclient/netclient") {
+		_, err := copy("./netclient/netclient", "/etc/netclient/netclient")
 	if err != nil {
 	if err != nil {
                 fmt.Println("could not create /etc/netclient")
                 fmt.Println("could not create /etc/netclient")
 		return err
 		return err
 	}
 	}
-	defer out.Close()
+	}
+	//defer out.Close()
 
 
 	// Write the body to file
 	// Write the body to file
-	_, err = io.Copy(out, resp.Body)
-	return err
+	//_, err = io.Copy(out, resp.Body)
+	return nil
+}
+
+func FileExists(f string) bool {
+    info, err := os.Stat(f)
+    if os.IsNotExist(err) {
+        return false
+    }
+    return !info.IsDir()
 }
 }
+
+func copy(src, dst string) (int64, error) {
+        sourceFileStat, err := os.Stat(src)
+        if err != nil {
+                return 0, err
+        }
+
+        if !sourceFileStat.Mode().IsRegular() {
+                return 0, fmt.Errorf("%s is not a regular file", src)
+        }
+
+        source, err := os.Open(src)
+        if err != nil {
+                return 0, err
+        }
+        defer source.Close()
+
+        destination, err := os.Create(dst)
+        if err != nil {
+                return 0, err
+        }
+        defer destination.Close()
+        nBytes, err := io.Copy(destination, source)
+        err = os.Chmod(dst, 0755)
+        if err != nil {
+                fmt.Println(err)
+        }
+        return nBytes, err
+}
+
 func RemoveNetwork(network string) (bool, error) {
 func RemoveNetwork(network string) (bool, error) {
 	_, err := os.Stat("/etc/netclient/netclient")
 	_, err := os.Stat("/etc/netclient/netclient")
         if err != nil {
         if err != nil {
@@ -50,7 +125,13 @@ func RemoveNetwork(network string) (bool, error) {
 }
 }
 
 
 func AddNetwork(network string) (bool, error) {
 func AddNetwork(network string) (bool, error) {
-	_, err := os.Stat("/etc/netclient")
+	pubip, err := GetPublicIP()
+        if err != nil {
+                fmt.Println("could not get public IP.")
+                return false, err
+        }
+
+	_, err = os.Stat("/etc/netclient")
         if os.IsNotExist(err) {
         if os.IsNotExist(err) {
                 os.Mkdir("/etc/netclient", 744)
                 os.Mkdir("/etc/netclient", 744)
         } else if err != nil {
         } else if err != nil {
@@ -78,7 +159,7 @@ func AddNetwork(network string) (bool, error) {
                 return false, err
                 return false, err
         }
         }
 	fmt.Println("Client is ready. Running install.")
 	fmt.Println("Client is ready. Running install.")
-	out, err := exec.Command("/etc/netclient/netclient","-c","install","-t",token,"-name","netmaker").Output()
+	out, err := exec.Command("/etc/netclient/netclient","-c","install","-t",token,"-name","netmaker","-ip4",pubip).Output()
         fmt.Println(string(out))
         fmt.Println(string(out))
 	if err != nil {
 	if err != nil {
                 return false, errors.New(string(out) + err.Error())
                 return false, errors.New(string(out) + err.Error())