Browse Source

Merge pull request #1167 from gravitl/v0.14.2

V0.14.2
Alex Feiszli 3 years ago
parent
commit
24f7fbb7b7
71 changed files with 648 additions and 693 deletions
  1. 1 0
      .github/ISSUE_TEMPLATE/bug-report.yml
  2. 3 13
      .github/workflows/publish-netclient-docker-userspace.yml
  3. 13 7
      README.md
  4. 2 1
      auth/azure-ad.go
  5. 2 1
      auth/github.go
  6. 2 1
      auth/google.go
  7. 2 2
      compose/docker-compose.contained.yml
  8. 2 2
      compose/docker-compose.hostnetwork.yml
  9. 2 2
      compose/docker-compose.nocaddy.yml
  10. 2 2
      compose/docker-compose.nodns.yml
  11. 2 2
      compose/docker-compose.reference.yml
  12. 137 0
      compose/docker-compose.traefik.yml
  13. 2 2
      compose/docker-compose.yml
  14. 1 0
      config/config.go
  15. 1 0
      controllers/config/dnsconfig/netmaker.hosts
  16. 2 1
      controllers/network_test.go
  17. 6 4
      controllers/node.go
  18. 1 1
      controllers/node_test.go
  19. 13 19
      controllers/server.go
  20. 0 23
      docker/Dockerfile-builder
  21. 0 36
      docker/Dockerfile-full
  22. 0 22
      docker/Dockerfile-netclient
  23. 1 1
      docker/Dockerfile-netclient-doks
  24. 1 1
      docker/Dockerfile-netclient-doks-uspace
  25. 0 39
      docker/Dockerfile-netclient-full
  26. 0 39
      docker/Dockerfile-netclient-kernel
  27. 1 1
      docker/Dockerfile-netclient-multiarch
  28. 1 1
      docker/Dockerfile-netclient-multiarch-userspace
  29. 0 26
      docker/Dockerfile-netmaker-slim
  30. 0 26
      docker/Dockerfile-userspace
  31. 5 6
      go.mod
  32. 10 12
      go.sum
  33. 14 12
      logger/logger.go
  34. 6 0
      logger/types.go
  35. 2 6
      logic/accesskeys.go
  36. 0 62
      logic/ips/ips.go
  37. 0 50
      logic/ips/ips_test.go
  38. 36 32
      logic/networks.go
  39. 2 6
      logic/nodes.go
  40. 92 51
      logic/peers.go
  41. 6 6
      logic/server.go
  42. 1 1
      logic/telemetry.go
  43. 3 2
      logic/timer.go
  44. 1 0
      logic/util.go
  45. 1 6
      models/accessToken.go
  46. 5 4
      models/mqtt.go
  47. 2 2
      models/node.go
  48. 15 2
      models/structs.go
  49. 1 0
      mq/publishers.go
  50. 31 23
      netclient/config/config.go
  51. 36 0
      netclient/functions/common.go
  52. 17 12
      netclient/functions/daemon.go
  53. 16 27
      netclient/functions/join.go
  54. 1 1
      netclient/functions/localport.go
  55. 1 1
      netclient/functions/localport_freebsd.go
  56. 12 3
      netclient/functions/mqhandlers.go
  57. 16 2
      netclient/functions/mqpublish.go
  58. 7 2
      netclient/functions/pull.go
  59. 18 10
      netclient/functions/register.go
  60. 2 3
      netclient/gui/components/views/join.go
  61. 3 4
      netclient/local/routes_darwin.go
  62. 3 4
      netclient/local/routes_freebsd.go
  63. 3 4
      netclient/local/routes_linux.go
  64. 1 1
      netclient/netclient.exe.manifest.xml
  65. 3 3
      netclient/versioninfo.json
  66. 11 8
      netclient/wireguard/common.go
  67. 16 3
      scripts/netclient.sh
  68. 9 14
      scripts/nm-quick.sh
  69. 34 8
      servercfg/serverconf.go
  70. 1 1
      serverctl/iptables.go
  71. 5 24
      serverctl/serverctl.go

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

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

+ 3 - 13
.github/workflows/publish-netclient-docker-go.yml → .github/workflows/publish-netclient-docker-userspace.yml

@@ -1,4 +1,4 @@
-name: Publish Netclient-go Docker
+name: Publish Netclient-Userspace Docker
 
 on:
   workflow_dispatch:
@@ -39,23 +39,13 @@ jobs:
         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
+          file: ./docker/Dockerfile-netclient-multiarch-userspace
           push: true
-          tags: gravitl/netclient-go:${{ env.TAG }}, gravitl/netclient-go:latest
+          tags: gravitl/netclient-go:${{ env.TAG }}, gravitl/netclient-userspace:latest
           build-args: version=${{ env.TAG }}  

+ 13 - 7
README.md

@@ -10,23 +10,26 @@ a platform for modern, blazing fast virtual networks
 
 <p align="center">
   <a href="https://github.com/gravitl/netmaker/releases">
-    <img src="https://img.shields.io/badge/Version-0.14.1-informational?style=flat-square" />
+    <img src="https://img.shields.io/badge/Version-0.14.2-informational?style=flat-square" />
   </a>
   <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?label=downloads" />
   </a>  
   <a href="https://goreportcard.com/report/github.com/gravitl/netmaker">
     <img src="https://goreportcard.com/badge/github.com/gravitl/netmaker" />
   </a>
-  <a href="https://github.com/gravitl/netmaker/graphs/contributors">
-    <img src="https://img.shields.io/github/commit-activity/m/gravitl/netmaker?color=blue" />
-  </a>
   <a href="https://twitter.com/intent/follow?screen_name=netmaker_io">
-    <img src="https://img.shields.io/twitter/follow/netmaker_io?style=social" />
+    <img src="https://img.shields.io/twitter/follow/netmaker_io?label=follow&style=social" />
   </a>
   <a href="https://www.youtube.com/channel/UCach3lJY_xBV7rGrbUSvkZQ">
     <img src="https://img.shields.io/youtube/channel/views/UCach3lJY_xBV7rGrbUSvkZQ?style=social" />
   </a>
+  <a href="https://reddit.com/r/netmaker">
+    <img src="https://img.shields.io/reddit/subreddit-subscribers/netmaker?label=%2Fr%2Fnetmaker&style=social" />
+  </a>  
+  <a href="https://discord.gg/zRb9Vfhk8A">
+    <img src="https://img.shields.io/discord/825071750290210916?color=%09%237289da&label=chat" />
+  </a> 
 </p>
 
 # WireGuard® Automation from Homelab to Enterprise
