Browse Source

Merge pull request #586 from gravitl/develop

Develop
dcarns 3 years ago
parent
commit
9d462c079b
57 changed files with 434 additions and 419 deletions
  1. 68 2
      .github/workflows/buildandrelease.yml
  2. 4 0
      .github/workflows/test-artifacts.yml
  3. 4 0
      .github/workflows/test.yml
  4. 2 0
      .gitignore
  5. 2 2
      README.md
  6. 3 4
      auth/azure-ad.go
  7. 2 2
      auth/github.go
  8. 2 2
      auth/google.go
  9. 2 2
      compose/docker-compose.caddy.yml
  10. 2 2
      compose/docker-compose.contained.yml
  11. 2 2
      compose/docker-compose.nodns.yml
  12. 2 2
      compose/docker-compose.reference.yml
  13. 2 2
      compose/docker-compose.yml
  14. 9 7
      config/config.go
  15. 3 4
      controllers/controller.go
  16. 2 3
      controllers/dns_test.go
  17. 7 2
      controllers/network.go
  18. 6 0
      controllers/node.go
  19. 7 0
      controllers/node_grpc.go
  20. 1 1
      controllers/user.go
  21. 1 1
      docs/api.rst
  22. 3 3
      docs/architecture.rst
  23. 4 3
      go.mod
  24. 6 6
      go.sum
  25. 1 2
      logger/logger.go
  26. 1 2
      logic/dns.go
  27. 4 0
      logic/nodes.go
  28. 57 14
      logic/util.go
  29. 3 4
      logic/wireguard.go
  30. 6 8
      main.go
  31. 6 6
      netclient/auth/auth.go
  32. 2 2
      netclient/cli_options/cmds.go
  33. 13 14
      netclient/command/commands.go
  34. 4 5
      netclient/config/config.go
  35. 1 2
      netclient/daemon/macos.go
  36. 2 3
      netclient/daemon/systemd.go
  37. 1 2
      netclient/daemon/windows.go
  38. 13 12
      netclient/functions/checkin.go
  39. 23 61
      netclient/functions/common.go
  40. 2 2
      netclient/functions/join.go
  41. 1 2
      netclient/local/dns.go
  42. 1 1
      netclient/local/local.go
  43. 1 1
      netclient/main.go
  44. 2 3
      netclient/ncutils/netclientutils.go
  45. 8 7
      netclient/ncutils/netclientutils_darwin.go
  46. 10 8
      netclient/ncutils/netclientutils_freebsd.go
  47. 24 12
      netclient/ncutils/netclientutils_linux.go
  48. 8 7
      netclient/ncutils/netclientutils_windows.go
  49. 2 3
      netclient/ncwindows/windows.go
  50. 1 1
      netclient/netclient.exe.manifest.xml
  51. 4 1
      netclient/server/grpc.go
  52. 1 1
      netclient/versioninfo.json
  53. 56 151
      netclient/wireguard/common.go
  54. 0 21
      netclient/wireguard/kernel.go
  55. 5 5
      netclient/wireguard/unix.go
  56. 1 1
      scripts/nm-quick.sh
  57. 24 3
      servercfg/serverconf.go

+ 68 - 2
.github/workflows/buildandrelease.yml

@@ -29,7 +29,7 @@ jobs:
       - name: Setup go
       - name: Setup go
         uses: actions/setup-go@v2
         uses: actions/setup-go@v2
         with:
         with:
-          go-version: 1.16
+          go-version: 1.17
 
 
       - name: Build
       - name: Build
         run: |
         run: |
@@ -40,7 +40,13 @@ jobs:
           env GOOS=linux GOARCH=arm GOARM=7 go build -o build/netclient-arm7/netclient main.go
           env GOOS=linux GOARCH=arm GOARM=7 go build -o build/netclient-arm7/netclient main.go
           env GOOS=linux GOARCH=arm64 go build -o build/netclient-arm64/netclient main.go
           env GOOS=linux GOARCH=arm64 go build -o build/netclient-arm64/netclient main.go
           env GOOS=linux GOARCH=mipsle go build -ldflags "-s -w" -o build/netclient-mipsle/netclient main.go && upx build/netclient-mipsle/netclient
           env GOOS=linux GOARCH=mipsle go build -ldflags "-s -w" -o build/netclient-mipsle/netclient main.go && upx build/netclient-mipsle/netclient
-
+          env CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -o build/netclient-freebsd/netclient main.go
+          env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=5 go build -o build/netclient-freebsd-arm5/netclient main.go
+          env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=6 go build -o build/netclient-freebsd-arm6/netclient main.go
+          env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm GOARM=7 go build -o build/netclient-freebsd-arm7/netclient main.go
+          env CGO_ENABLED=0 GOOS=freebsd GOARCH=arm64 go build -o build/netclient-freebsd-arm64/netclient main.go
+          env CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o build/netclient-darwin/netclient main.go
+          
       - name: Upload x86 to Release
       - name: Upload x86 to Release
         uses: svenstaro/upload-release-action@v2
         uses: svenstaro/upload-release-action@v2
         with:
         with:
@@ -100,3 +106,63 @@ jobs:
           overwrite: true
           overwrite: true
           prerelease: true
           prerelease: true
           asset_name: netclient-mipsle
           asset_name: netclient-mipsle
+
+      - name: Upload freebsd to Release
+        uses: svenstaro/upload-release-action@v2
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          file: netclient/build/netclient-freebsd/netclient
+          tag: ${{ env.NETMAKER_VERSION }}
+          overwrite: true
+          prerelease: true
+          asset_name: netclient-freebsd      
+          
+      - name: Upload freebsd-arm5 to Release
+        uses: svenstaro/upload-release-action@v2
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          file: netclient/build/netclient-freebsd-arm5/netclient
+          tag: ${{ env.NETMAKER_VERSION }}
+          overwrite: true
+          prerelease: true
+          asset_name: netclient-freebsd-arm5
+          
+      - name: Upload freebsd-arm6 to Release
+        uses: svenstaro/upload-release-action@v2
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          file: netclient/build/netclient-freebsd-arm6/netclient
+          tag: ${{ env.NETMAKER_VERSION }}
+          overwrite: true
+          prerelease: true
+          asset_name: netclient-freebsd-arm6
+          
+      - name: Upload freebsd-arm7 to Release
+        uses: svenstaro/upload-release-action@v2
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          file: netclient/build/netclient-freebsd-arm7/netclient
+          tag: ${{ env.NETMAKER_VERSION }}
+          overwrite: true
+          prerelease: true
+          asset_name: netclient-freebsd-arm7
+          
+      - name: Upload freebsd-arm64 to Release
+        uses: svenstaro/upload-release-action@v2
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          file: netclient/build/netclient-freebsd-arm64/netclient
+          tag: ${{ env.NETMAKER_VERSION }}
+          overwrite: true
+          prerelease: true
+          asset_name: netclient-freebsd-arm64
+          
+      - name: Upload darwin to Release
+        uses: svenstaro/upload-release-action@v2
+        with:
+          repo_token: ${{ secrets.GITHUB_TOKEN }}
+          file: netclient/build/netclient-darwin/netclient
+          tag: ${{ env.NETMAKER_VERSION }}
+          overwrite: true
+          prerelease: true
+          asset_name: netclient-darwin

+ 4 - 0
.github/workflows/test-artifacts.yml

@@ -12,6 +12,10 @@ jobs:
         steps:
         steps:
             - name: Checkout
             - name: Checkout
               uses: actions/checkout@v2
               uses: actions/checkout@v2
+            - name: Setup Go
+              uses: actions/setup-go@v2
+              with:
+                  go-version: 1.17
             - name: Set up QEMU
             - name: Set up QEMU
               uses: docker/setup-qemu-action@v1
               uses: docker/setup-qemu-action@v1
             - name: Set up Docker Buildx
             - name: Set up Docker Buildx

+ 4 - 0
.github/workflows/test.yml

@@ -11,6 +11,10 @@ jobs:
     steps:
     steps:
       - name: Checkout
       - name: Checkout
         uses: actions/checkout@v2
         uses: actions/checkout@v2
+      - name: Setup Go
+        uses: actions/setup-go@v2
+        with:
+          go-version: 1.17
       - name: run tests
       - name: run tests
         run: |
         run: |
             go test -p 1 ./... -v
             go test -p 1 ./... -v

+ 2 - 0
.gitignore

@@ -15,3 +15,5 @@ netclient/netclient32
 netclient/netclient.exe
 netclient/netclient.exe
 config/dnsconfig/
 config/dnsconfig/
 data/
 data/
+.vscode/
+.idea/

+ 2 - 2
README.md

@@ -8,7 +8,7 @@
 
 
 <p align="center">
 <p align="center">
   <a href="https://github.com/gravitl/netmaker/releases">
   <a href="https://github.com/gravitl/netmaker/releases">
-    <img src="https://img.shields.io/badge/Version-0.9.2-informational?style=flat-square" />
+    <img src="https://img.shields.io/badge/Version-0.9.3-informational?style=flat-square" />
   </a>
   </a>
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker" />
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker" />
@@ -47,7 +47,7 @@
 
 
 <img src="./docs/images/install-server.gif" width="50%" /><img src="./docs/images/visit-website.gif" width="50%" />
 <img src="./docs/images/install-server.gif" width="50%" /><img src="./docs/images/visit-website.gif" width="50%" />
 
 
-Upon completion, the logs will display the instructions to connect various devices. These can also be retrived from the UI under "Access Keys."
+Upon completion, the logs will display the instructions to connect various devices. These can also be retrieved from the UI under "Access Keys."
 
 
 After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting-started-with-netmaker-a-wireguard-virtual-networking-platform-3d563fbd87f0) and [Getting Started](https://netmaker.readthedocs.io/en/master/getting-started.html) guides to learn more about configuring networks. Or, check out some of our other [Tutorials](https://gravitl.com/resources) for different use cases, including Kubernetes.
 After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting-started-with-netmaker-a-wireguard-virtual-networking-platform-3d563fbd87f0) and [Getting Started](https://netmaker.readthedocs.io/en/master/getting-started.html) guides to learn more about configuring networks. Or, check out some of our other [Tutorials](https://gravitl.com/resources) for different use cases, including Kubernetes.
 
 

+ 3 - 4
auth/azure-ad.go

@@ -3,9 +3,8 @@ package auth
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http"
-	"os"
 
 
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
@@ -36,7 +35,7 @@ func initAzureAD(redirectURL string, clientID string, clientSecret string) {
 		ClientID:     clientID,
 		ClientID:     clientID,
 		ClientSecret: clientSecret,
 		ClientSecret: clientSecret,
 		Scopes:       []string{"User.Read"},
 		Scopes:       []string{"User.Read"},
-		Endpoint:     microsoft.AzureADEndpoint(os.Getenv("AZURE_TENANT")),
+		Endpoint:     microsoft.AzureADEndpoint(servercfg.GetAzureTenant()),
 	}
 	}
 }
 }
 
 
@@ -110,7 +109,7 @@ func getAzureUserInfo(state string, code string) (*azureOauthUser, error) {
 		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
 		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
 	}
 	}
 	defer response.Body.Close()
 	defer response.Body.Close()
-	contents, err := ioutil.ReadAll(response.Body)
+	contents, err := io.ReadAll(response.Body)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("failed reading response body: %s", err.Error())
 		return nil, fmt.Errorf("failed reading response body: %s", err.Error())
 	}
 	}

+ 2 - 2
auth/github.go

@@ -3,7 +3,7 @@ package auth
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http"
 
 
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
@@ -113,7 +113,7 @@ func getGithubUserInfo(state string, code string) (*githubOauthUser, error) {
 		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
 		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
 	}
 	}
 	defer response.Body.Close()
 	defer response.Body.Close()
