Browse Source

Merge pull request #1129 from gravitl/v0.14.1

V0.14.1
dcarns 3 years ago
parent
commit
d592a1bf01

+ 1 - 0
.github/ISSUE_TEMPLATE/bug-report.yml

@@ -31,6 +31,7 @@ body:
       label: Version
       label: Version
       description: What version are you running?
       description: What version are you running?
       options:
       options:
+        - v0.14.1
         - v0.14.0      
         - v0.14.0      
         - v0.13.1
         - v0.13.1
         - v0.13.0
         - v0.13.0

+ 61 - 0
.github/workflows/publish-netclient-docker-go.yml

@@ -0,0 +1,61 @@
+name: Publish Netclient-go Docker
+
+on:
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: 'docker tag'
+        required: true
+  release:
+    types: [published]
+
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      - 
+        name: Set tag
+        run: |
+            if [[ -n "${{ github.event.inputs.tag }}" ]]; then
+              TAG=${{ github.event.inputs.tag }}
+            elif [[ "${{ github.ref_name }}" == 'master' ]]; then
+              TAG="latest"
+            else
+              TAG="${{ github.ref_name }}"
+            fi
+            echo "TAG=${TAG}" >> $GITHUB_ENV
+      - 
+        name: Checkout
+        uses: actions/checkout@v2
+      - 
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      - 
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      - 
+        name: Login to DockerHub
+        uses: docker/login-action@v1
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      - 
+        name: Build x86 and export to Docker
+        uses: docker/build-push-action@v2
+        with:
+          context: .
+          load: true
+          platforms: linux/amd64
+          file: ./docker/Dockerfile-netclient-multiarch-go
+          tags: ${{ env.TAG }}
+          build-args: version=${{ env.TAG }}  
+      -
+        name: Build and push
+        uses: docker/build-push-action@v2
+        with:
+          context: .
+          platforms: linux/amd64
+          file: ./docker/Dockerfile-netclient-multiarch-go
+          push: true
+          tags: gravitl/netclient-go:${{ env.TAG }}, gravitl/netclient-go:latest
+          build-args: version=${{ env.TAG }}  

+ 9 - 4
README.md

@@ -10,7 +10,7 @@ a platform for modern, blazing fast virtual networks
 
 
 <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.14.0-informational?style=flat-square" />
+    <img src="https://img.shields.io/badge/Version-0.14.1-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" />
@@ -21,8 +21,8 @@ a platform for modern, blazing fast virtual networks
   <a href="https://github.com/gravitl/netmaker/graphs/contributors">
   <a href="https://github.com/gravitl/netmaker/graphs/contributors">
     <img src="https://img.shields.io/github/commit-activity/m/gravitl/netmaker?color=blue" />
     <img src="https://img.shields.io/github/commit-activity/m/gravitl/netmaker?color=blue" />
   </a>
   </a>
-  <a href="https://twitter.com/intent/follow?screen_name=gravitlcorp">
-    <img src="https://img.shields.io/twitter/follow/gravitlcorp?style=social" />
+  <a href="https://twitter.com/intent/follow?screen_name=netmaker_io">
+    <img src="https://img.shields.io/twitter/follow/netmaker_io?style=social" />
   </a>
   </a>
   <a href="https://www.youtube.com/channel/UCach3lJY_xBV7rGrbUSvkZQ">
   <a href="https://www.youtube.com/channel/UCach3lJY_xBV7rGrbUSvkZQ">
     <img src="https://img.shields.io/youtube/channel/views/UCach3lJY_xBV7rGrbUSvkZQ?style=social" />
     <img src="https://img.shields.io/youtube/channel/views/UCach3lJY_xBV7rGrbUSvkZQ?style=social" />
@@ -48,7 +48,9 @@ a platform for modern, blazing fast virtual networks
 
 
 `wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash`
 `wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash`
 
 
-<img src="./img/visit-website.gif" width="50%" /><img src="./img/graph-readme.gif" width="50%" />
+<p float="left" align="middle">
+<img src="./img/readme.gif" />
+</p>
 
 
 Upon completion, the logs will display the instructions to connect various devices. These can also be retrieved 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."
 
 