@@ -43,7 +46,7 @@ a platform for modern, blazing fast virtual networks
 **For production-grade installations, visit the [Install Docs](https://netmaker.readthedocs.io/en/master/install.html).**  
 **For an HA install using helm on k8s, visit the [Helm Repo](https://github.com/gravitl/netmaker-helm/).**
 1. Get a cloud VM with Ubuntu 20.04 and a public IP.
-2. Open ports 443, 80, 53, 8883, and 51821-51830/udp on the VM firewall and in cloud security settings.
+2. Open ports 443, 53, and 51821-51830/udp on the VM firewall and in cloud security settings.
 3. Run the script **(see below for optional configurations)**:
 
 `wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash`
@@ -90,6 +93,9 @@ After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting
 
 - [Community (Discord)](https://discord.gg/zRb9Vfhk8A)
 
+- [Community (Reddit)](https://reddit.com/r/netmaker)
+
+
 - [Business (Subscription)](https://gravitl.com/plans/business)
 
 - [Learning Resources](https://gravitl.com/resources)

+ 2 - 1
auth/azure-ad.go

@@ -1,6 +1,7 @@
 package auth
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
 	"io"
@@ -90,7 +91,7 @@ func getAzureUserInfo(state string, code string) (*azureOauthUser, error) {
 	if state != oauth_state_string {
 		return nil, fmt.Errorf("invalid oauth state")
 	}
-	var token, err = auth_provider.Exchange(oauth2.NoContext, code)
+	var token, err = auth_provider.Exchange(context.Background(), code)
 	if err != nil {
 		return nil, fmt.Errorf("code exchange failed: %s", err.Error())
 	}

+ 2 - 1
auth/github.go

@@ -1,6 +1,7 @@
 package auth
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
 	"io"
@@ -90,7 +91,7 @@ func getGithubUserInfo(state string, code string) (*githubOauthUser, error) {
 	if state != oauth_state_string {
 		return nil, fmt.Errorf("invalid OAuth state")
 	}
-	var token, err = auth_provider.Exchange(oauth2.NoContext, code)
+	var token, err = auth_provider.Exchange(context.Background(), code)
 	if err != nil {
 		return nil, fmt.Errorf("code exchange failed: %s", err.Error())
 	}

+ 2 - 1
auth/google.go

@@ -1,6 +1,7 @@
 package auth
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
 	"io"
@@ -91,7 +92,7 @@ func getGoogleUserInfo(state string, code string) (*googleOauthUser, error) {
 	if state != oauth_state_string {
 		return nil, fmt.Errorf("invalid OAuth state")
 	}
-	var token, err = auth_provider.Exchange(oauth2.NoContext, code)
+	var token, err = auth_provider.Exchange(context.Background(), code)
 	if err != nil {
 		return nil, fmt.Errorf("code exchange failed: %s", err.Error())
 	}

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

@@ -3,7 +3,7 @@ version: "3.4"
 services:
   netmaker:
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.1
+    image: gravitl/netmaker:v0.14.2
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
@@ -43,7 +43,7 @@ services:
     container_name: netmaker-ui
     depends_on:
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.1
+    image: gravitl/netmaker-ui:v0.14.2
     links:
       - "netmaker:api"
     environment:

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

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

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

@@ -3,7 +3,7 @@ version: "3.4"
 services:
   netmaker:
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.1
+    image: gravitl/netmaker:v0.14.2
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
@@ -44,7 +44,7 @@ services:
     container_name: netmaker-ui
     depends_on:
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.1
+    image: gravitl/netmaker-ui:v0.14.2
     links:
       - "netmaker:api"
     ports:

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

@@ -3,7 +3,7 @@ version: "3.4"
 services:
   netmaker:
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.1
+    image: gravitl/netmaker:v0.14.2
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
@@ -45,7 +45,7 @@ services:
     container_name: netmaker-ui
     depends_on:
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.1
+    image: gravitl/netmaker-ui:v0.14.2
     links:
       - "netmaker:api"
     ports:

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

@@ -2,7 +2,7 @@ services:
   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.
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.1
+    image: gravitl/netmaker:v0.14.2
     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.
       - sqldata:/root/data
@@ -46,7 +46,7 @@ services:
     container_name: netmaker-ui
     depends_on:
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.1
+    image: gravitl/netmaker-ui:v0.14.2
     links:
       - "netmaker:api"
     ports:

+ 137 - 0
compose/docker-compose.traefik.yml

@@ -0,0 +1,137 @@
+version: "3.4"
+
+services:
+  netmaker:
+    container_name: netmaker
+    image: gravitl/netmaker:v0.14.2
+    cap_add: 
+      - NET_ADMIN
+      - NET_RAW
+      - SYS_MODULE
+    sysctls:
+      - net.ipv4.ip_forward=1
+      - net.ipv4.conf.all.src_valid_mark=1
+      - net.ipv6.conf.all.disable_ipv6=0
+      - net.ipv6.conf.all.forwarding=1
+    restart: always
+    volumes:
+      - dnsconfig:/root/config/dnsconfig
+      - sqldata:/root/data
+      - shared_certs:/etc/netmaker
+    environment:
+      SERVER_NAME: "broker.NETMAKER_BASE_DOMAIN"
+      SERVER_HOST: "SERVER_PUBLIC_IP"
+      SERVER_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443"
+      COREDNS_ADDR: "SERVER_PUBLIC_IP"
+      DNS_MODE: "on"
+      SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN"
+      API_PORT: "8081"
+      CLIENT_MODE: "on"
+      MASTER_KEY: "REPLACE_MASTER_KEY"
+      CORS_ALLOWED_ORIGIN: "*"
+      DISPLAY_KEYS: "on"
+      DATABASE: "sqlite"
+      NODE_ID: "netmaker-server-1"
+      MQ_HOST: "mq"
+      # uncomment once netmaker supports changing MQ port
+      MQ_PORT: "443"
+      HOST_NETWORK: "off"
+      VERBOSITY: "1"
+      MANAGE_IPTABLES: "on"
+      PORT_FORWARD_SERVICES: "dns"
+    ports:
+      - "51821-51830:51821-51830/udp"
+    expose:
+      - "8081"
+    labels:
+      - traefik.enable=true
+      - traefik.http.routers.netmaker-api.entrypoints=websecure
+      - traefik.http.routers.netmaker-api.rule=Host(`api.NETMAKER_BASE_DOMAIN`)
+      - traefik.http.routers.netmaker-api.service=netmaker-api
+      - traefik.http.services.netmaker-api.loadbalancer.server.port=8081
+  netmaker-ui:
+    container_name: netmaker-ui
+    image: gravitl/netmaker-ui:v0.14.2
+    depends_on:
+      - netmaker
+    links:
+      - "netmaker:api"
+    restart: always
+    environment:
+      BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN"
+    expose:
+      - "80"
+    labels:
+      - traefik.enable=true
+      - traefik.http.middlewares.nmui-security.headers.accessControlAllowOriginList=*.NETMAKER_BASE_DOMAIN
+      - traefik.http.middlewares.nmui-security.headers.stsSeconds=31536000
+      - traefik.http.middlewares.nmui-security.headers.browserXssFilter=true
+      - traefik.http.middlewares.nmui-security.headers.customFrameOptionsValue=SAMEORIGIN
+      - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.X-Robots-Tag=none
+      - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.Server= # Remove the server name
+      - traefik.http.routers.netmaker-ui.entrypoints=websecure
+      - traefik.http.routers.netmaker-ui.middlewares=nmui-security@docker
+      - traefik.http.routers.netmaker-ui.rule=Host(`dashboard.NETMAKER_BASE_DOMAIN`)
+      - traefik.http.routers.netmaker-ui.service=netmaker-ui
+      - traefik.http.services.netmaker-ui.loadbalancer.server.port=80
+  coredns:
+    container_name: coredns
+    image: coredns/coredns
+    command: -conf /root/dnsconfig/Corefile
+    depends_on:
+      - netmaker
+    restart: always
+    volumes:
+      - dnsconfig:/root/dnsconfig
+  traefik:
+    image: traefik:v2.6
+    container_name: traefik
+    command:
+      - "--certificatesresolvers.http.acme.email=YOUR_EMAIL"
+      - "--certificatesresolvers.http.acme.storage=/letsencrypt/acme.json"
+      - "--certificatesresolvers.http.acme.tlschallenge=true"
+      - "--entrypoints.websecure.address=:443"
+      - "--entrypoints.websecure.http.tls=true"
+      - "--entrypoints.websecure.http.tls.certResolver=http"
+      - "--log.level=INFO"
+      - "--providers.docker=true"
+      - "--providers.docker.exposedByDefault=false"
+      - "--serverstransport.insecureskipverify=true"
+    restart: always
+    volumes:
+      - /var/run/docker.sock:/var/run/docker.sock:ro
+      - traefik_certs:/letsencrypt
+    ports:
+      - "443:443"
+  mq:
+    container_name: mq
+    image: eclipse-mosquitto:2.0.11-openssl
+    depends_on:
+      - netmaker
+    restart: unless-stopped
+    volumes:
+      - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
+      - mosquitto_data:/mosquitto/data
+      - mosquitto_logs:/mosquitto/log
+      - shared_certs:/mosquitto/certs
+    ports:
+      - "127.0.0.1:1883:1883"
+    # comment once netmaker supports changing MQ port
+    #  - "8883:8883"
+    # uncomment once netmaker supports changing MQ port
+    expose:
+      - "8883"
+    labels:
+      - traefik.enable=true
+      - traefik.tcp.routers.mqtts.rule=HostSNI(`broker.NETMAKER_BASE_DOMAIN`)
+      - traefik.tcp.routers.mqtts.tls.passthrough=true
+      - traefik.tcp.services.mqtts-svc.loadbalancer.server.port=8883
+      - traefik.tcp.routers.mqtts.service=mqtts-svc
+      - traefik.tcp.routers.mqtts.entrypoints=websecure
+volumes:
+  traefik_certs: {}
+  shared_certs: {}
+  sqldata: {}
+  dnsconfig: {}
+  mosquitto_data: {}
+  mosquitto_logs: {}

+ 2 - 2
compose/docker-compose.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
   netmaker:
     container_name: netmaker
-    image: gravitl/netmaker:v0.14.1
+    image: gravitl/netmaker:v0.14.2
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
@@ -43,7 +43,7 @@ services:
     container_name: netmaker-ui
     depends_on:
       - netmaker
-    image: gravitl/netmaker-ui:v0.14.1
+    image: gravitl/netmaker-ui:v0.14.2
     links:
       - "netmaker:api"
     environment:

+ 1 - 0
config/config.go

@@ -66,6 +66,7 @@ type ServerConfig struct {
 	PortForwardServices   string `yaml:"portforwardservices"`
 	HostNetwork           string `yaml:"hostnetwork"`
 	MQPort                string `yaml:"mqport"`
+	MQServerPort          string `yaml:"mqserverport"`
 	Server                string `yaml:"server"`
 }
 

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

@@ -1 +1,2 @@
+10.0.0.3         testnode3.skynet
 10.0.0.2         testnode.skynet myhost.skynet

+ 2 - 1
controllers/network_test.go

@@ -289,6 +289,7 @@ func TestIpv6Network(t *testing.T) {
 
 	database.InitializeDatabase()
 	os.Setenv("MASTER_KEY", "secretkey")
+	deleteAllNetworks()
 	createNet()
 	createNetDualStack()
 	network, err := logic.GetNetwork("skynet6")
@@ -300,7 +301,7 @@ func TestIpv6Network(t *testing.T) {
 	nodeErr := logic.CreateNode(&node1)
 	t.Run("Test node on network IPv6", func(t *testing.T) {
 		assert.Nil(t, nodeErr)
-		assert.Equal(t, node1.Address6, "fde6:be04:fa5e:d076::1")
+		assert.Equal(t, "fde6:be04:fa5e:d076::", node1.Address6)
 	})
 }
 

+ 6 - 4
controllers/node.go

@@ -373,8 +373,9 @@ func getNode(w http.ResponseWriter, r *http.Request) {
 	}
 
 	response := models.NodeGet{
-		Node:  node,
-		Peers: peerUpdate.Peers,
+		Node:         node,
+		Peers:        peerUpdate.Peers,
+		ServerConfig: servercfg.GetServerInfo(),
 	}
 
 	logger.Log(2, r.Header.Get("user"), "fetched node", params["nodeid"])
@@ -492,8 +493,9 @@ func createNode(w http.ResponseWriter, r *http.Request) {
 	}
 
 	response := models.NodeGet{
-		Node:  node,
-		Peers: peerUpdate.Peers,
+		Node:         node,
+		Peers:        peerUpdate.Peers,
+		ServerConfig: servercfg.GetServerInfo(),
 	}
 
 	logger.Log(1, r.Header.Get("user"), "created new node", node.Name, "on network", node.Network)

+ 1 - 1
controllers/node_test.go

@@ -188,7 +188,7 @@ func TestNodeACLs(t *testing.T) {
 		currentACL.Save(acls.ContainerID(node1.Network))
 	})
 	t.Run("node acls correct after add new node not allowed", func(t *testing.T) {
-		node3 := models.Node{PublicKey: "DM5qhLAE20FG7BbfBCger+Ac9D2NDOwCtY1rbYDXv24=", Name: "testnode3", Endpoint: "10.0.0.100", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet", OS: "linux"}
+		node3 := models.Node{PublicKey: "this-is-not-valid", Name: "testnode3", Endpoint: "10.0.0.100", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet", OS: "linux"}
 		logic.CreateNode(&node3)
 		var currentACL, err = nodeacls.FetchAllACLs(nodeacls.NetworkID(node3.Network))
 		assert.Nil(t, err)

+ 13 - 19
controllers/server.go

@@ -23,6 +23,7 @@ func serverHandlers(r *mux.Router) {
 	r.HandleFunc("/api/server/getconfig", securityCheckServer(false, http.HandlerFunc(getConfig))).Methods("GET")
 	r.HandleFunc("/api/server/removenetwork/{network}", securityCheckServer(true, http.HandlerFunc(removeNetwork))).Methods("DELETE")
 	r.HandleFunc("/api/server/register", authorize(true, false, "node", http.HandlerFunc(register))).Methods("POST")
+	r.HandleFunc("/api/server/getserverinfo", authorize(true, false, "node", http.HandlerFunc(getServerInfo))).Methods("GET")
 }
 
 //Security check is middleware for every function and just checks to make sure that its the master calling
@@ -81,35 +82,26 @@ func removeNetwork(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode("Server removed from network " + params["network"])
 }
 
-func getConfig(w http.ResponseWriter, r *http.Request) {
+func getServerInfo(w http.ResponseWriter, r *http.Request) {
 	// Set header
 	w.Header().Set("Content-Type", "application/json")
 
 	// get params
 
-	scfg := servercfg.GetServerConfig()
-	json.NewEncoder(w).Encode(scfg)
+	json.NewEncoder(w).Encode(servercfg.GetServerInfo())
 	//w.WriteHeader(http.StatusOK)
 }
 
-// func addNetwork(w http.ResponseWriter, r *http.Request) {
-// 	// Set header
-// 	w.Header().Set("Content-Type", "application/json")
-
-// 	// get params
-// 	var params = mux.Vars(r)
-// 	var networkName = params["network"]
-// 	var networkSettings, err := logic.GetNetwork(netwnetworkName)
-
-// 	success, err := serverctl.AddNetwork(params["network"])
+func getConfig(w http.ResponseWriter, r *http.Request) {
+	// Set header
+	w.Header().Set("Content-Type", "application/json")
 
-// 	if err != nil || !success {
-// 		json.NewEncoder(w).Encode("Could not add server to network " + params["network"])
-// 		return
-// 	}
+	// get params
 
-// 	json.NewEncoder(w).Encode("Server added to network " + params["network"])
-// }
+	scfg := servercfg.GetServerConfig()
+	json.NewEncoder(w).Encode(scfg)
+	//w.WriteHeader(http.StatusOK)
+}
 
 // register - registers a client with the server and return the CA and cert
 func register(w http.ResponseWriter, r *http.Request) {
@@ -141,6 +133,8 @@ func register(w http.ResponseWriter, r *http.Request) {
 		CAPubKey:   (ca.PublicKey).(ed25519.PublicKey),
 		Cert:       *cert,
 		CertPubKey: (cert.PublicKey).(ed25519.PublicKey),
+		Broker:     servercfg.GetServer(),
+		Port:       servercfg.GetMQPort(),
 	}
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(response)

+ 0 - 23
docker/Dockerfile-builder

@@ -1,23 +0,0 @@
-FROM alpine:3.15.2
-
-RUN apk add --no-cache --virtual .build-deps bash gcc musl-dev openssl go 
-
-RUN wget -O go.tgz https://go.dev/dl/go1.18.linux-amd64.tar.gz
-
-RUN tar -C /usr/local -xzf go.tgz 
-
-WORKDIR /usr/local/go/src
-
-RUN chmod +x make.bash
-
-RUN ./make.bash 
-
-ENV PATH="/usr/local/go/bin:$PATH"
-
-ENV GOPATH=/opt/go/ 
-
-ENV PATH=$PATH:$GOPATH/bin 
-
-RUN apk del .build-deps
-
-RUN apk add build-base

+ 0 - 36
docker/Dockerfile-full

@@ -1,36 +0,0 @@
-#first stage - builder
-
-FROM golang:latest as builder
-
-COPY . /app
-
-WORKDIR /app
-
-ENV GO111MODULE=auto
-
-RUN GOARCH=amd64 CGO_ENABLED=1 GOOS=linux go build -ldflags="-w -s" -o app main.go
-
-WORKDIR /app/netclient
-
-ENV GO111MODULE=auto
-
-RUN GOARCH=amd64 CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o netclient main.go
-
-#second stage
-
-FROM debian:latest
-
-RUN apt-get update && apt-get -y install systemd procps
-
-WORKDIR /root/
-
-COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
-
-COPY --from=builder /app .
-COPY --from=builder /app/config config
-COPY --from=builder /app/netclient netclient
-
-EXPOSE 8081
-EXPOSE 50051
-
-CMD ["./app"]

+ 0 - 22
docker/Dockerfile-netclient

@@ -1,22 +0,0 @@
-FROM gravitl/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
-
-FROM alpine:3.15.2
-
-RUN apk add gcompat iptables && mkdir -p /etc/netclient
-# set the working directory
-WORKDIR /root/
-
-COPY --from=builder /app/netclient-app /etc/netclient/netclient
-COPY --from=builder /app/scripts/netclient.sh .
-
-RUN chmod 0755 /etc/netclient/netclient && chmod 0755 netclient.sh
-
-ENTRYPOINT ["./netclient.sh"]

+ 1 - 1
docker/Dockerfile-netclient-doks

@@ -36,4 +36,4 @@ COPY --from=builder /app/netclient-app ./netclient
 COPY --from=builder /app/scripts/netclient.sh .
 RUN chmod 0755 netclient && chmod 0755 netclient.sh
 
-ENTRYPOINT ["/bin/sh", "./netclient.sh"]
+ENTRYPOINT ["/bin/bash", "./netclient.sh"]

+ 1 - 1
docker/Dockerfile-netclient-doks-uspace

@@ -54,4 +54,4 @@ RUN chmod 0755 netclient && chmod 0755 netclient.sh
 
 ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard-go
 
-ENTRYPOINT ["/bin/sh", "./netclient.sh"]
+ENTRYPOINT ["/bin/bash", "./netclient.sh"]

+ 0 - 39
docker/Dockerfile-netclient-full

@@ -1,39 +0,0 @@
-FROM gravitl/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.15.2
-
-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"]

+ 0 - 39
docker/Dockerfile-netclient-kernel

@@ -1,39 +0,0 @@
-FROM debian:buster as builder
-# add glib support daemon manager
-
-RUN apt update -y && apt install -y wget bash gcc musl-dev openssl golang git build-essential libmnl-dev iptables
-
-RUN wget -O go.tgz https://go.dev/dl/go1.18.linux-amd64.tar.gz
-
-RUN tar -C /usr/local -xzf go.tgz
-
-WORKDIR /usr/local/go/src
-
-RUN chmod +x make.bash
-
-RUN ./make.bash
-
-ENV PATH="/usr/local/go/bin:$PATH"
-
-ENV GOPATH=/opt/go/
-
-ENV PATH=$PATH:$GOPATH/bin
-
-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
-
-FROM debian:buster
-
-WORKDIR /root/
-
-RUN apt update -y && apt install -y bash curl wget traceroute procps dnsutils iptables openresolv iproute2
-COPY --from=builder /app/netclient-app ./netclient
-COPY --from=builder /app/scripts/netclient.sh .
-RUN chmod 0755 netclient && chmod 0755 netclient.sh
-
-ENTRYPOINT ["/bin/sh", "./netclient.sh"]

+ 1 - 1
docker/Dockerfile-netclient-multiarch

@@ -19,4 +19,4 @@ COPY --from=builder /app/scripts/netclient.sh .
 RUN chmod 0755 netclient && chmod 0755 netclient.sh
 
 
-ENTRYPOINT ["/bin/sh", "./netclient.sh"]
+ENTRYPOINT ["/bin/bash", "./netclient.sh"]

+ 1 - 1
docker/Dockerfile-netclient-multiarch-go → docker/Dockerfile-netclient-multiarch-userspace

@@ -36,4 +36,4 @@ RUN chmod 0755 netclient && chmod 0755 netclient.sh
 
 ENV WG_QUICK_USERSPACE_IMPLEMENTATION=wireguard-go
 
-ENTRYPOINT ["/bin/sh", "./netclient.sh"]
+ENTRYPOINT ["/bin/bash", "./netclient.sh"]

+ 0 - 26
docker/Dockerfile-netmaker-slim

@@ -1,26 +0,0 @@
-#first stage - builder
-FROM gravitl/builder as builder
-
-WORKDIR /app
-
-COPY . .
-
-ENV GO111MODULE=auto
-
-RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=1 /usr/local/go/bin/go build -ldflags="-w -s" -o netmaker main.go
-
-FROM alpine:3.15.2
-# add a c lib
-RUN apk add gcompat iptables wireguard-tools
-# set the working directory
-WORKDIR /root/
-
-RUN mkdir -p /etc/netclient/config
-
-COPY --from=builder /app/netmaker .
-COPY --from=builder /app/config config
-
-EXPOSE 8081
-EXPOSE 50051
-
-ENTRYPOINT ["./netmaker"]

+ 0 - 26
docker/Dockerfile-userspace

@@ -1,26 +0,0 @@
-ARG NM_VERSION=
-
-FROM gravitl/builder as builder
-
-RUN apk add --update git build-base libmnl-dev iptables
-
-WORKDIR /root/
-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 gravitl/netmaker:${NM_VERSION}
-
-RUN apk add --no-cache --update bash libmnl iptables openresolv iproute2
-COPY --from=builder /usr/bin/wireguard-go /usr/bin/wg* /usr/bin/
-COPY scripts/netclient.sh ./entrypoint.sh
-
-ENTRYPOINT ["/bin/sh", "./entrypoint.sh"]

+ 5 - 6
go.mod

@@ -16,7 +16,7 @@ require (
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.7.1
 	github.com/txn2/txeh v1.3.0
-	github.com/urfave/cli/v2 v2.8.0
+	github.com/urfave/cli/v2 v2.8.1
 	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
@@ -25,24 +25,23 @@ require (
 	golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 // indirect
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220324164955-056925b7df31
 	google.golang.org/protobuf v1.28.0 // indirect
-	gopkg.in/ini.v1 v1.66.4
+	gopkg.in/ini.v1 v1.66.6
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 )
 
 require (
-	filippo.io/edwards25519 v1.0.0-rc.1
+	filippo.io/edwards25519 v1.0.0
 	fyne.io/fyne/v2 v2.1.4
+	github.com/c-robinson/iplib v1.0.3
 	github.com/cloverstd/tcping v0.1.1
 	github.com/guumaster/hostctl v1.1.2
 	github.com/kr/pretty v0.3.0
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
-	github.com/seancfoley/ipaddress-go v1.1.2
 )
 
 require (
 	cloud.google.com/go v0.34.0 // 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/davecgh/go-spew v1.1.1 // indirect
 	github.com/docker/distribution v2.7.1+incompatible // indirect
@@ -73,10 +72,10 @@ require (
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/rogpeppe/go-internal v1.8.0 // indirect
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
-	github.com/seancfoley/bintree v1.0.1 // indirect
 	github.com/spf13/afero v1.3.2 // indirect
 	github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 // indirect
 	github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 // indirect
+	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
 	github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
 	github.com/yuin/goldmark v1.3.8 // indirect
 	golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect

+ 10 - 12
go.sum

@@ -1,8 +1,8 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
-filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
+filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
+filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
 fyne.io/fyne/v2 v2.1.4 h1:bt1+28++kAzRzPB0GM2EuSV4cnl8rXNX4cjfd8G06Rc=
 fyne.io/fyne/v2 v2.1.4/go.mod h1:p+E/Dh+wPW8JwR2DVcsZ9iXgR9ZKde80+Y+40Is54AQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -14,11 +14,11 @@ 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/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/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/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/c-robinson/iplib v1.0.3 h1:NG0UF0GoEsrC1/vyfX1Lx2Ss7CySWl3KqqXh3q4DdPU=
+github.com/c-robinson/iplib v1.0.3/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cloverstd/tcping v0.1.1 h1:3Yp9nvSDI7Z63zoVQDJzVk1PUczrF9tJoOrKGV30iOk=
@@ -200,10 +200,6 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/seancfoley/bintree v1.0.1 h1:rCb5DEugf2B2DtkrxJ80CP6HT24yohDEcXPOqkQRizo=
-github.com/seancfoley/bintree v1.0.1/go.mod h1:CtE6qO6/n9H3V2CAGEC0lpaYr6/OijhNaMG/dt7P70c=
-github.com/seancfoley/ipaddress-go v1.1.2 h1:zeAUfL7foAPe1pIlT2agp17tgpwzU6YKuEAa2VrRKOw=
-github.com/seancfoley/ipaddress-go v1.1.2/go.mod h1:gR/Gr3Sx+pzusadtM9s98e/tZjvL4YnumYTPcKoHWec=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
@@ -242,10 +238,12 @@ 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/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.8.0 h1:EZsAB20oRW4nHcB99TTL6PrXpBGIEujMEKdjwruY9KQ=
-github.com/urfave/cli/v2 v2.8.0/go.mod h1:TYFbtzt/azQoJOrGH5mDfZtS0jIkl/OeFwlRWPR9KRM=
+github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4=
+github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY=
 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/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
+github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -372,8 +370,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/gookit/color.v1 v1.1.6/go.mod h1:IcEkFGaveVShJ+j8ew+jwe9epHyGpJ9IrptHmW3laVY=
-gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
-gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI=
+gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 14 - 12
logger/logger.go

@@ -16,7 +16,7 @@ const TimeFormatDay = "2006-01-02"
 const TimeFormat = "2006-01-02 15:04:05"
 
 // == fields ==
-var currentLogs = make(map[string]string)
+var currentLogs = make(map[string]entry)
 var mu sync.Mutex
 var program string
 
@@ -38,7 +38,10 @@ func Log(verbosity int, message ...string) {
 		fmt.Printf("[%s] %s %s \n", program, currentTime.Format(TimeFormat), currentMessage)
 	}
 	if program == "netmaker" {
-		currentLogs[currentMessage] = currentTime.Format("2006-01-02 15:04:05.999999999")
+		currentLogs[currentMessage] = entry{
+			Time:  currentTime.Format("2006-01-02 15:04:05.999999999"),
+			Count: currentLogs[currentMessage].Count + 1,
+		}
 	}
 }
 
@@ -47,21 +50,23 @@ func Dump() string {
 	if program != "netmaker" {
 		return ""
 	}
+	mu.Lock()
+	defer mu.Unlock()
 	var dumpString = ""
 	type keyVal struct {
 		Key   string
 		Value time.Time
+		Count int
 	}
-	var mu sync.Mutex
-	mu.Lock()
-	defer mu.Unlock()
 	var dumpLogs = make([]keyVal, 0, len(currentLogs))
-	for key, value := range currentLogs {
-		parsedTime, err := time.Parse(TimeFormat, value)
+	for key := range currentLogs {
+		currentEntry := currentLogs[key]
+		parsedTime, err := time.Parse(TimeFormat, currentEntry.Time)
 		if err == nil {
 			dumpLogs = append(dumpLogs, keyVal{
 				Key:   key,
 				Value: parsedTime,
+				Count: currentEntry.Count,
 			})
 		}
 	}
@@ -71,7 +76,7 @@ func Dump() string {
 
 	for i := range dumpLogs {
 		var currLog = dumpLogs[i]
-		dumpString += MakeString(" ", "[netmaker]", currLog.Value.Format(TimeFormat), currLog.Key, "\n")
+		dumpString += MakeString(" ", "[netmaker]", currLog.Value.Format(TimeFormat), currLog.Key, fmt.Sprintf("(%d)", currLog.Count), "\n")
 	}
 
 	resetLogs()
@@ -107,9 +112,6 @@ func Retrieve(filePath string) string {
 
 // FatalLog - exits os after logging
 func FatalLog(message ...string) {
-	var mu sync.Mutex
-	mu.Lock()
-	defer mu.Unlock()
 	fmt.Printf("[netmaker] Fatal: %s \n", MakeString(" ", message...))
 	os.Exit(2)
 }
@@ -118,5 +120,5 @@ func FatalLog(message ...string) {
 
 // resetLogs - reallocates logs map
 func resetLogs() {
-	currentLogs = make(map[string]string)
+	currentLogs = make(map[string]entry)
 }

+ 6 - 0
logger/types.go

@@ -0,0 +1,6 @@
+package logger
+
+type entry struct {
+	Time  string
+	Count int
+}

+ 2 - 6
logic/accesskeys.go

@@ -52,12 +52,8 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
 	netID := network.NetID
 
 	var accessToken models.AccessToken
-	s := servercfg.GetServerConfig()
-	servervals := models.ServerConfig{
-		Server:        s.Server,
-		APIConnString: s.APIConnString,
-	}
-	accessToken.ServerConfig = servervals
+
+	accessToken.APIConnString = servercfg.GetAPIConnString()
 	accessToken.ClientConfig.Network = netID
 	accessToken.ClientConfig.Key = accesskey.Value
 	accessToken.ClientConfig.LocalRange = privAddr

+ 0 - 62
logic/ips/ips.go

@@ -1,62 +0,0 @@
-package ips
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/seancfoley/ipaddress-go/ipaddr"
-)
-
-// GetFirstAddr - gets the first valid address in a given IPv4 CIDR
-func GetFirstAddr(cidr4 string) (*ipaddr.IPAddress, error) {
-	currentCidr := ipaddr.NewIPAddressString(cidr4).GetAddress()
-	if !currentCidr.IsIPv4() {
-		return nil, fmt.Errorf("invalid IPv4 CIDR provided to GetFirstAddr")
-	}
-	lower := currentCidr.GetLower()
-	ipParts := strings.Split(lower.GetNetIPAddr().IP.String(), ".")
-	if ipParts[len(ipParts)-1] == "0" {
-		lower = lower.Increment(1)
-	}
-	return lower, nil
-}
-
-// GetLastAddr - gets the last valid address in a given IPv4 CIDR
-func GetLastAddr(cidr4 string) (*ipaddr.IPAddress, error) {
-	currentCidr := ipaddr.NewIPAddressString(cidr4).GetAddress()
-	if !currentCidr.IsIPv4() {
-		return nil, fmt.Errorf("invalid IPv4 CIDR provided to GetLastAddr")
-	}
-	upper := currentCidr.GetUpper()
-	ipParts := strings.Split(upper.GetNetIPAddr().IP.String(), ".")
-	if ipParts[len(ipParts)-1] == "255" {
-		upper = upper.Increment(-1)
-	}
-	return upper, nil
-}
-
-// GetFirstAddr6 - gets the first valid IPv6 address in a given IPv6 CIDR
-func GetFirstAddr6(cidr6 string) (*ipaddr.IPAddress, error) {
-	currentCidr := ipaddr.NewIPAddressString(cidr6).GetAddress()
-	if !currentCidr.IsIPv6() {
-		return nil, fmt.Errorf("invalid IPv6 CIDR provided to GetFirstAddr6")
-	}
-	lower := currentCidr.GetLower()
-	ipParts := strings.Split(lower.GetNetIPAddr().IP.String(), "::")
-	if len(ipParts) == 2 {
-		if len(ipParts[len(ipParts)-1]) == 0 {
-			lower = lower.Increment(1)
-		}
-	}
-	return lower, nil
-}
-
-// GetLastAddr6 - gets the last valid IPv6 address in a given IPv6 CIDR
-func GetLastAddr6(cidr6 string) (*ipaddr.IPAddress, error) {
-	currentCidr := ipaddr.NewIPAddressString(cidr6).GetAddress()
-	if !currentCidr.IsIPv6() {
-		return nil, fmt.Errorf("invalid IPv6 CIDR provided to GetLastAddr6")
-	}
-	upper := currentCidr.GetUpper()
-	return upper, nil
-}

+ 0 - 50
logic/ips/ips_test.go

@@ -1,50 +0,0 @@
-package ips_test
-
-import (
-	"testing"
-
-	"github.com/gravitl/netmaker/logic/ips"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestIp4(t *testing.T) {
-	const ipv4Cidr = "192.168.0.0/16"
-	const ipv6Cidr = "fde6:be04:fa5e:d076::/64"
-	//delete all current users
-	t.Run("Valid Ipv4", func(t *testing.T) {
-		_, err := ips.GetFirstAddr(ipv4Cidr)
-		assert.Nil(t, err)
-	})
-	t.Run("Invalid Ipv4", func(t *testing.T) {
-		_, err := ips.GetFirstAddr(ipv6Cidr)
-		assert.NotNil(t, err)
-	})
-	t.Run("Valid IPv6", func(t *testing.T) {
-		_, err := ips.GetFirstAddr6(ipv6Cidr)
-		assert.Nil(t, err)
-	})
-	t.Run("Invalid IPv6", func(t *testing.T) {
-		_, err := ips.GetFirstAddr6(ipv4Cidr)
-		assert.NotNil(t, err)
-	})
-	t.Run("Last IPv4", func(t *testing.T) {
-		addr, err := ips.GetLastAddr(ipv4Cidr)
-		assert.Nil(t, err)
-		assert.Equal(t, addr.GetNetIPAddr().IP.String(), "192.168.255.254")
-	})
-	t.Run("First IPv4", func(t *testing.T) {
-		addr, err := ips.GetFirstAddr(ipv4Cidr)
-		assert.Nil(t, err)
-		assert.Equal(t, addr.GetNetIPAddr().IP.String(), "192.168.0.1")
-	})
-	t.Run("Last IPv6", func(t *testing.T) {
-		last, err := ips.GetLastAddr6(ipv6Cidr)
-		assert.Nil(t, err)
-		assert.Equal(t, last.GetNetIPAddr().IP.String(), "fde6:be04:fa5e:d076:ffff:ffff:ffff:ffff")
-	})
-	t.Run("First IPv6", func(t *testing.T) {
-		first, err := ips.GetFirstAddr6(ipv6Cidr)
-		assert.Nil(t, err)
-		assert.Equal(t, first.GetNetIPAddr().IP.String(), "fde6:be04:fa5e:d076::1")
-	})
-}

+ 36 - 32
logic/networks.go

@@ -8,11 +8,11 @@ import (
 	"os/exec"
 	"strings"
 
+	"github.com/c-robinson/iplib"
 	"github.com/go-playground/validator/v10"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic/acls/nodeacls"
-	"github.com/gravitl/netmaker/logic/ips"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/validation"
@@ -185,29 +185,30 @@ func UniqueAddress(networkName string, reverse bool) (string, error) {
 	if network.IsIPv4 == "no" {
 		return "", fmt.Errorf("IPv4 not active on network " + networkName)
 	}
-
-	newAddr, err := ips.GetFirstAddr(network.AddressRange)
-	if err != nil {
+	//ensure AddressRange is valid
+	if _, _, err := net.ParseCIDR(network.AddressRange); err != nil {
 		logger.Log(0, "UniqueAddress encountered  an error")
 		return "666", err
 	}
+	net4 := iplib.Net4FromStr(network.AddressRange)
+	newAddrs := net4.FirstAddress()
 
-	incVal := 1
 	if reverse {
-		incVal = -1
-		newAddr, err = ips.GetLastAddr(network.AddressRange)
-		if err != nil {
-			if err != nil {
-				logger.Log(0, "UniqueAddressServer encountered  an error")
-				return "666", err
-			}
-		}
+		newAddrs = net4.LastAddress()
 	}
 
-	for ; newAddr.ToAddressString().IsValid(); newAddr = newAddr.Increment(int64(incVal)) {
-		if IsIPUnique(networkName, newAddr.GetNetIPAddr().IP.String(), database.NODES_TABLE_NAME, false) &&
-			IsIPUnique(networkName, newAddr.GetNetIPAddr().IP.String(), database.EXT_CLIENT_TABLE_NAME, false) {
-			return newAddr.GetNetIPAddr().IP.String(), nil
+	for {
+		if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) &&
+			IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) {
+			return newAddrs.String(), nil
+		}
+		if reverse {
+			newAddrs, err = net4.PreviousIP(newAddrs)
+		} else {
+			newAddrs, err = net4.NextIP(newAddrs)
+		}
+		if err != nil {
+			break
 		}
 	}
 
@@ -256,27 +257,30 @@ func UniqueAddress6(networkName string, reverse bool) (string, error) {
 		return "", fmt.Errorf("IPv6 not active on network " + networkName)
 	}
 
-	newAddr6, err := ips.GetFirstAddr6(network.AddressRange6)
-	if err != nil {
+	//ensure AddressRange is valid
+	if _, _, err := net.ParseCIDR(network.AddressRange6); err != nil {
 		return "666", err
 	}
+	net6 := iplib.Net6FromStr(network.AddressRange6)
+	newAddrs := net6.FirstAddress()
 
-	incVal := 1
 	if reverse {
-		incVal = -1
-		newAddr6, err = ips.GetLastAddr6(network.AddressRange6)
-		if err != nil {
-			if err != nil {
-				logger.Log(0, "UniqueAddress6Server encountered  an error")
-				return "666", err
-			}
-		}
+		newAddrs = net6.LastAddress()
 	}
 
-	for ; newAddr6.ToAddressString().IsValid(); newAddr6 = newAddr6.Increment(int64(incVal)) {
-		if IsIPUnique(networkName, newAddr6.GetNetIPAddr().IP.String(), database.NODES_TABLE_NAME, true) &&
-			IsIPUnique(networkName, newAddr6.GetNetIPAddr().IP.String(), database.EXT_CLIENT_TABLE_NAME, true) {
-			return newAddr6.GetNetIPAddr().IP.String(), nil
+	for {
+
+		if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) &&
+			IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) {
+			return newAddrs.String(), nil
+		}
+		if reverse {
+			newAddrs, err = net6.PreviousIP(newAddrs)
+		} else {
+			newAddrs, err = net6.NextIP(newAddrs)
+		}
+		if err != nil {
+			break
 		}
 	}
 

+ 2 - 6
logic/nodes.go

@@ -220,16 +220,12 @@ func IsNodeIDUnique(node *models.Node) (bool, error) {
 // ValidateNode - validates node values
 func ValidateNode(node *models.Node, isUpdate bool) error {
 	v := validator.New()
-	_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
+	_ = v.RegisterValidation("id_unique", func(fl validator.FieldLevel) bool {
 		if isUpdate {
 			return true
 		}
-		var unique = true
-		if !(node.MacAddress == "") {
-			unique, _ = isMacAddressUnique(node.MacAddress, node.Network)
-		}
 		isFieldUnique, _ := IsNodeIDUnique(node)
-		return isFieldUnique && unique
+		return isFieldUnique
 	})
 	_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
 		_, err := GetNetworkByNode(node)

+ 92 - 51
logic/peers.go

@@ -8,83 +8,110 @@ import (
 	"strings"
 	"time"
 
+	"github.com/c-robinson/iplib"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/logic/acls/nodeacls"
 	"github.com/gravitl/netmaker/models"
-	"github.com/seancfoley/ipaddress-go/ipaddr"
+	"github.com/gravitl/netmaker/servercfg"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 
-// GetHubPeer - in HubAndSpoke networks, if not the hub, return the hub
-/*
-func GetHubPeer(networkName string) []models.Node {
-	var hubpeer = make([]models.Node, 0)
-	servernodes, err := GetNetworkNodes(networkName)
-	if err != nil {
-		return hubpeer
-	}
-	for i := range servernodes {
-		if servernodes[i].IsHub == "yes" {
-			return []models.Node{servernodes[i]}
-		}
-	}
-	return hubpeer
-}
-*/
-
 // GetNodePeers - fetches peers for a given node
 func GetNodePeers(network *models.Network, nodeid string, excludeRelayed bool, isP2S bool) ([]models.Node, error) {
 	var peers []models.Node
+
+	// networkNodes = all nodes in network
+	// egressNetworkNodes = all egress gateways in network
 	var networkNodes, egressNetworkNodes, err = getNetworkEgressAndNodes(network.NetID)
 	if err != nil {
 		return peers, nil
 	}
 
+	// udppeers = the peers parsed from the local interface
+	// gives us correct port to reach
 	udppeers, errN := database.GetPeers(network.NetID)
 	if errN != nil {
 		logger.Log(2, errN.Error())
 	}
 
+	// gets all the ACL rules
 	currentNetworkACLs, aclErr := nodeacls.FetchAllACLs(nodeacls.NetworkID(network.NetID))
 	if aclErr != nil {
 		return peers, aclErr
 	}
 
+	/*
+		at this point we have 4 lists of node information:
+		- networkNodes: all nodes in network (models.Node)
+		- egressNetworkNodes: all egress gateways in network (models.Node)
+		- udppeers: all peers in database (parsed by server off of active WireGuard interface)
+		- currentNetworkACLs: all ACL rules associated with the network
+		- peers: a currently empty list that will be filled and returned
+
+	*/
+
+	// we now parse through all networkNodes and format properly to set as "peers"
 	for _, node := range networkNodes {
+
+		// skip over any node that is disallowed by ACL rules
 		if !currentNetworkACLs.IsAllowed(acls.AclID(nodeid), acls.AclID(node.ID)) {
 			continue
 		}
 
+		// create an empty model to fill with peer info
 		var peer = models.Node{}
+
+		// set egress gateway information if it's an egress gateway
 		if node.IsEgressGateway == "yes" { // handle egress stuff
 			peer.EgressGatewayRanges = node.EgressGatewayRanges
 			peer.IsEgressGateway = node.IsEgressGateway
 		}
 
+		// set ingress gateway information
 		peer.IsIngressGateway = node.IsIngressGateway
+
+		/*
+			- similar to ACLs, we must determine if peer is allowed based on Relay information
+			- if the nodes is "not relayed" (not behind a relay), it is ok
+			- if the node IS relayed, but excludeRelay has not been marked, it is ok
+			- excludeRelayed is marked for any node that is NOT a Relay Server
+			- therefore, the peer is allowed as long as it is not "relayed", or the node it is being sent to is its relay server
+		*/
 		allow := node.IsRelayed != "yes" || !excludeRelayed
 
+		// confirm conditions allow node to be added as peer
+		// node should be in same network, not pending, and "allowed" based on above logic
 		if node.Network == network.NetID && node.IsPending != "yes" && allow {
+
+			// node info is cleansed to remove sensitive info using setPeerInfo
 			peer = setPeerInfo(&node)
+
+			// Sets ListenPort to UDP Hole Punching Port assuming:
+			// - UDP Hole Punching is enabled
+			// - udppeers retrieval did not return an error
+			// - the endpoint is valid
 			if node.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[node.PublicKey]) {
 				endpointstring := udppeers[node.PublicKey]
 				endpointarr := strings.Split(endpointstring, ":")
 				if len(endpointarr) == 2 {
 					port, err := strconv.Atoi(endpointarr[1])
 					if err == nil {
-						// peer.Endpoint = endpointarr[0]
 						peer.ListenPort = int32(port)
 					}
 				}
 			}
-			// if udp hole punching is on, but port is still set to default (e.g. 51821), use the LocalListenPort
-			// 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 {
+
+			// if udp hole punching is on, but the node's port is still set to default (e.g. 51821), use the LocalListenPort
+			// or, if port is for some reason zero use the LocalListenPort
+			// but only do this if LocalListenPort is not zero
+			if node.UDPHolePunch == "yes" &&
+				((peer.ListenPort == node.ListenPort || peer.ListenPort == 0) && node.LocalListenPort != 0) {
 				peer.ListenPort = node.LocalListenPort
 			}
+
+			// if the node is a relay, append the network cidr and any relayed egress ranges
 			if node.IsRelay == "yes" { // TODO, check if addressrange6 needs to be appended
 				peer.AllowedIPs = append(peer.AllowedIPs, network.AddressRange)
 				for _, egressNode := range egressNetworkNodes {
@@ -93,6 +120,8 @@ func GetNodePeers(network *models.Network, nodeid string, excludeRelayed bool, i
 					}
 				}
 			}
+
+			// if the node is an ingress gateway, append all the extclient allowedips
 			if peer.IsIngressGateway == "yes" { // handle ingress stuff
 				if currentExtClients, err := GetExtPeersList(&node); err == nil {
 					for i := range currentExtClients {
@@ -106,6 +135,7 @@ func GetNodePeers(network *models.Network, nodeid string, excludeRelayed bool, i
 				}
 			}
 
+			// dont appent if this isn't a p2p network or if ACLs disallow
 			if (!isP2S || peer.IsHub == "yes") && currentNetworkACLs.IsAllowed(acls.AclID(nodeid), acls.AclID(node.ID)) {
 				peers = append(peers, peer)
 			}
@@ -133,30 +163,39 @@ func GetPeersList(refnode *models.Node) ([]models.Node, error) {
 	} else if network.IsPointToSite == "yes" && refnode.IsHub != "yes" {
 		isP2S = true
 	}
-	if relayedNodeAddr == "" {
+	if refnode.IsRelayed != "yes" {
+		// if the node is not being relayed, retrieve peers as normal
 		peers, err = GetNodePeers(&network, refnode.ID, excludeRelayed, isP2S)
 	} else {
 		var relayNode models.Node
+		// If this node IS being relayed node, we must first retrieve its relay
 		relayNode, err = GetNodeRelay(networkName, relayedNodeAddr)
-		if relayNode.Address != "" {
+		if relayNode.Address != "" && err == nil {
+			// we must cleanse sensitive info from the relay node
 			var peerNode = setPeerInfo(&relayNode)
-			network, err := GetNetwork(networkName)
-			if err == nil { // TODO: check if addressrange6 needs to be appended
-				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...)
-						}
+
+			// we must append the CIDR to the relay so the relayed node can reach the network
+			peerNode.AllowedIPs = append(peerNode.AllowedIPs, network.AddressRange)
+
+			// we must append the egress ranges to the relay so the relayed node can reach egress
+			var _, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName)
+			if err == nil {
+				for _, egress := range egressNetworkNodes {
+					if egress.Address != relayedNodeAddr {
+						peerNode.AllowedIPs = append(peerNode.AllowedIPs, egress.EgressGatewayRanges...)
 					}
 				}
-			} else {
-				peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...)
 			}
+
+			// get the other peers that are behind the Relay
+			// we dont want to go through the relay to reach them
+			// I'm not sure if this is actually a good call to have this here
+			// may want to test without it, I think it may return bad info
 			nodepeers, err := GetNodePeers(&network, refnode.ID, false, isP2S)
 			if err == nil && peerNode.UDPHolePunch == "yes" {
 				for _, nodepeer := range nodepeers {
+
+					// im not sure if this is good either
 					if nodepeer.Address == peerNode.Address {
 						// peerNode.Endpoint = nodepeer.Endpoint
 						peerNode.ListenPort = nodepeer.ListenPort
@@ -239,6 +278,7 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
 	}
 
 	peerUpdate.Network = node.Network
+	peerUpdate.ServerVersion = servercfg.Version
 	peerUpdate.Peers = peers
 	peerUpdate.ServerAddrs = serverNodeAddresses
 	peerUpdate.DNS = getPeerDNS(node.Network)
@@ -313,29 +353,30 @@ func GetAllowedIPs(node, peer *models.Node) []net.IPNet {
 		}
 		allowedips = append(allowedips, addr6)
 	}
-
 	// handle manually set peers
 	for _, allowedIp := range peer.AllowedIPs {
-		currentAddr := ipaddr.NewIPAddressString(allowedIp).GetAddress()
-		if currentAddr.IsIPv4() {
-			if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil {
-				nodeEndpointArr := strings.Split(node.Endpoint, ":")
-				if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != peer.Address { // don't need to add an allowed ip that already exists..
-					allowedips = append(allowedips, *ipnet)
-				}
-			} else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != peer.Address {
+
+		// parsing as a CIDR first. If valid CIDR, append
+		if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil {
+			nodeEndpointArr := strings.Split(node.Endpoint, ":")
+			if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != peer.Address { // don't need to add an allowed ip that already exists..
+				allowedips = append(allowedips, *ipnet)
+			}
+
+		} else { // parsing as an IP second. If valid IP, check if ipv4 or ipv6, then append
+			if iplib.Version(net.ParseIP(allowedIp)) == 4 && allowedIp != peer.Address {
 				ipnet := net.IPNet{
 					IP:   net.ParseIP(allowedIp),
 					Mask: net.CIDRMask(32, 32),
 				}
 				allowedips = append(allowedips, ipnet)
+			} else if iplib.Version(net.ParseIP(allowedIp)) == 6 && allowedIp != peer.Address6 {
+				ipnet := net.IPNet{
+					IP:   net.ParseIP(allowedIp),
+					Mask: net.CIDRMask(128, 128),
+				}
+				allowedips = append(allowedips, ipnet)
 			}
-		} else if currentAddr.IsIPv6() {
-			ipnet := net.IPNet{
-				IP:   net.ParseIP(allowedIp),
-				Mask: net.CIDRMask(128, 128),
-			}
-			allowedips = append(allowedips, ipnet)
 		}
 	}
 	// handle egress gateway peers

+ 6 - 6
logic/server.go

@@ -10,13 +10,13 @@ import (
 	"strings"
 	"time"
 
+	"github.com/c-robinson/iplib"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/logic/acls/nodeacls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/servercfg"
-	"github.com/seancfoley/ipaddress-go/ipaddr"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
 
@@ -95,7 +95,7 @@ func ServerJoin(networkSettings *models.Network) (models.Node, error) {
 		if node.IsLocal == "yes" && node.LocalAddress != "" {
 			node.Endpoint = node.LocalAddress
 		} else {
-			node.Endpoint, err = ncutils.GetPublicIP()
+			node.Endpoint, err = servercfg.GetPublicIP()
 		}
 		if err != nil || node.Endpoint == "" {
 			logger.Log(0, "Error setting server node Endpoint.")
@@ -261,8 +261,7 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
 
 		// handle manually set peers
 		for _, allowedIp := range node.AllowedIPs {
-			currentIP := ipaddr.NewIPAddressString(allowedIp).GetAddress()
-			if currentIP.IsIPv4() {
+			if iplib.Version(net.ParseIP(allowedIp)) == 4 {
 				if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil {
 					nodeEndpointArr := strings.Split(node.Endpoint, ":")
 					if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != node.Address { // don't need to add an allowed ip that already exists..
@@ -275,9 +274,10 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
 					}
 					allowedips = append(allowedips, ipnet)
 				}
-			} else if currentIP.IsIPv6() {
+			} else if iplib.Version(net.ParseIP(allowedIp)) == 6 {
+				//ipnet : = iplib.Net6FromStr(allowedIp).IP()
 				ipnet := net.IPNet{
-					IP:   currentIP.GetNetIP(),
+					IP:   iplib.Net6FromStr(allowedIp).IP(),
 					Mask: net.CIDRMask(128, 128),
 				}
 				allowedips = append(allowedips, ipnet)

+ 1 - 1
logic/telemetry.go

@@ -95,7 +95,7 @@ func getClientCount(nodes []models.Node) clientCount {
 	var count clientCount
 	for _, node := range nodes {
 		switch node.OS {
-		case "macos":
+		case "darwin":
 			count.MacOS += 1
 		case "windows":
 			count.Windows += 1

+ 3 - 2
logic/timer.go

@@ -29,9 +29,10 @@ func TimerCheckpoint() error {
 	if enoughTimeElapsed {
 		// run any time hooks
 		runHooks()
+		return setTelemetryTimestamp(&telRecord)
+
 	}
-	// set telemetry timestamp for server, restarts 24 hour cycle
-	return setTelemetryTimestamp(&telRecord)
+	return nil
 }
 
 // AddHook - adds a hook function to run every 24hrs

+ 1 - 0
logic/util.go

@@ -115,6 +115,7 @@ func RandomString(length int) string {
 
 // == Private Methods ==
 
+// getNetworkEgressAndNodes - returns two slices, #1 is all nodes in the network, #2 is the egress nodes in the network
 func getNetworkEgressAndNodes(networkName string) ([]models.Node, []models.Node, error) {
 	var networkNodes, egressNetworkNodes []models.Node
 	collection, err := database.FetchRecords(database.NODES_TABLE_NAME)

+ 1 - 6
models/accessToken.go

@@ -1,7 +1,7 @@
 package models
 
 type AccessToken struct {
-	ServerConfig
+	APIConnString string `json:"apiconnstring"`
 	ClientConfig
 }
 
@@ -10,8 +10,3 @@ type ClientConfig struct {
 	Key        string `json:"key"`
 	LocalRange string `json:"localrange"`
 }
-
-type ServerConfig struct {
-	Server        string `json:"server"`
-	APIConnString string `json:"apiconnstring"`
-}

+ 5 - 4
models/mqtt.go

@@ -4,10 +4,11 @@ import "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 
 // PeerUpdate - struct
 type PeerUpdate struct {
-	Network     string               `json:"network" bson:"network" yaml:"network"`
-	ServerAddrs []ServerAddr         `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"`
-	Peers       []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"`
-	DNS         string               `json:"dns" bson:"dns" yaml:"dns"`
+	Network       string               `json:"network" bson:"network" yaml:"network"`
+	ServerVersion string               `json:"serverversion" bson:"serverversion" yaml:"serverversion"`
+	ServerAddrs   []ServerAddr         `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"`
+	Peers         []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"`
+	DNS           string               `json:"dns" bson:"dns" yaml:"dns"`
 }
 
 // KeyUpdate - key update struct

+ 2 - 2
models/node.go

@@ -35,7 +35,7 @@ var seededRand *rand.Rand = rand.New(
 
 // Node - struct for node model
 type Node struct {
-	ID                  string   `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5"`
+	ID                  string   `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5" validate:"id_unique`
 	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"`
@@ -56,7 +56,7 @@ type Node struct {
 	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"`
+	MacAddress          string   `json:"macaddress" bson:"macaddress" yaml:"macaddress"`
 	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"`

+ 15 - 2
models/structs.go

@@ -190,6 +190,19 @@ type TrafficKeys struct {
 
 // NodeGet - struct for a single node get response
 type NodeGet struct {
-	Node  Node                 `json:"node" bson:"node" yaml:"node"`
-	Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"`
+	Node         Node                 `json:"node" bson:"node" yaml:"node"`
+	Peers        []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"`
+	ServerConfig ServerConfig         `json:"serverconfig" bson:"serverconfig" yaml:"serverconfig"`
+}
+
+// ServerConfig - struct for dealing with the server information for a netclient
+type ServerConfig struct {
+	CoreDNSAddr string `yaml:"corednsaddr"`
+	API         string `yaml:"apihost"`
+	APIPort     string `yaml:"apiport"`
+	ClientMode  string `yaml:"clientmode"`
+	DNSMode     string `yaml:"dnsmode"`
+	Version     string `yaml:"version"`
+	MQPort      string `yaml:"mqport"`
+	Server      string `yaml:"server"`
 }

+ 1 - 0
mq/publishers.go

@@ -103,6 +103,7 @@ func sendPeers() {
 		if servercfg.ManageIPTables() != "off" {
 			serverctl.InitIPTables(false)
 		}
+		servercfg.SetHost()
 
 		force = true
 		peer_force_send = 0

+ 31 - 23
netclient/config/config.go

@@ -1,8 +1,6 @@
 package config
 
 import (
-	//"github.com/davecgh/go-spew/spew"
-
 	"crypto/ed25519"
 	"crypto/x509"
 	"crypto/x509/pkix"
@@ -25,20 +23,13 @@ var (
 
 // ClientConfig - struct for dealing with client configuration
 type ClientConfig struct {
-	Server          ServerConfig   `yaml:"server"`
-	Node            models.Node    `yaml:"node"`
-	NetworkSettings models.Network `yaml:"networksettings"`
-	Network         string         `yaml:"network"`
-	Daemon          string         `yaml:"daemon"`
-	OperatingSystem string         `yaml:"operatingsystem"`
-}
-
-// ServerConfig - struct for dealing with the server information for a netclient
-type ServerConfig struct {
-	CoreDNSAddr string `yaml:"corednsaddr"`
-	AccessKey   string `yaml:"accesskey"`
-	Server      string `yaml:"server"`
-	API         string `yaml:"api"`
+	Server          models.ServerConfig `yaml:"server"`
+	Node            models.Node         `yaml:"node"`
+	NetworkSettings models.Network      `yaml:"networksettings"`
+	Network         string              `yaml:"network"`
+	Daemon          string              `yaml:"daemon"`
+	OperatingSystem string              `yaml:"operatingsystem"`
+	AccessKey       string              `yaml:"accesskey"`
 }
 
 // RegisterRequest - struct for registation with netmaker server
@@ -53,6 +44,8 @@ type RegisterResponse struct {
 	CAPubKey   ed25519.PublicKey
 	Cert       x509.Certificate
 	CertPubKey ed25519.PublicKey
+	Broker     string
+	Port       string
 }
 
 // Write - writes the config of a client to disk
@@ -127,8 +120,8 @@ func (config *ClientConfig) ReadConfig() {
 	}
 }
 
-// ModConfig - overwrites the node inside client config on disk
-func ModConfig(node *models.Node) error {
+// ModNodeConfig - overwrites the node inside client config on disk
+func ModNodeConfig(node *models.Node) error {
 	network := node.Network
 	if network == "" {
 		return errors.New("no network provided")
@@ -147,6 +140,21 @@ func ModConfig(node *models.Node) error {
 	return Write(&modconfig, network)
 }
 
+// ModNodeConfig - overwrites the server settings inside client config on disk
+func ModServerConfig(scfg *models.ServerConfig, network string) error {
+	var modconfig ClientConfig
+	if FileExists(ncutils.GetNetclientPathSpecific() + "netconfig-" + network) {
+		useconfig, err := ReadConfig(network)
+		if err != nil {
+			return err
+		}
+		modconfig = *useconfig
+	}
+
+	modconfig.Server = (*scfg)
+	return Write(&modconfig, network)
+}
+
 // SaveBackup - saves a backup file of a given network
 func SaveBackup(network string) error {
 
@@ -195,12 +203,12 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 		}
 		cfg.Network = accesstoken.ClientConfig.Network
 		cfg.Node.Network = accesstoken.ClientConfig.Network
-		cfg.Server.AccessKey = accesstoken.ClientConfig.Key
+		cfg.AccessKey = accesstoken.ClientConfig.Key
 		cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange
-		cfg.Server.Server = accesstoken.ServerConfig.Server
-		cfg.Server.API = accesstoken.ServerConfig.APIConnString
+		//cfg.Server.Server = accesstoken.ServerConfig.Server
+		cfg.Server.API = accesstoken.APIConnString
 		if c.String("key") != "" {
-			cfg.Server.AccessKey = c.String("key")
+			cfg.AccessKey = c.String("key")
 		}
 		if c.String("network") != "all" {
 			cfg.Network = c.String("network")
@@ -216,7 +224,7 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 			cfg.Server.API = c.String("apiserver")
 		}
 	} else {
-		cfg.Server.AccessKey = c.String("key")
+		cfg.AccessKey = c.String("key")
 		cfg.Network = c.String("network")
 		cfg.Node.Network = c.String("network")
 		cfg.Node.LocalRange = c.String("localrange")

+ 36 - 0
netclient/functions/common.go

@@ -373,3 +373,39 @@ func Authenticate(cfg *config.ClientConfig) (string, error) {
 	token := tokenData["AuthToken"]
 	return token.(string), nil
 }
+
+// RegisterWithServer calls the register endpoint with privatekey and commonname - api returns ca and client certificate
+func SetServerInfo(cfg *config.ClientConfig) error {
+	cfg, err := config.ReadConfig(cfg.Network)
+	if err != nil {
+		return err
+	}
+	url := "https://" + cfg.Server.API + "/api/server/getserverinfo"
+	logger.Log(1, "server at "+url)
+
+	token, err := Authenticate(cfg)
+	if err != nil {
+		return err
+	}
+	response, err := API("", http.MethodGet, url, token)
+	if err != nil {
+		return err
+	}
+	if response.StatusCode != http.StatusOK {
+		return errors.New(response.Status)
+	}
+	var resp models.ServerConfig
+	if err := json.NewDecoder(response.Body).Decode(&resp); err != nil {
+		return errors.New("unmarshal cert error " + err.Error())
+	}
+
+	// set broker information on register
+	cfg.Server.Server = resp.Server
+	cfg.Server.MQPort = resp.MQPort
+
+	if err = config.ModServerConfig(&cfg.Server, cfg.Node.Network); err != nil {
+		logger.Log(0, "error overwriting config with broker information: "+err.Error())
+	}
+
+	return nil
+}

+ 17 - 12
netclient/functions/daemon.go

@@ -209,7 +209,8 @@ func NewTLSConfig(server string) *tls.Config {
 func setupMQTT(cfg *config.ClientConfig, publish bool) (mqtt.Client, error) {
 	opts := mqtt.NewClientOptions()
 	server := cfg.Server.Server
-	opts.AddBroker("ssl://" + server + ":8883") // TODO get the appropriate port of the comms mq server
+	port := cfg.Server.MQPort
+	opts.AddBroker("ssl://" + server + ":" + port)
 	opts.SetTLSConfig(NewTLSConfig(server))
 	opts.SetClientID(ncutils.MakeRandomString(23))
 	opts.SetDefaultPublishHandler(All)
@@ -247,26 +248,30 @@ func setupMQTT(cfg *config.ClientConfig, publish bool) (mqtt.Client, error) {
 		} else {
 			err = token.Error()
 		}
-		if err := checkBroker(cfg.Server.Server); err != nil {
+		if err := checkBroker(cfg.Server.Server, cfg.Server.MQPort); err != nil {
 			return nil, err
 		}
 		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") {
-			logger.Log(0, "connection issue detected.. attempt connection with new certs")
-			key, err := ssl.ReadKey(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
-			if err != nil {
-				_, *key, err = ed25519.GenerateKey(rand.Reader)
-				if err != nil {
-					log.Fatal("could not generate new key")
-				}
-			}
-			RegisterWithServer(key, cfg)
-			daemon.Restart()
+			reRegisterWithServer(cfg)
 		}
 	}
 	return client, nil
 }
 
+func reRegisterWithServer(cfg *config.ClientConfig) {
+	logger.Log(0, "connection issue detected.. attempt connection with new certs and broker information")
+	key, err := ssl.ReadKey(ncutils.GetNetclientPath() + ncutils.GetSeparator() + "client.key")
+	if err != nil {
+		_, *key, err = ed25519.GenerateKey(rand.Reader)
+		if err != nil {
+			log.Fatal("could not generate new key")
+		}
+	}
+	RegisterWithServer(key, cfg)
+	daemon.Restart()
+}
+
 // publishes a message to server to update peers on this peer's behalf
 func publishSignal(nodeCfg *config.ClientConfig, signal byte) error {
 	if err := publish(nodeCfg, fmt.Sprintf("signal/%s", nodeCfg.Node.ID), []byte{signal}, 1); err != nil {

+ 16 - 27
netclient/functions/join.go

@@ -42,10 +42,9 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	if cfg.Node.Password == "" {
 		cfg.Node.Password = logic.GenKey()
 	}
-	manualPort := false
+	//check if ListenPort was set on command line
 	if cfg.Node.ListenPort != 0 {
 		cfg.Node.UDPHolePunch = "no"
-		manualPort = true
 	}
 	var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys
 	if errT != nil {
@@ -120,12 +119,12 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	cfg.Node.Name = formatName(cfg.Node)
 	cfg.Node.OS = runtime.GOOS
 	cfg.Node.Version = ncutils.Version
-	cfg.Node.AccessKey = cfg.Server.AccessKey
+	cfg.Node.AccessKey = cfg.AccessKey
 	//not sure why this is needed ... setnode defaults should take care of this on server
 	cfg.Node.IPForwarding = "yes"
 	logger.Log(0, "joining "+cfg.Network+" at "+cfg.Server.API)
 	url := "https://" + cfg.Server.API + "/api/nodes/" + cfg.Network
-	response, err := API(cfg.Node, http.MethodPost, url, cfg.Server.AccessKey)
+	response, err := API(cfg.Node, http.MethodPost, url, cfg.AccessKey)
 	if err != nil {
 		return fmt.Errorf("error creating node %w", err)
 	}
@@ -144,6 +143,7 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	if nodeGET.Peers == nil {
 		nodeGET.Peers = []wgtypes.PeerConfig{}
 	}
+
 	// safety check. If returned node from server is local, but not currently configured as local, set to local addr
 	if cfg.Node.IsLocal != "yes" && node.IsLocal == "yes" && node.LocalRange != "" {
 		node.LocalAddress, err = ncutils.GetLocalIP(node.LocalRange)
@@ -156,6 +156,7 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 		node.UDPHolePunch = "no"
 		cfg.Node.IsStatic = "yes"
 	}
+	cfg.Server = nodeGET.ServerConfig
 
 	err = wireguard.StorePrivKey(privateKey, cfg.Network)
 	if err != nil {
@@ -170,11 +171,11 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	}
 	logger.Log(1, "node created on remote server...updating configs")
 	cfg.Node = node
-	logger.Log(1, "turn on UDP hole punching (dynamic port setting)? "+cfg.Node.UDPHolePunch)
-	if !manualPort && (cfg.Node.UDPHolePunch == "no") {
-		setListenPort(cfg)
+	err = config.ModNodeConfig(&cfg.Node)
+	if err != nil {
+		return err
 	}
-	err = config.ModConfig(&cfg.Node)
+	err = config.ModServerConfig(&cfg.Server, node.Network)
 	if err != nil {
 		return err
 	}
@@ -190,8 +191,13 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	if err := Register(cfg, privateKey); err != nil {
 		return err
 	}
-
-	_ = UpdateLocalListenPort(cfg)
+	if cfg.Server.Server == "" {
+		return errors.New("did not recieve broker address from registration")
+	}
+	// update server with latest data
+	if err := PublishNodeUpdate(cfg); err != nil {
+		logger.Log(0, "failed to publish update for join", err.Error())
+	}
 
 	if cfg.Daemon == "install" || ncutils.IsFreeBSD() {
 		err = daemon.InstallDaemon(cfg)
@@ -220,20 +226,3 @@ func formatName(node models.Node) string {
 	}
 	return node.Name
 }
-
-func setListenPort(cfg *config.ClientConfig) {
-	// keep track of the returned listenport value
-	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 has been modified to find an available port, publish to server
-	if cfg.Node.ListenPort != newListenPort {
-		PublishNodeUpdate(cfg)
-	}
-}

+ 1 - 1
netclient/functions/localport.go

@@ -39,7 +39,7 @@ func UpdateLocalListenPort(nodeCfg *config.ClientConfig) error {
 	} else if nodeCfg.Node.LocalListenPort != localPort && localPort != 0 {
 		logger.Log(1, "local port has changed from ", strconv.Itoa(int(nodeCfg.Node.LocalListenPort)), " to ", strconv.Itoa(int(localPort)))
 		nodeCfg.Node.LocalListenPort = localPort
-		err = config.ModConfig(&nodeCfg.Node)
+		err = config.ModNodeConfig(&nodeCfg.Node)
 		if err != nil {
 			return err
 		}

+ 1 - 1
netclient/functions/localport_freebsd.go

@@ -38,7 +38,7 @@ func UpdateLocalListenPort(nodeCfg *config.ClientConfig) error {
 	} else if nodeCfg.Node.LocalListenPort != localPort && localPort != 0 {
 		logger.Log(1, "local port has changed from ", strconv.Itoa(int(nodeCfg.Node.LocalListenPort)), " to ", strconv.Itoa(int(localPort)))
 		nodeCfg.Node.LocalListenPort = localPort
-		err = config.ModConfig(&nodeCfg.Node)
+		err = config.ModNodeConfig(&nodeCfg.Node)
 		if err != nil {
 			return err
 		}

+ 12 - 3
netclient/functions/mqhandlers.go

@@ -149,7 +149,7 @@ func NodeUpdate(client mqtt.Client, msg mqtt.Message) {
 	//deal with DNS
 	if newNode.DNSOn != "yes" && shouldDNSChange && nodeCfg.Node.Interface != "" {
 		logger.Log(0, "settng DNS off")
-		if err := removeHostDNS(nodeCfg.Network, ncutils.IsWindows()); err != nil {
+		if err := removeHostDNS(nodeCfg.Node.Interface, ncutils.IsWindows()); err != nil {
 			logger.Log(0, "error removing netmaker profile from /etc/hosts "+err.Error())
 		}
 		//		_, err := ncutils.RunCmd("/usr/bin/resolvectl revert "+nodeCfg.Node.Interface, true)
@@ -183,6 +183,15 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) {
 		return
 	}
 	insert(peerUpdate.Network, lastPeerUpdate, string(data))
+	// check version
+	if peerUpdate.ServerVersion != ncutils.Version {
+		logger.Log(0, "server/client version mismatch server: ", peerUpdate.ServerVersion, " client: ", ncutils.Version)
+	}
+	if peerUpdate.ServerVersion != cfg.Server.Version {
+		logger.Log(1, "updating server version")
+		cfg.Server.Version = peerUpdate.ServerVersion
+		config.Write(&cfg, cfg.Network)
+	}
 
 	file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf"
 	err = wireguard.UpdateWgPeers(file, peerUpdate.Peers)
@@ -208,12 +217,12 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) {
 	}
 	logger.Log(0, "received peer update for node "+cfg.Node.Name+" "+cfg.Node.Network)
 	if cfg.Node.DNSOn == "yes" {
-		if err := setHostDNS(peerUpdate.DNS, cfg.Node.Network, ncutils.IsWindows()); err != nil {
+		if err := setHostDNS(peerUpdate.DNS, cfg.Node.Interface, ncutils.IsWindows()); err != nil {
 			logger.Log(0, "error updating /etc/hosts "+err.Error())
 			return
 		}
 	} else {
-		if err := removeHostDNS(cfg.Node.Network, ncutils.IsWindows()); err != nil {
+		if err := removeHostDNS(cfg.Node.Interface, ncutils.IsWindows()); err != nil {
 			logger.Log(0, "error removing profile from /etc/hosts "+err.Error())
 			return
 		}

+ 16 - 2
netclient/functions/mqpublish.go

@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"net"
 	"os"
+	"strconv"
 	"sync"
 	"time"
 
@@ -14,6 +15,7 @@ import (
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/netclient/auth"
 	"github.com/gravitl/netmaker/netclient/config"
+	"github.com/gravitl/netmaker/netclient/daemon"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/tls"
 )
@@ -106,6 +108,8 @@ func Hello(nodeCfg *config.ClientConfig) {
 		_, err := Pull(nodeCfg.Node.Network, true)
 		if err != nil {
 			logger.Log(0, "could not run pull on "+nodeCfg.Node.Network+", error: "+err.Error())
+		} else {
+			daemon.Restart()
 		}
 	}
 	logger.Log(3, "checkin for", nodeCfg.Network, "complete")
@@ -164,16 +168,26 @@ func checkCertExpiry(cfg *config.ClientConfig) error {
 	return nil
 }
 
-func checkBroker(broker string) error {
+func checkBroker(broker string, port string) error {
+	if broker == "" {
+		return errors.New("error: broker address is blank")
+	}
+	if port == "" {
+		return errors.New("error: broker port is blank")
+	}
 	_, err := net.LookupIP(broker)
 	if err != nil {
 		return errors.New("nslookup failed for broker ... check dns records")
 	}
 	pinger := ping.NewTCPing()
+	intPort, err := strconv.Atoi(port)
+	if err != nil {
+		logger.Log(1, "error converting port to int: "+err.Error())
+	}
 	pinger.SetTarget(&ping.Target{
 		Protocol: ping.TCP,
 		Host:     broker,
-		Port:     8883,
+		Port:     intPort,
 		Counter:  3,
 		Interval: 1 * time.Second,
 		Timeout:  2 * time.Second,

+ 7 - 2
netclient/functions/pull.go

@@ -57,9 +57,13 @@ func Pull(network string, iface bool) (*models.Node, error) {
 	if nodeGET.Peers == nil {
 		nodeGET.Peers = []wgtypes.PeerConfig{}
 	}
-
+	if nodeGET.ServerConfig.API != "" && nodeGET.ServerConfig.MQPort != "" {
+		if err = config.ModServerConfig(&nodeGET.ServerConfig, resNode.Network); err != nil {
+			logger.Log(0, "unable to update server config: "+err.Error())
+		}
+	}
 	if iface {
-		if err = config.ModConfig(&resNode); err != nil {
+		if err = config.ModNodeConfig(&resNode); err != nil {
 			return nil, err
 		}
 		if err = wireguard.SetWGConfig(network, false, nodeGET.Peers[:]); err != nil {
@@ -78,5 +82,6 @@ func Pull(network string, iface bool) (*models.Node, error) {
 	if bkupErr != nil {
 		logger.Log(0, "unable to update backup file")
 	}
+
 	return &resNode, err
 }

+ 18 - 10
netclient/functions/register.go

@@ -16,12 +16,7 @@ import (
 
 // Register - the function responsible for registering with the server and acquiring certs
 func Register(cfg *config.ClientConfig, key string) error {
-	if cfg.Server.Server == "" {
-		return errors.New("no server provided")
-	}
-	if cfg.Server.AccessKey == "" {
-		return errors.New("no access key provided")
-	}
+
 	//generate new key if one doesn' exist
 	var private *ed25519.PrivateKey
 	var err error
@@ -50,10 +45,6 @@ func Register(cfg *config.ClientConfig, key string) error {
 
 // RegisterWithServer calls the register endpoint with privatekey and commonname - api returns ca and client certificate
 func RegisterWithServer(private *ed25519.PrivateKey, cfg *config.ClientConfig) error {
-	cfg, err := config.ReadConfig(cfg.Network)
-	if err != nil {
-		return err
-	}
 	data := config.RegisterRequest{
 		Key:        *private,
 		CommonName: tls.NewCName(cfg.Node.Name),
@@ -76,6 +67,23 @@ func RegisterWithServer(private *ed25519.PrivateKey, cfg *config.ClientConfig) e
 	if err := json.NewDecoder(response.Body).Decode(&resp); err != nil {
 		return errors.New("unmarshal cert error " + err.Error())
 	}
+
+	// set broker information on register
+	var modServer bool
+	if resp.Broker != "" && resp.Broker != cfg.Server.Server {
+		cfg.Server.Server = resp.Broker
+		modServer = true
+	}
+	if resp.Port != "" && resp.Port != cfg.Server.MQPort {
+		cfg.Server.MQPort = resp.Port
+		modServer = true
+	}
+	if modServer {
+		if err = config.ModServerConfig(&cfg.Server, cfg.Node.Network); err != nil {
+			logger.Log(0, "error overwriting config with broker information: "+err.Error())
+		}
+	}
+
 	//x509.Certificate.PublicKey is an interface so json encoding/decoding results in a string rather that []byte
 	//the pubkeys are included in the response so the values in the certificate can be updated appropriately
 	resp.CA.PublicKey = resp.CAPubKey

+ 2 - 3
netclient/gui/components/views/join.go

@@ -29,10 +29,9 @@ func GetJoinView() fyne.CanvasObject {
 		cfg.Network = accesstoken.ClientConfig.Network
 		cfg.Node.Network = accesstoken.ClientConfig.Network
 		cfg.Node.Name = ncutils.GetHostname()
-		cfg.Server.AccessKey = accesstoken.ClientConfig.Key
+		cfg.AccessKey = accesstoken.ClientConfig.Key
 		cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange
-		cfg.Server.Server = accesstoken.ServerConfig.Server
-		cfg.Server.API = accesstoken.ServerConfig.APIConnString
+		cfg.Server.API = accesstoken.APIConnString
 		err = functions.JoinNetwork(&cfg, "")
 		if err != nil {
 			ErrorNotify("Failed to join " + cfg.Network + "!")

+ 3 - 4
netclient/local/routes_darwin.go

@@ -4,9 +4,9 @@ import (
 	"net"
 	"strings"
 
+	"github.com/c-robinson/iplib"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/netclient/ncutils"
-	"github.com/seancfoley/ipaddress-go/ipaddr"
 )
 
 // route -n add -net 10.0.0.0/8 192.168.0.254
@@ -35,10 +35,9 @@ func deleteRoute(iface string, addr *net.IPNet, address string) error {
 }
 
 func setCidr(iface, address string, addr *net.IPNet) {
-	cidr := ipaddr.NewIPAddressString(addr.String()).GetAddress()
-	if cidr.IsIPv4() {
+	if iplib.Version(addr.IP) == 4 {
 		ncutils.RunCmd("route -q -n add -net "+addr.String()+" "+address, false)
-	} else if cidr.IsIPv6() {
+	} else if iplib.Version(addr.IP) == 6 {
 		ncutils.RunCmd("route -A inet6 -q -n add -net "+addr.String()+" "+address, false)
 	} else {
 		logger.Log(1, "could not parse address: "+addr.String())

+ 3 - 4
netclient/local/routes_freebsd.go

@@ -3,9 +3,9 @@ package local
 import (
 	"net"
 
+	"github.com/c-robinson/iplib"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/netclient/ncutils"
-	"github.com/seancfoley/ipaddress-go/ipaddr"
 )
 
 func setRoute(iface string, addr *net.IPNet, address string) error {
@@ -21,10 +21,9 @@ func deleteRoute(iface string, addr *net.IPNet, address string) error {
 }
 
 func setCidr(iface, address string, addr *net.IPNet) {
-	cidr := ipaddr.NewIPAddressString(addr.String()).GetAddress()
-	if cidr.IsIPv4() {
+	if iplib.Version(addr.IP) == 4 {
 		ncutils.RunCmd("route add -net "+addr.String()+" -interface "+iface, false)
-	} else if cidr.IsIPv6() {
+	} else if iplib.Version(addr.IP) == 6 {
 		ncutils.RunCmd("route add -net -inet6 "+addr.String()+" -interface "+iface, false)
 	} else {
 		logger.Log(1, "could not parse address: "+addr.String())

+ 3 - 4
netclient/local/routes_linux.go

@@ -7,9 +7,9 @@ import (
 	"net"
 	"strings"
 
+	"github.com/c-robinson/iplib"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/netclient/ncutils"
-	"github.com/seancfoley/ipaddress-go/ipaddr"
 )
 
 func setRoute(iface string, addr *net.IPNet, address string) error {
@@ -30,10 +30,9 @@ func deleteRoute(iface string, addr *net.IPNet, address string) error {
 }
 
 func setCidr(iface, address string, addr *net.IPNet) {
-	cidr := ipaddr.NewIPAddressString(addr.String()).GetAddress()
-	if cidr.IsIPv4() {
+	if iplib.Version(addr.IP) == 4 {
 		ncutils.RunCmd("ip -4 route add "+addr.String()+" dev "+iface, false)
-	} else if cidr.IsIPv6() {
+	} else if iplib.Version(addr.IP) == 6 {
 		ncutils.RunCmd("ip -6 route add "+addr.String()+" dev "+iface, false)
 	} else {
 		logger.Log(1, "could not parse address: "+addr.String())

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

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

+ 3 - 3
netclient/versioninfo.json

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

+ 11 - 8
netclient/wireguard/common.go

@@ -135,14 +135,14 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		return err
 	}
 	defer wgclient.Close()
-	modcfg, err := config.ReadConfig(node.Network)
+	cfg, err := config.ReadConfig(node.Network)
 	if err != nil {
 		return err
 	}
-	nodecfg := modcfg.Node
+	//nodecfg := modcfg.Node
 	var ifacename string
-	if nodecfg.Interface != "" {
-		ifacename = nodecfg.Interface
+	if cfg.Node.Interface != "" {
+		ifacename = cfg.Node.Interface
 	} else if node.Interface != "" {
 		ifacename = node.Interface
 	} else {
@@ -151,11 +151,14 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 	if node.PrimaryAddress() == "" {
 		return fmt.Errorf("no address to configure")
 	}
-
+	logger.Log(1, "turn on UDP hole punching (dynamic port setting)? "+cfg.Node.UDPHolePunch)
 	if node.UDPHolePunch == "yes" {
 		node.ListenPort = 0
+	} else {
+		//get available port based on current default
+		node.ListenPort, err = ncutils.GetFreePort(node.ListenPort)
 	}
-	if err := WriteWgConfig(&modcfg.Node, key.String(), peers); err != nil {
+	if err := WriteWgConfig(&cfg.Node, key.String(), peers); err != nil {
 		logger.Log(1, "error writing wg conf file: ", err.Error())
 		return err
 	}
@@ -216,7 +219,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 
 	//ipv4
 	if node.Address != "" {
-		_, cidr, cidrErr := net.ParseCIDR(modcfg.NetworkSettings.AddressRange)
+		_, cidr, cidrErr := net.ParseCIDR(cfg.NetworkSettings.AddressRange)
 		if cidrErr == nil {
 			local.SetCIDRRoute(ifacename, node.Address, cidr)
 		} else {
@@ -226,7 +229,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 	}
 	if node.Address6 != "" {
 		//ipv6
-		_, cidr, cidrErr := net.ParseCIDR(modcfg.NetworkSettings.AddressRange6)
+		_, cidr, cidrErr := net.ParseCIDR(cfg.NetworkSettings.AddressRange6)
 		if cidrErr == nil {
 			local.SetCIDRRoute(ifacename, node.Address6, cidr)
 		} else {

+ 16 - 3
scripts/netclient.sh

@@ -1,4 +1,16 @@
-#!/bin/sh
+#!/bin/bash
+
+#Define cleanup
+cleanup() {
+    nets=($(wg show interfaces))
+    for net in ${nets[@]}; do
+        echo "deleting interface" $net
+        ip link del $net
+    done
+}
+
+#Trap SigTerm
+trap 'cleanup' SIGTERM
 
 echo "[netclient] joining network"
 
@@ -11,11 +23,12 @@ if [ "$TOKEN" != "" ]; then
     TOKEN_CMD="-t $TOKEN"
 fi
 
-/root/netclient join $TOKEN_CMD -daemon off -dnson no -udpholepunch no
+/root/netclient join $TOKEN_CMD -dnson no -udpholepunch no
 if [ $? -ne 0 ]; then { echo "Failed to join, quitting." ; exit 1; } fi
 
 echo "[netclient] Starting netclient daemon"
 
-/root/netclient daemon
+/root/netclient daemon &
 
+wait $!
 echo "[netclient] exiting"

+ 9 - 14
scripts/nm-quick.sh

@@ -125,14 +125,6 @@ echo "   ----------------------------"
 
 sleep 5
 
-
-echo "setting caddyfile..."
-
-
-wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/master/docker/Caddyfile
-sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile
-sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile
-
 echo "setting mosquitto.conf..."
 
 wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/master/docker/mosquitto.conf
@@ -141,11 +133,12 @@ echo "setting docker-compose..."
 
 mkdir -p /etc/netmaker
 
-wget -q -O /root/docker-compose.yml https://raw.githubusercontent.com/gravitl/netmaker/master/compose/docker-compose.contained.yml
+wget -q -O /root/docker-compose.yml https://raw.githubusercontent.com/gravitl/netmaker/master/compose/docker-compose.traefik.yml
 sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml
 sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/docker-compose.yml
 sed -i "s/COREDNS_IP/$COREDNS_IP/g" /root/docker-compose.yml
 sed -i "s/REPLACE_MASTER_KEY/$MASTER_KEY/g" /root/docker-compose.yml
+sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/docker-compose.yml
 
 echo "starting containers..."
 
@@ -170,22 +163,22 @@ cat << "EOF"
 EOF
 
 
-echo "visit dashboard.$NETMAKER_BASE_DOMAIN to log in"
-sleep 2
+echo "visit https://dashboard.$NETMAKER_BASE_DOMAIN to log in"
+sleep 7
 
 setup_mesh() {
 echo "creating netmaker network (10.101.0.0/16)"
 
 curl -s -o /dev/null -d '{"addressrange":"10.101.0.0/16","netid":"netmaker"}' -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/networks
 
-sleep 2
+sleep 5
 
 echo "creating netmaker access key"
 
 curlresponse=$(curl -s -d '{"uses":99999,"name":"netmaker-key"}' -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/networks/netmaker/keys)
 ACCESS_TOKEN=$(jq -r '.accessstring' <<< ${curlresponse})
 
-sleep 2
+sleep 5
 
 echo "configuring netmaker server as ingress gateway"
 
@@ -194,6 +187,8 @@ SERVER_ID=$(jq -r '.[0].id' <<< ${curlresponse})
 
 curl -o /dev/null -s -X POST -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker/$SERVER_ID/createingress
 
+sleep 5
+
 echo "finished configuring server and network. You can now add clients."
 echo ""
 echo "For Linux, Mac, Windows, and FreeBSD:"
@@ -214,7 +209,7 @@ echo "creating vpn network (10.201.0.0/16)"
 
 curl -s -o /dev/null -d '{"addressrange":"10.201.0.0/16","netid":"vpn","defaultextclientdns":"8.8.8.8"}' -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/networks
 
-sleep 2
+sleep 5
 
 echo "configuring netmaker server as vpn inlet..."
 

+ 34 - 8
servercfg/serverconf.go

@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/gravitl/netmaker/config"
+	"github.com/gravitl/netmaker/models"
 )
 
 var (
@@ -33,14 +34,12 @@ func GetServerConfig() config.ServerConfig {
 	cfg.CoreDNSAddr = GetCoreDNSAddr()
 	cfg.APIHost = GetAPIHost()
 	cfg.APIPort = GetAPIPort()
-	cfg.APIPort = GetAPIPort()
 	cfg.MQPort = GetMQPort()
 	cfg.MasterKey = "(hidden)"
 	cfg.DNSKey = "(hidden)"
 	cfg.AllowedOrigin = GetAllowedOrigin()
 	cfg.RestBackend = "off"
 	cfg.NodeID = GetNodeID()
-	cfg.MQPort = GetMQPort()
 	if IsRestBackend() {
 		cfg.RestBackend = "on"
 	}
@@ -89,6 +88,23 @@ func GetServerConfig() config.ServerConfig {
 	return cfg
 }
 
+// GetServerConfig - gets the server config into memory from file or env
+func GetServerInfo() models.ServerConfig {
+	var cfg models.ServerConfig
+	cfg.API = GetAPIConnString()
+	cfg.CoreDNSAddr = GetCoreDNSAddr()
+	cfg.APIPort = GetAPIPort()
+	cfg.MQPort = GetMQPort()
+	cfg.DNSMode = "off"
+	if IsDNSMode() {
+		cfg.DNSMode = "on"
+	}
+	cfg.Version = GetVersion()
+	cfg.Server = GetServer()
+
+	return cfg
+}
+
 // GetFrontendURL - gets the frontend url
 func GetFrontendURL() string {
 	var frontend = ""
@@ -196,13 +212,24 @@ func GetCoreDNSAddr() string {
 
 // GetMQPort - gets the mq port
 func GetMQPort() string {
-	mqport := "1883"
+	port := "8883" //default
 	if os.Getenv("MQ_PORT") != "" {
-		mqport = os.Getenv("MQ_PORT")
+		port = os.Getenv("MQ_PORT")
 	} else if config.Config.Server.MQPort != "" {
-		mqport = config.Config.Server.MQPort
+		port = config.Config.Server.MQPort
+	}
+	return port
+}
+
+// GetMQServerPort - get mq port for server
+func GetMQServerPort() string {
+	port := "1883" //default
+	if os.Getenv("MQ_SERVER_PORT") != "" {
+		port = os.Getenv("MQ_SERVER_PORT")
+	} else if config.Config.Server.MQServerPort != "" {
+		port = config.Config.Server.MQServerPort
 	}
-	return mqport
+	return port
 }
 
 // GetMessageQueueEndpoint - gets the message queue endpoint
@@ -213,8 +240,7 @@ func GetMessageQueueEndpoint() string {
 	} else if config.Config.Server.MQHOST != "" {
 		host = config.Config.Server.MQHOST
 	}
-	//Do we want MQ port configurable???
-	return host + ":1883"
+	return host + ":" + GetMQServerPort()
 }
 
 // GetMasterKey - gets the configured master key of server

+ 1 - 1
serverctl/iptables.go

@@ -46,7 +46,7 @@ func portForwardServices(force bool) error {
 	for _, service := range services {
 		switch service {
 		case "mq":
-			err = iptablesPortForward("mq", "1883", "1883", false, force)
+			err = iptablesPortForward("mq", servercfg.GetMQServerPort(), servercfg.GetMQServerPort(), false, force)
 		case "dns":
 			err = iptablesPortForward("coredns", "53", "53", false, force)
 		case "ssh":

+ 5 - 24
serverctl/serverctl.go

@@ -79,32 +79,13 @@ func SyncServerNetwork(network string) error {
 			if err == nil {
 				err = errors.New("network add failed for " + serverNetworkSettings.NetID)
 			}
-			if !strings.Contains(err.Error(), "macaddress_unique") { // ignore macaddress unique error throws
-				logger.Log(1, "error adding network", serverNetworkSettings.NetID, "during sync:", err.Error())
-			}
-		}
-	}
-
-	// remove networks locally that do not exist in database
-	/*
-		for _, localnet := range localnets {
-			if strings.Contains(localnet.Name, "nm-") {
-				var exists = ""
-				if serverNetworkSettings.DefaultInterface == localnet.Name {
-					exists = serverNetworkSettings.NetID
+			/*
+				if !strings.Contains(err.Error(), "macaddress_unique") { // ignore macaddress unique error throws
+					logger.Log(1, "error adding network", serverNetworkSettings.NetID, "during sync:", err.Error())
 				}
-				if exists == "" {
-					err := logic.DeleteNodeByID(serverNode, true)
-					if err != nil {
-						if err == nil {
-							err = errors.New("network delete failed for " + exists)
-						}
-						logger.Log(1, "error removing network", exists, "during sync", err.Error())
-					}
-				}
-			}
+			*/
 		}
-	*/
+	}
 	return nil
 }