-	contents, err := ioutil.ReadAll(response.Body)
+	contents, err := io.ReadAll(response.Body)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("failed reading response body: %s", err.Error())
 		return nil, fmt.Errorf("failed reading response body: %s", err.Error())
 	}
 	}

+ 2 - 2
auth/google.go

@@ -3,7 +3,7 @@ package auth
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http"
 
 
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
@@ -104,7 +104,7 @@ func getGoogleUserInfo(state string, code string) (*googleOauthUser, error) {
 		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
 		return nil, fmt.Errorf("failed getting user info: %s", err.Error())
 	}
 	}
 	defer response.Body.Close()
 	defer response.Body.Close()
-	contents, err := ioutil.ReadAll(response.Body)
+	contents, err := io.ReadAll(response.Body)
 	if err != nil {
 	if err != nil {
 		return nil, fmt.Errorf("failed reading response body: %s", err.Error())
 		return nil, fmt.Errorf("failed reading response body: %s", err.Error())
 	}
 	}

+ 2 - 2
compose/docker-compose.caddy.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.9.2
+    image: gravitl/netmaker:v0.9.3
     volumes:
     volumes:
       - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
       - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
       - /run/systemd/system:/run/systemd/system
       - /run/systemd/system:/run/systemd/system
@@ -40,7 +40,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.9.2
+    image: gravitl/netmaker-ui:v0.9.3
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 2 - 2
compose/docker-compose.contained.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.9.2
+    image: gravitl/netmaker:v0.9.3
     volumes:
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
       - /usr/bin/wg:/usr/bin/wg
       - /usr/bin/wg:/usr/bin/wg
@@ -38,7 +38,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.9.2
+    image: gravitl/netmaker-ui:v0.9.3
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 2 - 2
compose/docker-compose.nodns.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.9.2
+    image: gravitl/netmaker:v0.9.3
     volumes:
     volumes:
       - /usr/bin/wg:/usr/bin/wg
       - /usr/bin/wg:/usr/bin/wg
       - sqldata:/root/data
       - sqldata:/root/data
@@ -36,7 +36,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.9.2
+    image: gravitl/netmaker-ui:v0.9.3
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 2 - 2
compose/docker-compose.reference.yml

@@ -11,7 +11,7 @@ services:
     container_name: netmaker
     container_name: netmaker
     depends_on:
     depends_on:
       - rqlite
       - rqlite
-    image: gravitl/netmaker:v0.9.2
+    image: gravitl/netmaker:v0.9.3
     volumes: # Volume mounts necessary for CLIENT_MODE to control wireguard networking on host (except dnsconfig, which is where dns config files are stored for use by CoreDNS)
     volumes: # Volume mounts necessary for CLIENT_MODE to control wireguard networking on host (except dnsconfig, which is where dns config files are stored for use by CoreDNS)
       - dnsconfig:/root/config/dnsconfig # Netmaker writes Corefile to this location, which gets mounted by CoreDNS for DNS configuration.
       - dnsconfig:/root/config/dnsconfig # Netmaker writes Corefile to this location, which gets mounted by CoreDNS for DNS configuration.
       - /usr/bin/wg:/usr/bin/wg
       - /usr/bin/wg:/usr/bin/wg
@@ -41,7 +41,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.9.2
+    image: gravitl/netmaker-ui:v0.9.3
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 2 - 2
compose/docker-compose.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.9.0
+    image: gravitl/netmaker:v0.9.3
     volumes:
     volumes:
       - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
       - /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
       - /run/systemd/system:/run/systemd/system
       - /run/systemd/system:/run/systemd/system
@@ -40,7 +40,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.9.2
+    image: gravitl/netmaker-ui:v0.9.3
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 9 - 7
config/config.go

@@ -12,7 +12,7 @@ import (
 	"gopkg.in/yaml.v3"
 	"gopkg.in/yaml.v3"
 )
 )
 
 
-//setting dev by default
+// setting dev by default
 func getEnv() string {
 func getEnv() string {
 
 
 	env := os.Getenv("NETMAKER_ENV")
 	env := os.Getenv("NETMAKER_ENV")
@@ -27,13 +27,13 @@ func getEnv() string {
 // Config : application config stored as global variable
 // Config : application config stored as global variable
 var Config *EnvironmentConfig
 var Config *EnvironmentConfig
 
 
-// EnvironmentConfig :
+// EnvironmentConfig - environment conf struct
 type EnvironmentConfig struct {
 type EnvironmentConfig struct {
 	Server ServerConfig `yaml:"server"`
 	Server ServerConfig `yaml:"server"`
 	SQL    SQLConfig    `yaml:"sql"`
 	SQL    SQLConfig    `yaml:"sql"`
 }
 }
 
 
-// ServerConfig :
+// ServerConfig - server conf struct
 type ServerConfig struct {
 type ServerConfig struct {
 	CoreDNSAddr           string `yaml:"corednsaddr"`
 	CoreDNSAddr           string `yaml:"corednsaddr"`
 	APIConnString         string `yaml:"apiconn"`
 	APIConnString         string `yaml:"apiconn"`
@@ -58,8 +58,8 @@ type ServerConfig struct {
 	Version               string `yaml:"version"`
 	Version               string `yaml:"version"`
 	SQLConn               string `yaml:"sqlconn"`
 	SQLConn               string `yaml:"sqlconn"`
 	Platform              string `yaml:"platform"`
 	Platform              string `yaml:"platform"`
-	Database              string `yaml:database`
-	CheckinInterval       string `yaml:checkininterval`
+	Database              string `yaml:"database"`
+	CheckinInterval       string `yaml:"checkininterval"`
 	DefaultNodeLimit      int32  `yaml:"defaultnodelimit"`
 	DefaultNodeLimit      int32  `yaml:"defaultnodelimit"`
 	Verbosity             int32  `yaml:"verbosity"`
 	Verbosity             int32  `yaml:"verbosity"`
 	ServerCheckinInterval int64  `yaml:"servercheckininterval"`
 	ServerCheckinInterval int64  `yaml:"servercheckininterval"`
@@ -68,9 +68,11 @@ type ServerConfig struct {
 	ClientSecret          string `yaml:"clientsecret"`
 	ClientSecret          string `yaml:"clientsecret"`
 	FrontendURL           string `yaml:"frontendurl"`
 	FrontendURL           string `yaml:"frontendurl"`
 	DisplayKeys           string `yaml:"displaykeys"`
 	DisplayKeys           string `yaml:"displaykeys"`
+	AzureTenant           string `yaml:"azuretenant"`
+	RCE                   string `yaml:"rce"`
 }
 }
 
 
-// Generic SQL Config
+// SQLConfig - Generic SQL Config
 type SQLConfig struct {
 type SQLConfig struct {
 	Host     string `yaml:"host"`
 	Host     string `yaml:"host"`
 	Port     int32  `yaml:"port"`
 	Port     int32  `yaml:"port"`
@@ -80,7 +82,7 @@ type SQLConfig struct {
 	SSLMode  string `yaml:"sslmode"`
 	SSLMode  string `yaml:"sslmode"`
 }
 }
 
 
-//reading in the env file
+// reading in the env file
 func readConfig() *EnvironmentConfig {
 func readConfig() *EnvironmentConfig {
 	file := fmt.Sprintf("config/environments/%s.yaml", getEnv())
 	file := fmt.Sprintf("config/environments/%s.yaml", getEnv())
 	f, err := os.Open(file)
 	f, err := os.Open(file)

+ 3 - 4
controllers/controller.go

@@ -52,20 +52,19 @@ func HandleRESTRequests(wg *sync.WaitGroup) {
 		}
 		}
 	}()
 	}()
 	logger.Log(0, "REST Server successfully started on port ", port, " (REST)")
 	logger.Log(0, "REST Server successfully started on port ", port, " (REST)")
-	c := make(chan os.Signal)
 
 
 	// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
 	// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
 	// Ignore other incoming signals
 	// Ignore other incoming signals
-	signal.Notify(c, os.Interrupt)
+	ctx, stop := signal.NotifyContext(context.TODO(), os.Interrupt)
+	defer stop()
 
 
 	// Block main routine until a signal is received
 	// Block main routine until a signal is received
 	// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
 	// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
-	<-c
+	<-ctx.Done()
 
 
 	// After receiving CTRL+C Properly stop the server
 	// After receiving CTRL+C Properly stop the server
 	logger.Log(0, "Stopping the REST server...")
 	logger.Log(0, "Stopping the REST server...")
 	srv.Shutdown(context.TODO())
 	srv.Shutdown(context.TODO())
 	logger.Log(0, "REST Server closed.")
 	logger.Log(0, "REST Server closed.")
 	logger.DumpFile(fmt.Sprintf("data/netmaker.log.%s", time.Now().Format(logger.TimeFormatDay)))
 	logger.DumpFile(fmt.Sprintf("data/netmaker.log.%s", time.Now().Format(logger.TimeFormatDay)))
-
 }
 }

+ 2 - 3
controllers/dns_test.go

@@ -1,7 +1,6 @@
 package controller
 package controller
 
 
 import (
 import (
-	"io/ioutil"
 	"os"
 	"os"
 	"testing"
 	"testing"
 
 
@@ -200,7 +199,7 @@ func TestSetDNS(t *testing.T) {
 		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
 		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.False(t, info.IsDir())
 		assert.False(t, info.IsDir())
-		content, err := ioutil.ReadFile("./config/dnsconfig/netmaker.hosts")
+		content, err := os.ReadFile("./config/dnsconfig/netmaker.hosts")
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.Contains(t, string(content), "testnode.skynet")
 		assert.Contains(t, string(content), "testnode.skynet")
 	})
 	})
@@ -212,7 +211,7 @@ func TestSetDNS(t *testing.T) {
 		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
 		info, err := os.Stat("./config/dnsconfig/netmaker.hosts")
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.False(t, info.IsDir())
 		assert.False(t, info.IsDir())
-		content, err := ioutil.ReadFile("./config/dnsconfig/netmaker.hosts")
+		content, err := os.ReadFile("./config/dnsconfig/netmaker.hosts")
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.Contains(t, string(content), "newhost.skynet")
 		assert.Contains(t, string(content), "newhost.skynet")
 	})
 	})

+ 7 - 2
controllers/network.go

@@ -68,7 +68,7 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(allnetworks)
 	json.NewEncoder(w).Encode(allnetworks)
 }
 }
 
 
-//Simple get network function
+// Simple get network function
 func getNetwork(w http.ResponseWriter, r *http.Request) {
 func getNetwork(w http.ResponseWriter, r *http.Request) {
 	// set header.
 	// set header.
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
@@ -101,7 +101,7 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(network)
 	json.NewEncoder(w).Encode(network)
 }
 }
 
 
-//Update a network
+// Update a network
 func updateNetwork(w http.ResponseWriter, r *http.Request) {
 func updateNetwork(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 	var params = mux.Vars(r)
 	var params = mux.Vars(r)
@@ -119,6 +119,11 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
+	if !servercfg.GetRce() {
+		newNetwork.DefaultPostDown = network.DefaultPostDown
+		newNetwork.DefaultPostUp = network.DefaultPostUp
+	}
+
 	rangeupdate, localrangeupdate, err := logic.UpdateNetwork(&network, &newNetwork)
 	rangeupdate, localrangeupdate, err := logic.UpdateNetwork(&network, &newNetwork)
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		returnErrorResponse(w, r, formatError(err, "badrequest"))

+ 6 - 0
controllers/node.go

@@ -524,6 +524,12 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 			}
 			}
 		}
 		}
 	}
 	}
+
+	if !servercfg.GetRce() {
+		newNode.PostDown = node.PostDown
+		newNode.PostUp = node.PostUp
+	}
+
 	err = logic.UpdateNode(&node, &newNode)
 	err = logic.UpdateNode(&node, &newNode)
 	if err != nil {
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
 		returnErrorResponse(w, r, formatError(err, "internal"))

+ 7 - 0
controllers/node_grpc.go

@@ -10,6 +10,7 @@ import (
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/servercfg"
 )
 )
 
 
 // NodeServiceServer - represents the service server for gRPC
 // NodeServiceServer - represents the service server for gRPC