@@ -106,6 +108,9 @@ After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting
 
 
 - [Terraform Provider](https://github.com/madacluster/netmaker-terraform-provider)
 - [Terraform Provider](https://github.com/madacluster/netmaker-terraform-provider)
 
 
+- [VyOS Integration](https://github.com/kylechase/vyos-netmaker)
+
+- [Netmaker K3S](https://github.com/geragcp/netmaker-k3s)
 
 
 ## Disclaimer
 ## Disclaimer
  [WireGuard](https://wireguard.com/) is a registered trademark of Jason A. Donenfeld.
  [WireGuard](https://wireguard.com/) is a registered trademark of Jason A. Donenfeld.

+ 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.14.0
+    image: gravitl/netmaker:v0.14.1
     volumes:
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
       - sqldata:/root/data
@@ -43,7 +43,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.0
+    image: gravitl/netmaker-ui:v0.14.1
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     environment:
     environment:

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

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.13.1
+    image: gravitl/netmaker:v0.14.1
     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.13.1
+    image: gravitl/netmaker-ui:v0.14.1
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 3 - 2
compose/docker-compose.nocaddy.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.0
+    image: gravitl/netmaker:v0.14.1
     volumes:
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
       - sqldata:/root/data
@@ -44,7 +44,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.0
+    image: gravitl/netmaker-ui:v0.14.1
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:
@@ -73,6 +73,7 @@ services:
       - "8883:8883"
       - "8883:8883"
     volumes:
     volumes:
       - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
       - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
+      - /root/certs/:/mosquitto/certs/
       - mosquitto_data:/mosquitto/data
       - mosquitto_data:/mosquitto/data
       - mosquitto_logs:/mosquitto/log
       - mosquitto_logs:/mosquitto/log
 volumes:
 volumes:

+ 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.14.0
+    image: gravitl/netmaker:v0.14.1
     volumes:
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
       - sqldata:/root/data
@@ -45,7 +45,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.13.1
+    image: gravitl/netmaker-ui:v0.14.1
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

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

@@ -2,7 +2,7 @@ services:
   netmaker: # The Primary Server for running Netmaker
   netmaker: # The Primary Server for running Netmaker
     privileged: true # Necessary to run sudo/root level commands on host system. Likely using this if running with host networking on.
     privileged: true # Necessary to run sudo/root level commands on host system. Likely using this if running with host networking on.
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.0
+    image: gravitl/netmaker:v0.14.1
     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.
       - sqldata:/root/data
       - sqldata:/root/data
@@ -46,7 +46,7 @@ services:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.0
+    image: gravitl/netmaker-ui:v0.14.1
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
     ports:
     ports:

+ 6 - 8
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.14.0
+    image: gravitl/netmaker:v0.14.1
     volumes:
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
       - sqldata:/root/data
@@ -35,20 +35,17 @@ services:
       MQ_HOST: "mq"
       MQ_HOST: "mq"
       HOST_NETWORK: "off"
       HOST_NETWORK: "off"
       VERBOSITY: "1"
       VERBOSITY: "1"
-      PORT_FORWARD_SERVICES: "dns"
       MANAGE_IPTABLES: "on"
       MANAGE_IPTABLES: "on"
+      PORT_FORWARD_SERVICES: "dns"
     ports:
     ports:
       - "51821-51830:51821-51830/udp"
       - "51821-51830:51821-51830/udp"
-      - "8081:8081"
   netmaker-ui:
   netmaker-ui:
     container_name: netmaker-ui
     container_name: netmaker-ui
     depends_on:
     depends_on:
       - netmaker
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.0
+    image: gravitl/netmaker-ui:v0.14.1
     links:
     links:
       - "netmaker:api"
       - "netmaker:api"
-    ports:
-      - "8082:80"
     environment:
     environment:
       BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN"
       BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN"
     restart: always
     restart: always
@@ -65,7 +62,9 @@ services:
     image: caddy:latest
     image: caddy:latest
     container_name: caddy
     container_name: caddy
     restart: unless-stopped
     restart: unless-stopped
-    network_mode: host # Wants ports 80 and 443!
+    ports:
+      - "80:80"
+      - "443:443"
     volumes:
     volumes:
       - /root/Caddyfile:/etc/caddy/Caddyfile
       - /root/Caddyfile:/etc/caddy/Caddyfile
       # - $PWD/site:/srv # you could also serve a static site in site folder
       # - $PWD/site:/srv # you could also serve a static site in site folder
@@ -78,7 +77,6 @@ services:
     container_name: mq
     container_name: mq
     restart: unless-stopped
     restart: unless-stopped
     ports:
     ports:
-      - "127.0.0.1:1883:1883"
       - "8883:8883"
       - "8883:8883"
     volumes:
     volumes:
       - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
       - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf

+ 7 - 24
controllers/node.go

@@ -38,9 +38,6 @@ func nodeHandlers(r *mux.Router) {
 
 
 func authenticate(response http.ResponseWriter, request *http.Request) {
 func authenticate(response http.ResponseWriter, request *http.Request) {
 
 
-	var params = mux.Vars(request)
-	networkname := params["network"]
-
 	var authRequest models.AuthParams
 	var authRequest models.AuthParams
 	var result models.Node
 	var result models.Node
 	var errorResponse = models.ErrorResponse{
 	var errorResponse = models.ErrorResponse{
@@ -58,8 +55,8 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
 		return
 		return
 	} else {
 	} else {
 		errorResponse.Code = http.StatusBadRequest
 		errorResponse.Code = http.StatusBadRequest
-		if authRequest.MacAddress == "" {
-			errorResponse.Message = "W1R3: MacAddress can't be empty"
+		if authRequest.ID == "" {
+			errorResponse.Message = "W1R3: ID can't be empty"
 			returnErrorResponse(response, request, errorResponse)
 			returnErrorResponse(response, request, errorResponse)
 			return
 			return
 		} else if authRequest.Password == "" {
 		} else if authRequest.Password == "" {
@@ -67,22 +64,8 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
 			returnErrorResponse(response, request, errorResponse)
 			returnErrorResponse(response, request, errorResponse)
 			return
 			return
 		} else {
 		} else {
-
-			collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
-			if err != nil {
-				errorResponse.Code = http.StatusBadRequest
-				errorResponse.Message = err.Error()
-				returnErrorResponse(response, request, errorResponse)
-				return
-			}
-			for _, value := range collection {
-				if err := json.Unmarshal([]byte(value), &result); err != nil {
-					continue
-				}
-				if (result.ID == authRequest.ID || result.MacAddress == authRequest.MacAddress) && result.IsPending != "yes" && result.Network == networkname {
-					break
-				}
-			}
+			var err error
+			result, err = logic.GetNodeByID(authRequest.ID)
 
 
 			if err != nil {
 			if err != nil {
 				errorResponse.Code = http.StatusBadRequest
 				errorResponse.Code = http.StatusBadRequest
@@ -109,10 +92,10 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
 
 
 				var successResponse = models.SuccessResponse{
 				var successResponse = models.SuccessResponse{
 					Code:    http.StatusOK,
 					Code:    http.StatusOK,
-					Message: "W1R3: Device " + authRequest.MacAddress + " Authorized",
+					Message: "W1R3: Device " + authRequest.ID + " Authorized",
 					Response: models.SuccessfulLoginResponse{
 					Response: models.SuccessfulLoginResponse{
-						AuthToken:  tokenString,
-						MacAddress: authRequest.MacAddress,
+						AuthToken: tokenString,
+						ID:        authRequest.ID,
 					},
 					},
 				}
 				}
 				successJSONResponse, jsonError := json.Marshal(successResponse)
 				successJSONResponse, jsonError := json.Marshal(successResponse)

+ 39 - 0
docker/Dockerfile-netclient-multiarch-go

@@ -0,0 +1,39 @@
+FROM gravitl/go-builder:latest as builder
+# add glib support daemon manager
+WORKDIR /app
+
+COPY . .
+
+ENV GO111MODULE=auto
+
+RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 /usr/local/go/bin/go build -ldflags="-w -s" -o netclient-app netclient/main.go
+
+WORKDIR /root/
+
+RUN apk add --update git build-base libmnl-dev iptables
+
+RUN git clone https://git.zx2c4.com/wireguard-go && \
+    cd wireguard-go && \
+    make && \
+    make install
+
+ENV WITH_WGQUICK=yes
+RUN git clone https://git.zx2c4.com/wireguard-tools && \
+    cd wireguard-tools && \
+    cd src && \
+    make && \
+    make install
+
+FROM alpine:3.13.6
+
+WORKDIR /root/
+
+RUN apk add --no-cache --update bash libmnl gcompat iptables openresolv iproute2
+COPY --from=builder /usr/bin/wireguard-go /usr/bin/wg* /usr/bin/
+COPY --from=builder /app/netclient-app ./netclient
+COPY --from=builder /app/scripts/netclient.sh .
+RUN chmod 0755 netclient && chmod 0755 netclient.sh
+
+ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard-go
+
+ENTRYPOINT ["/bin/sh", "./netclient.sh"]

+ 4 - 2
go.mod

@@ -10,13 +10,13 @@ require (
 	github.com/google/uuid v1.3.0
 	github.com/google/uuid v1.3.0
 	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.5
+	github.com/lib/pq v1.10.6
 	github.com/mattn/go-sqlite3 v1.14.10
 	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.1
 	github.com/stretchr/testify v1.7.1
 	github.com/txn2/txeh v1.3.0
 	github.com/txn2/txeh v1.3.0
-	github.com/urfave/cli/v2 v2.6.0
+	github.com/urfave/cli/v2 v2.8.0
 	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
 	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
@@ -32,6 +32,7 @@ require (
 require (
 require (
 	filippo.io/edwards25519 v1.0.0-rc.1
 	filippo.io/edwards25519 v1.0.0-rc.1
 	fyne.io/fyne/v2 v2.1.4
 	fyne.io/fyne/v2 v2.1.4
+	github.com/cloverstd/tcping v0.1.1
 	github.com/guumaster/hostctl v1.1.2
 	github.com/guumaster/hostctl v1.1.2
 	github.com/kr/pretty v0.3.0
 	github.com/kr/pretty v0.3.0
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
@@ -41,6 +42,7 @@ require (
 require (
 require (
 	cloud.google.com/go v0.34.0 // indirect
 	cloud.google.com/go v0.34.0 // indirect
 	github.com/Microsoft/go-winio v0.4.14 // indirect
 	github.com/Microsoft/go-winio v0.4.14 // indirect
+	github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/docker/distribution v2.7.1+incompatible // indirect
 	github.com/docker/distribution v2.7.1+incompatible // indirect

+ 8 - 4
go.sum

@@ -14,11 +14,15 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
 github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
 github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 h1:R/qAiUxFT3mNgQaNqJe0IVznjKRNm23ohAIh9lgtlzc=
+github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0/go.mod h1:v3ZDlfVAL1OrkKHbGSFFK60k0/7hruHPDq2XMs9Gu6U=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloverstd/tcping v0.1.1 h1:3Yp9nvSDI7Z63zoVQDJzVk1PUczrF9tJoOrKGV30iOk=
+github.com/cloverstd/tcping v0.1.1/go.mod h1:NYXTrTDwlwuOKQ0vwksUVUbIr0sxDDsf1J6aFpScCBo=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
@@ -137,8 +141,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
-github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
+github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
 github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
 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-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
@@ -238,8 +242,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
 github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
-github.com/urfave/cli/v2 v2.6.0 h1:yj2Drkflh8X/zUrkWlWlUjZYHyWN7WMmpVxyxXIUyv8=
-github.com/urfave/cli/v2 v2.6.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs=
+github.com/urfave/cli/v2 v2.8.0 h1:EZsAB20oRW4nHcB99TTL6PrXpBGIEujMEKdjwruY9KQ=
+github.com/urfave/cli/v2 v2.8.0/go.mod h1:TYFbtzt/azQoJOrGH5mDfZtS0jIkl/OeFwlRWPR9KRM=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=

BIN
img/readme.gif


+ 1 - 1
logic/networks.go

@@ -680,7 +680,7 @@ func networkNodesUpdateAction(networkName string, action string) error {
 			fmt.Println("error in node address assignment!")
 			fmt.Println("error in node address assignment!")
 			return err
 			return err
 		}
 		}
-		if action == models.NODE_UPDATE_KEY && node.IsStatic == "yes" {
+		if action == models.NODE_UPDATE_KEY {
 			continue
 			continue
 		}
 		}
 		if node.Network == networkName {
 		if node.Network == networkName {

+ 3 - 1
logic/peers.go

@@ -80,7 +80,9 @@ func GetNodePeers(network *models.Network, nodeid string, excludeRelayed bool, i
 				}
 				}
 			}
 			}
 			// if udp hole punching is on, but port is still set to default (e.g. 51821), use the LocalListenPort
 			// if udp hole punching is on, but port is still set to default (e.g. 51821), use the LocalListenPort
-			if node.UDPHolePunch == "yes" && node.IsStatic != "yes" && peer.ListenPort == node.ListenPort {
+			// removing IsStatic check. IsStatic will now ONLY refer to endpoint.
+			//if node.UDPHolePunch == "yes" && node.IsStatic != "yes" && peer.ListenPort == node.ListenPort {
+			if node.UDPHolePunch == "yes" && peer.ListenPort == node.ListenPort {
 				peer.ListenPort = node.LocalListenPort
 				peer.ListenPort = node.LocalListenPort
 			}
 			}
 			if node.IsRelay == "yes" { // TODO, check if addressrange6 needs to be appended
 			if node.IsRelay == "yes" { // TODO, check if addressrange6 needs to be appended

+ 1 - 2
logic/server.go

@@ -406,8 +406,7 @@ func isDeleteError(err error) bool {
 }
 }
 
 
 func checkNodeActions(node *models.Node) string {
 func checkNodeActions(node *models.Node) string {
-	if (node.Action == models.NODE_UPDATE_KEY) &&
-		node.IsStatic != "yes" {
+	if node.Action == models.NODE_UPDATE_KEY {
 		err := setWGKeyConfig(node)
 		err := setWGKeyConfig(node)
 		if err != nil {
 		if err != nil {
 			logger.Log(1, "unable to process reset keys request:", err.Error())
 			logger.Log(1, "unable to process reset keys request:", err.Error())

+ 54 - 53
models/node.go

@@ -35,53 +35,54 @@ var seededRand *rand.Rand = rand.New(
 
 
 // Node - struct for node model
 // Node - struct for node model
 type Node struct {
 type Node struct {
-	ID                  string      `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5"`
-	Address             string      `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
-	Address6            string      `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
-	LocalAddress        string      `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
-	Name                string      `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"`
-	NetworkSettings     Network     `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
-	ListenPort          int32       `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
-	LocalListenPort     int32       `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"`
-	PublicKey           string      `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
-	Endpoint            string      `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
-	PostUp              string      `json:"postup" bson:"postup" yaml:"postup"`
-	PostDown            string      `json:"postdown" bson:"postdown" yaml:"postdown"`
-	AllowedIPs          []string    `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
-	PersistentKeepalive int32       `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
-	IsHub               string      `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"`
-	AccessKey           string      `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
-	Interface           string      `json:"interface" bson:"interface" yaml:"interface"`
-	LastModified        int64       `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
-	ExpirationDateTime  int64       `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
-	LastPeerUpdate      int64       `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
-	LastCheckIn         int64       `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
-	MacAddress          string      `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"macaddress_unique"`
-	Password            string      `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
-	Network             string      `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
-	IsRelayed           string      `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
-	IsPending           string      `json:"ispending" bson:"ispending" yaml:"ispending"`
-	IsRelay             string      `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"`
-	IsDocker            string      `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"`
-	IsK8S               string      `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"`
-	IsEgressGateway     string      `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
-	IsIngressGateway    string      `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
-	EgressGatewayRanges []string    `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
-	RelayAddrs          []string    `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"`
-	IngressGatewayRange string      `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
-	IsStatic            string      `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"`
-	UDPHolePunch        string      `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
-	DNSOn               string      `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"`
-	IsServer            string      `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"`
-	Action              string      `json:"action" bson:"action" yaml:"action"`
-	IsLocal             string      `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"`
-	LocalRange          string      `json:"localrange" bson:"localrange" yaml:"localrange"`
-	IPForwarding        string      `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"`
-	OS                  string      `json:"os" bson:"os" yaml:"os"`
-	MTU                 int32       `json:"mtu" bson:"mtu" yaml:"mtu"`
-	Version             string      `json:"version" bson:"version" yaml:"version"`
-	Server              string      `json:"server" bson:"server" yaml:"server"`
-	TrafficKeys         TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"`
+	ID                  string   `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5"`
+	Address             string   `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
+	Address6            string   `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
+	LocalAddress        string   `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
+	Name                string   `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"`
+	NetworkSettings     Network  `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
+	ListenPort          int32    `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
+	LocalListenPort     int32    `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"`
+	PublicKey           string   `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
+	Endpoint            string   `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
+	PostUp              string   `json:"postup" bson:"postup" yaml:"postup"`
+	PostDown            string   `json:"postdown" bson:"postdown" yaml:"postdown"`
+	AllowedIPs          []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
+	PersistentKeepalive int32    `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
+	IsHub               string   `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"`
+	AccessKey           string   `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
+	Interface           string   `json:"interface" bson:"interface" yaml:"interface"`
+	LastModified        int64    `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
+	ExpirationDateTime  int64    `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
+	LastPeerUpdate      int64    `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
+	LastCheckIn         int64    `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
+	MacAddress          string   `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"macaddress_unique"`
+	Password            string   `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
+	Network             string   `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
+	IsRelayed           string   `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
+	IsPending           string   `json:"ispending" bson:"ispending" yaml:"ispending"`
+	IsRelay             string   `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"`
+	IsDocker            string   `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"`
+	IsK8S               string   `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"`
+	IsEgressGateway     string   `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
+	IsIngressGateway    string   `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
+	EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
+	RelayAddrs          []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"`
+	IngressGatewayRange string   `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
+	// IsStatic - refers to if the Endpoint is set manually or dynamically
+	IsStatic     string      `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"`
+	UDPHolePunch string      `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
+	DNSOn        string      `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"`
+	IsServer     string      `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"`
+	Action       string      `json:"action" bson:"action" yaml:"action"`
+	IsLocal      string      `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"`
+	LocalRange   string      `json:"localrange" bson:"localrange" yaml:"localrange"`
+	IPForwarding string      `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"`
+	OS           string      `json:"os" bson:"os" yaml:"os"`
+	MTU          int32       `json:"mtu" bson:"mtu" yaml:"mtu"`
+	Version      string      `json:"version" bson:"version" yaml:"version"`
+	Server       string      `json:"server" bson:"server" yaml:"server"`
+	TrafficKeys  TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"`
 }
 }
 
 
 // NodesArray - used for node sorting
 // NodesArray - used for node sorting
@@ -255,10 +256,10 @@ func (node *Node) SetDefaultName() {
 func (newNode *Node) Fill(currentNode *Node) {
 func (newNode *Node) Fill(currentNode *Node) {
 	newNode.ID = currentNode.ID
 	newNode.ID = currentNode.ID
 
 
-	if newNode.Address == "" && newNode.IsStatic != "yes" {
+	if newNode.Address == "" {
 		newNode.Address = currentNode.Address
 		newNode.Address = currentNode.Address
 	}
 	}
-	if newNode.Address6 == "" && newNode.IsStatic != "yes" {
+	if newNode.Address6 == "" {
 		newNode.Address6 = currentNode.Address6
 		newNode.Address6 = currentNode.Address6
 	}
 	}
 	if newNode.LocalAddress == "" {
 	if newNode.LocalAddress == "" {
@@ -267,16 +268,16 @@ func (newNode *Node) Fill(currentNode *Node) {
 	if newNode.Name == "" {
 	if newNode.Name == "" {
 		newNode.Name = currentNode.Name
 		newNode.Name = currentNode.Name
 	}
 	}
-	if newNode.ListenPort == 0 && newNode.IsStatic != "yes" {
+	if newNode.ListenPort == 0 {
 		newNode.ListenPort = currentNode.ListenPort
 		newNode.ListenPort = currentNode.ListenPort
 	}
 	}
-	if newNode.LocalListenPort == 0 && newNode.IsStatic != "yes" {
+	if newNode.LocalListenPort == 0 {
 		newNode.LocalListenPort = currentNode.LocalListenPort
 		newNode.LocalListenPort = currentNode.LocalListenPort
 	}
 	}
-	if newNode.PublicKey == "" && newNode.IsStatic != "yes" {
+	if newNode.PublicKey == "" {
 		newNode.PublicKey = currentNode.PublicKey
 		newNode.PublicKey = currentNode.PublicKey
 	}
 	}
-	if newNode.Endpoint == "" && newNode.IsStatic != "yes" {
+	if newNode.Endpoint == "" {
 		newNode.Endpoint = currentNode.Endpoint
 		newNode.Endpoint = currentNode.Endpoint
 	}
 	}
 	if newNode.PostUp == "" {
 	if newNode.PostUp == "" {

+ 2 - 2
models/structs.go

@@ -61,8 +61,8 @@ type Claims struct {
 
 
 // SuccessfulLoginResponse is struct to send the request response
 // SuccessfulLoginResponse is struct to send the request response
 type SuccessfulLoginResponse struct {
 type SuccessfulLoginResponse struct {
-	MacAddress string
-	AuthToken  string
+	ID        string
+	AuthToken string
 }
 }
 
 
 // ErrorResponse is struct for error
 // ErrorResponse is struct for error

+ 0 - 6
netclient/cli_options/cmds.go

@@ -1,8 +1,6 @@
 package cli_options
 package cli_options
 
 
 import (
 import (
-	"errors"
-
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/netclient/command"
 	"github.com/gravitl/netmaker/netclient/command"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/config"
@@ -22,10 +20,6 @@ func GetCommands(cliFlags []cli.Flag) []*cli.Command {
 				if err != nil {
 				if err != nil {
 					return err
 					return err
 				}
 				}
-				if cfg.Network == "all" {
-					err = errors.New("no network provided")
-					return err
-				}
 				err = command.Join(&cfg, pvtKey)
 				err = command.Join(&cfg, pvtKey)
 				return err
 				return err
 			},
 			},

+ 8 - 1
netclient/config/config.go

@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"fmt"
 	"log"
 	"log"
 	"os"
 	"os"
+	"sync"
 
 
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
@@ -18,6 +19,10 @@ import (
 	"gopkg.in/yaml.v3"
 	"gopkg.in/yaml.v3"
 )
 )
 
 
+var (
+	configLock sync.Mutex
+)
+
 // ClientConfig - struct for dealing with client configuration
 // ClientConfig - struct for dealing with client configuration
 type ClientConfig struct {
 type ClientConfig struct {
 	Server          ServerConfig   `yaml:"server"`
 	Server          ServerConfig   `yaml:"server"`
@@ -52,6 +57,8 @@ type RegisterResponse struct {
 
 
 // Write - writes the config of a client to disk
 // Write - writes the config of a client to disk
 func Write(config *ClientConfig, network string) error {
 func Write(config *ClientConfig, network string) error {
+	configLock.Lock()
+	defer configLock.Unlock()
 	if network == "" {
 	if network == "" {
 		err := errors.New("no network provided - exiting")
 		err := errors.New("no network provided - exiting")
 		return err
 		return err
@@ -140,7 +147,7 @@ func ModConfig(node *models.Node) error {
 	return Write(&modconfig, network)
 	return Write(&modconfig, network)
 }
 }
 
 
-// ModConfig - overwrites the node inside client config on disk
+// SaveBackup - saves a backup file of a given network
 func SaveBackup(network string) error {
 func SaveBackup(network string) error {
 
 
 	var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network
 	var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network

+ 27 - 19
netclient/functions/daemon.go

@@ -42,35 +42,36 @@ type cachedMessage struct {
 
 
 // Daemon runs netclient daemon from command line
 // Daemon runs netclient daemon from command line
 func Daemon() error {
 func Daemon() error {
-	serverSet := make(map[string]config.ClientConfig)
+	serverSet := make(map[string]bool)
 	// == initial pull of all networks ==
 	// == initial pull of all networks ==
 	networks, _ := ncutils.GetSystemNetworks()
 	networks, _ := ncutils.GetSystemNetworks()
 	if len(networks) == 0 {
 	if len(networks) == 0 {
 		return errors.New("no networks")
 		return errors.New("no networks")
 	}
 	}
+	pubNetworks = append(pubNetworks, networks...)
+	// set ipforwarding on startup
+	err := local.SetIPForwarding()
+	if err != nil {
+		logger.Log(0, err.Error())
+	}
+
 	for _, network := range networks {
 	for _, network := range networks {
 		logger.Log(3, "initializing network", network)
 		logger.Log(3, "initializing network", network)
 		cfg := config.ClientConfig{}
 		cfg := config.ClientConfig{}
 		cfg.Network = network
 		cfg.Network = network
 		cfg.ReadConfig()
 		cfg.ReadConfig()
-		serverSet[cfg.Server.Server] = cfg
 		if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, ncutils.GetNetclientPathSpecific()+cfg.Node.Interface+".conf"); err != nil {
 		if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, ncutils.GetNetclientPathSpecific()+cfg.Node.Interface+".conf"); err != nil {
 			logger.Log(0, "failed to start ", cfg.Node.Interface, "wg interface", err.Error())
 			logger.Log(0, "failed to start ", cfg.Node.Interface, "wg interface", err.Error())
 		}
 		}
-		//initialPull(cfg.Network)
-	}
-	// set ipforwarding on startup
-	err := local.SetIPForwarding()
-	if err != nil {
-		logger.Log(0, err.Error())
-	}
-
-	// == subscribe to all nodes for each on machine ==
-	for server, config := range serverSet {
-		logger.Log(1, "started daemon for server ", server)
-		ctx, cancel := context.WithCancel(context.Background())
-		networkcontext.Store(server, cancel)
-		go messageQueue(ctx, &config)
+		server := cfg.Server.Server
+		if !serverSet[server] {
+			// == subscribe to all nodes for each on machine ==
+			serverSet[server] = true
+			logger.Log(1, "started daemon for server ", server)
+			ctx, cancel := context.WithCancel(context.Background())
+			networkcontext.Store(server, cancel)
+			go messageQueue(ctx, &cfg)
+		}
 	}
 	}
 
 
 	// == add waitgroup and cancel for checkin routine ==
 	// == add waitgroup and cancel for checkin routine ==
@@ -167,7 +168,11 @@ func unsubscribeNode(client mqtt.Client, nodeCfg *config.ClientConfig) {
 // the client should subscribe to ALL nodes that exist on server locally
 // the client should subscribe to ALL nodes that exist on server locally
 func messageQueue(ctx context.Context, cfg *config.ClientConfig) {
 func messageQueue(ctx context.Context, cfg *config.ClientConfig) {
 	logger.Log(0, "netclient daemon started for server: ", cfg.Server.Server)
 	logger.Log(0, "netclient daemon started for server: ", cfg.Server.Server)
-	client := setupMQTT(cfg, false)
+	client, err := setupMQTT(cfg, false)
+	if err != nil {
+		logger.Log(0, "unable to connect to broker", err.Error())
+		return
+	}
 	defer client.Disconnect(250)
 	defer client.Disconnect(250)
 	<-ctx.Done()
 	<-ctx.Done()
 	logger.Log(0, "shutting down daemon for server ", cfg.Server.Server)
 	logger.Log(0, "shutting down daemon for server ", cfg.Server.Server)
@@ -201,7 +206,7 @@ func NewTLSConfig(server string) *tls.Config {
 
 
 // setupMQTT creates a connection to broker and returns client
 // setupMQTT creates a connection to broker and returns client
 // this function is primarily used to create a connection to publish to the broker
 // this function is primarily used to create a connection to publish to the broker
-func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client {
+func setupMQTT(cfg *config.ClientConfig, publish bool) (mqtt.Client, error) {
 	opts := mqtt.NewClientOptions()
 	opts := mqtt.NewClientOptions()
 	server := cfg.Server.Server
 	server := cfg.Server.Server
 	opts.AddBroker("ssl://" + server + ":8883") // TODO get the appropriate port of the comms mq server
 	opts.AddBroker("ssl://" + server + ":8883") // TODO get the appropriate port of the comms mq server
@@ -242,6 +247,9 @@ func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client {
 		} else {
 		} else {
 			err = token.Error()
 			err = token.Error()
 		}
 		}
+		if err := checkBroker(cfg.Server.Server); err != nil {
+			return nil, err
+		}
 		logger.Log(0, "could not connect to broker", cfg.Server.Server, err.Error())
 		logger.Log(0, "could not connect to broker", cfg.Server.Server, err.Error())
 		if strings.Contains(err.Error(), "connectex") || strings.Contains(err.Error(), "connect timeout") {
 		if strings.Contains(err.Error(), "connectex") || strings.Contains(err.Error(), "connect timeout") {
 			logger.Log(0, "connection issue detected.. attempt connection with new certs")
 			logger.Log(0, "connection issue detected.. attempt connection with new certs")
@@ -256,7 +264,7 @@ func setupMQTT(cfg *config.ClientConfig, publish bool) mqtt.Client {
 			daemon.Restart()
 			daemon.Restart()
 		}
 		}
 	}
 	}
-	return client
+	return client, nil
 }
 }
 
 
 // publishes a message to server to update peers on this peer's behalf
 // publishes a message to server to update peers on this peer's behalf

+ 20 - 17
netclient/functions/join.go

@@ -42,6 +42,11 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	if cfg.Node.Password == "" {
 	if cfg.Node.Password == "" {
 		cfg.Node.Password = logic.GenKey()
 		cfg.Node.Password = logic.GenKey()
 	}
 	}
+	manualPort := false
+	if cfg.Node.ListenPort != 0 {
+		cfg.Node.UDPHolePunch = "no"
+		manualPort = true
+	}
 	var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys
 	var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys
 	if errT != nil {
 	if errT != nil {
 		return errT
 		return errT
@@ -164,10 +169,11 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 		}
 		}
 	}
 	}
 	logger.Log(1, "node created on remote server...updating configs")
 	logger.Log(1, "node created on remote server...updating configs")
-	// keep track of the old listenport value
-	oldListenPort := node.ListenPort
 	cfg.Node = node
 	cfg.Node = node
-	setListenPort(oldListenPort, cfg)
+	logger.Log(1, "turn on UDP hole punching (dynamic port setting)? "+cfg.Node.UDPHolePunch)
+	if !manualPort && (cfg.Node.UDPHolePunch == "no") {
+		setListenPort(cfg)
+	}
 	err = config.ModConfig(&cfg.Node)
 	err = config.ModConfig(&cfg.Node)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -215,22 +221,19 @@ func formatName(node models.Node) string {
 	return node.Name
 	return node.Name
 }
 }
 
 
-func setListenPort(oldListenPort int32, cfg *config.ClientConfig) {
+func setListenPort(cfg *config.ClientConfig) {
 	// keep track of the returned listenport value
 	// keep track of the returned listenport value
 	newListenPort := cfg.Node.ListenPort
 	newListenPort := cfg.Node.ListenPort
+	var errN error
+	// get free port based on returned default listen port
+	cfg.Node.ListenPort, errN = ncutils.GetFreePort(cfg.Node.ListenPort)
+	if errN != nil {
+		cfg.Node.ListenPort = newListenPort
+		logger.Log(1, "Error retrieving port: ", errN.Error())
+	}
 
 
-	if newListenPort != oldListenPort {
-		var errN error
-		// get free port based on returned default listen port
-		cfg.Node.ListenPort, errN = ncutils.GetFreePort(cfg.Node.ListenPort)
-		if errN != nil {
-			cfg.Node.ListenPort = newListenPort
-			logger.Log(1, "Error retrieving port: ", errN.Error())
-		}
-
-		// if newListenPort has been modified to find an available port, publish to server
-		if cfg.Node.ListenPort != newListenPort {
-			PublishNodeUpdate(cfg)
-		}
+	// if newListenPort has been modified to find an available port, publish to server
+	if cfg.Node.ListenPort != newListenPort {
+		PublishNodeUpdate(cfg)
 	}
 	}
 }
 }

+ 34 - 10
netclient/functions/mqpublish.go

@@ -5,10 +5,12 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
+	"net"
 	"os"
 	"os"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"github.com/cloverstd/tcping/ping"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/config"
 	"github.com/gravitl/netmaker/netclient/config"
@@ -16,6 +18,9 @@ import (
 	"github.com/gravitl/netmaker/tls"
 	"github.com/gravitl/netmaker/tls"
 )
 )
 
 
+// pubNetworks hold the currently publishable networks
+var pubNetworks []string
+
 // Checkin  -- go routine that checks for public or local ip changes, publishes changes
 // Checkin  -- go routine that checks for public or local ip changes, publishes changes
 //   if there are no updates, simply "pings" the server as a checkin
 //   if there are no updates, simply "pings" the server as a checkin
 func Checkin(ctx context.Context, wg *sync.WaitGroup) {
 func Checkin(ctx context.Context, wg *sync.WaitGroup) {
@@ -27,13 +32,7 @@ func Checkin(ctx context.Context, wg *sync.WaitGroup) {
 			return
 			return
 			//delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ??
 			//delay should be configuraable -> use cfg.Node.NetworkSettings.DefaultCheckInInterval ??
 		case <-time.After(time.Second * 60):
 		case <-time.After(time.Second * 60):
-			// logger.Log(0, "Checkin running")
-			//read latest config
-			networks, err := ncutils.GetSystemNetworks()
-			if err != nil {
-				return
-			}
-			for _, network := range networks {
+			for _, network := range pubNetworks {
 				var nodeCfg config.ClientConfig
 				var nodeCfg config.ClientConfig
 				nodeCfg.Network = network
 				nodeCfg.Network = network
 				nodeCfg.ReadConfig()
 				nodeCfg.ReadConfig()
@@ -109,7 +108,7 @@ func Hello(nodeCfg *config.ClientConfig) {
 			logger.Log(0, "could not run pull on "+nodeCfg.Node.Network+", error: "+err.Error())
 			logger.Log(0, "could not run pull on "+nodeCfg.Node.Network+", error: "+err.Error())
 		}
 		}
 	}
 	}
-	logger.Log(3, "server checkin complete")
+	logger.Log(3, "checkin for", nodeCfg.Network, "complete")
 }
 }
 
 
 // node cfg is required  in order to fetch the traffic keys of that node for encryption
 // node cfg is required  in order to fetch the traffic keys of that node for encryption
@@ -124,7 +123,10 @@ func publish(nodeCfg *config.ClientConfig, dest string, msg []byte, qos byte) er
 		return err
 		return err
 	}
 	}
 
 
-	client := setupMQTT(nodeCfg, true)
+	client, err := setupMQTT(nodeCfg, true)
+	if err != nil {
+		return fmt.Errorf("mq setup error %w", err)
+	}
 	defer client.Disconnect(250)
 	defer client.Disconnect(250)
 	encrypted, err := ncutils.Chunk(msg, serverPubKey, trafficPrivKey)
 	encrypted, err := ncutils.Chunk(msg, serverPubKey, trafficPrivKey)
 	if err != nil {
 	if err != nil {
@@ -140,7 +142,7 @@ func publish(nodeCfg *config.ClientConfig, dest string, msg []byte, qos byte) er
 			err = token.Error()
 			err = token.Error()
 		}
 		}
 		if err != nil {
 		if err != nil {
-			return token.Error()
+			return err
 		}
 		}
 	}
 	}
 	return nil
 	return nil
@@ -161,3 +163,25 @@ func checkCertExpiry(cfg *config.ClientConfig) error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+
+func checkBroker(broker string) error {
+	_, err := net.LookupIP(broker)
+	if err != nil {
+		return errors.New("nslookup failed for broker ... check dns records")
+	}
+	pinger := ping.NewTCPing()
+	pinger.SetTarget(&ping.Target{
+		Protocol: ping.TCP,
+		Host:     broker,
+		Port:     8883,
+		Counter:  3,
+		Interval: 1 * time.Second,
+		Timeout:  2 * time.Second,
+	})
+	pingerDone := pinger.Start()
+	<-pingerDone
+	if pinger.Result().SuccessCounter == 0 {
+		return errors.New("unable to connect to broker port ... check netmaker server and firewalls")
+	}
+	return nil
+}

+ 4 - 3
netclient/gui/components/views/networks.go

@@ -67,6 +67,7 @@ func GetSingleNetworkView(network string) fyne.CanvasObject {
 	LoadingNotify()
 	LoadingNotify()
 	nets, err := functions.List(network)
 	nets, err := functions.List(network)
 	if err != nil || len(nets) < 1 {
 	if err != nil || len(nets) < 1 {
+		ClearNotification()
 		return container.NewCenter(widget.NewLabel("No data retrieved."))
 		return container.NewCenter(widget.NewLabel("No data retrieved."))
 	}
 	}
 	var nodecfg config.ClientConfig
 	var nodecfg config.ClientConfig
@@ -79,10 +80,10 @@ func GetSingleNetworkView(network string) fyne.CanvasObject {
 	privateAddr6 := nodecfg.Node.Address6
 	privateAddr6 := nodecfg.Node.Address6
 	endpoint := nodecfg.Node.Endpoint
 	endpoint := nodecfg.Node.Endpoint
 	health := " (HEALTHY)"
 	health := " (HEALTHY)"
-	if time.Now().After(lastCheckInTime.Add(time.Minute * 5)) {
-		health = " (WARNING)"
-	} else if time.Now().After(lastCheckInTime.Add(time.Minute * 30)) {
+	if time.Now().After(lastCheckInTime.Add(time.Minute * 30)) {
 		health = " (ERROR)"
 		health = " (ERROR)"
+	} else if time.Now().After(lastCheckInTime.Add(time.Minute * 5)) {
+		health = " (WARNING)"
 	}
 	}
 	lastCheckIn += health
 	lastCheckIn += health
 	version := nodecfg.Node.Version
 	version := nodecfg.Node.Version

+ 0 - 149
netclient/local/dns.go

@@ -1,149 +0,0 @@
-package local
-
-import (
-	"fmt"
-	"net"
-	"os"
-	"strings"
-	"time"
-
-	//"github.com/davecgh/go-spew/spew"
-	"log"
-	"os/exec"
-
-	"github.com/gravitl/netmaker/logger"
-	"github.com/gravitl/netmaker/models"
-	"github.com/gravitl/netmaker/netclient/ncutils"
-)
-
-const DNS_UNREACHABLE_ERROR = "nameserver unreachable"
-
-// SetDNSWithRetry - Attempt setting dns, if it fails return true (to reset dns)
-func SetDNSWithRetry(node models.Node, address string) bool {
-	var reachable bool
-	if !hasPrereqs() {
-		return true
-	}
-	for counter := 0; !reachable && counter < 5; counter++ {
-		reachable = IsDNSReachable(address)
-		time.Sleep(time.Second << 1)
-	}
-	if !reachable {
-		logger.Log(0, "not setting dns (server unreachable), will try again later: "+address)
-		return true
-	} else if err := UpdateDNS(node.Interface, node.Network, address); err != nil {
-		logger.Log(0, "error applying dns"+err.Error())
-	} else if IsDNSWorking(node.Network, address) {
-		return true
-	}
-	resetDNS()
-	return false
-}
-
-func resetDNS() {
-	ncutils.RunCmd("systemctl restart systemd-resolved", true)
-}
-
-// SetDNS - sets the DNS of a local machine
-func SetDNS(nameserver string) error {
-	bytes, err := os.ReadFile("/etc/resolv.conf")
-	if err != nil {
-		return err
-	}
-	resolvstring := string(bytes)
-	// //check whether s contains substring text
-	hasdns := strings.Contains(resolvstring, nameserver)
-	if hasdns {
-		return nil
-	}
-	resolv, err := os.OpenFile("/etc/resolv.conf", os.O_APPEND|os.O_WRONLY, 0644)
-	if err != nil {
-		return err
-	}
-	defer resolv.Close()
-	_, err = resolv.WriteString("nameserver " + nameserver + "\n")
-
-	return err
-}
-
-func hasPrereqs() bool {
-	if !ncutils.IsLinux() {
-		return false
-	}
-	_, err := exec.LookPath("resolvectl")
-	return err == nil
-}
-
-// UpdateDNS - updates local DNS of client
-func UpdateDNS(ifacename string, network string, nameserver string) error {
-	if !ncutils.IsLinux() {
-		return nil
-	}
-	if ifacename == "" {
-		return fmt.Errorf("cannot set dns: interface name is blank")
-	}
-	if network == "" {
-		return fmt.Errorf("cannot set dns: network name is blank")
-	}
-	if nameserver == "" {
-		return fmt.Errorf("cannot set dns: nameserver is blank")
-	}
-	if !IsDNSReachable(nameserver) {
-		return fmt.Errorf(DNS_UNREACHABLE_ERROR + " : " + nameserver + ":53")
-	}
-	_, err := exec.LookPath("resolvectl")
-	if err != nil {
-		log.Println(err)
-		log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
-	} else {
-		_, err = ncutils.RunCmd("resolvectl domain "+ifacename+" ~"+network, true)
-		if err != nil {
-			log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
-		} else {
-			_, err = ncutils.RunCmd("resolvectl default-route "+ifacename+" false", true)
-			if err != nil {
-				log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
-			} else {
-				_, err = ncutils.RunCmd("resolvectl dns "+ifacename+" "+nameserver, true)
-				if err != nil {
-					log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
-				}
-			}
-		}
-	}
-	return err
-}
-
-// IsDNSReachable - checks if nameserver is reachable
-func IsDNSReachable(nameserver string) bool {
-	port := "53"
-	protocols := [2]string{"tcp", "udp"}
-	for _, proto := range protocols {
-		timeout := time.Second
-		conn, err := net.DialTimeout(proto, net.JoinHostPort(nameserver, port), timeout)
-		if err != nil {
-			return false
-		}
-		if conn != nil {
-			defer conn.Close()
-		} else {
-			return false
-		}
-	}
-	return true
-}
-
-// IsDNSWorking - checks if record is returned by correct nameserver
-func IsDNSWorking(network string, nameserver string) bool {
-	var isworking bool
-	servers, err := net.LookupNS("netmaker" + "." + network)
-	if err != nil {
-		return isworking
-	}
-	for _, ns := range servers {
-		if strings.Contains(ns.Host, nameserver) {
-			isworking = true
-		}
-	}
-	return isworking
-}

+ 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.14.0.0"
+            version="0.14.1.0"
             processorArchitecture="*"
             processorArchitecture="*"
             name="netclient.exe"
             name="netclient.exe"
             type="win32"
             type="win32"

+ 3 - 3
netclient/versioninfo.json

@@ -3,13 +3,13 @@
         "FileVersion": {
         "FileVersion": {
             "Major": 0,
             "Major": 0,
             "Minor": 14,
             "Minor": 14,
-            "Patch": 0,
+            "Patch": 1,
             "Build": 0
             "Build": 0
         },
         },
         "ProductVersion": {
         "ProductVersion": {
             "Major": 0,
             "Major": 0,
             "Minor": 14,
             "Minor": 14,
-            "Patch": 0,
+            "Patch": 1,
             "Build": 0
             "Build": 0
         },
         },
         "FileFlagsMask": "3f",
         "FileFlagsMask": "3f",
@@ -29,7 +29,7 @@
         "OriginalFilename": "",
         "OriginalFilename": "",
         "PrivateBuild": "",
         "PrivateBuild": "",
         "ProductName": "Netclient",
         "ProductName": "Netclient",
-        "ProductVersion": "v0.14.0.0",
+        "ProductVersion": "v0.14.1.0",
         "SpecialBuild": ""
         "SpecialBuild": ""
     },
     },
     "VarFileInfo": {
     "VarFileInfo": {

+ 13 - 8
netclient/wireguard/common.go

@@ -40,9 +40,14 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
 		return err
 		return err
 	}
 	}
 	for _, peer := range peers {
 	for _, peer := range peers {
-
+		// make sure peer has AllowedIP's before comparison
+		hasPeerIP := len(peer.AllowedIPs) > 0
 		for _, currentPeer := range devicePeers {
 		for _, currentPeer := range devicePeers {
-			if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
+			// make sure currenPeer has AllowedIP's before comparison
+			hascurrentPeerIP := len(currentPeer.AllowedIPs) > 0
+
+			if hasPeerIP && hascurrentPeerIP &&
+				currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
 				currentPeer.PublicKey.String() != peer.PublicKey.String() {
 				currentPeer.PublicKey.String() != peer.PublicKey.String() {
 				_, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true)
 				_, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true)
 				if err != nil {
 				if err != nil {
@@ -54,7 +59,7 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
 		var allowedips string
 		var allowedips string
 		var iparr []string
 		var iparr []string
 		for _, ipaddr := range peer.AllowedIPs {
 		for _, ipaddr := range peer.AllowedIPs {
-			if len(peer.AllowedIPs) > 0 && (&ipaddr) != nil {
+			if hasPeerIP && (&ipaddr) != nil {
 				iparr = append(iparr, ipaddr.String())
 				iparr = append(iparr, ipaddr.String())
 			}
 			}
 		}
 		}
@@ -85,7 +90,9 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
 			shouldDelete := true
 			shouldDelete := true
 			if peers != nil && len(peers) > 0 {
 			if peers != nil && len(peers) > 0 {
 				for _, peer := range peers {
 				for _, peer := range peers {
-					if peer.AllowedIPs[0].String() == currentPeer.AllowedIPs[0].String() {
+
+					if len(peer.AllowedIPs) > 0 && len(currentPeer.AllowedIPs) > 0 &&
+						peer.AllowedIPs[0].String() == currentPeer.AllowedIPs[0].String() {
 						shouldDelete = false
 						shouldDelete = false
 					}
 					}
 					// re-check this if logic is not working, added in case of allowedips not working
 					// re-check this if logic is not working, added in case of allowedips not working
@@ -238,7 +245,7 @@ func SetWGConfig(network string, peerupdate bool, peers []wgtypes.PeerConfig) er
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	servercfg := cfg.Server
+
 	nodecfg := cfg.Node
 	nodecfg := cfg.Node
 
 
 	privkey, err := RetrievePrivKey(network)
 	privkey, err := RetrievePrivKey(network)
@@ -260,9 +267,7 @@ func SetWGConfig(network string, peerupdate bool, peers []wgtypes.PeerConfig) er
 	} else {
 	} else {
 		err = InitWireguard(&nodecfg, privkey, peers, false)
 		err = InitWireguard(&nodecfg, privkey, peers, false)
 	}
 	}
-	if nodecfg.DNSOn == "yes" {
-		_ = local.UpdateDNS(nodecfg.Interface, nodecfg.Network, servercfg.CoreDNSAddr)
-	}
+
 	return err
 	return err
 }
 }
 
 

+ 1 - 2
netclient/wireguard/noquick.go

@@ -40,8 +40,7 @@ func ApplyWithoutWGQuick(node *models.Node, ifacename string, confPath string) e
 	nodeport := int(node.ListenPort)
 	nodeport := int(node.ListenPort)
 	if node.UDPHolePunch == "yes" &&
 	if node.UDPHolePunch == "yes" &&
 		node.IsServer == "no" &&
 		node.IsServer == "no" &&
-		node.IsIngressGateway != "yes" &&
-		node.IsStatic != "yes" {
+		node.IsIngressGateway != "yes" {
 		conf = wgtypes.Config{
 		conf = wgtypes.Config{
 			PrivateKey: &key,
 			PrivateKey: &key,
 		}
 		}