@@ -107,6 +108,12 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
+
+	if !servercfg.GetRce() {
+		newnode.PostDown = node.PostDown
+		newnode.PostUp = node.PostUp
+	}
+
 	err = logic.UpdateNode(&node, &newnode)
 	err = logic.UpdateNode(&node, &newnode)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err

+ 1 - 1
controllers/user.go

@@ -23,7 +23,7 @@ func userHandlers(r *mux.Router) {
 	r.HandleFunc("/api/users/networks/{username}", securityCheck(true, http.HandlerFunc(updateUserNetworks))).Methods("PUT")
 	r.HandleFunc("/api/users/networks/{username}", securityCheck(true, http.HandlerFunc(updateUserNetworks))).Methods("PUT")
 	r.HandleFunc("/api/users/{username}/adm", securityCheck(true, http.HandlerFunc(updateUserAdm))).Methods("PUT")
 	r.HandleFunc("/api/users/{username}/adm", securityCheck(true, http.HandlerFunc(updateUserAdm))).Methods("PUT")
 	r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(createUser))).Methods("POST")
 	r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(createUser))).Methods("POST")
-	r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(deleteUser)))).Methods("DELETE")
+	r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(deleteUser))).Methods("DELETE")
 	r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(getUser)))).Methods("GET")
 	r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(getUser)))).Methods("GET")
 	r.HandleFunc("/api/users", securityCheck(true, http.HandlerFunc(getUsers))).Methods("GET")
 	r.HandleFunc("/api/users", securityCheck(true, http.HandlerFunc(getUsers))).Methods("GET")
 	r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods("GET")
 	r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods("GET")

+ 1 - 1
docs/api.rst

@@ -12,7 +12,7 @@ Authentication
 ==============
 ==============
 API calls must be authenticated via a header of  the format  `-H "Authorization: Bearer <YOUR_SECRET_KEY>"` There are two methods to obtain YOUR_SECRET_KEY:
 API calls must be authenticated via a header of  the format  `-H "Authorization: Bearer <YOUR_SECRET_KEY>"` There are two methods to obtain YOUR_SECRET_KEY:
 1. Using the masterkey. By default, this value is "secret key," but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [general usage](./USAGE.md) documentation for more details.
 1. Using the masterkey. By default, this value is "secret key," but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [general usage](./USAGE.md) documentation for more details.
-2. Using a JWT recieved for a node. This  can be retrieved by calling the `/api/nodes/<network>/authenticate` endpoint, as documented below.
+2. Using a JWT received for a node. This  can be retrieved by calling the `/api/nodes/<network>/authenticate` endpoint, as documented below.
 
 
 
 
 Format of Calls for Curl
 Format of Calls for Curl

+ 3 - 3
docs/architecture.rst

@@ -21,7 +21,7 @@ WireGuard
 
 
 WireGuard is a relatively new but very important technology which was recently added to the Linux kernel. WireGuard creates very fast but simple encrypted tunnels between devices. From the `WireGuard <https://www.wireguard.com/>`_ website, "it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry."
 WireGuard is a relatively new but very important technology which was recently added to the Linux kernel. WireGuard creates very fast but simple encrypted tunnels between devices. From the `WireGuard <https://www.wireguard.com/>`_ website, "it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry."
 
 
-Previous solutions like OpenVPN and IPSec are considerably more heavy and complex, while being less performant. All existing VPN tunnelling solutions will cause a significant increase in your network latency. WireGuard is the first to achieve near over-the-line network speeds, meaning you see no signigifant performance impact.  With the release of WireGuard, there is little reason to use any other existing tunnel encryption technology.
+Previous solutions like OpenVPN and IPSec are considerably more heavy and complex, while being less performant. All existing VPN tunneling solutions will cause a significant increase in your network latency. WireGuard is the first to achieve near over-the-line network speeds, meaning you see no significant performance impact.  With the release of WireGuard, there is little reason to use any other existing tunnel encryption technology.
 
 
 Mesh Network
 Mesh Network
 -------------
 -------------
@@ -56,7 +56,7 @@ Netmaker does a lot of work to set configurations for you, so that you don't hav
 Node
 Node
 ------
 ------
 
 
-A machine in a Netmaker network, which is managed by the Netclient, is referred to as a Node, as you will see in the UI. A Node can be a VM, a bare metal server, a desktop computer, an IoT device, or any other number of internet-connected machines on which the netclient is installed. A node is simply an endpoint in the network, which can send traffic to all the other nodes, and recieve traffic from all of the other nodes.
+A machine in a Netmaker network, which is managed by the Netclient, is referred to as a Node, as you will see in the UI. A Node can be a VM, a bare metal server, a desktop computer, an IoT device, or any other number of internet-connected machines on which the netclient is installed. A node is simply an endpoint in the network, which can send traffic to all the other nodes, and receive traffic from all of the other nodes.
 
 
 SystemD
 SystemD
 -------
 -------
@@ -153,7 +153,7 @@ Below is a high level, step-by-step overview of the flow of communications withi
 9. Netmaker server verifies information and creates the node, setting default values for any missing information. 
 9. Netmaker server verifies information and creates the node, setting default values for any missing information. 
 10. Timestamp is set for the network (see #16). 
 10. Timestamp is set for the network (see #16). 
 11. Netmaker returns settings as response to netclient. Some settings may be added or modified based on the network.
 11. Netmaker returns settings as response to netclient. Some settings may be added or modified based on the network.
-12. Netclient recieves response. If successful, it takes any additional info returned from Netmaker and configures the local system/WireGuard
+12. Netclient receives response. If successful, it takes any additional info returned from Netmaker and configures the local system/WireGuard
 13. Netclient sends another request to Netmaker's GRPC server, this time to retrieve the peers list (all other clients in the network).
 13. Netclient sends another request to Netmaker's GRPC server, this time to retrieve the peers list (all other clients in the network).
 14. Netmaker sends back peers list, including current known configurations of all nodes in network.
 14. Netmaker sends back peers list, including current known configurations of all nodes in network.
 15. Netclient configures WireGuard with this information. At this point, the node is fully configured as a part of the network and should be able to reach the other nodes via private address.
 15. Netclient configures WireGuard with this information. At this point, the node is fully configured as a part of the network and should be able to reach the other nodes via private address.

+ 4 - 3
go.mod

@@ -3,13 +3,13 @@ module github.com/gravitl/netmaker
 go 1.17
 go 1.17
 
 
 require (
 require (
-	github.com/go-playground/validator/v10 v10.9.0
+	github.com/go-playground/validator/v10 v10.10.0
 	github.com/golang-jwt/jwt/v4 v4.2.0
 	github.com/golang-jwt/jwt/v4 v4.2.0
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
 	github.com/gorilla/mux v1.8.0
 	github.com/lib/pq v1.10.4
 	github.com/lib/pq v1.10.4
-	github.com/mattn/go-sqlite3 v1.14.9
+	github.com/mattn/go-sqlite3 v1.14.10
 	github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
 	github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.7.0
 	github.com/stretchr/testify v1.7.0
@@ -23,7 +23,7 @@ require (
 	golang.zx2c4.com/wireguard v0.0.0-20210805125648-3957e9b9dd19 // indirect
 	golang.zx2c4.com/wireguard v0.0.0-20210805125648-3957e9b9dd19 // indirect
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210913210325-91d1988e44de
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210913210325-91d1988e44de
 	google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
 	google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
-	google.golang.org/grpc v1.42.0
+	google.golang.org/grpc v1.43.0
 	google.golang.org/protobuf v1.27.1
 	google.golang.org/protobuf v1.27.1
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 )
 )
@@ -31,6 +31,7 @@ require (
 require (
 require (
 	cloud.google.com/go v0.34.0 // indirect
 	cloud.google.com/go v0.34.0 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/felixge/httpsnoop v1.0.1 // indirect
 	github.com/felixge/httpsnoop v1.0.1 // indirect
 	github.com/go-playground/locales v0.14.0 // indirect
 	github.com/go-playground/locales v0.14.0 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect

+ 6 - 6
go.sum

@@ -40,8 +40,8 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A=
-github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
+github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
+github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
 github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
 github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -100,8 +100,8 @@ github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ic
 github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
 github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
-github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
+github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY=
 github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY=
 github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
 github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
 github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
 github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
@@ -258,8 +258,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A=
-google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
+google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
+google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

+ 1 - 2
logger/logger.go

@@ -2,7 +2,6 @@ package logger
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"os"
 	"sort"
 	"sort"
 	"strconv"
 	"strconv"
@@ -90,7 +89,7 @@ func DumpFile(filePath string) {
 
 
 // Retrieve - retrieves logs from given file
 // Retrieve - retrieves logs from given file
 func Retrieve(filePath string) string {
 func Retrieve(filePath string) string {
-	contents, err := ioutil.ReadFile(filePath)
+	contents, err := os.ReadFile(filePath)
 	if err != nil {
 	if err != nil {
 		panic(err)
 		panic(err)
 	}
 	}

+ 1 - 2
logic/dns.go

@@ -2,7 +2,6 @@ package logic
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
-	"io/ioutil"
 	"os"
 	"os"
 
 
 	"github.com/go-playground/validator/v10"
 	"github.com/go-playground/validator/v10"
@@ -135,7 +134,7 @@ func SetCorefile(domains string) error {
 `
 `
 	corebytes := []byte(corefile)
 	corebytes := []byte(corefile)
 
 
-	err = ioutil.WriteFile(dir+"/config/dnsconfig/Corefile", corebytes, 0644)
+	err = os.WriteFile(dir+"/config/dnsconfig/Corefile", corebytes, 0644)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 4 - 0
logic/nodes.go

@@ -253,6 +253,10 @@ func SetNodeDefaults(node *models.Node) {
 		postup := parentNetwork.DefaultPostUp
 		postup := parentNetwork.DefaultPostUp
 		node.PostUp = postup
 		node.PostUp = postup
 	}
 	}
+	if node.PostDown == "" {
+		postdown := parentNetwork.DefaultPostDown
+		node.PostDown = postdown
+	}
 	if node.IsStatic == "" {
 	if node.IsStatic == "" {
 		node.IsStatic = "no"
 		node.IsStatic = "no"
 	}
 	}

+ 57 - 14
logic/util.go

@@ -184,26 +184,18 @@ func GetNode(macaddress string, network string) (models.Node, error) {
 // GetNodePeers - fetches peers for a given node
 // GetNodePeers - fetches peers for a given node
 func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) {
 func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) {
 	var peers []models.Node
 	var peers []models.Node
-	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
+	var networkNodes, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName)
 	if err != nil {
 	if err != nil {
-		if database.IsEmptyRecord(err) {
-			return peers, nil
-		}
-		logger.Log(2, err.Error())
-		return nil, err
+		return peers, nil
 	}
 	}
+
 	udppeers, errN := database.GetPeers(networkName)
 	udppeers, errN := database.GetPeers(networkName)
 	if errN != nil {
 	if errN != nil {
 		logger.Log(2, errN.Error())
 		logger.Log(2, errN.Error())
 	}
 	}
-	for _, value := range collection {
-		var node = &models.Node{}
+
+	for _, node := range networkNodes {
 		var peer = models.Node{}
 		var peer = models.Node{}
-		err := json.Unmarshal([]byte(value), node)
-		if err != nil {
-			logger.Log(2, err.Error())
-			continue
-		}
 		if node.IsEgressGateway == "yes" { // handle egress stuff
 		if node.IsEgressGateway == "yes" { // handle egress stuff
 			peer.EgressGatewayRanges = node.EgressGatewayRanges
 			peer.EgressGatewayRanges = node.EgressGatewayRanges
 			peer.IsEgressGateway = node.IsEgressGateway
 			peer.IsEgressGateway = node.IsEgressGateway
@@ -211,7 +203,7 @@ func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error
 		allow := node.IsRelayed != "yes" || !excludeRelayed
 		allow := node.IsRelayed != "yes" || !excludeRelayed
 
 
 		if node.Network == networkName && node.IsPending != "yes" && allow {
 		if node.Network == networkName && node.IsPending != "yes" && allow {
-			peer = setPeerInfo(node)
+			peer = setPeerInfo(&node)
 			if node.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[node.PublicKey]) {
 			if node.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[node.PublicKey]) {
 				endpointstring := udppeers[node.PublicKey]
 				endpointstring := udppeers[node.PublicKey]
 				endpointarr := strings.Split(endpointstring, ":")
 				endpointarr := strings.Split(endpointstring, ":")
@@ -230,6 +222,11 @@ func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error
 				} else {
 				} else {
 					peer.AllowedIPs = append(peer.AllowedIPs, node.RelayAddrs...)
 					peer.AllowedIPs = append(peer.AllowedIPs, node.RelayAddrs...)
 				}
 				}
+				for _, egressNode := range egressNetworkNodes {
+					if egressNode.IsRelayed == "yes" && StringSliceContains(node.RelayAddrs, egressNode.Address) {
+						peer.AllowedIPs = append(peer.AllowedIPs, egressNode.EgressGatewayRanges...)
+					}
+				}
 			}
 			}
 			peers = append(peers, peer)
 			peers = append(peers, peer)
 		}
 		}
@@ -252,6 +249,14 @@ func GetPeersList(networkName string, excludeRelayed bool, relayedNodeAddr strin
 			network, err := GetNetwork(networkName)
 			network, err := GetNetwork(networkName)
 			if err == nil {
 			if err == nil {
 				peerNode.AllowedIPs = append(peerNode.AllowedIPs, network.AddressRange)
 				peerNode.AllowedIPs = append(peerNode.AllowedIPs, network.AddressRange)
+				var _, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName)
+				if err == nil {
+					for _, egress := range egressNetworkNodes {
+						if egress.Address != relayedNodeAddr {
+							peerNode.AllowedIPs = append(peerNode.AllowedIPs, egress.EgressGatewayRanges...)
+						}
+					}
+				}
 			} else {
 			} else {
 				peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...)
 				peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...)
 			}
 			}
@@ -286,6 +291,34 @@ func RandomString(length int) string {
 
 
 // == Private Methods ==
 // == Private Methods ==
 
 
+func getNetworkEgressAndNodes(networkName string) ([]models.Node, []models.Node, error) {
+	var networkNodes, egressNetworkNodes []models.Node
+	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
+	if err != nil {
+		if database.IsEmptyRecord(err) {
+			return networkNodes, egressNetworkNodes, nil
+		}
+		logger.Log(2, err.Error())
+		return nil, nil, err
+	}
+
+	for _, value := range collection {
+		var node = models.Node{}
+		err := json.Unmarshal([]byte(value), &node)
+		if err != nil {
+			logger.Log(2, err.Error())
+			continue
+		}
+		if node.Network == networkName {
+			networkNodes = append(networkNodes, node)
+			if node.IsEgressGateway == "yes" {
+				egressNetworkNodes = append(egressNetworkNodes, node)
+			}
+		}
+	}
+	return networkNodes, egressNetworkNodes, nil
+}
+
 func setPeerInfo(node *models.Node) models.Node {
 func setPeerInfo(node *models.Node) models.Node {
 	var peer models.Node
 	var peer models.Node
 	peer.RelayAddrs = node.RelayAddrs
 	peer.RelayAddrs = node.RelayAddrs
@@ -326,3 +359,13 @@ func setIPForwardingLinux() error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+
+// StringSliceContains - sees if a string slice contains a string element
+func StringSliceContains(slice []string, item string) bool {
+	for _, s := range slice {
+		if s == item {
+			return true
+		}
+	}
+	return false
+}

+ 3 - 4
logic/wireguard.go

@@ -3,7 +3,6 @@ package logic
 import (
 import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
 	"strconv"
 	"strconv"
@@ -86,10 +85,10 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 
 
 	if !ncutils.IsKernel() {
 	if !ncutils.IsKernel() {
 		var newConf string
 		var newConf string
-		newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, node.PersistentKeepalive, peers)
+		newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), peers)
 		confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf"
 		confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf"
 		logger.Log(1, "writing wg conf file to:", confPath)
 		logger.Log(1, "writing wg conf file to:", confPath)
-		err = ioutil.WriteFile(confPath, []byte(newConf), 0644)
+		err = os.WriteFile(confPath, []byte(newConf), 0644)
 		if err != nil {
 		if err != nil {
 			logger.Log(1, "error writing wg conf file to", confPath, ":", err.Error())
 			logger.Log(1, "error writing wg conf file to", confPath, ":", err.Error())
 			return err
 			return err
@@ -97,7 +96,7 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		if ncutils.IsWindows() {
 		if ncutils.IsWindows() {
 			wgConfPath := ncutils.GetWGPathSpecific() + ifacename + ".conf"
 			wgConfPath := ncutils.GetWGPathSpecific() + ifacename + ".conf"
 			logger.Log(1, "writing wg conf file to:", confPath)
 			logger.Log(1, "writing wg conf file to:", confPath)
-			err = ioutil.WriteFile(wgConfPath, []byte(newConf), 0644)
+			err = os.WriteFile(wgConfPath, []byte(newConf), 0644)
 			if err != nil {
 			if err != nil {
 				logger.Log(1, "error writing wg conf file to", wgConfPath, ":", err.Error())
 				logger.Log(1, "error writing wg conf file to", wgConfPath, ":", err.Error())
 				return err
 				return err

+ 6 - 8
main.go

@@ -1,6 +1,7 @@
 package main
 package main
 
 
 import (
 import (
+	"context"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 	"os"
 	"os"
@@ -43,7 +44,7 @@ func initialize() { // Client Mode Prereq Check
 
 
 	var authProvider = auth.InitializeAuthProvider()
 	var authProvider = auth.InitializeAuthProvider()
 	if authProvider != "" {
 	if authProvider != "" {
-		logger.Log(0, "OAuth provider, ", authProvider, ", initialized")
+		logger.Log(0, "OAuth provider,", authProvider+",", "initialized")
 	} else {
 	} else {
 		logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth")
 		logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth")
 	}
 	}
@@ -157,21 +158,18 @@ func runGRPC(wg *sync.WaitGroup) {
 	}()
 	}()
 	logger.Log(0, "Agent Server successfully started on port ", grpcport, "(gRPC)")
 	logger.Log(0, "Agent Server successfully started on port ", grpcport, "(gRPC)")
 
 
-	// Right way to stop the server using a SHUTDOWN HOOK
-	// Create a channel to receive OS signals
-	c := make(chan os.Signal, 1)
-
 	// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
 	// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
 	// Ignore other incoming signals
 	// Ignore other incoming signals
-	signal.Notify(c, os.Interrupt)
+	ctx, stop := signal.NotifyContext(context.TODO(), os.Interrupt)
+	defer stop()
 
 
 	// Block main routine until a signal is received
 	// Block main routine until a signal is received
 	// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
 	// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
-	<-c
+	<-ctx.Done()
 
 
 	// After receiving CTRL+C Properly stop the server
 	// After receiving CTRL+C Properly stop the server
 	logger.Log(0, "Stopping the Agent server...")
 	logger.Log(0, "Stopping the Agent server...")
-	s.Stop()
+	s.GracefulStop()
 	listener.Close()
 	listener.Close()
 	logger.Log(0, "Agent server closed..")
 	logger.Log(0, "Agent server closed..")
 	logger.Log(0, "Closed DB connection.")
 	logger.Log(0, "Closed DB connection.")

+ 6 - 6
netclient/auth/auth.go

@@ -3,6 +3,7 @@ package auth
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
+	"os"
 
 
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/config"
@@ -10,7 +11,6 @@ import (
 
 
 	//    "os"
 	//    "os"
 	"context"
 	"context"
-	"io/ioutil"
 
 
 	nodepb "github.com/gravitl/netmaker/grpc"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/codes"
@@ -21,13 +21,13 @@ import (
 // SetJWT func will used to create the JWT while signing in and signing out
 // SetJWT func will used to create the JWT while signing in and signing out
 func SetJWT(client nodepb.NodeServiceClient, network string) (context.Context, error) {
 func SetJWT(client nodepb.NodeServiceClient, network string) (context.Context, error) {
 	home := ncutils.GetNetclientPathSpecific()
 	home := ncutils.GetNetclientPathSpecific()
-	tokentext, err := ioutil.ReadFile(home + "nettoken-" + network)
+	tokentext, err := os.ReadFile(home + "nettoken-" + network)
 	if err != nil {
 	if err != nil {
 		err = AutoLogin(client, network)
 		err = AutoLogin(client, network)
 		if err != nil {
 		if err != nil {
 			return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err))
 			return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err))
 		}
 		}
-		tokentext, err = ioutil.ReadFile(home + "nettoken-" + network)
+		tokentext, err = os.ReadFile(home + "nettoken-" + network)
 		if err != nil {
 		if err != nil {
 			return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err))
 			return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err))
 		}
 		}
@@ -71,7 +71,7 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error {
 		return err
 		return err
 	}
 	}
 	tokenstring := []byte(res.Data)
 	tokenstring := []byte(res.Data)
-	err = ioutil.WriteFile(home+"nettoken-"+network, tokenstring, 0644)
+	err = os.WriteFile(home+"nettoken-"+network, tokenstring, 0644)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -81,13 +81,13 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error {
 // StoreSecret - stores auth secret locally
 // StoreSecret - stores auth secret locally
 func StoreSecret(key string, network string) error {
 func StoreSecret(key string, network string) error {
 	d1 := []byte(key)
 	d1 := []byte(key)
-	err := ioutil.WriteFile(ncutils.GetNetclientPathSpecific()+"secret-"+network, d1, 0644)
+	err := os.WriteFile(ncutils.GetNetclientPathSpecific()+"secret-"+network, d1, 0644)
 	return err
 	return err
 }
 }
 
 
 // RetrieveSecret - fetches secret locally
 // RetrieveSecret - fetches secret locally
 func RetrieveSecret(network string) (string, error) {
 func RetrieveSecret(network string) (string, error) {
-	dat, err := ioutil.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + network)
+	dat, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + network)
 	return string(dat), err
 	return string(dat), err
 }
 }
 
 

+ 2 - 2
netclient/cli_options/cmds.go

@@ -21,11 +21,11 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command {
 					return err
 					return err
 				}
 				}
 				if cfg.Network == "all" {
 				if cfg.Network == "all" {
-					err = errors.New("No network provided.")
+					err = errors.New("no network provided")
 					return err
 					return err
 				}
 				}
 				if cfg.Server.GRPCAddress == "" {
 				if cfg.Server.GRPCAddress == "" {
-					err = errors.New("No server address provided.")
+					err = errors.New("no server address provided")
 					return err
 					return err
 				}
 				}
 				err = command.Join(cfg, pvtKey)
 				err = command.Join(cfg, pvtKey)

+ 13 - 14
netclient/command/commands.go

@@ -7,22 +7,13 @@ import (
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
-	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/daemon"
 	"github.com/gravitl/netmaker/netclient/daemon"
 	"github.com/gravitl/netmaker/netclient/functions"
 	"github.com/gravitl/netmaker/netclient/functions"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
-	"golang.zx2c4.com/wireguard/wgctrl"
-)
-
-var (
-	wgclient *wgctrl.Client
-)
-
-var (
-	wcclient nodepb.NodeServiceClient
 )
 )
 
 
+// Join - join command to run from cli
 func Join(cfg config.ClientConfig, privateKey string) error {
 func Join(cfg config.ClientConfig, privateKey string) error {
 
 
 	var err error
 	var err error
@@ -83,6 +74,7 @@ func getWindowsInterval() int {
 	return interval
 	return interval
 }
 }
 
 
+// RunUserspaceDaemon - runs continual checkins
 func RunUserspaceDaemon() {
 func RunUserspaceDaemon() {
 
 
 	cfg := config.ClientConfig{
 	cfg := config.ClientConfig{
@@ -91,14 +83,15 @@ func RunUserspaceDaemon() {
 	interval := getWindowsInterval()
 	interval := getWindowsInterval()
 	dur := time.Duration(interval) * time.Second
 	dur := time.Duration(interval) * time.Second
 	for {
 	for {
-		if err := CheckIn(cfg); err != nil {
-			// pass
-		}
+		CheckIn(cfg)
 		time.Sleep(dur)
 		time.Sleep(dur)
 	}
 	}
 }
 }
 
 
+// CheckIn - runs checkin command from cli
 func CheckIn(cfg config.ClientConfig) error {
 func CheckIn(cfg config.ClientConfig) error {
+	//log.Println("checkin --- diabled for now")
+	//return nil
 	var err error
 	var err error
 	var errN error
 	var errN error
 	if cfg.Network == "" {
 	if cfg.Network == "" {
@@ -139,6 +132,7 @@ func CheckIn(cfg config.ClientConfig) error {
 	return err
 	return err
 }
 }
 
 
+// Leave - runs the leave command from cli
 func Leave(cfg config.ClientConfig) error {
 func Leave(cfg config.ClientConfig) error {
 	err := functions.LeaveNetwork(cfg.Network)
 	err := functions.LeaveNetwork(cfg.Network)
 	if err != nil {
 	if err != nil {
@@ -149,6 +143,7 @@ func Leave(cfg config.ClientConfig) error {
 	return err
 	return err
 }
 }
 
 
+// Push - runs push command
 func Push(cfg config.ClientConfig) error {
 func Push(cfg config.ClientConfig) error {
 	var err error
 	var err error
 	if cfg.Network == "all" || ncutils.IsWindows() {
 	if cfg.Network == "all" || ncutils.IsWindows() {
@@ -175,6 +170,7 @@ func Push(cfg config.ClientConfig) error {
 	return err
 	return err
 }
 }
 
 
+// Pull - runs pull command from cli
 func Pull(cfg config.ClientConfig) error {
 func Pull(cfg config.ClientConfig) error {
 	var err error
 	var err error
 	if cfg.Network == "all" {
 	if cfg.Network == "all" {
@@ -201,13 +197,16 @@ func Pull(cfg config.ClientConfig) error {
 	return err
 	return err
 }
 }
 
 
+// List - runs list command from cli
 func List(cfg config.ClientConfig) error {
 func List(cfg config.ClientConfig) error {
 	err := functions.List(cfg.Network)
 	err := functions.List(cfg.Network)
 	return err
 	return err
 }
 }
 
 
+// Uninstall - runs uninstall command from cli
 func Uninstall() error {
 func Uninstall() error {
-	ncutils.PrintLog("uninstalling netclient", 0)
+	ncutils.PrintLog("uninstalling netclient...", 0)
 	err := functions.Uninstall()
 	err := functions.Uninstall()
+	ncutils.PrintLog("uninstalled netclient", 0)
 	return err
 	return err
 }
 }

+ 4 - 5
netclient/config/config.go

@@ -6,7 +6,6 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
 
 
@@ -133,12 +132,12 @@ func SaveBackup(network string) error {
 	var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network
 	var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network
 	var backupPath = ncutils.GetNetclientPathSpecific() + "backup.netconfig-" + network
 	var backupPath = ncutils.GetNetclientPathSpecific() + "backup.netconfig-" + network
 	if FileExists(configPath) {
 	if FileExists(configPath) {
-		input, err := ioutil.ReadFile(configPath)
+		input, err := os.ReadFile(configPath)
 		if err != nil {
 		if err != nil {
 			ncutils.Log("failed to read " + configPath + " to make a backup")
 			ncutils.Log("failed to read " + configPath + " to make a backup")
 			return err
 			return err
 		}
 		}
-		if err = ioutil.WriteFile(backupPath, input, 0644); err != nil {
+		if err = os.WriteFile(backupPath, input, 0644); err != nil {
 			ncutils.Log("failed to copy backup to " + backupPath)
 			ncutils.Log("failed to copy backup to " + backupPath)
 			return err
 			return err
 		}
 		}
@@ -151,12 +150,12 @@ func ReplaceWithBackup(network string) error {
 	var backupPath = ncutils.GetNetclientPathSpecific() + "backup.netconfig-" + network
 	var backupPath = ncutils.GetNetclientPathSpecific() + "backup.netconfig-" + network
 	var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network
 	var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network
 	if FileExists(backupPath) {
 	if FileExists(backupPath) {
-		input, err := ioutil.ReadFile(backupPath)
+		input, err := os.ReadFile(backupPath)
 		if err != nil {
 		if err != nil {
 			ncutils.Log("failed to read file " + backupPath + " to backup network: " + network)
 			ncutils.Log("failed to read file " + backupPath + " to backup network: " + network)
 			return err
 			return err
 		}
 		}
-		if err = ioutil.WriteFile(configPath, input, 0644); err != nil {
+		if err = os.WriteFile(configPath, input, 0644); err != nil {
 			ncutils.Log("failed backup " + backupPath + " to " + configPath)
 			ncutils.Log("failed backup " + backupPath + " to " + configPath)
 			return err
 			return err
 		}
 		}

+ 1 - 2
netclient/daemon/macos.go

@@ -2,7 +2,6 @@ package daemon
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
@@ -64,7 +63,7 @@ func CreateMacService(servicename string, interval string) error {
 	daemonbytes := []byte(daemonstring)
 	daemonbytes := []byte(daemonstring)
 
 
 	if !ncutils.FileExists("/Library/LaunchDaemons/com.gravitl.netclient.plist") {
 	if !ncutils.FileExists("/Library/LaunchDaemons/com.gravitl.netclient.plist") {
-		err = ioutil.WriteFile("/Library/LaunchDaemons/com.gravitl.netclient.plist", daemonbytes, 0644)
+		err = os.WriteFile("/Library/LaunchDaemons/com.gravitl.netclient.plist", daemonbytes, 0644)
 	}
 	}
 	return err
 	return err
 }
 }

+ 2 - 3
netclient/daemon/systemd.go

@@ -3,7 +3,6 @@ package daemon
 import (
 import (
 	//"github.com/davecgh/go-spew/spew"
 	//"github.com/davecgh/go-spew/spew"
 
 
-	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
 	"path/filepath"
 	"path/filepath"
@@ -75,7 +74,7 @@ WantedBy=timers.target
 	timerbytes := []byte(systemtimer)
 	timerbytes := []byte(systemtimer)
 
 
 	if !ncutils.FileExists("/etc/systemd/system/netclient.service") {
 	if !ncutils.FileExists("/etc/systemd/system/netclient.service") {
-		err = ioutil.WriteFile("/etc/systemd/system/netclient.service", servicebytes, 0644)
+		err = os.WriteFile("/etc/systemd/system/netclient.service", servicebytes, 0644)
 		if err != nil {
 		if err != nil {
 			log.Println(err)
 			log.Println(err)
 			return err
 			return err
@@ -83,7 +82,7 @@ WantedBy=timers.target
 	}
 	}
 
 
 	if !ncutils.FileExists("/etc/systemd/system/netclient.timer") {
 	if !ncutils.FileExists("/etc/systemd/system/netclient.timer") {
-		err = ioutil.WriteFile("/etc/systemd/system/netclient.timer", timerbytes, 0644)
+		err = os.WriteFile("/etc/systemd/system/netclient.timer", timerbytes, 0644)
 		if err != nil {
 		if err != nil {
 			log.Println(err)
 			log.Println(err)
 			return err
 			return err

+ 1 - 2
netclient/daemon/windows.go

@@ -2,7 +2,6 @@ package daemon
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
 	"strings"
 	"strings"
@@ -57,7 +56,7 @@ func writeServiceConfig() error {
 </service>
 </service>
 `, strings.Replace(ncutils.GetNetclientPathSpecific()+"netclient.exe", `\\`, `\`, -1))
 `, strings.Replace(ncutils.GetNetclientPathSpecific()+"netclient.exe", `\\`, `\`, -1))
 	if !ncutils.FileExists(serviceConfigPath) {
 	if !ncutils.FileExists(serviceConfigPath) {
-		err := ioutil.WriteFile(serviceConfigPath, []byte(scriptString), 0644)
+		err := os.WriteFile(serviceConfigPath, []byte(scriptString), 0644)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}

+ 13 - 12
netclient/functions/checkin.go

@@ -82,14 +82,15 @@ func checkIP(node *models.Node, servercfg config.ServerConfig, cliconf config.Cl
 	return ipchange && err == nil
 	return ipchange && err == nil
 }
 }
 
 
-func setDNS(node *models.Node, servercfg config.ServerConfig, nodecfg *models.Node) {
-	if nodecfg.DNSOn == "yes" {
-		ifacename := node.Interface
-		nameserver := servercfg.CoreDNSAddr
-		network := node.Network
-		local.UpdateDNS(ifacename, network, nameserver)
-	}
-}
+// DEPRECATED
+// func setDNS(node *models.Node, servercfg config.ServerConfig, nodecfg *models.Node) {
+// 	if nodecfg.DNSOn == "yes" {
+// 		ifacename := node.Interface
+// 		nameserver := servercfg.CoreDNSAddr
+// 		network := node.Network
+// 		local.UpdateDNS(ifacename, network, nameserver)
+// 	}
+// }
 
 
 func checkNodeActions(node *models.Node, networkName string, servercfg config.ServerConfig, localNode *models.Node, cfg *config.ClientConfig) string {
 func checkNodeActions(node *models.Node, networkName string, servercfg config.ServerConfig, localNode *models.Node, cfg *config.ClientConfig) string {
 	if (node.Action == models.NODE_UPDATE_KEY || localNode.Action == models.NODE_UPDATE_KEY) &&
 	if (node.Action == models.NODE_UPDATE_KEY || localNode.Action == models.NODE_UPDATE_KEY) &&
@@ -156,7 +157,7 @@ func Pull(network string, manual bool) (*models.Node, error) {
 	}
 	}
 
 
 	node := cfg.Node
 	node := cfg.Node
-	servercfg := cfg.Server
+	//servercfg := cfg.Server
 
 
 	if cfg.Node.IPForwarding == "yes" && !ncutils.IsWindows() {
 	if cfg.Node.IPForwarding == "yes" && !ncutils.IsWindows() {
 		if err = local.SetIPForwarding(); err != nil {
 		if err = local.SetIPForwarding(); err != nil {
@@ -241,9 +242,9 @@ func Pull(network string, manual bool) (*models.Node, error) {
 			}
 			}
 		}
 		}
 	}
 	}
-	if ncutils.IsLinux() {
-		setDNS(&resNode, servercfg, &cfg.Node)
-	}
+	//if ncutils.IsLinux() {
+	//	setDNS(&resNode, servercfg, &cfg.Node)
+	//}
 	var bkupErr = config.SaveBackup(network)
 	var bkupErr = config.SaveBackup(network)
 	if bkupErr != nil {
 	if bkupErr != nil {
 		ncutils.Log("unable to update backup file")
 		ncutils.Log("unable to update backup file")

+ 23 - 61
netclient/functions/common.go

@@ -1,15 +1,11 @@
 package functions
 package functions
 
 
 import (
 import (
-	"context"
-	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"log"
 	"log"
 	"net"
 	"net"
 	"os"
 	"os"
-	"os/exec"
-	"strings"
 
 
 	nodepb "github.com/gravitl/netmaker/grpc"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
@@ -23,10 +19,6 @@ import (
 	"google.golang.org/grpc/metadata"
 	"google.golang.org/grpc/metadata"
 )
 )
 
 
-var (
-	wcclient nodepb.NodeServiceClient
-)
-
 // ListPorts - lists ports of WireGuard devices
 // ListPorts - lists ports of WireGuard devices
 func ListPorts() error {
 func ListPorts() error {
 	wgclient, err := wgctrl.New()
 	wgclient, err := wgctrl.New()
@@ -103,30 +95,31 @@ func getPrivateAddrBackup() (string, error) {
 		}
 		}
 	}
 	}
 	if !found {
 	if !found {
-		err := errors.New("Local Address Not Found.")
+		err := errors.New("local ip address not found")
 		return "", err
 		return "", err
 	}
 	}
 	return local, err
 	return local, err
 }
 }
 
 
-func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
-	var header metadata.MD
-	req := &nodepb.Object{
-		Data: mac + "###" + network,
-		Type: nodepb.STRING_TYPE,
-	}
-	readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
-	if err != nil {
-		return false, "", err
-	}
-	var resNode models.Node
-	if err := json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
-		return false, iface, err
-	}
-	oldiface := resNode.Interface
+// DEPRECATED
+// func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
+// 	var header metadata.MD
+// 	req := &nodepb.Object{
+// 		Data: mac + "###" + network,
+// 		Type: nodepb.STRING_TYPE,
+// 	}
+// 	readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
+// 	if err != nil {
+// 		return false, "", err
+// 	}
+// 	var resNode models.Node
+// 	if err := json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
+// 		return false, iface, err
+// 	}
+// 	oldiface := resNode.Interface
 
 
-	return iface != oldiface, oldiface, err
-}
+// 	return iface != oldiface, oldiface, err
+// }
 
 
 // GetNode - gets node locally
 // GetNode - gets node locally
 func GetNode(network string) models.Node {
 func GetNode(network string) models.Node {
@@ -244,22 +237,7 @@ func RemoveLocalInstance(cfg *config.ClientConfig, networkName string) error {
 
 
 // DeleteInterface - delete an interface of a network
 // DeleteInterface - delete an interface of a network
 func DeleteInterface(ifacename string, postdown string) error {
 func DeleteInterface(ifacename string, postdown string) error {
-	var err error
-	if !ncutils.IsKernel() {
-		err = wireguard.RemoveConf(ifacename, true)
-	} else {
-		ipExec, errN := exec.LookPath("ip")
-		err = errN
-		if err != nil {
-			ncutils.PrintLog(err.Error(), 1)
-		}
-		_, err = ncutils.RunCmd(ipExec+" link del "+ifacename, false)
-		if postdown != "" {
-			runcmds := strings.Split(postdown, "; ")
-			err = ncutils.RunCmds(runcmds, true)
-		}
-	}
-	return err
+	return wireguard.RemoveConf(ifacename, true)
 }
 }
 
 
 // WipeLocal - wipes local instance
 // WipeLocal - wipes local instance
@@ -271,27 +249,11 @@ func WipeLocal(network string) error {
 	nodecfg := cfg.Node
 	nodecfg := cfg.Node
 	ifacename := nodecfg.Interface
 	ifacename := nodecfg.Interface
 	if ifacename != "" {
 	if ifacename != "" {
-		if !ncutils.IsKernel() {
-			if err = wireguard.RemoveConf(ifacename, true); err == nil {
-				ncutils.PrintLog("removed WireGuard interface: "+ifacename, 1)
-			}
-		} else {
-			ipExec, err := exec.LookPath("ip")
-			if err != nil {
-				return err
-			}
-			out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false)
-			dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device")
-			if err != nil && !dontprint {
-				ncutils.PrintLog("error running command: "+ipExec+" link del "+ifacename, 1)
-				ncutils.PrintLog(out, 1)
-			}
-			if nodecfg.PostDown != "" {
-				runcmds := strings.Split(nodecfg.PostDown, "; ")
-				_ = ncutils.RunCmds(runcmds, false)
-			}
+		if err = wireguard.RemoveConf(ifacename, true); err == nil {
+			ncutils.PrintLog("removed WireGuard interface: "+ifacename, 1)
 		}
 		}
 	}
 	}
+
 	home := ncutils.GetNetclientPathSpecific()
 	home := ncutils.GetNetclientPathSpecific()
 	if ncutils.FileExists(home + "netconfig-" + network) {
 	if ncutils.FileExists(home + "netconfig-" + network) {
 		_ = os.Remove(home + "netconfig-" + network)
 		_ = os.Remove(home + "netconfig-" + network)

+ 2 - 2
netclient/functions/join.go

@@ -83,9 +83,9 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
 		}
 		}
 	}
 	}
 	if ncutils.IsLinux() {
 	if ncutils.IsLinux() {
-		_, err := exec.LookPath("resolvectl")
+		_, err := exec.LookPath("resolvconf")
 		if err != nil {
 		if err != nil {
-			ncutils.PrintLog("resolvectl not present", 2)
+			ncutils.PrintLog("resolvconf not present", 2)
 			ncutils.PrintLog("unable to configure DNS automatically, disabling automated DNS management", 2)
 			ncutils.PrintLog("unable to configure DNS automatically, disabling automated DNS management", 2)
 			cfg.Node.DNSOn = "no"
 			cfg.Node.DNSOn = "no"
 		}
 		}

+ 1 - 2
netclient/local/dns.go

@@ -1,7 +1,6 @@
 package local
 package local
 
 
 import (
 import (
-	"io/ioutil"
 	"os"
 	"os"
 	"strings"
 	"strings"
 
 
@@ -14,7 +13,7 @@ import (
 
 
 // SetDNS - sets the DNS of a local machine
 // SetDNS - sets the DNS of a local machine
 func SetDNS(nameserver string) error {
 func SetDNS(nameserver string) error {
-	bytes, err := ioutil.ReadFile("/etc/resolv.conf")
+	bytes, err := os.ReadFile("/etc/resolv.conf")
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 1 - 1
netclient/local/local.go

@@ -25,7 +25,7 @@ func SetIPForwarding() error {
 	case "darwin":
 	case "darwin":
 		err = SetIPForwardingMac()
 		err = SetIPForwardingMac()
 	default:
 	default:
-		err = errors.New("This OS is not supported")
+		err = errors.New("this OS is not currently supported")
 	}
 	}
 	return err
 	return err
 }
 }

+ 1 - 1
netclient/main.go

@@ -18,7 +18,7 @@ func main() {
 	app := cli.NewApp()
 	app := cli.NewApp()
 	app.Name = "Netclient CLI"
 	app.Name = "Netclient CLI"
 	app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
 	app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
-	app.Version = "v0.9.2"
+	app.Version = "v0.9.3"
 
 
 	cliFlags := cli_options.GetFlags(ncutils.GetHostname())
 	cliFlags := cli_options.GetFlags(ncutils.GetHostname())
 	app.Commands = cli_options.GetCommands(cliFlags[:])
 	app.Commands = cli_options.GetCommands(cliFlags[:])

+ 2 - 3
netclient/ncutils/netclientutils.go

@@ -5,7 +5,6 @@ import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
-	"io/ioutil"
 	"log"
 	"log"
 	"math/rand"
 	"math/rand"
 	"net"
 	"net"
@@ -132,7 +131,7 @@ func GetPublicIP() (string, error) {
 		}
 		}
 		defer resp.Body.Close()
 		defer resp.Body.Close()
 		if resp.StatusCode == http.StatusOK {
 		if resp.StatusCode == http.StatusOK {
-			bodyBytes, err := ioutil.ReadAll(resp.Body)
+			bodyBytes, err := io.ReadAll(resp.Body)
 			if err != nil {
 			if err != nil {
 				continue
 				continue
 			}
 			}
@@ -409,7 +408,7 @@ func PrintLog(message string, loglevel int) {
 // GetSystemNetworks - get networks locally
 // GetSystemNetworks - get networks locally
 func GetSystemNetworks() ([]string, error) {
 func GetSystemNetworks() ([]string, error) {
 	var networks []string
 	var networks []string
-	files, err := ioutil.ReadDir(GetNetclientPathSpecific())
+	files, err := os.ReadDir(GetNetclientPathSpecific())
 	if err != nil {
 	if err != nil {
 		return networks, err
 		return networks, err
 	}
 	}

+ 8 - 7
netclient/ncutils/netclientutils_darwin.go

@@ -7,6 +7,7 @@ import (
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 
 
+	"github.com/gravitl/netmaker/models"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 )
 
 
@@ -33,12 +34,12 @@ func GetEmbedded() error {
 	return nil
 	return nil
 }
 }
 
 
-// CreateUserSpaceConf - creates a user space WireGuard conf
-func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) {
-	peersString, err := parsePeers(perskeepalive, peers)
+// CreateWireGuardConf - creates a WireGuard conf string
+func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) {
+	peersString, err := parsePeers(node.PersistentKeepalive, peers)
 	var listenPortString string
 	var listenPortString string
-	if mtu <= 0 {
-		mtu = 1280
+	if node.MTU <= 0 {
+		node.MTU = 1280
 	}
 	}
 	if listenPort != "" {
 	if listenPort != "" {
 		listenPortString += "ListenPort = " + listenPort
 		listenPortString += "ListenPort = " + listenPort
@@ -55,9 +56,9 @@ MTU = %s
 %s
 %s
 
 
 `,
 `,
-		address+"/32",
+		node.Address+"/32",
 		privatekey,
 		privatekey,
-		strconv.Itoa(int(mtu)),
+		strconv.Itoa(int(node.MTU)),
 		listenPortString,
 		listenPortString,
 		peersString)
 		peersString)
 	return config, nil
 	return config, nil

+ 10 - 8
netclient/ncutils/netclientutils_freebsd.go

@@ -3,13 +3,15 @@ package ncutils
 import (
 import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
-	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"log"
 	"log"
 	"os/exec"
 	"os/exec"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"syscall"
 	"syscall"
 	"time"
 	"time"
+
+	"github.com/gravitl/netmaker/models"
+	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 )
 
 
 // RunCmdFormatted - run a command formatted for freebsd
 // RunCmdFormatted - run a command formatted for freebsd
@@ -41,12 +43,12 @@ func RunCmd(command string, printerr bool) (string, error) {
 	return string(out), err
 	return string(out), err
 }
 }
 
 
-// CreateUserSpaceConf - creates a user space WireGuard conf
-func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) {
-	peersString, err := parsePeers(perskeepalive, peers)
+// CreateWireGuardConf - creates a WireGuard conf string
+func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) {
+	peersString, err := parsePeers(node.PersistentKeepalive, peers)
 	var listenPortString string
 	var listenPortString string
-	if mtu <= 0 {
-		mtu = 1280
+	if node.MTU <= 0 {
+		node.MTU = 1280
 	}
 	}
 	if listenPort != "" {
 	if listenPort != "" {
 		listenPortString += "ListenPort = " + listenPort
 		listenPortString += "ListenPort = " + listenPort
@@ -63,9 +65,9 @@ MTU = %s
 %s
 %s
 
 
 `,
 `,
-		address+"/32",
+		node.Address+"/32",
 		privatekey,
 		privatekey,
-		strconv.Itoa(int(mtu)),
+		strconv.Itoa(int(node.MTU)),
 		listenPortString,
 		listenPortString,
 		peersString)
 		peersString)
 	return config, nil
 	return config, nil

+ 24 - 12
netclient/ncutils/netclientutils_linux.go

@@ -2,11 +2,11 @@ package ncutils
 
 
 import (
 import (
 	"fmt"
 	"fmt"
-	"log"
 	"os/exec"
 	"os/exec"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 
 
+	"github.com/gravitl/netmaker/models"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 )
 
 
@@ -17,8 +17,8 @@ func RunCmd(command string, printerr bool) (string, error) {
 	cmd.Wait()
 	cmd.Wait()
 	out, err := cmd.CombinedOutput()
 	out, err := cmd.CombinedOutput()
 	if err != nil && printerr {
 	if err != nil && printerr {
-		log.Println("error running command:", command)
-		log.Println(strings.TrimSuffix(string(out), "\n"))
+		Log(fmt.Sprintf("error running command: %s", command))
+		Log(strings.TrimSuffix(string(out), "\n"))
 	}
 	}
 	return string(out), err
 	return string(out), err
 }
 }
@@ -33,16 +33,24 @@ func GetEmbedded() error {
 	return nil
 	return nil
 }
 }
 
 
-// CreateUserSpaceConf - creates a user space WireGuard conf
-func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) {
-	peersString, err := parsePeers(perskeepalive, peers)
-	var listenPortString string
-	if mtu <= 0 {
-		mtu = 1280
+// CreateWireGuardConf - creates a user space WireGuard conf
+func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, peers []wgtypes.PeerConfig) (string, error) {
+	peersString, err := parsePeers(node.PersistentKeepalive, peers)
+	var listenPortString, postDownString, postUpString string
+	if node.MTU <= 0 {
+		node.MTU = 1280
 	}
 	}
+	if node.PostDown != "" {
+		postDownString = fmt.Sprintf("PostDown = %s", node.PostDown)
+	}
+	if node.PostUp != "" {
+		postUpString = fmt.Sprintf("PostUp = %s", node.PostUp)
+	}
+
 	if listenPort != "" {
 	if listenPort != "" {
-		listenPortString += "ListenPort = " + listenPort
+		listenPortString = fmt.Sprintf("ListenPort = %s", listenPort)
 	}
 	}
+
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
@@ -51,13 +59,17 @@ Address = %s
 PrivateKey = %s
 PrivateKey = %s
 MTU = %s
 MTU = %s
 %s
 %s
+%s
+%s
 
 
 %s
 %s
 
 
 `,
 `,
-		address+"/32",
+		node.Address+"/32",
 		privatekey,
 		privatekey,
-		strconv.Itoa(int(mtu)),
+		strconv.Itoa(int(node.MTU)),
+		postDownString,
+		postUpString,
 		listenPortString,
 		listenPortString,
 		peersString)
 		peersString)
 	return config, nil
 	return config, nil

+ 8 - 7
netclient/ncutils/netclientutils_windows.go

@@ -10,6 +10,7 @@ import (
 	"strings"
 	"strings"
 	"syscall"
 	"syscall"
 
 
+	"github.com/gravitl/netmaker/models"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 )
 
 
@@ -47,12 +48,12 @@ func RunCmdFormatted(command string, printerr bool) (string, error) {
 	return string(out), err
 	return string(out), err
 }
 }
 
 
-// CreateUserSpaceConf - creates a user space WireGuard conf
-func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) {
-	peersString, err := parsePeers(perskeepalive, peers)
+// CreateWireGuardConf - creates a WireGuard conf string
+func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) {
+	peersString, err := parsePeers(node.PersistentKeepalive, peers)
 	var listenPortString string
 	var listenPortString string
-	if mtu <= 0 {
-		mtu = 1280
+	if node.MTU <= 0 {
+		node.MTU = 1280
 	}
 	}
 	if listenPort != "" {
 	if listenPort != "" {
 		listenPortString += "ListenPort = " + listenPort
 		listenPortString += "ListenPort = " + listenPort
@@ -69,9 +70,9 @@ MTU = %s
 %s
 %s
 
 
 `,
 `,
-		address+"/32",
+		node.Address+"/32",
 		privatekey,
 		privatekey,
-		strconv.Itoa(int(mtu)),
+		strconv.Itoa(int(node.MTU)),
 		listenPortString,
 		listenPortString,
 		peersString)
 		peersString)
 	return config, nil
 	return config, nil

+ 2 - 3
netclient/ncwindows/windows.go

@@ -1,7 +1,6 @@
 package ncwindows
 package ncwindows
 
 
 import (
 import (
-	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
 
 
@@ -24,12 +23,12 @@ func InitWindows() {
 
 
 	if os.IsNotExist(dataNetclientErr) { // check and see if netclient.exe is in appdata
 	if os.IsNotExist(dataNetclientErr) { // check and see if netclient.exe is in appdata
 		if currentNetclientErr == nil { // copy it if it exists locally
 		if currentNetclientErr == nil { // copy it if it exists locally
-			input, err := ioutil.ReadFile(wdPath + "\\netclient.exe")
+			input, err := os.ReadFile(wdPath + "\\netclient.exe")
 			if err != nil {
 			if err != nil {
 				log.Println("failed to find netclient.exe")
 				log.Println("failed to find netclient.exe")
 				return
 				return
 			}
 			}
-			if err = ioutil.WriteFile(ncutils.GetNetclientPathSpecific()+"netclient.exe", input, 0644); err != nil {
+			if err = os.WriteFile(ncutils.GetNetclientPathSpecific()+"netclient.exe", input, 0644); err != nil {
 				log.Println("failed to copy netclient.exe to", ncutils.GetNetclientPath())
 				log.Println("failed to copy netclient.exe to", ncutils.GetNetclientPath())
 				return
 				return
 			}
 			}

+ 1 - 1
netclient/netclient.exe.manifest.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
     <assemblyIdentity
     <assemblyIdentity
-            version="0.9.2.0"
+            version="0.9.3.0"
             processorArchitecture="*"
             processorArchitecture="*"
             name="netclient.exe"
             name="netclient.exe"
             type="win32"
             type="win32"

+ 4 - 1
netclient/server/grpc.go

@@ -50,6 +50,9 @@ func CheckIn(network string) (*models.Node, error) {
 		// == run client action ==
 		// == run client action ==
 		var header metadata.MD
 		var header metadata.MD
 		ctx, err := auth.SetJWT(wcclient, network)
 		ctx, err := auth.SetJWT(wcclient, network)
+		if err != nil {
+			return nil, err
+		}
 		nodeData, err := json.Marshal(&node)
 		nodeData, err := json.Marshal(&node)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
@@ -123,7 +126,7 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
 	}
 	}
 
 
 	keepalive := nodecfg.PersistentKeepalive
 	keepalive := nodecfg.PersistentKeepalive
-	keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
+	keepalivedur, _ := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
 	keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
 	keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
 	if err != nil {
 	if err != nil {
 		log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
 		log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)

+ 1 - 1
netclient/versioninfo.json

@@ -29,7 +29,7 @@
         "OriginalFilename": "",
         "OriginalFilename": "",
         "PrivateBuild": "",
         "PrivateBuild": "",
         "ProductName": "Netclient",
         "ProductName": "Netclient",
-        "ProductVersion": "v0.9.2.0",
+        "ProductVersion": "v0.9.3.0",
         "SpecialBuild": ""
         "SpecialBuild": ""
     },
     },
     "VarFileInfo": {
     "VarFileInfo": {

+ 56 - 151
netclient/wireguard/common.go

@@ -2,11 +2,8 @@ package wireguard
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"fmt"
-	"io/ioutil"
 	"log"
 	"log"
 	"os"
 	"os"
-	"os/exec"
 	"runtime"
 	"runtime"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
@@ -121,7 +118,6 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		return err
 		return err
 	}
 	}
 	nodecfg := modcfg.Node
 	nodecfg := modcfg.Node
-	servercfg := modcfg.Server
 
 
 	if err != nil {
 	if err != nil {
 		log.Fatalf("failed to open client: %v", err)
 		log.Fatalf("failed to open client: %v", err)
@@ -138,167 +134,73 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 	if node.Address == "" {
 	if node.Address == "" {
 		log.Fatal("no address to configure")
 		log.Fatal("no address to configure")
 	}
 	}
-
-	nameserver := servercfg.CoreDNSAddr
-	network := node.Network
-	if nodecfg.Network != "" {
-		network = nodecfg.Network
-	} else if node.Network != "" {
-		network = node.Network
+	var newConf string
+	if node.UDPHolePunch != "yes" {
+		newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), peers)
+	} else {
+		newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), "", peers)
 	}
 	}
-
-	if ncutils.IsKernel() {
-		setKernelDevice(ifacename, node.Address)
+	confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf"
+	ncutils.PrintLog("writing wg conf file to: "+confPath, 1)
+	err = os.WriteFile(confPath, []byte(newConf), 0644)
+	if err != nil {
+		ncutils.PrintLog("error writing wg conf file to "+confPath+": "+err.Error(), 1)
+		return err
 	}
 	}
-
-	nodeport := int(node.ListenPort)
-	conf := wgtypes.Config{}
-	if nodecfg.UDPHolePunch == "yes" &&
-		nodecfg.IsServer == "no" &&
-		nodecfg.IsIngressGateway != "yes" &&
-		nodecfg.IsStatic != "yes" {
-		conf = wgtypes.Config{
-			PrivateKey:   &key,
-			ReplacePeers: true,
-			Peers:        peers,
-		}
-	} else {
-		conf = wgtypes.Config{
-			PrivateKey:   &key,
-			ListenPort:   &nodeport,
-			ReplacePeers: true,
-			Peers:        peers,
+	if ncutils.IsWindows() {
+		wgConfPath := ncutils.GetWGPathSpecific() + ifacename + ".conf"
+		err = os.WriteFile(wgConfPath, []byte(newConf), 0644)
+		if err != nil {
+			ncutils.PrintLog("error writing wg conf file to "+wgConfPath+": "+err.Error(), 1)
+			return err
 		}
 		}
+		confPath = wgConfPath
 	}
 	}
-	if !ncutils.IsKernel() {
-		var newConf string
-		if node.UDPHolePunch != "yes" {
-			newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, node.PersistentKeepalive, peers)
-		} else {
-			newConf, _ = ncutils.CreateUserSpaceConf(node.Address, key.String(), "", node.MTU, node.PersistentKeepalive, peers)
+	// spin up userspace / windows interface + apply the conf file
+	var deviceiface string
+	if ncutils.IsMac() {
+		deviceiface, err = local.GetMacIface(node.Address)
+		if err != nil || deviceiface == "" {
+			deviceiface = ifacename
 		}
 		}
-		confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf"
-		ncutils.PrintLog("writing wg conf file to: "+confPath, 1)
-		err = ioutil.WriteFile(confPath, []byte(newConf), 0644)
-		if err != nil {
-			ncutils.PrintLog("error writing wg conf file to "+confPath+": "+err.Error(), 1)
-			return err
+	}
+	if syncconf {
+		err = SyncWGQuickConf(ifacename, confPath)
+	} else {
+		d, _ := wgclient.Device(deviceiface)
+		for d != nil && d.Name == deviceiface {
+			RemoveConf(ifacename, false) // remove interface first
+			time.Sleep(time.Second >> 2)
+			d, _ = wgclient.Device(deviceiface)
 		}
 		}
-		if ncutils.IsWindows() {
-			wgConfPath := ncutils.GetWGPathSpecific() + ifacename + ".conf"
-			err = ioutil.WriteFile(wgConfPath, []byte(newConf), 0644)
+		if !ncutils.IsWindows() {
+			err = ApplyConf(confPath)
 			if err != nil {
 			if err != nil {
-				ncutils.PrintLog("error writing wg conf file to "+wgConfPath+": "+err.Error(), 1)
+				ncutils.PrintLog("failed to create wireguard interface", 1)
 				return err
 				return err
 			}
 			}
-			confPath = wgConfPath
-		}
-		// spin up userspace / windows interface + apply the conf file
-		var deviceiface string
-		if ncutils.IsMac() {
-			deviceiface, err = local.GetMacIface(node.Address)
-			if err != nil || deviceiface == "" {
-				deviceiface = ifacename
-			}
-		}
-		if syncconf {
-			log.Println("syncing conf")
-			err = SyncWGQuickConf(ifacename, confPath)
 		} else {
 		} else {
-			d, _ := wgclient.Device(deviceiface)
-			for d != nil && d.Name == deviceiface {
-				_ = RemoveConf(ifacename, false) // remove interface first
-				time.Sleep(time.Second >> 2)
-				d, _ = wgclient.Device(deviceiface)
-			}
-			if !ncutils.IsWindows() {
+			var output string
+			starttime := time.Now()
+			RemoveConf(ifacename, false)
+			time.Sleep(time.Second >> 2)
+			ncutils.PrintLog("waiting for interface...", 1)
+			for !strings.Contains(output, ifacename) && !(time.Now().After(starttime.Add(time.Duration(10) * time.Second))) {
+				output, _ = ncutils.RunCmd("wg", false)
 				err = ApplyConf(confPath)
 				err = ApplyConf(confPath)
-				if err != nil {
-					ncutils.PrintLog("failed to create wireguard interface", 1)
-					return err
-				}
-			} else {
-				var output string
-				starttime := time.Now()
-				RemoveConf(ifacename, false)
-				time.Sleep(time.Second >> 2)
-				ncutils.PrintLog("waiting for interface...", 1)
-				for !strings.Contains(output, ifacename) && !(time.Now().After(starttime.Add(time.Duration(10) * time.Second))) {
-					output, _ = ncutils.RunCmd("wg", false)
-					err = ApplyConf(confPath)
-					time.Sleep(time.Second)
-				}
-				if !strings.Contains(output, ifacename) {
-					return errors.New("could not create wg interface for " + ifacename)
-				}
-				ip, mask, err := ncutils.GetNetworkIPMask(nodecfg.NetworkSettings.AddressRange)
-				if err != nil {
-					log.Println(err.Error())
-					return err
-				}
-				ncutils.RunCmd("route add "+ip+" mask "+mask+" "+node.Address, true)
-				time.Sleep(time.Second >> 2)
-				ncutils.RunCmd("route change "+ip+" mask "+mask+" "+node.Address, true)
+				time.Sleep(time.Second)
 			}
 			}
-		}
-	} else {
-		ipExec, err := exec.LookPath("ip")
-		if err != nil {
-			return err
-		}
-
-		_, err = wgclient.Device(ifacename)
-		if err != nil {
-			if os.IsNotExist(err) {
-				fmt.Println("Device does not exist: ")
-				fmt.Println(err)
-			} else {
-				log.Fatalf("Unknown config error: %v", err)
+			if !strings.Contains(output, ifacename) {
+				return errors.New("could not create wg interface for " + ifacename)
 			}
 			}
-		}
-
-		err = wgclient.ConfigureDevice(ifacename, conf)
-		if err != nil {
-			if os.IsNotExist(err) {
-				fmt.Println("Device does not exist: ")
-				fmt.Println(err)
-			} else {
-				fmt.Printf("This is inconvenient: %v", err)
-			}
-		}
-
-		//=========DNS Setup==========\\
-		if nodecfg.DNSOn == "yes" {
-			_ = local.UpdateDNS(ifacename, network, nameserver)
-		}
-		//=========End DNS Setup=======\\
-		if _, err := ncutils.RunCmd(ipExec+" link set down dev "+ifacename, false); err != nil {
-			ncutils.Log("attempted to remove interface before editing")
-			return err
-		}
-
-		if nodecfg.PostDown != "" {
-			runcmds := strings.Split(nodecfg.PostDown, "; ")
-			_ = ncutils.RunCmds(runcmds, true)
-		}
-		// set MTU of node interface
-		if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(nodecfg.MTU))+" up dev "+ifacename, true); err != nil {
-			ncutils.Log("failed to create interface with mtu " + ifacename)
-			return err
-		}
-
-		if nodecfg.PostUp != "" {
-			runcmds := strings.Split(nodecfg.PostUp, "; ")
-			_ = ncutils.RunCmds(runcmds, true)
-		}
-		if hasGateway {
-			for _, gateway := range gateways {
-				_, _ = ncutils.RunCmd(ipExec+" -4 route add "+gateway+" dev "+ifacename, true)
+			ip, mask, err := ncutils.GetNetworkIPMask(nodecfg.NetworkSettings.AddressRange)
+			if err != nil {
+				log.Println(err.Error())
+				return err
 			}
 			}
-		}
-		if node.Address6 != "" && node.IsDualStack == "yes" {
-			log.Println("[netclient] adding address: "+node.Address6, 1)
-			_, _ = ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/64", true)
+			ncutils.RunCmd("route add "+ip+" mask "+mask+" "+node.Address, true)
+			time.Sleep(time.Second >> 2)
+			ncutils.RunCmd("route change "+ip+" mask "+mask+" "+node.Address, true)
 		}
 		}
 	}
 	}
 
 
@@ -345,6 +247,9 @@ func SetWGConfig(network string, peerupdate bool) error {
 	} else {
 	} else {
 		err = InitWireguard(&nodecfg, privkey, peers, hasGateway, gateways, false)
 		err = InitWireguard(&nodecfg, privkey, peers, hasGateway, gateways, false)
 	}
 	}
+	if nodecfg.DNSOn == "yes" {
+		_ = local.UpdateDNS(nodecfg.Interface, nodecfg.Network, servercfg.CoreDNSAddr)
+	}
 	return err
 	return err
 }
 }
 
 

+ 0 - 21
netclient/wireguard/kernel.go

@@ -1,21 +0,0 @@
-package wireguard
-
-import (
-	"os/exec"
-
-	"github.com/gravitl/netmaker/netclient/ncutils"
-	//homedir "github.com/mitchellh/go-homedir"
-)
-
-func setKernelDevice(ifacename string, address string) error {
-	ipExec, err := exec.LookPath("ip")
-	if err != nil {
-		return err
-	}
-
-	_, _ = ncutils.RunCmd("ip link delete dev "+ifacename, false)
-	_, _ = ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true)
-	_, _ = ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address+"/24", true)
-
-	return nil
-}

+ 5 - 5
netclient/wireguard/unix.go

@@ -1,7 +1,7 @@
 package wireguard
 package wireguard
 
 
 import (
 import (
-	"io/ioutil"
+	"fmt"
 	"log"
 	"log"
 	"os"
 	"os"
 	"regexp"
 	"regexp"
@@ -67,7 +67,7 @@ func SyncWGQuickConf(iface string, confPath string) error {
 	}
 	}
 	regex := regexp.MustCompile(".*Warning.*\n")
 	regex := regexp.MustCompile(".*Warning.*\n")
 	conf := regex.ReplaceAllString(confRaw, "")
 	conf := regex.ReplaceAllString(confRaw, "")
-	err = ioutil.WriteFile(tmpConf, []byte(conf), 0644)
+	err = os.WriteFile(tmpConf, []byte(conf), 0644)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -86,7 +86,7 @@ func SyncWGQuickConf(iface string, confPath string) error {
 
 
 // RemoveWGQuickConf - calls wg-quick down
 // RemoveWGQuickConf - calls wg-quick down
 func RemoveWGQuickConf(confPath string, printlog bool) error {
 func RemoveWGQuickConf(confPath string, printlog bool) error {
-	_, err := ncutils.RunCmd("wg-quick down "+confPath, printlog)
+	_, err := ncutils.RunCmd(fmt.Sprintf("wg-quick down %s", confPath), printlog)
 	return err
 	return err
 }
 }
 
 
@@ -94,12 +94,12 @@ func RemoveWGQuickConf(confPath string, printlog bool) error {
 func StorePrivKey(key string, network string) error {
 func StorePrivKey(key string, network string) error {
 	var err error
 	var err error
 	d1 := []byte(key)
 	d1 := []byte(key)
-	err = ioutil.WriteFile(ncutils.GetNetclientPathSpecific()+"wgkey-"+network, d1, 0644)
+	err = os.WriteFile(ncutils.GetNetclientPathSpecific()+"wgkey-"+network, d1, 0644)
 	return err
 	return err
 }
 }
 
 
 // RetrievePrivKey - reads wg priv key from local disk
 // RetrievePrivKey - reads wg priv key from local disk
 func RetrievePrivKey(network string) (string, error) {
 func RetrievePrivKey(network string) (string, error) {
-	dat, err := ioutil.ReadFile(ncutils.GetNetclientPathSpecific() + "wgkey-" + network)
+	dat, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "wgkey-" + network)
 	return string(dat), err
 	return string(dat), err
 }
 }

+ 1 - 1
scripts/nm-quick.sh

@@ -50,7 +50,7 @@ elif [ -f /etc/fedora-release ]; then
 	dnf update
 	dnf update
 fi
 fi
 
 
-dependencies=("docker.io" "docker-compose" "wireguard" "jq")
+dependencies=("docker.io" "docker-compose" "wireguard" "jq" "resolvconf")
 
 
 
 
 
 

+ 24 - 3
servercfg/serverconf.go

@@ -2,7 +2,7 @@ package servercfg
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"io/ioutil"
+	"io"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
 	"os"
 	"os"
@@ -80,6 +80,11 @@ func GetServerConfig() config.ServerConfig {
 	cfg.ClientID = authInfo[1]
 	cfg.ClientID = authInfo[1]
 	cfg.ClientSecret = authInfo[2]
 	cfg.ClientSecret = authInfo[2]
 	cfg.FrontendURL = GetFrontendURL()
 	cfg.FrontendURL = GetFrontendURL()
+	if GetRce() {
+		cfg.RCE = "on"
+	} else {
+		cfg.RCE = "off"
+	}
 
 
 	return cfg
 	return cfg
 }
 }
@@ -108,7 +113,7 @@ func GetAPIConnString() string {
 
 
 // GetVersion - version of netmaker
 // GetVersion - version of netmaker
 func GetVersion() string {
 func GetVersion() string {
-	version := "0.9.2"
+	version := "0.9.3"
 	if config.Config.Server.Version != "" {
 	if config.Config.Server.Version != "" {
 		version = config.Config.Server.Version
 		version = config.Config.Server.Version
 	}
 	}
@@ -412,7 +417,7 @@ func GetPublicIP() (string, error) {
 		}
 		}
 		defer resp.Body.Close()
 		defer resp.Body.Close()
 		if resp.StatusCode == http.StatusOK {
 		if resp.StatusCode == http.StatusOK {
-			bodyBytes, err := ioutil.ReadAll(resp.Body)
+			bodyBytes, err := io.ReadAll(resp.Body)
 			if err != nil {
 			if err != nil {
 				continue
 				continue
 			}
 			}
@@ -502,6 +507,17 @@ func GetAuthProviderInfo() []string {
 	return []string{"", "", ""}
 	return []string{"", "", ""}
 }
 }
 
 
+// GetAzureTenant - retrieve the azure tenant ID from env variable or config file
+func GetAzureTenant() string {
+	var azureTenant = ""
+	if os.Getenv("AZURE_TENANT") != "" {
+		azureTenant = os.Getenv("AZURE_TENANT")
+	} else if config.Config.Server.AzureTenant != "" {
+		azureTenant = config.Config.Server.AzureTenant
+	}
+	return azureTenant
+}
+
 // GetMacAddr - get's mac address
 // GetMacAddr - get's mac address
 func getMacAddr() string {
 func getMacAddr() string {
 	ifas, err := net.Interfaces()
 	ifas, err := net.Interfaces()
@@ -517,3 +533,8 @@ func getMacAddr() string {
 	}
 	}
 	return as[0]
 	return as[0]
 }
 }
+
+// GetRce - sees if Rce is enabled, off by default
+func GetRce() bool {
+	return os.Getenv("RCE") == "on" || config.Config.Server.RCE == "on"
+}