Browse Source

Merge branch 'develop' into refactor-controllers

Matthew R Kasun 4 years ago
parent
commit
073be947c6

+ 11 - 5
Dockerfile

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

+ 84 - 19
README.md

@@ -1,3 +1,4 @@
+
 <p align="center">
   <img src="netmaker.png"><break/>
 </p>
@@ -6,7 +7,11 @@
 </p>
 
 ## What is Netmaker?
-Netmaker is a tool for creating and managing virtual networks. The goal is to provide functionality similar to Tailscale, ZeroTier, and Nebula, but faster, easier, and more dynamic. It should be like clicking a button. Netmaker consists of a server, an agent, and a UI. You spin up the Netmaker server and then install netclient (the agent) on your computers. Netmaker will do the rest. It will tell all of your computers how to reach each other and will keep them informed of any changes to the network.
+Netmaker is a tool for creating and managing virtual networks. If you have servers spread across multiple locations, data centers, or clouds, they all live on separate networks. This can make life very difficult. Netmaker takes all those machines and puts them on a single, flat network so that they can talk to each other easily and securely.
+
+Think of it like Tailscale, ZeroTier, or Nebula, but faster, easier, and more dynamic.
+
+You spin up the Netmaker server and UI, and then install the Netclient (agent) on your computers. Netmaker will do the rest. It will tell all of your computers how to reach each other and will keep them informed of any changes to the network.
 
 Netmaker's handy dandy UI can be found [here](https://github.com/gravitl/netmaker-ui).
 
@@ -28,7 +33,9 @@ Under the hood, Netmaker uses WireGuard to create encrypted tunnels between ever
 
 ## Compatible Systems
 
-Netmaker works on most linux systems that have systemd. It works with Fedora, Ubuntu, and Raspian. Just make sure you have WireGuard installed. Having a problem? Open an issue or Contact us.
+Netmaker is primarily designed for **linux**, specifically **systemd-based linux.** This includes Fedora, Ubuntu, and Raspian. Just make sure you have WireGuard installed. Having a problem? Open an issue or Contact us.
+
+In version 0.3 we have released Private DNS. Nameservers can be configured manually on any system, but to have the Netclient add dns automatically, it requires **resolvectl.**
 
 In future releases, we have plans to support other platforms such as Windows and MacOS. 
 
@@ -47,33 +54,91 @@ In future releases, we have plans to support other platforms such as Windows and
 
 [Intro/Overview Video Tutorial](https://youtu.be/PWLPT320Ybo)  
 [Site-to-Site Video Tutorial](https://youtu.be/krCKBJhwwDk)  
-   
-#### Prereqs:
-1. A server with an IP reachable by your computers (a small ec2 instance or droplet would do just fine).
-2. Linux installed on the above server (we use Ubuntu, but anything that runs Docker should work).
-3. Install Docker if running in Docker Mode (see below).
 
+### Note about permissions
+The default installation requires special privileges on the server side, because Netmaker will control the local kernel Wireguard. This can be turned off and run in non-privileged mode if necessary (but disables some features). For more details, see the **Usage** docs.
+
+### Prereqs
+ 1. A running linux server to host Netmaker, with an IP reachable by your computers (Debian-based preferred but not required).
+ 2. Linux installed on the above server (Debian-based preferred but not required).
+ 3. Install Docker and Docker Compose if running in Docker Mode (see below).
+ 4. System dependencies installed:
+	 - Docker (if running in default Docker mode. DO NOT use snap install for docker.)
+	 - Docker Compose
+	 - Wireguard + Resolvectl (if running in default Client mode)
 
-#### Launch Netmaker:
+#### CoreDNS Preparation
+v0.3 introduces CoreDNS as a private nameserver. To run CoreDNS on your server host, you must disable systemd-resolved to open port 53: 
+1. systemctl stop systemd-resolved
+2. systemctl disable systemd-resolved
+3. vim /etc/systemd/resolved.conf
+	 - uncomment **DNS=** and add 8.8.8.8 or whatever is your preference
+	 - uncomment **DNSStubListener=** and set to **"no"**
+ 4. sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
 
-Netmaker v0.2 introduces the server as a 'client'. This means the server can add itself into networks if you would like. To do so, Netmaker requires privileged access where it is running, and needs to modify the host filesystem. To run in this mode, we are not currently using Docker.
 
-**If you would like to run with "client mode", you can use the following script to deploy:**
-`sudo curl -sfL https://raw.githubusercontent.com/gravitl/netmaker/v0.2/netmaker-install-clientmode.sh | sudo SERVER_DOMAIN=< your server IP > sh -`
 
-**If you would like to run without "client mode", and manually add/remove the server from networks:**
+### Launch Netmaker
+Note, this installs Netmaker with CoreDNS and a Netclient (privileged).  If you want to run the server non-privileged or without CoreDNS, see the advanced usage docs. 
 
 1. Clone this repo or just copy contents of "docker-compose.yml" to your Netmaker server (from prereqs).
 2. In docker-compose.yml, change BACKEND_URL to the public IP of your server.
 3. Run `sudo docker-compose up`
 4. Navigate to your server's IP in the browser and you should see the Netmaker UI asking to create a new admin user.
 5. Create a new admin user
-6. You are now ready to begin using Netmaker. There should be a default network you can use or you can create your own. Then, Create a key or enable manual node sign up so that your nodes can connect.
-
-#### On your machines :
-A command will be displayed when you generate a token for signing up nodes. Run it on each machine you would like to connect.
-`curl -sfL https://raw.githubusercontent.com/gravitl/netmaker/v0.2/netclient-install.sh | KEY=<your access key> sh -`  
-(Note: Key can be left out if manual node signup is enabled)
+6. You are now ready to begin using Netmaker. 
+
+### Create a Network
+You can also just use the "default" network.
+1. Click "CREATE NETWORK" in the upper left of your console
+2. Enter a valid address range, e.g. 10.11.12.0/24
+3. Enter a name such as "homenet"
+4. Additional options:
+	- **Dual Stack**: Machines will recieve a private IPv6 address in addition to their IPv4 address.
+	- **Local:** Will use local address range for endpoints instead of public. Use Case: Home or Office network where most devices do not have public IP's. In this case you can create a gateway into the network after creating the Local Network.
+
+After Network creation, you can edit the network in the NETWORK DETAILS pane, modifying the address range and default options. You can also toggle on **Allow Node Signup Without Keys**, which makes the next step unnecessary, but allows anyone to create a node in your network, which will be cordoned in pending state.
+
+### Create Keys
+1. Click the "ACCESS KEYS" tab
+2. Click "ADD NEW ACCESSS KEY"
+3. Give your key a name and number of uses
+4. Several values will be displayed. Save these somewhere, as they will only be displayed once:
+	- **Access Key:** Use only in special edge cases where server connection string must be modified
+	- **Access Token:** Use on machines that already have the netclient utility
+	- **Install Command:** Use on machines that do not have the netclient utility
+
+### Install Agent:
+For machines **without** netclient, run the install command (from above): `curl -sfL https://raw.githubusercontent.com/gravitl/netmaker/v0.2/netclient-install.sh | KEY=<your access key> sh -`  
+For machines **with** netclient run the following (with access token from above): `sudo netclient -c install -t <access token>`
+For networks with **manual signup** enabled (see above), install using the network name: `sudo netclient -c install -n <network name>`
+
+### Manage Nodes
+Your machines should now be visible in the control pane. 
+**Modify nodes:** Click the pencil icon in the NODES pane to modify details like WireGuard port, address, and node name. You can also **DELETE** nodes here and they will lose network access.
+**Approve nodes:** If a node is in pending state (signed up without key), you can approve it. An icon will appear for pending nodes that need approval.
+
+**Gateway Mode:** Click the Gateway icon to enable gateway mode on a given node. A popup will allow you to choose an existing network, or enter a custom address range.
+*Example: You create a network in netmaker called Homenet. It has several machines on your home server. You create another network called Cloudnet. It has several machines in AWS. You have one server (server X) which is added to both networks. On Cloudnet, you make Server X a gateway to Homenet. Now, the cloudnet machines have access to your homenet machines. via  Server X.*
+
+*On Homenet, you add Server Y, a machine in AWS, and make it a gateway to a custom address range 172.16.0.0/16. The machines on your home network now have access to any AWS machines in that address range via Server Y*
+
+### Manage DNS
+On the DNS tab you can create custom DNS entries for a given network.
+
+ 1. All dns entries will be *postfixed* with a private TLD of the network name, for example, ".mynet"
+ 2. Default DNS is created for node name + TLD, for instance, node-c42wt.mynet. This is not editable.
+ 3. Click ADD ENTRY to add custom DNS
+	 - You can click CHOOSE NODE to direct DNS to a specific node in the network
+	 - You can also specify any custom address you would like, which can be outside the network (for instance, the IP for google.com)
+	 - Add a dns entry name, which will be postfixed with the network TLD. E.g. if you enter "privateapi.com", it will become "privateapi.com.networkname" 
+
+### Uninstalling Client
+To uninstall the client from a network: `sudo netclient -c remove -n < networkname >`
+To uninstall entirely, run the above for each network,  and then run `sudo rm -rf /etc/netclient`
+
+### Uninstralling Netmaker
+To uninstall the netmaker server, simply run `docker-compose down`
 
 #### LICENSE
 
@@ -81,5 +146,5 @@ Netmaker's source code and all artifacts in this repository are freely available
 
 #### CONTACT
 
-Email: info@gravitl.com  
+Email: alex@gravitl.com  
 Discord: https://discord.gg/zRb9Vfhk8A

+ 16 - 12
config/config.go

@@ -15,7 +15,7 @@ import (
 //setting dev by default
 func getEnv() string {
 
-  env := os.Getenv("APP_ENV")
+  env := os.Getenv("NETMAKER_ENV")
 
   if len(env) == 0 {
     return "dev"
@@ -35,16 +35,17 @@ type EnvironmentConfig struct {
 
 // ServerConfig :
 type ServerConfig struct {
-  Host   string  `yaml:"host"`
-  ApiPort   string `yaml:"apiport"`
-  GrpcPort   string `yaml:"grpcport"`
+  APIHost   string  `yaml:"apihost"`
+  APIPort   string `yaml:"apiport"`
+  GRPCHost   string `yaml:"grpchost"`
+  GRPCPort   string `yaml:"grpcport"`
   MasterKey	string `yaml:"masterkey"`
   AllowedOrigin	string `yaml:"allowedorigin"`
-  RestBackend bool `yaml:"restbackend"`
-  AgentBackend bool `yaml:"agentbackend"`
-  DefaultNetName string `yaml:"defaultnetname"`
-  DefaultNetRange string `yaml:"defaultnetrange"`
-  CreateDefault bool `yaml:"createdefault"`
+  RestBackend string `yaml:"restbackend"`
+  AgentBackend string `yaml:"agentbackend"`
+  ClientMode string `yaml:"clientmode"`
+  DNSMode string `yaml:"dnsmode"`
+  DisableRemoteIPCheck string `yaml:"disableremoteipcheck"`
 }
 
 type MongoConnConfig struct {
@@ -60,13 +61,16 @@ type MongoConnConfig struct {
 func readConfig() *EnvironmentConfig {
   file := fmt.Sprintf("config/environments/%s.yaml", getEnv())
   f, err := os.Open(file)
+  var cfg EnvironmentConfig
   if err != nil {
-    log.Fatal(err)
-    os.Exit(2)
+    //log.Fatal(err)
+    //os.Exit(2)
+    log.Println("Unable to open config file at config/environments/" + getEnv())
+    log.Println("Will proceed with defaults or enironment variables (no config file).")
+    return &cfg
   }
   defer f.Close()
 
-  var cfg EnvironmentConfig
   decoder := yaml.NewDecoder(f)
   err = decoder.Decode(&cfg)
   if err != nil {

+ 16 - 15
config/environments/dev.yaml

@@ -1,17 +1,18 @@
 server:
-  host: "localhost"
-  apiport: "8081"
-  grpcport: "50051"
-  masterkey: "secretkey"
-  allowedorigin: "*"
-  restbackend: true            
-  agentbackend: true
-  defaultnetname: "default"
-  defaultnetrange: "10.10.10.0/24"
-  createdefault: true
+  apihost: "" # defaults to 127.0.0.1 or remote ip (SERVER_HOST) if DisableRemoteIPCheck is not set to true. SERVER_API_HOST if set
+  apiport: "" # defaults to 8081 or HTTP_PORT (if set)
+  grpchost: "" # defaults to 127.0.0.1 or remote ip (SERVER_HOST) if DisableRemoteIPCheck is not set to true. SERVER_GRPC_HOST if set.
+  grpcport: "" # defaults to 50051 or GRPC_PORT (if set)
+  masterkey: "" # defaults to 'secretkey' or MASTER_KEY (if set)
+  allowedorigin: "" # defaults to '*' or CORS_ALLOWED_ORIGIN (if set)
+  restbackend: "" # defaults to "on" or REST_BACKEND (if set)
+  agentbackend: "" # defaults to "on" or AGENT_BACKEND (if set)
+  clientmode: "" # defaults to "on" or CLIENT_MODE (if set)
+  dnsmode: "" # defaults to "on" or DNS_MODE (if set)
+  disableremoteipcheck: "" # defaults to "false" or DISABLE_REMOTE_IP_CHECK (if set)
 mongoconn:
-  user: "mongoadmin"
-  pass: "mongopass"
-  host: "localhost"
-  port: "27017"
-  opts: '/?authSource=admin'
+  user: "" # defaults to "mongoadmin" or MONGO_ADMIN (if set)
+  pass: "" # defaults to "mongopass" or MONGO_PASS (if set)
+  host: "" # defaults to 127.0.0.1 or MONGO_HOST (if set)
+  port: "" # defaults to 27017 or MONGO_PORT (if set)
+  opts: '' # defaults to '/?authSource=admin' or MONGO_OPTS (if set)

+ 11 - 6
controllers/common.go

@@ -10,6 +10,7 @@ import (
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mongoconn"
+	"github.com/gravitl/netmaker/servercfg"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo/options"
 	"golang.org/x/crypto/bcrypt"
@@ -210,6 +211,9 @@ func UpdateNode(nodechange models.NodeUpdate, node models.Node) (models.Node, er
 	if notifynetwork {
 		errN = SetNetworkNodesLastModified(queryNetwork)
 	}
+	if servercfg.IsDNSMode() {
+		errN = SetDNS()
+	}
 
 	return returnnode, errN
 }
@@ -236,6 +240,9 @@ func DeleteNode(macaddress string, network string) (bool, error) {
 
 	err = SetNetworkNodesLastModified(network)
 	fmt.Println("Deleted node " + macaddress + " from network " + network)
+	if servercfg.IsDNSMode() {
+		err = SetDNS()
+	}
 
 	return deleted, err
 }
@@ -279,16 +286,12 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
 	//Anyways, this scrolls through all the IP Addresses in the network range and checks against nodes
 	//until one is open and then returns it
 	node.Address, err = functions.UniqueAddress(networkName)
-	fmt.Println("Setting node address: " + node.Address)
 	if err != nil {
 		return node, err
 	}
-	fmt.Println("Setting node address: " + node.Address)
 
 	node.Address6, err = functions.UniqueAddress6(networkName)
-	if node.Address6 != "" {
-		fmt.Println("Setting node ipv6 address: " + node.Address6)
-	}
+
 	if err != nil {
 		return node, err
 	}
@@ -330,7 +333,9 @@ func CreateNode(node models.Node, networkName string) (models.Node, error) {
 	}
 
 	SetNetworkNodesLastModified(node.Network)
-
+	if servercfg.IsDNSMode() {
+		err = SetDNS()
+	}
 	return node, err
 }
 

+ 3 - 6
controllers/controller.go

@@ -2,6 +2,7 @@ package controller
 
 import (
     "github.com/gravitl/netmaker/mongoconn"
+    "github.com/gravitl/netmaker/servercfg"
     "os/signal"
     "os"
     "fmt"
@@ -10,7 +11,6 @@ import (
     "github.com/gorilla/mux"
     "github.com/gorilla/handlers"
     "sync"
-    "github.com/gravitl/netmaker/config"
 )
 
 
@@ -22,7 +22,7 @@ func HandleRESTRequests(wg *sync.WaitGroup) {
     // Currently allowed dev origin is all. Should change in prod
     // should consider analyzing the allowed methods further
     headersOk := handlers.AllowedHeaders([]string{"Access-Control-Allow-Origin", "X-Requested-With", "Content-Type", "authorization"})
-    originsOk := handlers.AllowedOrigins([]string{config.Config.Server.AllowedOrigin})
+    originsOk := handlers.AllowedOrigins([]string{servercfg.GetAllowedOrigin()})
     methodsOk := handlers.AllowedMethods([]string{"GET", "PUT", "POST", "DELETE"})
 
     nodeHandlers(r)
@@ -32,10 +32,7 @@ func HandleRESTRequests(wg *sync.WaitGroup) {
     fileHandlers(r)
     serverHandlers(r)
 
-		port := config.Config.Server.ApiPort
-	        if os.Getenv("API_PORT") != "" {
-			port = os.Getenv("API_PORT")
-		}
+		port := servercfg.GetAPIPort()
 
 		srv := &http.Server{Addr: ":" + port, Handler: handlers.CORS(originsOk, headersOk, methodsOk)(r)}
 		go func(){

+ 35 - 30
controllers/dnsHttpController.go

@@ -175,6 +175,40 @@ func GetCustomDNS(network string) ([]models.DNSEntry, error) {
 	return dns, err
 }
 
+func SetDNS() error {
+	hostfile := txeh.Hosts{}
+	var corefilestring string
+	networks, err := functions.ListNetworks()
+	if err != nil {
+		return err
+	}
+
+	for _, net := range networks {
+		corefilestring = corefilestring + net.NetID + " "
+		dns, err := GetDNS(net.NetID)
+		if err != nil {
+			return err
+		}
+		for _, entry := range dns {
+			hostfile.AddHost(entry.Address, entry.Name+"."+entry.Network)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	if corefilestring == "" {
+		corefilestring = "example.com"
+	}
+
+	err = hostfile.SaveAs("./config/dnsconfig/netmaker.hosts")
+	if err != nil {
+		return err
+	}
+	err = functions.SetCorefile(corefilestring)
+
+	return err
+}
+
 func GetDNSEntryNum(domain string, network string) (int, error) {
 
 	num := 0
@@ -418,7 +452,7 @@ func pushDNS(w http.ResponseWriter, r *http.Request) {
 	// Set header
 	w.Header().Set("Content-Type", "application/json")
 
-	err := WriteHosts()
+	err := SetDNS()
 
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "internal"))
@@ -427,35 +461,6 @@ func pushDNS(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode("DNS Pushed to CoreDNS")
 }
 
-func WriteHosts() error {
-	//hostfile, err := txeh.NewHostsDefault()
-	hostfile := txeh.Hosts{}
-	/*
-			if err != nil {
-		                return err
-		        }
-	*/
-	networks, err := functions.ListNetworks()
-	if err != nil {
-		return err
-	}
-
-	for _, net := range networks {
-		dns, err := GetDNS(net.NetID)
-		if err != nil {
-			return err
-		}
-		for _, entry := range dns {
-			hostfile.AddHost(entry.Address, entry.Name+"."+entry.Network)
-			if err != nil {
-				return err
-			}
-		}
-	}
-	err = hostfile.SaveAs("./config/netmaker.hosts")
-	return err
-}
-
 func ValidateDNSCreate(entry models.DNSEntry) error {
 
 	v := validator.New()

+ 6 - 12
controllers/networkHttpController.go

@@ -7,16 +7,15 @@ import (
 	"errors"
 	"fmt"
 	"net/http"
-	"os"
 	"strings"
 	"time"
 
 	"github.com/go-playground/validator/v10"
 	"github.com/gorilla/mux"
-	"github.com/gravitl/netmaker/config"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mongoconn"
+	"github.com/gravitl/netmaker/servercfg"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
@@ -91,7 +90,7 @@ func SecurityCheck(netname, token string) error {
 
 //Consider a more secure way of setting master key
 func authenticateMaster(tokenString string) bool {
-	if tokenString == config.Config.Server.MasterKey || (tokenString == os.Getenv("MASTER_KEY") && tokenString != "") {
+	if tokenString == servercfg.GetMasterKey() {
 		return true
 	}
 	return false
@@ -598,12 +597,6 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
 			return models.AccessKey{}, errors.New("Duplicate AccessKey Name")
 		}
 	}
-
-	_, gconf, err := functions.GetGlobalConfig()
-	if err != nil {
-		//returnErrorResponse(w, r, formatError(err, "internal"))
-		return models.AccessKey{}, err
-	}
 	privAddr := ""
 	if network.IsLocal != nil {
 		if *network.IsLocal {
@@ -611,9 +604,10 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
 		}
 	}
 
-	//netID := params["networkname"]
-	address := gconf.ServerGRPC + gconf.PortGRPC
-	accessstringdec := address + "|" + network.NetID + "|" + accesskey.Value + "|" + privAddr
+	netID := params["networkname"]
+	address := servercfg.GetGRPCHost() + ":" + servercfg.GetGRPCPort()
+
+	accessstringdec := address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
 	//validate accesskey
 	v := validator.New()

+ 45 - 7
controllers/nodeGrpcController.go

@@ -3,11 +3,11 @@ package controller
 import (
 	"context"
 	"fmt"
-	"strconv"
 
 	"github.com/gravitl/netmaker/functions"
 	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/servercfg"
 	"go.mongodb.org/mongo-driver/mongo"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -36,11 +36,21 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeRe
 		}
 	*/
 	// Cast to ReadNodeRes type
+	dualvar := false
+	if network.IsDualStack != nil {
+		dualvar = *network.IsDualStack
+	}
+	localvar := false
+	if network.IsLocal != nil {
+		localvar = *network.IsLocal
+	}
+
 	response := &nodepb.ReadNodeRes{
 		Node: &nodepb.Node{
 			Macaddress:      node.MacAddress,
 			Name:            node.Name,
 			Address:         node.Address,
+			Address6:        node.Address6,
 			Endpoint:        node.Endpoint,
 			Password:        node.Password,
 			Nodenetwork:     node.Network,
@@ -49,11 +59,13 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeRe
 			Postdown:        node.PostDown,
 			Postup:          node.PostUp,
 			Checkininterval: node.CheckInInterval,
+			Dnsoff:          !servercfg.IsDNSMode(),
 			Ispending:       node.IsPending,
 			Publickey:       node.PublicKey,
 			Listenport:      node.ListenPort,
 			Keepalive:       node.PersistentKeepalive,
-			Islocal:         *network.IsLocal,
+			Islocal:         localvar,
+			Isdualstack:     dualvar,
 			Localrange:      network.LocalRange,
 		},
 	}
@@ -71,6 +83,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 		LocalAddress:        data.GetLocaladdress(),
 		Name:                data.GetName(),
 		Address:             data.GetAddress(),
+		Address6:            data.GetAddress6(),
 		AccessKey:           data.GetAccesskey(),
 		Endpoint:            data.GetEndpoint(),
 		PersistentKeepalive: data.GetKeepalive(),
@@ -97,8 +110,6 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 		return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find network: %v", err))
 	} else {
 		fmt.Println("Creating node in network " + network.NetID)
-		fmt.Println("Network is local? " + strconv.FormatBool(*network.IsLocal))
-		fmt.Println("Range if local: " + network.LocalRange)
 	}
 
 	if !validKey {
@@ -123,6 +134,15 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 			fmt.Sprintf("Internal error: %v", err),
 		)
 	}
+	dualvar := false
+	if network.IsDualStack != nil {
+		dualvar = *network.IsDualStack
+	}
+	localvar := false
+	if network.IsLocal != nil {
+		localvar = *network.IsLocal
+	}
+
 	// return the node in a CreateNodeRes type
 	response := &nodepb.CreateNodeRes{
 		Node: &nodepb.Node{
@@ -130,15 +150,18 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
 			Localaddress: node.LocalAddress,
 			Name:         node.Name,
 			Address:      node.Address,
+			Address6:     node.Address6,
 			Endpoint:     node.Endpoint,
 			Password:     node.Password,
 			Interface:    node.Interface,
 			Nodenetwork:  node.Network,
+			Dnsoff:       !servercfg.IsDNSMode(),
 			Ispending:    node.IsPending,
 			Publickey:    node.PublicKey,
 			Listenport:   node.ListenPort,
 			Keepalive:    node.PersistentKeepalive,
-			Islocal:      *network.IsLocal,
+			Islocal:      localvar,
+			Isdualstack:  dualvar,
 			Localrange:   network.LocalRange,
 		},
 	}
@@ -160,6 +183,7 @@ func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq)
 		// ID:       primitive.NilObjectID,
 		MacAddress:          data.GetMacaddress(),
 		Address:             data.GetAddress(),
+		Address6:            data.GetAddress6(),
 		Endpoint:            data.GetEndpoint(),
 		Network:             data.GetNodenetwork(),
 		Password:            data.GetPassword(),
@@ -199,11 +223,12 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 	// Get the node data from the request
 	data := req.GetNode()
 	// Now we have to convert this into a NodeItem type to convert into BSON
-	nodechange := models.NodeUpdate{
+	nodechange := models.Node{
 		// ID:       primitive.NilObjectID,
 		MacAddress:          data.GetMacaddress(),
 		Name:                data.GetName(),
 		Address:             data.GetAddress(),
+		Address6:            data.GetAddress6(),
 		LocalAddress:        data.GetLocaladdress(),
 		Endpoint:            data.GetEndpoint(),
 		Password:            data.GetPassword(),
@@ -243,12 +268,22 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 			fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
 		)
 	}
+	dualvar := false
+	if network.IsDualStack != nil {
+		dualvar = *network.IsDualStack
+	}
+	localvar := false
+	if network.IsLocal != nil {
+		localvar = *network.IsLocal
+	}
+
 	return &nodepb.UpdateNodeRes{
 		Node: &nodepb.Node{
 			Macaddress:   newnode.MacAddress,
 			Localaddress: newnode.LocalAddress,
 			Name:         newnode.Name,
 			Address:      newnode.Address,
+			Address6:     newnode.Address6,
 			Endpoint:     newnode.Endpoint,
 			Password:     newnode.Password,
 			Interface:    newnode.Interface,
@@ -257,9 +292,11 @@ func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNo
 			Nodenetwork:  newnode.Network,
 			Ispending:    newnode.IsPending,
 			Publickey:    newnode.PublicKey,
+			Dnsoff:       !servercfg.IsDNSMode(),
 			Listenport:   newnode.ListenPort,
 			Keepalive:    newnode.PersistentKeepalive,
-			Islocal:      *network.IsLocal,
+			Islocal:      localvar,
+			Isdualstack:  dualvar,
 			Localrange:   network.LocalRange,
 		},
 	}, nil
@@ -308,6 +345,7 @@ func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.Node
 		stream.Send(&nodepb.GetPeersRes{
 			Peers: &nodepb.PeersResponse{
 				Address:      peers[i].Address,
+				Address6:     peers[i].Address6,
 				Endpoint:     peers[i].Endpoint,
 				Gatewayrange: peers[i].GatewayRange,
 				Isgateway:    peers[i].IsGateway,

+ 15 - 2
controllers/serverHttpController.go

@@ -3,7 +3,7 @@ package controller
 import (
     "github.com/gravitl/netmaker/models"
     "github.com/gravitl/netmaker/serverctl"
-    "github.com/gravitl/netmaker/config"
+    "github.com/gravitl/netmaker/servercfg"
     "encoding/json"
     "strings"
     "net/http"
@@ -12,6 +12,7 @@ import (
 
 func serverHandlers(r *mux.Router) {
     r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(http.HandlerFunc(addNetwork))).Methods("POST")
+    r.HandleFunc("/api/server/getconfig", securityCheckServer(http.HandlerFunc(getConfig))).Methods("GET")
     r.HandleFunc("/api/server/removenetwork/{network}", securityCheckServer(http.HandlerFunc(removeNetwork))).Methods("DELETE")
 }
 
@@ -49,7 +50,7 @@ func securityCheckServer(next http.Handler) http.HandlerFunc {
 }
 //Consider a more secure way of setting master key
 func authenticateMasterServer(tokenString string) bool {
-    if tokenString == config.Config.Server.MasterKey {
+    if tokenString == servercfg.GetMasterKey() {
         return true
     }
     return false
@@ -72,6 +73,18 @@ 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) {
+        // Set header
+        w.Header().Set("Content-Type", "application/json")
+
+        // get params
+
+        scfg := servercfg.GetConfig()
+
+        w.WriteHeader(http.StatusOK)
+        json.NewEncoder(w).Encode(scfg)
+}
+
 func addNetwork(w http.ResponseWriter, r *http.Request) {
         // Set header
         w.Header().Set("Content-Type", "application/json")

+ 3 - 11
controllers/userHttpController.go

@@ -228,7 +228,7 @@ func getUser(w http.ResponseWriter, r *http.Request) {
 	user, err := GetUser(params["username"])
 
 	if err != nil {
-		mongoconn.GetError(err, w)
+		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 	}
 
@@ -349,34 +349,26 @@ func UpdateUser(userchange models.User, user models.User) (models.User, error) {
 
 func updateUser(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
-
 	var params = mux.Vars(r)
-
 	var user models.User
-
 	//start here
 	user, err := GetUser(params["username"])
 	if err != nil {
-		json.NewEncoder(w).Encode(err)
+		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 	}
-
 	var userchange models.User
-
 	// we decode our body request params
 	err = json.NewDecoder(r.Body).Decode(&userchange)
 	if err != nil {
-		json.NewEncoder(w).Encode(err)
+		returnErrorResponse(w, r, formatError(err, "internal"))
 		return
 	}
-
 	user, err = UpdateUser(userchange, user)
-
 	if err != nil {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		return
 	}
-
 	json.NewEncoder(w).Encode(user)
 }
 

+ 66 - 0
docker-compose.nodns.yml

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

+ 36 - 6
docker-compose.yml

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

+ 36 - 48
functions/helpers.go

@@ -16,6 +16,7 @@ import (
 
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mongoconn"
+	"github.com/gravitl/netmaker/servercfg"
 	"go.mongodb.org/mongo-driver/bson"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 	"go.mongodb.org/mongo-driver/mongo"
@@ -38,22 +39,13 @@ func CreateServerToken(netID string) (string, error) {
 	accesskey.Name = GenKeyName()
 	accesskey.Value = GenKey()
 	accesskey.Uses = 1
-	_, gconf, errG := GetGlobalConfig()
-	if errG != nil {
-		return "", errG
-	}
-	address := "localhost" + gconf.PortGRPC
+	address := "127.0.0.1:" + servercfg.GetGRPCPort()
 
 	privAddr := ""
 	if *network.IsLocal {
 		privAddr = network.LocalRange
 	}
 
-	fmt.Println("Token details:")
-	fmt.Println("    grpc address + port: " + address)
-	fmt.Println("                network: " + netID)
-	fmt.Println("          private range: " + privAddr)
-
 	accessstringdec := address + "|" + netID + "|" + accesskey.Value + "|" + privAddr
 
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
@@ -131,8 +123,6 @@ func NetworkExists(name string) (bool, error) {
 		if err == mongo.ErrNoDocuments {
 			return false, nil
 		}
-		fmt.Println("ERROR RETRIEVING GROUP!")
-		fmt.Println(err)
 	}
 	return true, err
 }
@@ -529,13 +519,12 @@ func UniqueAddress6(networkName string) (string, error) {
 
 	var network models.Network
 	network, err := GetParentNetwork(networkName)
-	if !*network.IsDualStack {
-		return "", nil
-	}
-
 	if err != nil {
-		fmt.Println("UniqueAddress6 encountered  an error")
-		return "666", err
+		fmt.Println("Network Not Found")
+		return "", err
+	}
+	if network.IsDualStack == nil || *network.IsDualStack == false {
+		return "", nil
 	}
 
 	offset := true
@@ -549,7 +538,7 @@ func UniqueAddress6(networkName string) (string, error) {
 			offset = false
 			continue
 		}
-		if IsIPUnique(networkName, ip.String()) {
+		if IsIP6Unique(networkName, ip.String()) {
 			return ip.String(), err
 		}
 	}
@@ -558,35 +547,6 @@ func UniqueAddress6(networkName string) (string, error) {
 	return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
 }
 
-//pretty simple get
-func GetGlobalConfig() (bool, models.GlobalConfig, error) {
-
-	create := false
-
-	filter := bson.M{}
-
-	var globalconf models.GlobalConfig
-
-	collection := mongoconn.Client.Database("netmaker").Collection("config")
-
-	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-
-	err := collection.FindOne(ctx, filter).Decode(&globalconf)
-
-	defer cancel()
-
-	if err == mongo.ErrNoDocuments {
-		fmt.Println("Global config does not exist. Need to create.")
-		create = true
-		return create, globalconf, err
-	} else if err != nil {
-		fmt.Println(err)
-		fmt.Println("Could not get global config")
-		return create, globalconf, err
-	}
-	return create, globalconf, err
-}
-
 //generate an access key value
 func GenKey() string {
 
@@ -650,6 +610,34 @@ func IsIPUnique(network string, ip string) bool {
 	return isunique
 }
 
+//checks if IP is unique in the address range
+//used by UniqueAddress
+func IsIP6Unique(network string, ip string) bool {
+
+	var node models.Node
+
+	isunique := true
+
+	collection := mongoconn.Client.Database("netmaker").Collection("nodes")
+	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+
+	filter := bson.M{"address6": ip, "network": network}
+
+	err := collection.FindOne(ctx, filter).Decode(&node)
+
+	defer cancel()
+
+	if err != nil {
+		fmt.Println(err)
+		return isunique
+	}
+
+	if node.Address6 == ip {
+		isunique = false
+	}
+	return isunique
+}
+
 //called once key has been used by createNode
 //reduces value by one and deletes if necessary
 func DecrimentKey(networkName string, keyvalue string) {

+ 3 - 4
functions/jwt.go

@@ -2,9 +2,8 @@ package functions
 
 import (
     "time"
-    "os"
-    "github.com/gravitl/netmaker/config"
     "github.com/gravitl/netmaker/models"
+    "github.com/gravitl/netmaker/servercfg"
     "github.com/dgrijalva/jwt-go"
 )
 
@@ -51,7 +50,7 @@ func CreateUserJWT(username string, isadmin bool) (response string, err error) {
 func VerifyUserToken(tokenString string) (username string, isadmin bool, err error) {
     claims := &models.UserClaims{}
 
-    if tokenString == config.Config.Server.MasterKey || (tokenString == os.Getenv("MASTER_KEY") && tokenString != "") {
+    if tokenString == servercfg.GetMasterKey() {
         return "masteradministrator", true, nil
     }
 
@@ -71,7 +70,7 @@ func VerifyToken(tokenString string) (macaddress string, network string, err err
 
     //this may be a stupid way of serving up a master key
     //TODO: look into a different method. Encryption?
-    if tokenString == config.Config.Server.MasterKey || (tokenString == os.Getenv("MASTER_KEY") && tokenString != "") {
+    if tokenString == servercfg.GetMasterKey() {
         return "mastermac", "", nil
     }
 

+ 51 - 0
functions/local.go

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

+ 2 - 1
go.mod

@@ -5,7 +5,7 @@ go 1.15
 require (
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/go-playground/validator/v10 v10.5.0
-	github.com/golang/protobuf v1.4.3
+	github.com/golang/protobuf v1.4.3 // indirect
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
 	github.com/stretchr/testify v1.6.1
@@ -20,5 +20,6 @@ require (
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b
 	google.golang.org/genproto v0.0.0-20210201151548-94839c025ad4 // indirect
 	google.golang.org/grpc v1.35.0
+	google.golang.org/protobuf v1.25.0
 	gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
 )

+ 1257 - 705
grpc/node.pb.go

@@ -1,1095 +1,1647 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.25.0-devel
+// 	protoc        v3.14.0
 // source: grpc/node.proto
 
 package nodepb
 
 import (
-	fmt "fmt"
-	proto "github.com/golang/protobuf/proto"
-	math "math"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
 
 type LoginRequest struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Password             string   `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
-	Network              string   `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *LoginRequest) Reset()         { *m = LoginRequest{} }
-func (m *LoginRequest) String() string { return proto.CompactTextString(m) }
-func (*LoginRequest) ProtoMessage()    {}
-func (*LoginRequest) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{0}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Password   string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+	Network    string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *LoginRequest) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_LoginRequest.Unmarshal(m, b)
-}
-func (m *LoginRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_LoginRequest.Marshal(b, m, deterministic)
-}
-func (m *LoginRequest) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_LoginRequest.Merge(m, src)
+func (x *LoginRequest) Reset() {
+	*x = LoginRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *LoginRequest) XXX_Size() int {
-	return xxx_messageInfo_LoginRequest.Size(m)
+
+func (x *LoginRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *LoginRequest) XXX_DiscardUnknown() {
-	xxx_messageInfo_LoginRequest.DiscardUnknown(m)
+
+func (*LoginRequest) ProtoMessage() {}
+
+func (x *LoginRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_LoginRequest proto.InternalMessageInfo
+// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead.
+func (*LoginRequest) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{0}
+}
 
-func (m *LoginRequest) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *LoginRequest) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *LoginRequest) GetPassword() string {
-	if m != nil {
-		return m.Password
+func (x *LoginRequest) GetPassword() string {
+	if x != nil {
+		return x.Password
 	}
 	return ""
 }
 
-func (m *LoginRequest) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *LoginRequest) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type LoginResponse struct {
-	Accesstoken          string   `protobuf:"bytes,1,opt,name=accesstoken,proto3" json:"accesstoken,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *LoginResponse) Reset()         { *m = LoginResponse{} }
-func (m *LoginResponse) String() string { return proto.CompactTextString(m) }
-func (*LoginResponse) ProtoMessage()    {}
-func (*LoginResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{1}
+	Accesstoken string `protobuf:"bytes,1,opt,name=accesstoken,proto3" json:"accesstoken,omitempty"`
 }
 
-func (m *LoginResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_LoginResponse.Unmarshal(m, b)
-}
-func (m *LoginResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_LoginResponse.Marshal(b, m, deterministic)
-}
-func (m *LoginResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_LoginResponse.Merge(m, src)
+func (x *LoginResponse) Reset() {
+	*x = LoginResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *LoginResponse) XXX_Size() int {
-	return xxx_messageInfo_LoginResponse.Size(m)
+
+func (x *LoginResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *LoginResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_LoginResponse.DiscardUnknown(m)
+
+func (*LoginResponse) ProtoMessage() {}
+
+func (x *LoginResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_LoginResponse proto.InternalMessageInfo
+// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead.
+func (*LoginResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{1}
+}
 
-func (m *LoginResponse) GetAccesstoken() string {
-	if m != nil {
-		return m.Accesstoken
+func (x *LoginResponse) GetAccesstoken() string {
+	if x != nil {
+		return x.Accesstoken
 	}
 	return ""
 }
 
 type Node struct {
-	Id                   string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name                 string   `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Address              string   `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
-	Listenport           int32    `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
-	Publickey            string   `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
-	Endpoint             string   `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
-	Macaddress           string   `protobuf:"bytes,7,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Password             string   `protobuf:"bytes,8,opt,name=password,proto3" json:"password,omitempty"`
-	Nodenetwork          string   `protobuf:"bytes,9,opt,name=nodenetwork,proto3" json:"nodenetwork,omitempty"`
-	Ispending            bool     `protobuf:"varint,10,opt,name=ispending,proto3" json:"ispending,omitempty"`
-	Postup               string   `protobuf:"bytes,11,opt,name=postup,proto3" json:"postup,omitempty"`
-	Postdown             string   `protobuf:"bytes,12,opt,name=postdown,proto3" json:"postdown,omitempty"`
-	Keepalive            int32    `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
-	Saveconfig           bool     `protobuf:"varint,14,opt,name=saveconfig,proto3" json:"saveconfig,omitempty"`
-	Accesskey            string   `protobuf:"bytes,15,opt,name=accesskey,proto3" json:"accesskey,omitempty"`
-	Interface            string   `protobuf:"bytes,16,opt,name=interface,proto3" json:"interface,omitempty"`
-	Lastcheckin          string   `protobuf:"bytes,17,opt,name=lastcheckin,proto3" json:"lastcheckin,omitempty"`
-	Lastmodified         string   `protobuf:"bytes,18,opt,name=lastmodified,proto3" json:"lastmodified,omitempty"`
-	Checkininterval      int32    `protobuf:"varint,19,opt,name=checkininterval,proto3" json:"checkininterval,omitempty"`
-	Localaddress         string   `protobuf:"bytes,20,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
-	Postchanges          string   `protobuf:"bytes,21,opt,name=postchanges,proto3" json:"postchanges,omitempty"`
-	Allowedips           string   `protobuf:"bytes,22,opt,name=allowedips,proto3" json:"allowedips,omitempty"`
-	Islocal              bool     `protobuf:"varint,23,opt,name=islocal,proto3" json:"islocal,omitempty"`
-	Localrange           string   `protobuf:"bytes,24,opt,name=localrange,proto3" json:"localrange,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *Node) Reset()         { *m = Node{} }
-func (m *Node) String() string { return proto.CompactTextString(m) }
-func (*Node) ProtoMessage()    {}
-func (*Node) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{2}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Id              string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name            string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Address         string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+	Address6        string `protobuf:"bytes,26,opt,name=address6,proto3" json:"address6,omitempty"`
+	Listenport      int32  `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
+	Publickey       string `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
+	Endpoint        string `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+	Macaddress      string `protobuf:"bytes,7,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Password        string `protobuf:"bytes,8,opt,name=password,proto3" json:"password,omitempty"`
+	Nodenetwork     string `protobuf:"bytes,9,opt,name=nodenetwork,proto3" json:"nodenetwork,omitempty"`
+	Ispending       bool   `protobuf:"varint,10,opt,name=ispending,proto3" json:"ispending,omitempty"`
+	Postup          string `protobuf:"bytes,11,opt,name=postup,proto3" json:"postup,omitempty"`
+	Postdown        string `protobuf:"bytes,12,opt,name=postdown,proto3" json:"postdown,omitempty"`
+	Keepalive       int32  `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
+	Saveconfig      bool   `protobuf:"varint,14,opt,name=saveconfig,proto3" json:"saveconfig,omitempty"`
+	Accesskey       string `protobuf:"bytes,15,opt,name=accesskey,proto3" json:"accesskey,omitempty"`
+	Interface       string `protobuf:"bytes,16,opt,name=interface,proto3" json:"interface,omitempty"`
+	Lastcheckin     string `protobuf:"bytes,17,opt,name=lastcheckin,proto3" json:"lastcheckin,omitempty"`
+	Lastmodified    string `protobuf:"bytes,18,opt,name=lastmodified,proto3" json:"lastmodified,omitempty"`
+	Checkininterval int32  `protobuf:"varint,19,opt,name=checkininterval,proto3" json:"checkininterval,omitempty"`
+	Localaddress    string `protobuf:"bytes,20,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
+	Postchanges     string `protobuf:"bytes,21,opt,name=postchanges,proto3" json:"postchanges,omitempty"`
+	Allowedips      string `protobuf:"bytes,22,opt,name=allowedips,proto3" json:"allowedips,omitempty"`
+	Islocal         bool   `protobuf:"varint,23,opt,name=islocal,proto3" json:"islocal,omitempty"`
+	Isdualstack     bool   `protobuf:"varint,27,opt,name=isdualstack,proto3" json:"isdualstack,omitempty"`
+	Dnsoff          bool   `protobuf:"varint,24,opt,name=dnsoff,proto3" json:"dnsoff,omitempty"`
+	Localrange      string `protobuf:"bytes,25,opt,name=localrange,proto3" json:"localrange,omitempty"`
+}
+
+func (x *Node) Reset() {
+	*x = Node{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *Node) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_Node.Unmarshal(m, b)
+func (x *Node) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *Node) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_Node.Marshal(b, m, deterministic)
-}
-func (m *Node) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_Node.Merge(m, src)
-}
-func (m *Node) XXX_Size() int {
-	return xxx_messageInfo_Node.Size(m)
+
+func (*Node) ProtoMessage() {}
+
+func (x *Node) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
-func (m *Node) XXX_DiscardUnknown() {
-	xxx_messageInfo_Node.DiscardUnknown(m)
+
+// Deprecated: Use Node.ProtoReflect.Descriptor instead.
+func (*Node) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{2}
 }
 
-var xxx_messageInfo_Node proto.InternalMessageInfo
+func (x *Node) GetId() string {
+	if x != nil {
+		return x.Id
+	}
+	return ""
+}
 
-func (m *Node) GetId() string {
-	if m != nil {
-		return m.Id
+func (x *Node) GetName() string {
+	if x != nil {
+		return x.Name
 	}
 	return ""
 }
 
-func (m *Node) GetName() string {
-	if m != nil {
-		return m.Name
+func (x *Node) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *Node) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *Node) GetAddress6() string {
+	if x != nil {
+		return x.Address6
 	}
 	return ""
 }
 
-func (m *Node) GetListenport() int32 {
-	if m != nil {
-		return m.Listenport
+func (x *Node) GetListenport() int32 {
+	if x != nil {
+		return x.Listenport
 	}
 	return 0
 }
 
-func (m *Node) GetPublickey() string {
-	if m != nil {
-		return m.Publickey
+func (x *Node) GetPublickey() string {
+	if x != nil {
+		return x.Publickey
 	}
 	return ""
 }
 
-func (m *Node) GetEndpoint() string {
-	if m != nil {
-		return m.Endpoint
+func (x *Node) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
 	}
 	return ""
 }
 
-func (m *Node) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *Node) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *Node) GetPassword() string {
-	if m != nil {
-		return m.Password
+func (x *Node) GetPassword() string {
+	if x != nil {
+		return x.Password
 	}
 	return ""
 }
 
-func (m *Node) GetNodenetwork() string {
-	if m != nil {
-		return m.Nodenetwork
+func (x *Node) GetNodenetwork() string {
+	if x != nil {
+		return x.Nodenetwork
 	}
 	return ""
 }
 
-func (m *Node) GetIspending() bool {
-	if m != nil {
-		return m.Ispending
+func (x *Node) GetIspending() bool {
+	if x != nil {
+		return x.Ispending
 	}
 	return false
 }
 
-func (m *Node) GetPostup() string {
-	if m != nil {
-		return m.Postup
+func (x *Node) GetPostup() string {
+	if x != nil {
+		return x.Postup
 	}
 	return ""
 }
 
-func (m *Node) GetPostdown() string {
-	if m != nil {
-		return m.Postdown
+func (x *Node) GetPostdown() string {
+	if x != nil {
+		return x.Postdown
 	}
 	return ""
 }
 
-func (m *Node) GetKeepalive() int32 {
-	if m != nil {
-		return m.Keepalive
+func (x *Node) GetKeepalive() int32 {
+	if x != nil {
+		return x.Keepalive
 	}
 	return 0
 }
 
-func (m *Node) GetSaveconfig() bool {
-	if m != nil {
-		return m.Saveconfig
+func (x *Node) GetSaveconfig() bool {
+	if x != nil {
+		return x.Saveconfig
 	}
 	return false
 }
 
-func (m *Node) GetAccesskey() string {
-	if m != nil {
-		return m.Accesskey
+func (x *Node) GetAccesskey() string {
+	if x != nil {
+		return x.Accesskey
 	}
 	return ""
 }
 
-func (m *Node) GetInterface() string {
-	if m != nil {
-		return m.Interface
+func (x *Node) GetInterface() string {
+	if x != nil {
+		return x.Interface
 	}
 	return ""
 }
 
-func (m *Node) GetLastcheckin() string {
-	if m != nil {
-		return m.Lastcheckin
+func (x *Node) GetLastcheckin() string {
+	if x != nil {
+		return x.Lastcheckin
 	}
 	return ""
 }
 
-func (m *Node) GetLastmodified() string {
-	if m != nil {
-		return m.Lastmodified
+func (x *Node) GetLastmodified() string {
+	if x != nil {
+		return x.Lastmodified
 	}
 	return ""
 }
 
-func (m *Node) GetCheckininterval() int32 {
-	if m != nil {
-		return m.Checkininterval
+func (x *Node) GetCheckininterval() int32 {
+	if x != nil {
+		return x.Checkininterval
 	}
 	return 0
 }
 
-func (m *Node) GetLocaladdress() string {
-	if m != nil {
-		return m.Localaddress
+func (x *Node) GetLocaladdress() string {
+	if x != nil {
+		return x.Localaddress
 	}
 	return ""
 }
 
-func (m *Node) GetPostchanges() string {
-	if m != nil {
-		return m.Postchanges
+func (x *Node) GetPostchanges() string {
+	if x != nil {
+		return x.Postchanges
 	}
 	return ""
 }
 
-func (m *Node) GetAllowedips() string {
-	if m != nil {
-		return m.Allowedips
+func (x *Node) GetAllowedips() string {
+	if x != nil {
+		return x.Allowedips
 	}
 	return ""
 }
 
-func (m *Node) GetIslocal() bool {
-	if m != nil {
-		return m.Islocal
+func (x *Node) GetIslocal() bool {
+	if x != nil {
+		return x.Islocal
 	}
 	return false
 }
 
-func (m *Node) GetLocalrange() string {
-	if m != nil {
-		return m.Localrange
+func (x *Node) GetIsdualstack() bool {
+	if x != nil {
+		return x.Isdualstack
 	}
-	return ""
+	return false
 }
 
-type CheckInResponse struct {
-	Success              bool     `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
-	Needpeerupdate       bool     `protobuf:"varint,2,opt,name=needpeerupdate,proto3" json:"needpeerupdate,omitempty"`
-	Needconfigupdate     bool     `protobuf:"varint,3,opt,name=needconfigupdate,proto3" json:"needconfigupdate,omitempty"`
-	Nodemessage          string   `protobuf:"bytes,4,opt,name=nodemessage,proto3" json:"nodemessage,omitempty"`
-	Ispending            bool     `protobuf:"varint,5,opt,name=ispending,proto3" json:"ispending,omitempty"`
-	Needkeyupdate        bool     `protobuf:"varint,6,opt,name=needkeyupdate,proto3" json:"needkeyupdate,omitempty"`
-	Needdelete           bool     `protobuf:"varint,7,opt,name=needdelete,proto3" json:"needdelete,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *CheckInResponse) Reset()         { *m = CheckInResponse{} }
-func (m *CheckInResponse) String() string { return proto.CompactTextString(m) }
-func (*CheckInResponse) ProtoMessage()    {}
-func (*CheckInResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{3}
+func (x *Node) GetDnsoff() bool {
+	if x != nil {
+		return x.Dnsoff
+	}
+	return false
 }
 
-func (m *CheckInResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CheckInResponse.Unmarshal(m, b)
-}
-func (m *CheckInResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CheckInResponse.Marshal(b, m, deterministic)
+func (x *Node) GetLocalrange() string {
+	if x != nil {
+		return x.Localrange
+	}
+	return ""
 }
-func (m *CheckInResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CheckInResponse.Merge(m, src)
+
+type CheckInResponse struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Success          bool   `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
+	Needpeerupdate   bool   `protobuf:"varint,2,opt,name=needpeerupdate,proto3" json:"needpeerupdate,omitempty"`
+	Needconfigupdate bool   `protobuf:"varint,3,opt,name=needconfigupdate,proto3" json:"needconfigupdate,omitempty"`
+	Nodemessage      string `protobuf:"bytes,4,opt,name=nodemessage,proto3" json:"nodemessage,omitempty"`
+	Ispending        bool   `protobuf:"varint,5,opt,name=ispending,proto3" json:"ispending,omitempty"`
+	Needkeyupdate    bool   `protobuf:"varint,6,opt,name=needkeyupdate,proto3" json:"needkeyupdate,omitempty"`
+	Needdelete       bool   `protobuf:"varint,7,opt,name=needdelete,proto3" json:"needdelete,omitempty"`
+}
+
+func (x *CheckInResponse) Reset() {
+	*x = CheckInResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CheckInResponse) XXX_Size() int {
-	return xxx_messageInfo_CheckInResponse.Size(m)
+
+func (x *CheckInResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CheckInResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_CheckInResponse.DiscardUnknown(m)
+
+func (*CheckInResponse) ProtoMessage() {}
+
+func (x *CheckInResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CheckInResponse proto.InternalMessageInfo
+// Deprecated: Use CheckInResponse.ProtoReflect.Descriptor instead.
+func (*CheckInResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{3}
+}
 
-func (m *CheckInResponse) GetSuccess() bool {
-	if m != nil {
-		return m.Success
+func (x *CheckInResponse) GetSuccess() bool {
+	if x != nil {
+		return x.Success
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeedpeerupdate() bool {
-	if m != nil {
-		return m.Needpeerupdate
+func (x *CheckInResponse) GetNeedpeerupdate() bool {
+	if x != nil {
+		return x.Needpeerupdate
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeedconfigupdate() bool {
-	if m != nil {
-		return m.Needconfigupdate
+func (x *CheckInResponse) GetNeedconfigupdate() bool {
+	if x != nil {
+		return x.Needconfigupdate
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNodemessage() string {
-	if m != nil {
-		return m.Nodemessage
+func (x *CheckInResponse) GetNodemessage() string {
+	if x != nil {
+		return x.Nodemessage
 	}
 	return ""
 }
 
-func (m *CheckInResponse) GetIspending() bool {
-	if m != nil {
-		return m.Ispending
+func (x *CheckInResponse) GetIspending() bool {
+	if x != nil {
+		return x.Ispending
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeedkeyupdate() bool {
-	if m != nil {
-		return m.Needkeyupdate
+func (x *CheckInResponse) GetNeedkeyupdate() bool {
+	if x != nil {
+		return x.Needkeyupdate
 	}
 	return false
 }
 
-func (m *CheckInResponse) GetNeeddelete() bool {
-	if m != nil {
-		return m.Needdelete
+func (x *CheckInResponse) GetNeeddelete() bool {
+	if x != nil {
+		return x.Needdelete
 	}
 	return false
 }
 
 type PeersResponse struct {
-	Isgateway            bool     `protobuf:"varint,1,opt,name=isgateway,proto3" json:"isgateway,omitempty"`
-	Gatewayrange         string   `protobuf:"bytes,2,opt,name=gatewayrange,proto3" json:"gatewayrange,omitempty"`
-	Publickey            string   `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
-	Endpoint             string   `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
-	Address              string   `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
-	Listenport           int32    `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
-	Localaddress         string   `protobuf:"bytes,7,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
-	Keepalive            int32    `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
-
-func (m *PeersResponse) Reset()         { *m = PeersResponse{} }
-func (m *PeersResponse) String() string { return proto.CompactTextString(m) }
-func (*PeersResponse) ProtoMessage()    {}
-func (*PeersResponse) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{4}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Isgateway    bool   `protobuf:"varint,1,opt,name=isgateway,proto3" json:"isgateway,omitempty"`
+	Gatewayrange string `protobuf:"bytes,2,opt,name=gatewayrange,proto3" json:"gatewayrange,omitempty"`
+	Publickey    string `protobuf:"bytes,5,opt,name=publickey,proto3" json:"publickey,omitempty"`
+	Endpoint     string `protobuf:"bytes,6,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
+	Address      string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+	Address6     string `protobuf:"bytes,8,opt,name=address6,proto3" json:"address6,omitempty"`
+	Listenport   int32  `protobuf:"varint,4,opt,name=listenport,proto3" json:"listenport,omitempty"`
+	Localaddress string `protobuf:"bytes,7,opt,name=localaddress,proto3" json:"localaddress,omitempty"`
+	Keepalive    int32  `protobuf:"varint,13,opt,name=keepalive,proto3" json:"keepalive,omitempty"`
+}
+
+func (x *PeersResponse) Reset() {
+	*x = PeersResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
 
-func (m *PeersResponse) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_PeersResponse.Unmarshal(m, b)
-}
-func (m *PeersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_PeersResponse.Marshal(b, m, deterministic)
-}
-func (m *PeersResponse) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_PeersResponse.Merge(m, src)
+func (x *PeersResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *PeersResponse) XXX_Size() int {
-	return xxx_messageInfo_PeersResponse.Size(m)
-}
-func (m *PeersResponse) XXX_DiscardUnknown() {
-	xxx_messageInfo_PeersResponse.DiscardUnknown(m)
+
+func (*PeersResponse) ProtoMessage() {}
+
+func (x *PeersResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_PeersResponse proto.InternalMessageInfo
+// Deprecated: Use PeersResponse.ProtoReflect.Descriptor instead.
+func (*PeersResponse) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{4}
+}
 
-func (m *PeersResponse) GetIsgateway() bool {
-	if m != nil {
-		return m.Isgateway
+func (x *PeersResponse) GetIsgateway() bool {
+	if x != nil {
+		return x.Isgateway
 	}
 	return false
 }
 
-func (m *PeersResponse) GetGatewayrange() string {
-	if m != nil {
-		return m.Gatewayrange
+func (x *PeersResponse) GetGatewayrange() string {
+	if x != nil {
+		return x.Gatewayrange
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetPublickey() string {
-	if m != nil {
-		return m.Publickey
+func (x *PeersResponse) GetPublickey() string {
+	if x != nil {
+		return x.Publickey
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetEndpoint() string {
-	if m != nil {
-		return m.Endpoint
+func (x *PeersResponse) GetEndpoint() string {
+	if x != nil {
+		return x.Endpoint
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetAddress() string {
-	if m != nil {
-		return m.Address
+func (x *PeersResponse) GetAddress() string {
+	if x != nil {
+		return x.Address
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetListenport() int32 {
-	if m != nil {
-		return m.Listenport
+func (x *PeersResponse) GetAddress6() string {
+	if x != nil {
+		return x.Address6
+	}
+	return ""
+}
+
+func (x *PeersResponse) GetListenport() int32 {
+	if x != nil {
+		return x.Listenport
 	}
 	return 0
 }
 
-func (m *PeersResponse) GetLocaladdress() string {
-	if m != nil {
-		return m.Localaddress
+func (x *PeersResponse) GetLocaladdress() string {
+	if x != nil {
+		return x.Localaddress
 	}
 	return ""
 }
 
-func (m *PeersResponse) GetKeepalive() int32 {
-	if m != nil {
-		return m.Keepalive
+func (x *PeersResponse) GetKeepalive() int32 {
+	if x != nil {
+		return x.Keepalive
 	}
 	return 0
 }
 
 type CreateNodeReq struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CreateNodeReq) Reset()         { *m = CreateNodeReq{} }
-func (m *CreateNodeReq) String() string { return proto.CompactTextString(m) }
-func (*CreateNodeReq) ProtoMessage()    {}
-func (*CreateNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{5}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` // Node id blank
 }
 
-func (m *CreateNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CreateNodeReq.Unmarshal(m, b)
-}
-func (m *CreateNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CreateNodeReq.Marshal(b, m, deterministic)
-}
-func (m *CreateNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CreateNodeReq.Merge(m, src)
+func (x *CreateNodeReq) Reset() {
+	*x = CreateNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CreateNodeReq) XXX_Size() int {
-	return xxx_messageInfo_CreateNodeReq.Size(m)
+
+func (x *CreateNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CreateNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_CreateNodeReq.DiscardUnknown(m)
+
+func (*CreateNodeReq) ProtoMessage() {}
+
+func (x *CreateNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CreateNodeReq proto.InternalMessageInfo
+// Deprecated: Use CreateNodeReq.ProtoReflect.Descriptor instead.
+func (*CreateNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{5}
+}
 
-func (m *CreateNodeReq) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *CreateNodeReq) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type CreateNodeRes struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CreateNodeRes) Reset()         { *m = CreateNodeRes{} }
-func (m *CreateNodeRes) String() string { return proto.CompactTextString(m) }
-func (*CreateNodeRes) ProtoMessage()    {}
-func (*CreateNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{6}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` // Node id filled in
 }
 
-func (m *CreateNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CreateNodeRes.Unmarshal(m, b)
-}
-func (m *CreateNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CreateNodeRes.Marshal(b, m, deterministic)
-}
-func (m *CreateNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CreateNodeRes.Merge(m, src)
+func (x *CreateNodeRes) Reset() {
+	*x = CreateNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CreateNodeRes) XXX_Size() int {
-	return xxx_messageInfo_CreateNodeRes.Size(m)
+
+func (x *CreateNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CreateNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_CreateNodeRes.DiscardUnknown(m)
+
+func (*CreateNodeRes) ProtoMessage() {}
+
+func (x *CreateNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[6]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CreateNodeRes proto.InternalMessageInfo
+// Deprecated: Use CreateNodeRes.ProtoReflect.Descriptor instead.
+func (*CreateNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{6}
+}
 
-func (m *CreateNodeRes) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *CreateNodeRes) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type UpdateNodeReq struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *UpdateNodeReq) Reset()         { *m = UpdateNodeReq{} }
-func (m *UpdateNodeReq) String() string { return proto.CompactTextString(m) }
-func (*UpdateNodeReq) ProtoMessage()    {}
-func (*UpdateNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{7}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
 }
 
-func (m *UpdateNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_UpdateNodeReq.Unmarshal(m, b)
-}
-func (m *UpdateNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_UpdateNodeReq.Marshal(b, m, deterministic)
-}
-func (m *UpdateNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UpdateNodeReq.Merge(m, src)
+func (x *UpdateNodeReq) Reset() {
+	*x = UpdateNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *UpdateNodeReq) XXX_Size() int {
-	return xxx_messageInfo_UpdateNodeReq.Size(m)
+
+func (x *UpdateNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *UpdateNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_UpdateNodeReq.DiscardUnknown(m)
+
+func (*UpdateNodeReq) ProtoMessage() {}
+
+func (x *UpdateNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[7]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_UpdateNodeReq proto.InternalMessageInfo
+// Deprecated: Use UpdateNodeReq.ProtoReflect.Descriptor instead.
+func (*UpdateNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{7}
+}
 
-func (m *UpdateNodeReq) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *UpdateNodeReq) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type UpdateNodeRes struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *UpdateNodeRes) Reset()         { *m = UpdateNodeRes{} }
-func (m *UpdateNodeRes) String() string { return proto.CompactTextString(m) }
-func (*UpdateNodeRes) ProtoMessage()    {}
-func (*UpdateNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{8}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
 }
 
-func (m *UpdateNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_UpdateNodeRes.Unmarshal(m, b)
-}
-func (m *UpdateNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_UpdateNodeRes.Marshal(b, m, deterministic)
-}
-func (m *UpdateNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_UpdateNodeRes.Merge(m, src)
+func (x *UpdateNodeRes) Reset() {
+	*x = UpdateNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[8]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *UpdateNodeRes) XXX_Size() int {
-	return xxx_messageInfo_UpdateNodeRes.Size(m)
+
+func (x *UpdateNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *UpdateNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_UpdateNodeRes.DiscardUnknown(m)
+
+func (*UpdateNodeRes) ProtoMessage() {}
+
+func (x *UpdateNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[8]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_UpdateNodeRes proto.InternalMessageInfo
+// Deprecated: Use UpdateNodeRes.ProtoReflect.Descriptor instead.
+func (*UpdateNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{8}
+}
 
-func (m *UpdateNodeRes) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *UpdateNodeRes) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type ReadNodeReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Network              string   `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ReadNodeReq) Reset()         { *m = ReadNodeReq{} }
-func (m *ReadNodeReq) String() string { return proto.CompactTextString(m) }
-func (*ReadNodeReq) ProtoMessage()    {}
-func (*ReadNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{9}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Network    string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *ReadNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ReadNodeReq.Unmarshal(m, b)
-}
-func (m *ReadNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ReadNodeReq.Marshal(b, m, deterministic)
-}
-func (m *ReadNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ReadNodeReq.Merge(m, src)
+func (x *ReadNodeReq) Reset() {
+	*x = ReadNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ReadNodeReq) XXX_Size() int {
-	return xxx_messageInfo_ReadNodeReq.Size(m)
+
+func (x *ReadNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ReadNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_ReadNodeReq.DiscardUnknown(m)
+
+func (*ReadNodeReq) ProtoMessage() {}
+
+func (x *ReadNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ReadNodeReq proto.InternalMessageInfo
+// Deprecated: Use ReadNodeReq.ProtoReflect.Descriptor instead.
+func (*ReadNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{9}
+}
 
-func (m *ReadNodeReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *ReadNodeReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *ReadNodeReq) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *ReadNodeReq) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type ReadNodeRes struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *ReadNodeRes) Reset()         { *m = ReadNodeRes{} }
-func (m *ReadNodeRes) String() string { return proto.CompactTextString(m) }
-func (*ReadNodeRes) ProtoMessage()    {}
-func (*ReadNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{10}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
 }
 
-func (m *ReadNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_ReadNodeRes.Unmarshal(m, b)
-}
-func (m *ReadNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_ReadNodeRes.Marshal(b, m, deterministic)
-}
-func (m *ReadNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_ReadNodeRes.Merge(m, src)
+func (x *ReadNodeRes) Reset() {
+	*x = ReadNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *ReadNodeRes) XXX_Size() int {
-	return xxx_messageInfo_ReadNodeRes.Size(m)
+
+func (x *ReadNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *ReadNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_ReadNodeRes.DiscardUnknown(m)
+
+func (*ReadNodeRes) ProtoMessage() {}
+
+func (x *ReadNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_ReadNodeRes proto.InternalMessageInfo
+// Deprecated: Use ReadNodeRes.ProtoReflect.Descriptor instead.
+func (*ReadNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{10}
+}
 
-func (m *ReadNodeRes) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *ReadNodeRes) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type DeleteNodeReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	NetworkName          string   `protobuf:"bytes,2,opt,name=networkName,proto3" json:"networkName,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *DeleteNodeReq) Reset()         { *m = DeleteNodeReq{} }
-func (m *DeleteNodeReq) String() string { return proto.CompactTextString(m) }
-func (*DeleteNodeReq) ProtoMessage()    {}
-func (*DeleteNodeReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{11}
+	Macaddress  string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	NetworkName string `protobuf:"bytes,2,opt,name=networkName,proto3" json:"networkName,omitempty"`
 }
 
-func (m *DeleteNodeReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_DeleteNodeReq.Unmarshal(m, b)
-}
-func (m *DeleteNodeReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_DeleteNodeReq.Marshal(b, m, deterministic)
-}
-func (m *DeleteNodeReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_DeleteNodeReq.Merge(m, src)
+func (x *DeleteNodeReq) Reset() {
+	*x = DeleteNodeReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[11]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *DeleteNodeReq) XXX_Size() int {
-	return xxx_messageInfo_DeleteNodeReq.Size(m)
+
+func (x *DeleteNodeReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *DeleteNodeReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_DeleteNodeReq.DiscardUnknown(m)
+
+func (*DeleteNodeReq) ProtoMessage() {}
+
+func (x *DeleteNodeReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[11]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_DeleteNodeReq proto.InternalMessageInfo
+// Deprecated: Use DeleteNodeReq.ProtoReflect.Descriptor instead.
+func (*DeleteNodeReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{11}
+}
 
-func (m *DeleteNodeReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *DeleteNodeReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *DeleteNodeReq) GetNetworkName() string {
-	if m != nil {
-		return m.NetworkName
+func (x *DeleteNodeReq) GetNetworkName() string {
+	if x != nil {
+		return x.NetworkName
 	}
 	return ""
 }
 
 type DeleteNodeRes struct {
-	Success              bool     `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *DeleteNodeRes) Reset()         { *m = DeleteNodeRes{} }
-func (m *DeleteNodeRes) String() string { return proto.CompactTextString(m) }
-func (*DeleteNodeRes) ProtoMessage()    {}
-func (*DeleteNodeRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{12}
+	Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
 }
 
-func (m *DeleteNodeRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_DeleteNodeRes.Unmarshal(m, b)
-}
-func (m *DeleteNodeRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_DeleteNodeRes.Marshal(b, m, deterministic)
-}
-func (m *DeleteNodeRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_DeleteNodeRes.Merge(m, src)
+func (x *DeleteNodeRes) Reset() {
+	*x = DeleteNodeRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[12]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *DeleteNodeRes) XXX_Size() int {
-	return xxx_messageInfo_DeleteNodeRes.Size(m)
+
+func (x *DeleteNodeRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *DeleteNodeRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_DeleteNodeRes.DiscardUnknown(m)
+
+func (*DeleteNodeRes) ProtoMessage() {}
+
+func (x *DeleteNodeRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[12]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_DeleteNodeRes proto.InternalMessageInfo
+// Deprecated: Use DeleteNodeRes.ProtoReflect.Descriptor instead.
+func (*DeleteNodeRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{12}
+}
 
-func (m *DeleteNodeRes) GetSuccess() bool {
-	if m != nil {
-		return m.Success
+func (x *DeleteNodeRes) GetSuccess() bool {
+	if x != nil {
+		return x.Success
 	}
 	return false
 }
 
 type GetPeersReq struct {
-	Macaddress           string   `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
-	Network              string   `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *GetPeersReq) Reset()         { *m = GetPeersReq{} }
-func (m *GetPeersReq) String() string { return proto.CompactTextString(m) }
-func (*GetPeersReq) ProtoMessage()    {}
-func (*GetPeersReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{13}
+	Macaddress string `protobuf:"bytes,1,opt,name=macaddress,proto3" json:"macaddress,omitempty"`
+	Network    string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
 }
 
-func (m *GetPeersReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_GetPeersReq.Unmarshal(m, b)
-}
-func (m *GetPeersReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_GetPeersReq.Marshal(b, m, deterministic)
-}
-func (m *GetPeersReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetPeersReq.Merge(m, src)
+func (x *GetPeersReq) Reset() {
+	*x = GetPeersReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[13]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *GetPeersReq) XXX_Size() int {
-	return xxx_messageInfo_GetPeersReq.Size(m)
+
+func (x *GetPeersReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *GetPeersReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetPeersReq.DiscardUnknown(m)
+
+func (*GetPeersReq) ProtoMessage() {}
+
+func (x *GetPeersReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[13]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_GetPeersReq proto.InternalMessageInfo
+// Deprecated: Use GetPeersReq.ProtoReflect.Descriptor instead.
+func (*GetPeersReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{13}
+}
 
-func (m *GetPeersReq) GetMacaddress() string {
-	if m != nil {
-		return m.Macaddress
+func (x *GetPeersReq) GetMacaddress() string {
+	if x != nil {
+		return x.Macaddress
 	}
 	return ""
 }
 
-func (m *GetPeersReq) GetNetwork() string {
-	if m != nil {
-		return m.Network
+func (x *GetPeersReq) GetNetwork() string {
+	if x != nil {
+		return x.Network
 	}
 	return ""
 }
 
 type GetPeersRes struct {
-	Peers                *PeersResponse `protobuf:"bytes,1,opt,name=peers,proto3" json:"peers,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}       `json:"-"`
-	XXX_unrecognized     []byte         `json:"-"`
-	XXX_sizecache        int32          `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *GetPeersRes) Reset()         { *m = GetPeersRes{} }
-func (m *GetPeersRes) String() string { return proto.CompactTextString(m) }
-func (*GetPeersRes) ProtoMessage()    {}
-func (*GetPeersRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{14}
+	Peers *PeersResponse `protobuf:"bytes,1,opt,name=peers,proto3" json:"peers,omitempty"`
 }
 
-func (m *GetPeersRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_GetPeersRes.Unmarshal(m, b)
-}
-func (m *GetPeersRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_GetPeersRes.Marshal(b, m, deterministic)
-}
-func (m *GetPeersRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_GetPeersRes.Merge(m, src)
+func (x *GetPeersRes) Reset() {
+	*x = GetPeersRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[14]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *GetPeersRes) XXX_Size() int {
-	return xxx_messageInfo_GetPeersRes.Size(m)
+
+func (x *GetPeersRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *GetPeersRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_GetPeersRes.DiscardUnknown(m)
+
+func (*GetPeersRes) ProtoMessage() {}
+
+func (x *GetPeersRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[14]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_GetPeersRes proto.InternalMessageInfo
+// Deprecated: Use GetPeersRes.ProtoReflect.Descriptor instead.
+func (*GetPeersRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{14}
+}
 
-func (m *GetPeersRes) GetPeers() *PeersResponse {
-	if m != nil {
-		return m.Peers
+func (x *GetPeersRes) GetPeers() *PeersResponse {
+	if x != nil {
+		return x.Peers
 	}
 	return nil
 }
 
 type CheckInReq struct {
-	Node                 *Node    `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"`
-	XXX_NoUnkeyedLiteral struct{} `json:"-"`
-	XXX_unrecognized     []byte   `json:"-"`
-	XXX_sizecache        int32    `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CheckInReq) Reset()         { *m = CheckInReq{} }
-func (m *CheckInReq) String() string { return proto.CompactTextString(m) }
-func (*CheckInReq) ProtoMessage()    {}
-func (*CheckInReq) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{15}
+	Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` //   bool postchanges = 2;
 }
 
-func (m *CheckInReq) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CheckInReq.Unmarshal(m, b)
-}
-func (m *CheckInReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CheckInReq.Marshal(b, m, deterministic)
-}
-func (m *CheckInReq) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CheckInReq.Merge(m, src)
+func (x *CheckInReq) Reset() {
+	*x = CheckInReq{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[15]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CheckInReq) XXX_Size() int {
-	return xxx_messageInfo_CheckInReq.Size(m)
+
+func (x *CheckInReq) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CheckInReq) XXX_DiscardUnknown() {
-	xxx_messageInfo_CheckInReq.DiscardUnknown(m)
+
+func (*CheckInReq) ProtoMessage() {}
+
+func (x *CheckInReq) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[15]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CheckInReq proto.InternalMessageInfo
+// Deprecated: Use CheckInReq.ProtoReflect.Descriptor instead.
+func (*CheckInReq) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{15}
+}
 
-func (m *CheckInReq) GetNode() *Node {
-	if m != nil {
-		return m.Node
+func (x *CheckInReq) GetNode() *Node {
+	if x != nil {
+		return x.Node
 	}
 	return nil
 }
 
 type CheckInRes struct {
-	Checkinresponse      *CheckInResponse `protobuf:"bytes,1,opt,name=checkinresponse,proto3" json:"checkinresponse,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
-	XXX_unrecognized     []byte           `json:"-"`
-	XXX_sizecache        int32            `json:"-"`
-}
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
 
-func (m *CheckInRes) Reset()         { *m = CheckInRes{} }
-func (m *CheckInRes) String() string { return proto.CompactTextString(m) }
-func (*CheckInRes) ProtoMessage()    {}
-func (*CheckInRes) Descriptor() ([]byte, []int) {
-	return fileDescriptor_d13bd996b67da4ef, []int{16}
+	Checkinresponse *CheckInResponse `protobuf:"bytes,1,opt,name=checkinresponse,proto3" json:"checkinresponse,omitempty"`
 }
 
-func (m *CheckInRes) XXX_Unmarshal(b []byte) error {
-	return xxx_messageInfo_CheckInRes.Unmarshal(m, b)
-}
-func (m *CheckInRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return xxx_messageInfo_CheckInRes.Marshal(b, m, deterministic)
-}
-func (m *CheckInRes) XXX_Merge(src proto.Message) {
-	xxx_messageInfo_CheckInRes.Merge(m, src)
+func (x *CheckInRes) Reset() {
+	*x = CheckInRes{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_grpc_node_proto_msgTypes[16]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
 }
-func (m *CheckInRes) XXX_Size() int {
-	return xxx_messageInfo_CheckInRes.Size(m)
+
+func (x *CheckInRes) String() string {
+	return protoimpl.X.MessageStringOf(x)
 }
-func (m *CheckInRes) XXX_DiscardUnknown() {
-	xxx_messageInfo_CheckInRes.DiscardUnknown(m)
+
+func (*CheckInRes) ProtoMessage() {}
+
+func (x *CheckInRes) ProtoReflect() protoreflect.Message {
+	mi := &file_grpc_node_proto_msgTypes[16]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-var xxx_messageInfo_CheckInRes proto.InternalMessageInfo
+// Deprecated: Use CheckInRes.ProtoReflect.Descriptor instead.
+func (*CheckInRes) Descriptor() ([]byte, []int) {
+	return file_grpc_node_proto_rawDescGZIP(), []int{16}
+}
 
-func (m *CheckInRes) GetCheckinresponse() *CheckInResponse {
-	if m != nil {
-		return m.Checkinresponse
+func (x *CheckInRes) GetCheckinresponse() *CheckInResponse {
+	if x != nil {
+		return x.Checkinresponse
 	}
 	return nil
 }
 
-func init() {
-	proto.RegisterType((*LoginRequest)(nil), "node.LoginRequest")
-	proto.RegisterType((*LoginResponse)(nil), "node.LoginResponse")
-	proto.RegisterType((*Node)(nil), "node.Node")
-	proto.RegisterType((*CheckInResponse)(nil), "node.CheckInResponse")
-	proto.RegisterType((*PeersResponse)(nil), "node.PeersResponse")
-	proto.RegisterType((*CreateNodeReq)(nil), "node.CreateNodeReq")
-	proto.RegisterType((*CreateNodeRes)(nil), "node.CreateNodeRes")
-	proto.RegisterType((*UpdateNodeReq)(nil), "node.UpdateNodeReq")
-	proto.RegisterType((*UpdateNodeRes)(nil), "node.UpdateNodeRes")
-	proto.RegisterType((*ReadNodeReq)(nil), "node.ReadNodeReq")
-	proto.RegisterType((*ReadNodeRes)(nil), "node.ReadNodeRes")
-	proto.RegisterType((*DeleteNodeReq)(nil), "node.DeleteNodeReq")
-	proto.RegisterType((*DeleteNodeRes)(nil), "node.DeleteNodeRes")
-	proto.RegisterType((*GetPeersReq)(nil), "node.GetPeersReq")
-	proto.RegisterType((*GetPeersRes)(nil), "node.GetPeersRes")
-	proto.RegisterType((*CheckInReq)(nil), "node.CheckInReq")
-	proto.RegisterType((*CheckInRes)(nil), "node.CheckInRes")
-}
-
-func init() { proto.RegisterFile("grpc/node.proto", fileDescriptor_d13bd996b67da4ef) }
-
-var fileDescriptor_d13bd996b67da4ef = []byte{
-	// 903 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x5f, 0x6f, 0xe4, 0x34,
-	0x10, 0x57, 0xf7, 0xba, 0xdd, 0xed, 0x6c, 0xb7, 0xed, 0xb9, 0xdc, 0x61, 0xad, 0x50, 0xb5, 0x8a,
-	0x10, 0xea, 0x21, 0xda, 0x2d, 0x45, 0x42, 0xbc, 0x21, 0x71, 0x48, 0x27, 0x24, 0x38, 0x41, 0x10,
-	0x2f, 0xbc, 0xb9, 0xf1, 0x34, 0x17, 0x6d, 0x6a, 0xa7, 0xb1, 0xb7, 0xab, 0x7e, 0x00, 0xc4, 0x57,
-	0xe4, 0xc3, 0xf0, 0x80, 0x3c, 0x76, 0x36, 0x4e, 0x5a, 0xda, 0x83, 0x7b, 0x8b, 0x7f, 0x9e, 0x3f,
-	0x9e, 0x9f, 0x7f, 0x33, 0x0e, 0x1c, 0xe4, 0x75, 0x95, 0x2d, 0x94, 0x96, 0x78, 0x56, 0xd5, 0xda,
-	0x6a, 0xb6, 0xed, 0xbe, 0x13, 0x09, 0x7b, 0x3f, 0xea, 0xbc, 0x50, 0x29, 0xde, 0xac, 0xd0, 0x58,
-	0x76, 0x0c, 0x70, 0x2d, 0x32, 0x21, 0x65, 0x8d, 0xc6, 0xf0, 0xad, 0xf9, 0xd6, 0xc9, 0x6e, 0x1a,
-	0x21, 0x6c, 0x06, 0xe3, 0x4a, 0x18, 0xb3, 0xd6, 0xb5, 0xe4, 0x03, 0xda, 0xdd, 0xac, 0x19, 0x87,
-	0x91, 0x42, 0xbb, 0xd6, 0xf5, 0x92, 0x3f, 0xa3, 0xad, 0x66, 0x99, 0x7c, 0x09, 0xd3, 0x90, 0xc5,
-	0x54, 0x5a, 0x19, 0x64, 0x73, 0x98, 0x88, 0x2c, 0x43, 0x63, 0xac, 0x5e, 0xa2, 0x0a, 0x79, 0x62,
-	0x28, 0xf9, 0x6b, 0x08, 0xdb, 0x6f, 0xb5, 0x44, 0xb6, 0x0f, 0x83, 0x42, 0x06, 0x8b, 0x41, 0x21,
-	0x19, 0x83, 0x6d, 0x25, 0xae, 0x31, 0x64, 0xa7, 0x6f, 0x97, 0xb9, 0x39, 0x72, 0xc8, 0xdc, 0x9c,
-	0xf7, 0x18, 0xa0, 0x2c, 0x8c, 0x45, 0x55, 0xe9, 0xda, 0xf2, 0xed, 0xf9, 0xd6, 0xc9, 0x30, 0x8d,
-	0x10, 0xf6, 0x09, 0xec, 0x56, 0xab, 0xcb, 0xb2, 0xc8, 0x96, 0x78, 0xc7, 0x87, 0xe4, 0xdb, 0x02,
-	0xae, 0x5a, 0x54, 0xb2, 0xd2, 0x85, 0xb2, 0x7c, 0xc7, 0x57, 0xdb, 0xac, 0x7b, 0x4c, 0x8d, 0x1e,
-	0x65, 0x6a, 0xdc, 0x63, 0x6a, 0x0e, 0x13, 0xc7, 0x7e, 0xc3, 0xd6, 0xae, 0x2f, 0x3f, 0x82, 0xdc,
-	0xb9, 0x0a, 0x53, 0xa1, 0x92, 0x85, 0xca, 0x39, 0xcc, 0xb7, 0x4e, 0xc6, 0x69, 0x0b, 0xb0, 0x97,
-	0xb0, 0x53, 0x69, 0x63, 0x57, 0x15, 0x9f, 0x90, 0x6b, 0x58, 0x51, 0x4e, 0x6d, 0xac, 0xd4, 0x6b,
-	0xc5, 0xf7, 0x42, 0xce, 0xb0, 0x76, 0x11, 0x97, 0x88, 0x95, 0x28, 0x8b, 0x5b, 0xe4, 0x53, 0x22,
-	0xa2, 0x05, 0x5c, 0x35, 0x46, 0xdc, 0x62, 0xa6, 0xd5, 0x55, 0x91, 0xf3, 0x7d, 0x4a, 0x18, 0x21,
-	0xce, 0xdb, 0xdf, 0x8e, 0xe3, 0xe9, 0xc0, 0xf3, 0xb4, 0x01, 0xe8, 0xb4, 0xca, 0x62, 0x7d, 0x25,
-	0x32, 0xe4, 0x87, 0x7e, 0x77, 0x03, 0xb8, 0x6a, 0x4b, 0x61, 0x6c, 0xf6, 0x0e, 0xb3, 0x65, 0xa1,
-	0xf8, 0x73, 0x5f, 0x6d, 0x04, 0xb1, 0x04, 0xf6, 0xdc, 0xf2, 0x5a, 0xcb, 0xe2, 0xaa, 0x40, 0xc9,
-	0x19, 0x99, 0x74, 0x30, 0x76, 0x02, 0x07, 0xc1, 0x9c, 0x22, 0xdf, 0x8a, 0x92, 0x1f, 0x51, 0x15,
-	0x7d, 0x98, 0xa2, 0xe9, 0x4c, 0x94, 0xcd, 0xdd, 0x7c, 0x14, 0xa2, 0x45, 0x98, 0x3b, 0x93, 0x63,
-	0x26, 0x7b, 0x27, 0x54, 0x8e, 0x86, 0xbf, 0xf0, 0x67, 0x8a, 0x20, 0xc7, 0x88, 0x28, 0x4b, 0xbd,
-	0x46, 0x59, 0x54, 0x86, 0xbf, 0xf4, 0xf7, 0xdb, 0x22, 0x4e, 0x73, 0x85, 0xa1, 0x98, 0xfc, 0x63,
-	0xa2, 0xab, 0x59, 0x92, 0xe6, 0xdc, 0x47, 0xed, 0x02, 0x71, 0xee, 0x3d, 0x5b, 0x24, 0xf9, 0x63,
-	0x00, 0x07, 0xaf, 0xdd, 0x99, 0x7f, 0x68, 0x1b, 0x82, 0xc3, 0xc8, 0xac, 0x88, 0x4f, 0x92, 0xfa,
-	0x38, 0x6d, 0x96, 0xec, 0x33, 0xd8, 0x57, 0x88, 0xb2, 0x42, 0xac, 0x57, 0x95, 0x14, 0xd6, 0x2b,
-	0x7f, 0x9c, 0xf6, 0x50, 0xf6, 0x39, 0x1c, 0x3a, 0xc4, 0xdf, 0x57, 0xb0, 0x7c, 0x46, 0x96, 0xf7,
-	0xf0, 0x46, 0x7f, 0xd7, 0x68, 0x8c, 0xc8, 0x91, 0xda, 0x22, 0xe8, 0x2f, 0x40, 0x5d, 0xfd, 0x0d,
-	0xfb, 0xfa, 0xfb, 0x14, 0xa6, 0x2e, 0xe6, 0x12, 0xef, 0x42, 0xa2, 0x1d, 0xb2, 0xe8, 0x82, 0x8e,
-	0x07, 0x07, 0x48, 0x2c, 0xd1, 0x22, 0x75, 0xc8, 0x38, 0x8d, 0x90, 0xe4, 0xcf, 0x01, 0x4c, 0x7f,
-	0x46, 0xac, 0xcd, 0x86, 0x05, 0xca, 0x9a, 0x0b, 0x8b, 0x6b, 0x71, 0x17, 0x78, 0x68, 0x01, 0x77,
-	0xaf, 0xe1, 0xd3, 0x33, 0xeb, 0x27, 0x40, 0x07, 0xfb, 0x80, 0x7e, 0xfe, 0xff, 0x33, 0xa4, 0xaf,
-	0xb7, 0xd1, 0x03, 0x7a, 0x7b, 0xb4, 0xfb, 0x92, 0x05, 0x4c, 0x5f, 0xd7, 0x28, 0x2c, 0xba, 0x89,
-	0x97, 0xe2, 0x0d, 0x3b, 0x06, 0x1a, 0xcf, 0xc4, 0xc1, 0xe4, 0x02, 0xce, 0x68, 0x6e, 0xd3, 0xa6,
-	0x1f, 0xdb, 0x3d, 0x07, 0xf3, 0x3e, 0x0e, 0xbf, 0xd1, 0xad, 0xfc, 0x87, 0x0c, 0xb1, 0xc3, 0xd3,
-	0x19, 0xde, 0xc0, 0x24, 0x45, 0x21, 0xdb, 0xf8, 0x8f, 0x3f, 0x24, 0xd1, 0x63, 0x31, 0xe8, 0x3e,
-	0x16, 0xa7, 0x71, 0xa0, 0xa7, 0xf3, 0xfe, 0x02, 0xd3, 0xef, 0x49, 0x4f, 0xef, 0x9b, 0xd9, 0x89,
-	0xdf, 0xa7, 0x7a, 0xdb, 0xbe, 0x23, 0x31, 0x94, 0xbc, 0xea, 0x86, 0x34, 0xff, 0xde, 0x9d, 0xae,
-	0xea, 0x37, 0x68, 0x83, 0x8a, 0x3f, 0xa4, 0xea, 0x6f, 0xe2, 0x40, 0x86, 0xbd, 0x82, 0xa1, 0xeb,
-	0x6d, 0x13, 0xca, 0x3e, 0xf2, 0x65, 0x77, 0xba, 0x25, 0xf5, 0x16, 0xc9, 0x17, 0x00, 0x9b, 0x69,
-	0xf2, 0xf4, 0xbd, 0xfe, 0x14, 0x59, 0x1b, 0xf6, 0xed, 0x66, 0xa8, 0xd6, 0x21, 0x6a, 0x70, 0x7c,
-	0xe1, 0x1d, 0x7b, 0x63, 0x2a, 0xed, 0x5b, 0x5f, 0xfc, 0x3d, 0x80, 0x89, 0x8b, 0xfe, 0x2b, 0xd6,
-	0xb7, 0x45, 0x86, 0xec, 0x1c, 0x86, 0xf4, 0xd2, 0x33, 0xe6, 0x03, 0xc4, 0x3f, 0x17, 0xb3, 0xa3,
-	0x0e, 0x16, 0x7a, 0xfe, 0x6b, 0x80, 0x56, 0xca, 0x2c, 0x98, 0x74, 0xba, 0x61, 0xf6, 0x00, 0x68,
-	0xd8, 0x39, 0x8c, 0x1b, 0x99, 0xb0, 0xe7, 0xde, 0x20, 0xd2, 0xdf, 0xec, 0x1e, 0x64, 0x5c, 0xa6,
-	0x56, 0xd2, 0x4d, 0xa6, 0x4e, 0x57, 0xcc, 0x1e, 0x00, 0xc9, 0xaf, 0x95, 0x43, 0xe3, 0xd7, 0xd1,
-	0xdc, 0xec, 0x01, 0xd0, 0xb0, 0x0b, 0x18, 0x37, 0x57, 0xda, 0x9c, 0x30, 0xd2, 0xca, 0xec, 0x1e,
-	0x64, 0xce, 0xb7, 0xd8, 0x29, 0x8c, 0x02, 0xe7, 0xec, 0xb0, 0x77, 0x05, 0x37, 0xb3, 0x3e, 0x62,
-	0xbe, 0x5b, 0xfc, 0x7e, 0x9a, 0x6b, 0x9d, 0x97, 0x78, 0x96, 0xeb, 0x52, 0xa8, 0xfc, 0x4c, 0xd7,
-	0xf9, 0x82, 0xfe, 0xef, 0x2e, 0x57, 0x57, 0x0b, 0x7b, 0x57, 0xa1, 0x59, 0x2c, 0x95, 0x5e, 0x2b,
-	0xfa, 0xf3, 0xab, 0x2e, 0x2f, 0x77, 0x68, 0xf3, 0xab, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x44,
-	0xc2, 0xe7, 0x07, 0x0f, 0x0a, 0x00, 0x00,
+var File_grpc_node_proto protoreflect.FileDescriptor
+
+var file_grpc_node_proto_rawDesc = []byte{
+	0x0a, 0x0f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x12, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x64, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, 0x6e,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
+	0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
+	0x6f, 0x72, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x31, 0x0a,
+	0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20,
+	0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+	0x22, 0xae, 0x06, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+	0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x36, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x36, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72,
+	0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70,
+	0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65,
+	0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1e, 0x0a,
+	0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a,
+	0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x64,
+	0x65, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+	0x6e, 0x6f, 0x64, 0x65, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x69,
+	0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
+	0x69, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6f, 0x73,
+	0x74, 0x75, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x73, 0x74, 0x75,
+	0x70, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x0c, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1c, 0x0a,
+	0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05,
+	0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73,
+	0x61, 0x76, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x0a, 0x73, 0x61, 0x76, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x61,
+	0x63, 0x63, 0x65, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x74,
+	0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e,
+	0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x63,
+	0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x61,
+	0x73, 0x74, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x61, 0x73,
+	0x74, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0c, 0x6c, 0x61, 0x73, 0x74, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x28, 0x0a,
+	0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+	0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69, 0x6e, 0x69,
+	0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c,
+	0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x70,
+	0x6f, 0x73, 0x74, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1e, 0x0a,
+	0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x69, 0x70, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x69, 0x70, 0x73, 0x12, 0x18, 0x0a,
+	0x07, 0x69, 0x73, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
+	0x69, 0x73, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x64, 0x75, 0x61,
+	0x6c, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73,
+	0x64, 0x75, 0x61, 0x6c, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6e, 0x73,
+	0x6f, 0x66, 0x66, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x6e, 0x73, 0x6f, 0x66,
+	0x66, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18,
+	0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x72, 0x61, 0x6e, 0x67,
+	0x65, 0x22, 0x85, 0x02, 0x0a, 0x0f, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12,
+	0x26, 0x0a, 0x0e, 0x6e, 0x65, 0x65, 0x64, 0x70, 0x65, 0x65, 0x72, 0x75, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6e, 0x65, 0x65, 0x64, 0x70, 0x65, 0x65,
+	0x72, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x6e, 0x65, 0x65, 0x64, 0x63,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x08, 0x52, 0x10, 0x6e, 0x65, 0x65, 0x64, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x70, 0x64,
+	0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x6d, 0x65, 0x73, 0x73, 0x61,
+	0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x6d, 0x65,
+	0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x69,
+	0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x70, 0x65, 0x6e, 0x64,
+	0x69, 0x6e, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x6e, 0x65, 0x65, 0x64, 0x6b, 0x65, 0x79, 0x75, 0x70,
+	0x64, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x65, 0x65, 0x64,
+	0x6b, 0x65, 0x79, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6e, 0x65, 0x65,
+	0x64, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6e,
+	0x65, 0x65, 0x64, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x22, 0xa3, 0x02, 0x0a, 0x0d, 0x50, 0x65,
+	0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x69,
+	0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
+	0x69, 0x73, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x67, 0x61, 0x74,
+	0x65, 0x77, 0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x0c, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a,
+	0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65,
+	0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65,
+	0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+	0x73, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36, 0x18, 0x08, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x36, 0x12, 0x1e, 0x0a,
+	0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x0a,
+	0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
+	0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x0d,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x22,
+	0x2f, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71,
+	0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a,
+	0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65,
+	0x22, 0x2f, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65,
+	0x73, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+	0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64,
+	0x65, 0x22, 0x2f, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52,
+	0x65, 0x71, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f,
+	0x64, 0x65, 0x22, 0x2f, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
+	0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e,
+	0x6f, 0x64, 0x65, 0x22, 0x47, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52,
+	0x65, 0x71, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x2d, 0x0a, 0x0b,
+	0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x04, 0x6e,
+	0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65,
+	0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x51, 0x0a, 0x0d, 0x44,
+	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x0a,
+	0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x0a, 0x6d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x0b,
+	0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x29,
+	0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12,
+	0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x47, 0x0a, 0x0b, 0x47, 0x65, 0x74,
+	0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x63, 0x61,
+	0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x61,
+	0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77,
+	0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f,
+	0x72, 0x6b, 0x22, 0x38, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65,
+	0x73, 0x12, 0x29, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2c, 0x0a, 0x0a,
+	0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1e, 0x0a, 0x04, 0x6e, 0x6f,
+	0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
+	0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x4d, 0x0a, 0x0a, 0x43, 0x68,
+	0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x0f, 0x63, 0x68, 0x65, 0x63,
+	0x6b, 0x69, 0x6e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x15, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x6e,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x69,
+	0x6e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xfc, 0x02, 0x0a, 0x0b, 0x4e, 0x6f,
+	0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x4c, 0x6f, 0x67,
+	0x69, 0x6e, 0x12, 0x12, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x4c, 0x6f,
+	0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0a, 0x43,
+	0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65,
+	0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x13,
+	0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
+	0x52, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x12,
+	0x11, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x52,
+	0x65, 0x71, 0x1a, 0x11, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x4e, 0x6f,
+	0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e,
+	0x6f, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x36, 0x0a,
+	0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x13, 0x2e, 0x6e, 0x6f,
+	0x64, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71,
+	0x1a, 0x13, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f,
+	0x64, 0x65, 0x52, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72,
+	0x73, 0x12, 0x11, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x65, 0x65, 0x72,
+	0x73, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50,
+	0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x30, 0x01, 0x12, 0x2d, 0x0a, 0x07, 0x43, 0x68, 0x65,
+	0x63, 0x6b, 0x49, 0x6e, 0x12, 0x10, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63,
+	0x6b, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x43, 0x68,
+	0x65, 0x63, 0x6b, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x6f, 0x6f, 0x67,
+	0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x6b, 0x6e, 0x6f,
+	0x77, 0x6e, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x33,
+}
+
+var (
+	file_grpc_node_proto_rawDescOnce sync.Once
+	file_grpc_node_proto_rawDescData = file_grpc_node_proto_rawDesc
+)
+
+func file_grpc_node_proto_rawDescGZIP() []byte {
+	file_grpc_node_proto_rawDescOnce.Do(func() {
+		file_grpc_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_node_proto_rawDescData)
+	})
+	return file_grpc_node_proto_rawDescData
+}
+
+var file_grpc_node_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
+var file_grpc_node_proto_goTypes = []interface{}{
+	(*LoginRequest)(nil),    // 0: node.LoginRequest
+	(*LoginResponse)(nil),   // 1: node.LoginResponse
+	(*Node)(nil),            // 2: node.Node
+	(*CheckInResponse)(nil), // 3: node.CheckInResponse
+	(*PeersResponse)(nil),   // 4: node.PeersResponse
+	(*CreateNodeReq)(nil),   // 5: node.CreateNodeReq
+	(*CreateNodeRes)(nil),   // 6: node.CreateNodeRes
+	(*UpdateNodeReq)(nil),   // 7: node.UpdateNodeReq
+	(*UpdateNodeRes)(nil),   // 8: node.UpdateNodeRes
+	(*ReadNodeReq)(nil),     // 9: node.ReadNodeReq
+	(*ReadNodeRes)(nil),     // 10: node.ReadNodeRes
+	(*DeleteNodeReq)(nil),   // 11: node.DeleteNodeReq
+	(*DeleteNodeRes)(nil),   // 12: node.DeleteNodeRes
+	(*GetPeersReq)(nil),     // 13: node.GetPeersReq
+	(*GetPeersRes)(nil),     // 14: node.GetPeersRes
+	(*CheckInReq)(nil),      // 15: node.CheckInReq
+	(*CheckInRes)(nil),      // 16: node.CheckInRes
+}
+var file_grpc_node_proto_depIdxs = []int32{
+	2,  // 0: node.CreateNodeReq.node:type_name -> node.Node
+	2,  // 1: node.CreateNodeRes.node:type_name -> node.Node
+	2,  // 2: node.UpdateNodeReq.node:type_name -> node.Node
+	2,  // 3: node.UpdateNodeRes.node:type_name -> node.Node
+	2,  // 4: node.ReadNodeRes.node:type_name -> node.Node
+	4,  // 5: node.GetPeersRes.peers:type_name -> node.PeersResponse
+	2,  // 6: node.CheckInReq.node:type_name -> node.Node
+	3,  // 7: node.CheckInRes.checkinresponse:type_name -> node.CheckInResponse
+	0,  // 8: node.NodeService.Login:input_type -> node.LoginRequest
+	5,  // 9: node.NodeService.CreateNode:input_type -> node.CreateNodeReq
+	9,  // 10: node.NodeService.ReadNode:input_type -> node.ReadNodeReq
+	7,  // 11: node.NodeService.UpdateNode:input_type -> node.UpdateNodeReq
+	11, // 12: node.NodeService.DeleteNode:input_type -> node.DeleteNodeReq
+	13, // 13: node.NodeService.GetPeers:input_type -> node.GetPeersReq
+	15, // 14: node.NodeService.CheckIn:input_type -> node.CheckInReq
+	1,  // 15: node.NodeService.Login:output_type -> node.LoginResponse
+	6,  // 16: node.NodeService.CreateNode:output_type -> node.CreateNodeRes
+	10, // 17: node.NodeService.ReadNode:output_type -> node.ReadNodeRes
+	8,  // 18: node.NodeService.UpdateNode:output_type -> node.UpdateNodeRes
+	12, // 19: node.NodeService.DeleteNode:output_type -> node.DeleteNodeRes
+	14, // 20: node.NodeService.GetPeers:output_type -> node.GetPeersRes
+	16, // 21: node.NodeService.CheckIn:output_type -> node.CheckInRes
+	15, // [15:22] is the sub-list for method output_type
+	8,  // [8:15] is the sub-list for method input_type
+	8,  // [8:8] is the sub-list for extension type_name
+	8,  // [8:8] is the sub-list for extension extendee
+	0,  // [0:8] is the sub-list for field type_name
+}
+
+func init() { file_grpc_node_proto_init() }
+func file_grpc_node_proto_init() {
+	if File_grpc_node_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_grpc_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*LoginRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*LoginResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*Node); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CheckInResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*PeersResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreateNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CreateNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*UpdateNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ReadNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ReadNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DeleteNodeReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DeleteNodeRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetPeersReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*GetPeersRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CheckInReq); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_grpc_node_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*CheckInRes); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_grpc_node_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   17,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_grpc_node_proto_goTypes,
+		DependencyIndexes: file_grpc_node_proto_depIdxs,
+		MessageInfos:      file_grpc_node_proto_msgTypes,
+	}.Build()
+	File_grpc_node_proto = out.File
+	file_grpc_node_proto_rawDesc = nil
+	file_grpc_node_proto_goTypes = nil
+	file_grpc_node_proto_depIdxs = nil
 }

+ 5 - 1
grpc/node.proto

@@ -24,6 +24,7 @@ message Node {
     string id = 1;
     string name = 2;
     string address = 3;
+    string address6 = 26;
     int32 listenport = 4;
     string publickey = 5;
     string endpoint = 6;
@@ -44,7 +45,9 @@ message Node {
     string postchanges = 21;
     string allowedips = 22;
     bool islocal = 23;
-    string localrange = 24;
+    bool isdualstack = 27;
+    bool dnsoff = 24;
+    string localrange = 25;
 }
 
 message CheckInResponse {
@@ -63,6 +66,7 @@ message PeersResponse {
     string publickey = 5;
     string endpoint = 6;
     string address = 3;
+    string address6 = 8;
     int32 listenport = 4;
     string localaddress = 7;
     int32 keepalive = 13;

+ 56 - 192
main.go

@@ -5,20 +5,11 @@ package main
 
 import (
     "log"
-    "flag"
-    "github.com/gravitl/netmaker/models"
     "github.com/gravitl/netmaker/controllers"
+    "github.com/gravitl/netmaker/servercfg"
     "github.com/gravitl/netmaker/serverctl"
-    "github.com/gravitl/netmaker/functions"
     "github.com/gravitl/netmaker/mongoconn"
-    "github.com/gravitl/netmaker/config"
-    "go.mongodb.org/mongo-driver/bson"
     "fmt"
-    "time"
-    "net/http"
-    "strings"
-    "errors"
-    "io/ioutil"
     "os"
     "os/exec"
     "net"
@@ -26,70 +17,82 @@ import (
     "strconv"
     "sync"
     "os/signal"
-    "go.mongodb.org/mongo-driver/mongo"
     service "github.com/gravitl/netmaker/controllers"
     nodepb "github.com/gravitl/netmaker/grpc"
     "google.golang.org/grpc"
 )
 
-var ServerGRPC string
-var PortGRPC string
-
 //Start MongoDB Connection and start API Request Handler
 func main() {
 
+	//Client Mode Prereq Check
+	if servercfg.IsClientMode() {
+		cmd := exec.Command("id", "-u")
+		output, err := cmd.Output()
 
-	var clientmode string
-	var defaultnet string
-	flag.StringVar(&clientmode, "clientmode", "on", "Have a client on the server")
-	flag.StringVar(&defaultnet, "defaultnet", "on", "Create a default network")
-	flag.Parse()
-	if clientmode == "on" {
-
-         cmd := exec.Command("id", "-u")
-         output, err := cmd.Output()
-
-         if err != nil {
-                 log.Fatal(err)
-         }
-         i, err := strconv.Atoi(string(output[:len(output)-1]))
-         if err != nil {
-                 log.Fatal(err)
-         }
-
-         if i != 0 {
-                 log.Fatal("To run in client mode requires root privileges. Either turn off client mode with the --clientmode=off flag, or run with sudo.")
-         }
+		if err != nil {
+			fmt.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.")
+			log.Fatal(err)
+		}
+		i, err := strconv.Atoi(string(output[:len(output)-1]))
+		if err != nil {
+                        fmt.Println("Error retrieving uid from 'id -u' for prereq check. Please investigate or disable client mode.")
+			log.Fatal(err)
+		}
+		if i != 0 {
+			log.Fatal("To run in client mode requires root privileges. Either disable client mode or run with sudo.")
+		}
 	}
 
-	log.Println("Server starting...")
+	//Start Mongodb
 	mongoconn.ConnectDatabase()
 
 	installserver := false
-	if !(defaultnet == "off") {
-	if config.Config.Server.CreateDefault {
-		created, err := createDefaultNetwork()
-		if err != nil {
-			fmt.Printf("Error creating default network: %v", err)
-		}
-		if created && clientmode != "off" {
-			installserver = true
-		}
+
+	//Create the default network (default: 10.10.10.0/24)
+	created, err := serverctl.CreateDefaultNetwork()
+	if err != nil {
+		fmt.Printf("Error creating default network: %v", err)
 	}
+
+	if created && servercfg.IsClientMode() {
+		installserver = true
 	}
+
+	//NOTE: Removed Check and Logic for DNS Mode
+	//Reasoning. DNS Logic is very small on server. Can run with little/no impact. Just sets a tiny config file.
+	//Real work is done by CoreDNS
+	//We can just not run CoreDNS. On Agent side is only necessary check for IsDNSMode, which we will pass.
+
 	var waitnetwork sync.WaitGroup
 
-	if config.Config.Server.AgentBackend {
+	//Run Agent Server
+	if servercfg.IsAgentBackend() {
+	        if !(servercfg.DisableRemoteIPCheck()) && servercfg.GetGRPCHost() == "127.0.0.1" {
+			err := servercfg.SetHost()
+			if err != nil {
+				fmt.Println("Unable to Set host. Exiting.")
+				log.Fatal(err)
+			}
+		}
 		waitnetwork.Add(1)
 		go runGRPC(&waitnetwork, installserver)
 	}
 
-	if config.Config.Server.RestBackend {
+	//Run Rest Server
+	if servercfg.IsRestBackend() {
+                if !servercfg.DisableRemoteIPCheck() && servercfg.GetAPIHost() == "127.0.0.1" {
+                        err := servercfg.SetHost()
+                        if err != nil {
+                                fmt.Println("Unable to Set host. Exiting.")
+                                log.Fatal(err)
+                        }
+                }
 		waitnetwork.Add(1)
 		controller.HandleRESTRequests(&waitnetwork)
 	}
-	if !config.Config.Server.RestBackend && !config.Config.Server.AgentBackend {
-		fmt.Println("Oops! No Server Mode selected. Nothing being served.")
+	if !servercfg.IsAgentBackend() && !servercfg.IsRestBackend() {
+		fmt.Println("Oops! No Server Mode selected. Nothing is being served! Set either Agent mode (AGENT_BACKEND) or Rest mode (REST_BACKEND) to 'true'.")
 	}
 	waitnetwork.Wait()
 	fmt.Println("Exiting now.")
@@ -105,38 +108,9 @@ func runGRPC(wg *sync.WaitGroup, installserver bool) {
         // Pipe flags to one another (log.LstdFLags = log.Ldate | log.Ltime)
         log.SetFlags(log.LstdFlags | log.Lshortfile)
 
-        // Start our listener, 50051 is the default gRPC port
-	grpcport := ":50051"
-	if config.Config.Server.GrpcPort != "" {
-		grpcport = ":" + config.Config.Server.GrpcPort
-	}
-        if os.Getenv("GRPC_PORT") != "" {
-		grpcport = ":" + os.Getenv("GRPC_PORT")
-        }
-	PortGRPC = grpcport
-	if os.Getenv("BACKEND_URL") == ""  {
-		if config.Config.Server.Host == "" {
-			ServerGRPC, _ = getPublicIP()
-		} else {
-			ServerGRPC = config.Config.Server.Host
-		}
-	} else {
-		ServerGRPC = os.Getenv("BACKEND_URL")
-	}
-	fmt.Println("GRPC Server set to: " + ServerGRPC)
-	fmt.Println("GRPC Port set to: " + PortGRPC)
-	var gconf models.GlobalConfig
-	gconf.ServerGRPC = ServerGRPC
-	gconf.PortGRPC = PortGRPC
-	gconf.Name = "netmaker"
-	err := setGlobalConfig(gconf)
+	grpcport := servercfg.GetGRPCPort()
 
-	if err != nil && err != mongo.ErrNoDocuments{
-	      log.Fatalf("Unable to set global config: %v", err)
-	}
-
-
-	listener, err := net.Listen("tcp", grpcport)
+	listener, err := net.Listen("tcp", ":"+grpcport)
         // Handle errors if any
         if err != nil {
                 log.Fatalf("Unable to listen on port" + grpcport + ": %v", err)
@@ -163,8 +137,8 @@ func runGRPC(wg *sync.WaitGroup, installserver bool) {
         fmt.Println("Agent Server succesfully started on port " + grpcport + " (gRPC)")
 
 	if installserver {
-			fmt.Println("Adding server to " + config.Config.Server.DefaultNetName)
-                        success, err := serverctl.AddNetwork(config.Config.Server.DefaultNetName)
+			fmt.Println("Adding server to default network")
+                        success, err := serverctl.AddNetwork("default")
                         if err != nil {
                                 fmt.Printf("Error adding to default network: %v", err)
 				fmt.Println("")
@@ -179,8 +153,6 @@ func runGRPC(wg *sync.WaitGroup, installserver bool) {
 	}
         fmt.Println("Setup complete. You are ready to begin using netmaker.")
 
-
-
         // Right way to stop the server using a SHUTDOWN HOOK
         // Create a channel to receive OS signals
         c := make(chan os.Signal)
@@ -202,113 +174,6 @@ func runGRPC(wg *sync.WaitGroup, installserver bool) {
         mongoconn.Client.Disconnect(context.TODO())
         fmt.Println("MongoDB connection closed.")
 }
-func setGlobalConfig(globalconf models.GlobalConfig) (error) {
-
-        collection := mongoconn.Client.Database("netmaker").Collection("config")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-
-	create, _, err := functions.GetGlobalConfig()
-	if create {
-		_, err := collection.InsertOne(ctx, globalconf)
-		defer cancel()
-		if err != nil {
-			if err == mongo.ErrNoDocuments || strings.Contains(err.Error(), "no documents in result"){
-				return nil
-			} else {
-				return err
-			}
-		}
-	} else {
-		filter := bson.M{"name": "netmaker"}
-		update := bson.D{
-			{"$set", bson.D{
-				{"servergrpc", globalconf.ServerGRPC},
-				{"portgrpc", globalconf.PortGRPC},
-			}},
-		}
-		err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&globalconf)
-                        if err == mongo.ErrNoDocuments {
-			//if err == mongo.ErrNoDocuments || strings.Contains(err.Error(), "no documents in result"){
-                                return nil
-                        }
-	}
-	return err
-}
-
-func createDefaultNetwork() (bool, error) {
-
-	iscreated := false
-	exists, err := functions.NetworkExists(config.Config.Server.DefaultNetName)
-
-	if exists || err != nil {
-		fmt.Println("Default network already exists")
-		fmt.Println("Skipping default network create")
-		return iscreated, err
-	} else {
-
-	var network models.Network
-
-	network.NetID = config.Config.Server.DefaultNetName
-	network.AddressRange = config.Config.Server.DefaultNetRange
-	network.DisplayName = config.Config.Server.DefaultNetName
-        network.SetDefaults()
-        network.SetNodesLastModified()
-        network.SetNetworkLastModified()
-        network.KeyUpdateTimeStamp = time.Now().Unix()
-	priv := false
-	network.IsLocal = &priv
-        network.KeyUpdateTimeStamp = time.Now().Unix()
-	allow := true
-	network.AllowManualSignUp = &allow
-
-	fmt.Println("Creating default network.")
-
-
-        collection := mongoconn.Client.Database("netmaker").Collection("networks")
-        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-
-
-        // insert our network into the network table
-        _, err = collection.InsertOne(ctx, network)
-        defer cancel()
-
-	}
-	if err == nil {
-		iscreated = true
-	}
-	return iscreated, err
-
-
-}
-
-
-func getPublicIP() (string, error) {
-
-        iplist := []string{"https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
-        endpoint := ""
-        var err error
-            for _, ipserver := range iplist {
-                resp, err := http.Get(ipserver)
-                if err != nil {
-                        continue
-                }
-                defer resp.Body.Close()
-                if resp.StatusCode == http.StatusOK {
-                        bodyBytes, err := ioutil.ReadAll(resp.Body)
-                        if err != nil {
-                                continue
-                        }
-                        endpoint = string(bodyBytes)
-                        break
-                }
-
-        }
-        if err == nil && endpoint == "" {
-                err =  errors.New("Public Address Not Found.")
-        }
-        return endpoint, err
-}
-
 
 func authServerUnaryInterceptor() grpc.ServerOption {
 	return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)
@@ -316,4 +181,3 @@ func authServerUnaryInterceptor() grpc.ServerOption {
 func authServerStreamInterceptor() grpc.ServerOption {
         return grpc.StreamInterceptor(controller.AuthServerStreamInterceptor)
 }
-

+ 1 - 0
models/structs.go

@@ -93,6 +93,7 @@ type PeersResponse struct {
 	PublicKey    string `json:"publickey" bson:"publickey"`
 	Endpoint     string `json:"endpoint" bson:"endpoint"`
 	Address      string `json:"address" bson:"address"`
+	Address6     string `json:"address6" bson:"address6"`
 	LocalAddress string `json:"localaddress" bson:"localaddress"`
 	IsGateway    bool   `json:"isgateway" bson:"isgateway"`
 	GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`

+ 10 - 86
mongoconn/mongoconn.go

@@ -2,13 +2,10 @@ package mongoconn
 
 import (
 	"context"
-	"encoding/json"
 	"log"
-	"os"
-	"net/http"
 	"go.mongodb.org/mongo-driver/mongo"
 	"go.mongodb.org/mongo-driver/mongo/options"
-        "github.com/gravitl/netmaker/config"
+        "github.com/gravitl/netmaker/servercfg"
 )
 
 var Client *mongo.Client
@@ -21,53 +18,14 @@ var port string
 var opts string
 
 func setVars() {
-
-	//defaults
-	user = "admin"
-	pass = "password"
-	host = "localhost"
-	port = "27017"
-	opts = "/?authSource=admin"
-
-	//override with settings from config file
-	if config.Config.MongoConn.User != "" {
-		user = config.Config.MongoConn.User
-	}
-        if config.Config.MongoConn.Pass != "" {
-                pass = config.Config.MongoConn.Pass
-        }
-        if config.Config.MongoConn.Host != "" {
-                host = config.Config.MongoConn.Host
-        }
-        if config.Config.MongoConn.Port != "" {
-                port = config.Config.MongoConn.Port
-        }
-        if config.Config.MongoConn.Opts != "" {
-                opts = config.Config.MongoConn.Opts
-        }
-
-	//override with settings from env
-	if os.Getenv("MONGO_USER") != "" {
-		user = os.Getenv("MONGO_USER")
-	}
-        if os.Getenv("MONGO_PASS") != "" {
-                pass = os.Getenv("MONGO_PASS")
-        }
-        if os.Getenv("MONGO_HOST") != "" {
-                host = os.Getenv("MONGO_HOST")
-        }
-        if os.Getenv("MONGO_PORT") != "" {
-                port = os.Getenv("MONGO_PORT")
-        }
-        if os.Getenv("MONGO_OPTS") != "" {
-                opts = os.Getenv("MONGO_OPTS")
-        }
+	user = servercfg.GetMongoUser()
+	pass = servercfg.GetMongoPass()
+	host = servercfg.GetMongoHost()
+	port = servercfg.GetMongoPort()
+	opts = servercfg.GetMongoOpts()
 }
 
-//TODO: are we  even using  this besides at startup? Is it truely necessary?
-//TODO: Use config file instead of os.Getenv
 func ConnectDatabase() {
-    log.Println("Database connecting...")
     // Set client options
 
     setVars()
@@ -80,9 +38,11 @@ func ConnectDatabase() {
 						opts )
 
     // Connect to MongoDB
+    log.Println("Connecting to MongoDB at " + host + ":" + port + "...")
     client, err := mongo.Connect(context.TODO(), clientOptions)
     Client = client
     if err != nil {
+	log.Println("Error encountered connecting to MongoDB. Terminating.")
         log.Fatal(err)
     }
 
@@ -90,36 +50,14 @@ func ConnectDatabase() {
     err = Client.Ping(context.TODO(), nil)
 
     if err != nil {
+	log.Println("Error encountered pinging MongoDB. Terminating.")
         log.Fatal(err)
     }
 
     NodeDB = Client.Database("netmaker").Collection("nodes")
     NetworkDB = Client.Database("netmaker").Collection("networks")
 
-    log.Println("Database Connected.")
-}
-
-//TODO: IDK if we're using ConnectDB any more.... I think we're just using Client.Database
-//Review and see if this is necessary
-// ConnectDB : This is helper function to connect mongoDB
-func ConnectDB(db string, targetCollection string) *mongo.Collection {
-
-	// Set client options
-	//clientOptions := options.Client().ApplyURI("mongodb://mongoadmin:mongopassword@localhost:27017/?authSource=admin")
-	clientOptions := options.Client().ApplyURI("mongodb://" + os.Getenv("MONGO_USER") + ":" +
-	os.Getenv("MONGO_PASS") + "@" + os.Getenv("MONGO_HOST") + ":" + os.Getenv("MONGO_PORT") + os.Getenv("MONGO_OPTS") )
-
-	// Connect to MongoDB
-	client, err := mongo.Connect(context.TODO(), clientOptions)
-
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	//collection := client.Database("go_rest_api").Collection("wg")
-	collection := client.Database(db).Collection(targetCollection)
-
-	return collection
+    log.Println("MongoDB Connected.")
 }
 
 // ErrorResponse : This is error model.
@@ -127,17 +65,3 @@ type ErrorResponse struct {
 	StatusCode   int    `json:"status"`
 	ErrorMessage string `json:"message"`
 }
-
-// GetError : This is helper function to prepare error model.
-func GetError(err error, w http.ResponseWriter) {
-
-	var response = ErrorResponse{
-		ErrorMessage: err.Error(),
-		StatusCode:   http.StatusInternalServerError,
-	}
-
-	message, _ := json.Marshal(response)
-
-	w.WriteHeader(response.StatusCode)
-	w.Write(message)
-}

+ 4 - 6
netclient/config/config.go

@@ -31,8 +31,11 @@ type NodeConfig struct {
         MacAddress string `yaml:"macaddress"`
         LocalAddress string `yaml:"localaddress"`
         WGAddress string `yaml:"wgaddress"`
+        WGAddress6 string `yaml:"wgaddress6"`
         RoamingOff bool `yaml:"roamingoff"`
+        DNSOff bool `yaml:"dnsoff"`
         IsLocal bool `yaml:"islocal"`
+        IsDualStack bool `yaml:"isdualstack"`
         AllowedIPs string `yaml:"allowedips"`
         LocalRange string `yaml:"localrange"`
         PostUp string `yaml:"postup"`
@@ -43,6 +46,7 @@ type NodeConfig struct {
         PrivateKey string `yaml:"privatekey"`
         Endpoint string `yaml:"endpoint"`
         PostChanges string `yaml:"postchanges"`
+        IPForwarding string `yaml:"ipforwarding"`
 }
 
 //reading in the env file
@@ -234,9 +238,3 @@ func ReadConfig(network string) (*ClientConfig, error) {
 	}
 	return &cfg, err
 }
-/*
-func init() {
-  Config = readConfig()
-}
-*/
-

+ 98 - 10
netclient/functions/common.go

@@ -72,7 +72,7 @@ func GetFreePort(rangestart int32) (int32, error){
         return portno, err
 }
 
-func Install(accesskey string, password string, server string, network string, noauto bool, accesstoken string,  inputname string) error {
+func Install(accesskey string, password string, server string, network string, noauto bool, accesstoken string,  inputname string, pubip string, dnsoff bool, ipforward string) error {
 
 	tserver := ""
 	tnetwork := ""
@@ -143,6 +143,9 @@ func Install(accesskey string, password string, server string, network string, n
 	servercfg := cfg.Server
 	fmt.Println("SERVER SETTINGS:")
 
+	nodecfg.DNSOff = dnsoff
+	nodecfg.IPForwarding = ipforward
+
 	if server == "" {
 		if servercfg.Address == "" && tserver == "" {
 			log.Fatal("no server provided")
@@ -252,6 +255,9 @@ func Install(accesskey string, password string, server string, network string, n
 	}
        fmt.Println("     Local Address: " + localaddress)
 
+        if pubip != "" && pubip != "nopubip" {
+                endpoint = pubip
+        } else {
         if nodecfg.Endpoint == "" {
 		if islocal && localaddress != "" {
 			endpoint = localaddress
@@ -269,6 +275,7 @@ func Install(accesskey string, password string, server string, network string, n
                 endpoint = nodecfg.Endpoint
 		fmt.Println("Endpoint set in config. Setting to address: " + endpoint)
         }
+	}
        fmt.Println("     Endpoint: " + endpoint)
 
 
@@ -404,6 +411,7 @@ func Install(accesskey string, password string, server string, network string, n
        fmt.Println("NODE RECIEVED SETTINGS: ")
        fmt.Println("     Password: " + node.Password)
        fmt.Println("     WG Address: " + node.Address)
+       fmt.Println("     WG ipv6 Address: " + node.Address6)
        fmt.Println("     Network: " + node.Nodenetwork)
        fmt.Println("     Public  Endpoint: " + node.Endpoint)
        fmt.Println("     Local Address: " + node.Localaddress)
@@ -416,8 +424,12 @@ func Install(accesskey string, password string, server string, network string, n
        fmt.Println("     Public Key: " + node.Publickey)
        fmt.Println("     Mac Address: " + node.Macaddress)
        fmt.Println("     Is Local?: " + strconv.FormatBool(node.Islocal))
+       fmt.Println("     Is Dual Stack?: " + strconv.FormatBool(node.Isdualstack))
        fmt.Println("     Local Range: " + node.Localrange)
 
+       if node.Dnsoff==true && !nodecfg.DNSOff {
+		nodecfg.DNSOff = true
+	}
 	if !islocal && node.Islocal && node.Localrange != "" {
 		fmt.Println("Resetting local settings for local network.")
 		node.Localaddress, err = getLocalIP(node.Localrange)
@@ -442,7 +454,7 @@ func Install(accesskey string, password string, server string, network string, n
 		}
 	}
 
-	peers, hasGateway, gateways, err := getPeers(node.Macaddress, network, server)
+	peers, hasGateway, gateways, err := getPeers(node.Macaddress, network, server, node.Isdualstack)
 
 	if err != nil {
                 return err
@@ -514,7 +526,7 @@ func getLocalIP(localrange string) (string, error) {
 
 func getPublicIP() (string, error) {
 
-	iplist := []string{"https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
+	iplist := []string{"http://ip.client.gravitl.com","https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
 	endpoint := ""
 	var err error
 	    for _, ipserver := range iplist {
@@ -588,9 +600,19 @@ func modConfig(node *nodepb.Node) error{
         if node.Address != ""{
                 nodecfg.WGAddress = node.Address
         }
+        if node.Address6 != ""{
+                nodecfg.WGAddress6 = node.Address6
+        }
         if node.Postchanges != "" {
                 nodecfg.PostChanges = node.Postchanges
         }
+        if node.Dnsoff == true {
+                nodecfg.DNSOff = node.Dnsoff
+        }
+        if node.Isdualstack == true {
+                nodecfg.IsDualStack = true
+        }
+
         if node.Localrange != "" && node.Islocal {
                 nodecfg.IsLocal = true
                 nodecfg.LocalRange = node.Localrange
@@ -638,6 +660,7 @@ func initWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 
 
 	nodecfg := modcfg.Node
+	servercfg := modcfg.Server
 	fmt.Println("beginning local WG config")
 
 
@@ -659,7 +682,14 @@ func initWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 	if node.Address == "" {
 		log.Fatal("no address to configure")
 	}
-
+	nameserver := servercfg.Address
+	nameserver = strings.Split(nameserver, ":")[0]
+	network := node.Nodenetwork
+        if nodecfg.Network != "" {
+                network = nodecfg.Network
+        } else if node.Nodenetwork != "" {
+                network = node.Nodenetwork
+        }
         cmdIPDevLinkAdd := &exec.Cmd {
                 Path: ipExec,
                 Args: []string{ ipExec, "link", "add", "dev", ifacename, "type",  "wireguard" },
@@ -673,7 +703,6 @@ func initWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
                 Stderr: os.Stdout,
         }
 
-
          currentiface, err := net.InterfaceByName(ifacename)
 
 
@@ -733,6 +762,33 @@ func initWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 			fmt.Printf("This is inconvenient: %v", err)
 		}
 	}
+
+	//=========DNS Setup==========\\
+	if nodecfg.DNSOff != true {
+
+	        _, err := exec.LookPath("resolvectl")
+		if err != nil {
+			fmt.Println(err)
+			fmt.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
+		} else {
+			_, err = exec.Command("resolvectl", "domain", ifacename, "~"+network).Output()
+			if err != nil {
+				fmt.Println(err)
+				fmt.Println("WARNING: Error encountered setting dns. Aborted setting dns.")
+			} else {
+				_, err = exec.Command("resolvectl", "default-route", ifacename, "false").Output()
+				if err != nil {
+	                                fmt.Println(err)
+	                                fmt.Println("WARNING: Error encountered setting dns. Aborted setting dns.")
+				} else {
+					_, err = exec.Command("resolvectl", "dns", ifacename, nameserver).Output()
+					fmt.Println(err)
+				}
+			}
+		}
+	}
+        //=========End DNS Setup=======\\
+
         cmdIPLinkUp := &exec.Cmd {
                 Path: ipExec,
                 Args: []string{ ipExec, "link", "set", "up", "dev", ifacename},
@@ -773,7 +829,15 @@ func initWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
 		if err != nil {
                         fmt.Println("Error encountered adding gateway: " + err.Error())
                 }
+		}
 	}
+        if (node.Address6 != "" && node.Isdualstack) {
+		fmt.Println("Adding address: " + node.Address6)
+                out, err := exec.Command(ipExec, "address", "add", "dev", ifacename, node.Address6+"/64").Output()
+                if err != nil {
+                        fmt.Println(out)
+                        fmt.Println("Error encountered adding ipv6: " + err.Error())
+                }
 	}
 	return err
 }
@@ -867,7 +931,7 @@ func setWGConfig(network string) error {
         nodecfg := cfg.Node
         node := getNode(network)
 
-	peers, hasGateway, gateways, err := getPeers(node.Macaddress, nodecfg.Network, servercfg.Address)
+	peers, hasGateway, gateways, err := getPeers(node.Macaddress, nodecfg.Network, servercfg.Address, node.Isdualstack)
         if err != nil {
                 return err
         }
@@ -952,6 +1016,23 @@ func CheckIn(network string) error {
 	setupcheck := true
 	ipchange := false
 
+	if !(nodecfg.IPForwarding == "off") {
+		out, err := exec.Command("sysctl", "net.ipv4.ip_forward").Output()
+                 if err != nil {
+	                 fmt.Println(err)
+			 fmt.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.")
+                 } else {
+                         s := strings.Fields(string(out))
+                         if s[2] != "1" {
+				_, err = exec.Command("sysctl", "-w", "net.ipv4.ip_forward=1").Output()
+				if err != nil {
+					fmt.Println(err)
+					fmt.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.")
+				}
+			}
+		}
+	}
+
 	if !nodecfg.RoamingOff {
 		if !nodecfg.IsLocal {
 		fmt.Println("Checking to see if public addresses have changed")
@@ -1220,6 +1301,7 @@ func getNode(network string) nodepb.Node {
 	node.Nodenetwork = nodecfg.Network
 	node.Localaddress = nodecfg.LocalAddress
 	node.Address = nodecfg.WGAddress
+	node.Address6 = nodecfg.WGAddress6
 	node.Listenport = nodecfg.Port
 	node.Keepalive = nodecfg.KeepAlive
 	node.Postup = nodecfg.PostUp
@@ -1228,9 +1310,8 @@ func getNode(network string) nodepb.Node {
 	node.Macaddress = nodecfg.MacAddress
 	node.Endpoint = nodecfg.Endpoint
 	node.Password = nodecfg.Password
-
-	//spew.Dump(node)
-
+	node.Dnsoff = nodecfg.DNSOff
+	node.Isdualstack = nodecfg.IsDualStack
         return node
 }
 
@@ -1371,7 +1452,7 @@ func DeleteInterface(ifacename string, postdown string) error{
         return err
 }
 
-func getPeers(macaddress string, network string, server string) ([]wgtypes.PeerConfig, bool, []string, error) {
+func getPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, bool, []string, error) {
         //need to  implement checkin on server side
 	hasGateway := false
 	var gateways []string
@@ -1470,6 +1551,13 @@ func getPeers(macaddress string, network string, server string) ([]wgtypes.PeerC
 				allowedips = append(allowedips, *ipnet)
 			}
 		}
+                if res.Peers.Address6 != "" && dualstack {
+			var addr6 = net.IPNet{
+	                        IP: net.ParseIP(res.Peers.Address6),
+	                        Mask: net.CIDRMask(128, 128),
+	                }
+                        allowedips = append(allowedips, addr6)
+                }
 		if keepalive != 0 {
 		peer = wgtypes.PeerConfig{
 			PublicKey: pubkey,

+ 42 - 28
netclient/functions/local.go

@@ -6,6 +6,7 @@ import (
         "io/ioutil"
 	"path/filepath"
         "io"
+	"strings"
         "log"
         "os"
         "os/exec"
@@ -20,6 +21,27 @@ func FileExists(f string) bool {
     return !info.IsDir()
 }
 
+func SetDNS(nameserver string) error {
+	bytes, err := ioutil.ReadFile("/etc/resolv.conf")
+	if err != nil {
+		return err
+	}
+	resolvstring := string(bytes)
+	// //check whether s contains substring text
+	hasdns := strings.Contains(resolvstring, nameserver)
+	if hasdns {
+		return nil
+	}
+	resolv, err := os.OpenFile("/etc/resolv.conf",os.O_APPEND|os.O_WRONLY, 0644)
+	if err != nil {
+		return err
+	}
+	defer resolv.Close()
+	_, err = resolv.WriteString("nameserver " + nameserver + "\n")
+
+	return err
+}
+
 func ConfigureSystemD(network string) error {
 	/*
 	path, err := os.Getwd()
@@ -118,40 +140,32 @@ WantedBy=timers.target
                 return err
         }
 	}
-        sysExec, err := exec.LookPath("systemctl")
+        //sysExec, err := exec.LookPath("systemctl")
 
-        cmdSysEnableService := &exec.Cmd {
+        cmdSysEnableService := exec.Command("systemctl", "enable", "[email protected]")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "enable", "[email protected]" },
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-	/*
-        cmdSysStartService := &exec.Cmd {
-                Path: sysExec,
-                Args: []string{ sysExec, "start", "[email protected]"},
-                Stdout: os.Stdout,
-                Stderr: os.Stdout,
-        }
-	*/
-        cmdSysDaemonReload := &exec.Cmd {
+        }*/
+        cmdSysDaemonReload := exec.Command("systemctl", "daemon-reload")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "daemon-reload"},
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysEnableTimer := &exec.Cmd {
+        }*/
+        cmdSysEnableTimer := exec.Command("systemctl", "enable", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "enable", "netclient-"+network+".timer" },
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysStartTimer := &exec.Cmd {
+        }*/
+        cmdSysStartTimer := exec.Command("systemctl", "start", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
 		Args: []string{ sysExec, "start", "netclient-"+network+".timer"},
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
+        }*/
 
         err = cmdSysEnableService.Run()
         if  err  !=  nil {
@@ -191,7 +205,7 @@ func isOnlyService(network string) (bool, error) {
 }
 
 func RemoveSystemDServices(network string) error {
-        sysExec, err := exec.LookPath("systemctl")
+        //sysExec, err := exec.LookPath("systemctl")
 
 
 	fullremove, err := isOnlyService(network)
@@ -199,36 +213,36 @@ func RemoveSystemDServices(network string) error {
 		fmt.Println(err)
 	}
 
-        cmdSysDisableService := &exec.Cmd {
+	cmdSysDisableService := exec.Command("systemctl","disable","[email protected]")/* &exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "disable", "[email protected]"},
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysDaemonReload := &exec.Cmd {
+        }*/
+        cmdSysDaemonReload := exec.Command("systemctl","daemon-reload")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "daemon-reload"},
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysResetFailed := &exec.Cmd {
+        }*/
+        cmdSysResetFailed := exec.Command("systemctl","reset-failed")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "reset-failed"},
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysStopTimer := &exec.Cmd {
+        }*/
+        cmdSysStopTimer := exec.Command("systemctl", "stop", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "stop", "netclient-"+network+".timer" },
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
-        cmdSysDisableTimer := &exec.Cmd {
+        }*/
+        cmdSysDisableTimer :=  exec.Command("systemctl", "disable", "netclient-"+network+".timer")/*&exec.Cmd {
                 Path: sysExec,
                 Args: []string{ sysExec, "disable", "netclient-"+network+".timer"},
                 Stdout: os.Stdout,
                 Stderr: os.Stdout,
-        }
+        }*/
 
         //err = cmdSysStopService.Run()
         if  err  !=  nil {

+ 6 - 4
netclient/main.go

@@ -39,8 +39,10 @@ func main() {
 	tname := flag.String("name", "noname", "give the node a name at runtime")
 	tserver := flag.String("s", "localhost:50051", "The location (including port) of the remote gRPC server.")
 	tnetwork := flag.String("n", "nonetwork", "The node network you are attempting to join.")
+	tdnsoff := flag.Bool("dnsoff", false, "DNS Mode. If true, netclient will not alter system dns. false by default.")
+	tpublicip := flag.String("ip4", "nopubip", "The node network you are attempting to join.")
 	tnoauto := flag.Bool("na", false, "No auto mode. If true, netmclient will not be installed as a system service and you will have to retrieve updates manually via checkin command.")
-	tnoforward := flag.Bool("nf", false, "No Forward mode. If true, netclient will not check for IP forwarding. This may break functionality")
+	tipforward := flag.String("nf", "on", "No Forward mode. If true, netclient will not check for IP forwarding. This may break functionality")
 	command := flag.String("c", "required", "The command to run")
 
 
@@ -89,7 +91,7 @@ func main() {
                                 fmt.Println("Required, '-n'. No network provided. Exiting.")
                                 os.Exit(1)
                         }
-
+			/*
 			if !*tnoforward {
 				forward := exec.Command("sysctl", "net.ipv4.ip_forward")
 				out, err := forward.Output()
@@ -106,9 +108,9 @@ func main() {
 					log.Fatal("It is recommended to enable IP Forwarding. Current status is: " +  s[2] + ", but should be 1. if you would like to run without IP Forwarding, re-run with flag '-nf true'")
 				}
 			}
-
+			*/
 			fmt.Println("Beginning agent installation.")
-			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken, *tname)
+			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken, *tname, *tpublicip, *tdnsoff, *tipforward)
 			if err != nil {
 				fmt.Println("Error encountered while installing.")
 				if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {

+ 0 - 0
netmaker-install-clientmode.sh → netmaker-install-v3.sh


+ 0 - 0
netclient-install.sh → scripts/netclient-install.sh


+ 60 - 0
scripts/netmaker-install-clientmode.sh

@@ -0,0 +1,60 @@
+#!/bin/sh
+set -e
+
+[ -z "$SERVER_DOMAIN" ] && echo "Need to set SERVER_DOMAIN (format: 1.2.3.4 or mybackend.com)" && exit 1;
+
+
+docker volume create mongovol && docker run -d --name mongodb -v mongovol:/data/db --network host -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=mongopass mongo --bind_ip 0.0.0.0 
+
+mkdir -p /etc/netmaker/config/environments
+wget -O /etc/netmaker/netmaker https://github.com/gravitl/netmaker/releases/download/latest/netmaker
+chmod +x /etc/netmaker/netmaker
+
+
+cat >/etc/netmaker/config/environments/dev.yaml<<EOL
+server:
+  host: "$SERVER_DOMAIN"
+  apiport: "8081"
+  grpcport: "50051"
+  masterkey: "secretkey"
+  allowedorigin: "*"
+  restbackend: true            
+  agentbackend: true
+  defaultnetname: "default"
+  defaultnetrange: "10.10.10.0/24"
+  createdefault: true
+mongoconn:
+  user: "mongoadmin"
+  pass: "mongopass"
+  host: "localhost"
+  port: "27017"
+  opts: '/?authSource=admin'
+EOL
+
+cat >/etc/netmaker/config/Corefile<<EOL
+. {
+    hosts /root/netmaker.hosts
+}
+EOL
+
+cat >/etc/systemd/system/netmaker.service<<EOL
+[Unit]
+Description=Netmaker Server
+After=network.target
+
+[Service]
+Type=simple
+Restart=on-failure
+
+WorkingDirectory=/etc/netmaker
+ExecStart=/etc/netmaker/netmaker
+
+[Install]
+WantedBy=multi-user.target
+EOL
+systemctl daemon-reload
+systemctl start netmaker.service
+
+
+docker run -d --name netmaker-ui -p 80:80 -e BACKEND_URL="http://$SERVER_DOMAIN:8081" gravitl/netmaker-ui:v0.2
+docker run -d --name coredns --restart=always --volume=/etc/netmaker/config/:/root/ -p 52:53/udp coredns/coredns -conf /root/Corefile

+ 101 - 0
scripts/netmaker-install-local.sh

@@ -0,0 +1,101 @@
+#!/bin/sh
+set -x
+
+[ -z "$SERVER_DOMAIN" ] && echo "Need to set SERVER_DOMAIN (format: 1.2.3.4 or mybackend.com)" && exit 1;
+
+
+install() {
+
+docker volume create mongovol && docker run -d --name mongodb -v mongovol:/data/db -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=mongoadmin -e MONGO_INITDB_ROOT_PASSWORD=mongopass mongo 
+
+echo "Giving Mongo Time to Start"
+sleep 10
+echo "Installing Netmaker API"
+
+mkdir -p /etc/netmaker/config/environments
+mkdir -p /etc/netmaker/config/dnsconfig
+cp ../netmaker /etc/netmaker/netmaker
+chmod +x /etc/netmaker/netmaker
+
+
+cat >/etc/netmaker/config/environments/dev.yaml<<EOL
+server:
+  host: "$SERVER_DOMAIN"
+  apiport: "8081"
+  grpcport: "50051"
+  masterkey: "secretkey"
+  allowedorigin: "*"
+  restbackend: true            
+  agentbackend: true
+  defaultnetname: "default"
+  defaultnetrange: "10.10.10.0/24"
+  createdefault: true
+mongoconn:
+  user: "mongoadmin"
+  pass: "mongopass"
+  host: "127.0.0.1"
+  port: "27017"
+  opts: '/?authSource=admin'
+EOL
+
+cat >/etc/netmaker/config/dnsconfig/Corefile<<EOL
+. {
+    hosts ./root/netmaker.hosts {
+	fallthrough	
+    }
+    forward . 8.8.8.8 8.8.4.4
+    log
+}
+EOL
+
+cat >/etc/systemd/system/netmaker.service<<EOL
+[Unit]
+Description=Netmaker Server
+After=network.target
+
+[Service]
+Type=simple
+Restart=on-failure
+
+WorkingDirectory=/etc/netmaker
+ExecStart=/etc/netmaker/netmaker
+
+[Install]
+WantedBy=multi-user.target
+EOL
+systemctl daemon-reload
+systemctl start netmaker.service
+sudo docker pull coredns/coredns
+sudo docker pull gravitl/netmaker-ui:v0.3
+
+systemctl stop systemd-resolved
+systemctl disable systemd-resolved
+echo "Running CoreDNS"
+sudo docker run -d --name coredns --restart=always --volume=/etc/netmaker/config/dnsconfig/:/root/ -p 53:53/udp coredns/coredns -conf /root/Corefile
+
+echo "Running UI"
+sudo docker run -d --name netmaker-ui -p 80:80 -e BACKEND_URL="http://$SERVER_DOMAIN:8081" gravitl/netmaker-ui:v0.3
+
+echo "Setup Complete"
+}
+
+cleanup() {
+sudo docker kill mongodb || true
+sudo docker rm mongodb || true
+sudo docker volume rm mongovol || true
+sudo docker kill coredns || true
+sudo docker rm coredns || true
+sudo docker kill netmaker-ui || true
+sudo docker rm netmaker-ui || true
+sudo netclient -c remove -n default || true
+sudo rm -rf /etc/systemd/system/netmaker.service || true
+sudo rm -rf /etc/netmaker || true
+sudo systemctl enable systemd-resolved
+sudo systemctl start systemd-resolved
+sleep 5
+sudo systemctl restart systemd-resolved
+}
+
+trap cleanup ERR
+cleanup
+install

+ 0 - 0
netmaker-server.sh → scripts/netmaker-server.sh


+ 12 - 0
scripts/uninstall-netclient.sh

@@ -0,0 +1,12 @@
+#!/bin/sh
+set -x
+
+echo "Starting."
+
+sudo netclient -c remove-all || true
+sudo rm -rf /usr/local/bin/netclient || true
+sudo rm -rf /etc/netclient|| true
+find  /etc/systemd/system/ -name 'netclient*' -exec rm {} \;
+sudo systemctl daemon-reload || true
+
+echo "Done."

+ 26 - 0
scripts/uninstall-netmaker.sh

@@ -0,0 +1,26 @@
+#!/bin/sh
+set -x
+
+echo "Starting."
+
+sudo docker kill mongodb || true
+sudo docker rm mongodb || true
+sudo docker volume rm mongovol || true
+sudo  docker volume rm `docker volume ls -q -f dangling=true` || true
+sudo docker kill coredns || true
+sudo docker rm coredns || true
+sudo docker kill netmaker-ui || true
+sudo docker rm netmaker-ui || true
+sudo netclient -c remove -n default || true
+sudo rm -rf /etc/systemd/system/netmaker.service || true
+sudo rm -rf /etc/netmaker || true
+sudo rm -rf /usr/local/bin/netclient || true
+sudo rm -rf /etc/netclient|| true
+find  /etc/systemd/system/ -name 'netclient*' -exec rm {} \;
+sudo systemctl daemon-reload || true
+sudo systemctl enable systemd-resolved || true
+sudo systemctl start systemd-resolved || true
+sleep 5
+sudo systemctl restart systemd-resolved || true
+
+echo "Done."

+ 53 - 0
servercfg/mongoconf.go

@@ -0,0 +1,53 @@
+package servercfg
+
+import (
+        "github.com/gravitl/netmaker/config"
+        "os"
+)
+
+func GetMongoUser() string {
+	user := "mongoadmin"
+	if os.Getenv("MONGO_ADMIN") != "" {
+		user = os.Getenv("MONGO_ADMIN")
+	} else if  config.Config.MongoConn.User != "" {
+		user = config.Config.MongoConn.User
+	}
+	return user
+}
+func GetMongoPass() string {
+        pass := "mongopass"
+        if os.Getenv("MONGO_PASS") != "" {
+                pass = os.Getenv("MONGO_PASS")
+        } else if  config.Config.MongoConn.Pass != "" {
+                pass = config.Config.MongoConn.Pass
+        }
+        return pass
+}
+func GetMongoHost() string {
+        host := "127.0.0.1"
+        if os.Getenv("MONGO_HOST") != "" {
+                host = os.Getenv("MONGO_HOST")
+        } else if  config.Config.MongoConn.Host != "" {
+                host = config.Config.MongoConn.Host
+        }
+        return host
+}
+func GetMongoPort() string {
+        port := "27017"
+        if os.Getenv("MONGO_PORT") != "" {
+                port = os.Getenv("MONGO_PORT")
+        } else if  config.Config.MongoConn.Port != "" {
+                port = config.Config.MongoConn.Port
+        }
+        return port
+}
+func GetMongoOpts() string {
+        opts := "/?authSource=admin"
+        if os.Getenv("MONGO_OPTS") != "" {
+                opts = os.Getenv("MONGO_OPTS")
+        } else if  config.Config.MongoConn.Opts != "" {
+                opts = config.Config.MongoConn.Opts
+        }
+        return opts
+}
+

+ 199 - 0
servercfg/serverconf.go

@@ -0,0 +1,199 @@
+package servercfg
+
+import (
+        "github.com/gravitl/netmaker/config"
+	"net/http"
+	"io/ioutil"
+	"os"
+	"errors"
+)
+
+func SetHost() error {
+	remoteip, err := GetPublicIP()
+	if err != nil {
+		return err
+	}
+	os.Setenv("SERVER_HOST", remoteip)
+	return nil
+}
+func GetConfig() config.ServerConfig {
+	var cfg config.ServerConfig
+	cfg.APIHost = GetAPIHost()
+	cfg.APIPort = GetAPIPort()
+	cfg.GRPCHost = GetGRPCHost()
+	cfg.GRPCPort = GetGRPCPort()
+	cfg.MasterKey = "(hidden)"
+	cfg.AllowedOrigin = GetAllowedOrigin()
+	cfg.RestBackend = "off"
+	if IsRestBackend() {
+		cfg.RestBackend = "on"
+	}
+	cfg.AgentBackend = "off"
+        if IsAgentBackend() {
+                cfg.AgentBackend = "on"
+        }
+	cfg.ClientMode = "off"
+	if IsClientMode() {
+		cfg.ClientMode = "on"
+	}
+	cfg.DNSMode = "off"
+	if IsDNSMode() {
+	        cfg.DNSMode = "on"
+	}
+	cfg.DisableRemoteIPCheck = "off"
+	if DisableRemoteIPCheck() {
+		cfg.DisableRemoteIPCheck = "on"
+	}
+	return cfg
+}
+
+func GetAPIHost() string {
+        serverhost := "127.0.0.1"
+        if os.Getenv("SERVER_HTTP_HOST") != ""  {
+                serverhost = os.Getenv("SERVER_HTTP_HOST")
+        } else if config.Config.Server.APIHost != "" {
+		serverhost = config.Config.Server.APIHost
+        } else if os.Getenv("SERVER_HOST") != ""  {
+                serverhost = os.Getenv("SERVER_HOST")
+        }
+	return serverhost
+}
+func GetAPIPort() string {
+	apiport := "8081"
+	if os.Getenv("API_PORT") != "" {
+		apiport = os.Getenv("API_PORT")
+	} else if  config.Config.Server.APIPort != "" {
+		apiport = config.Config.Server.APIPort
+	}
+	return apiport
+}
+func GetGRPCHost() string {
+        serverhost := "127.0.0.1"
+        if os.Getenv("SERVER_GRPC_HOST") != ""  {
+                serverhost = os.Getenv("SERVER_GRPC_HOST")
+        } else if config.Config.Server.GRPCHost != "" {
+                serverhost = config.Config.Server.GRPCHost
+        } else if os.Getenv("SERVER_HOST") != ""  {
+                serverhost = os.Getenv("SERVER_HOST")
+        }
+        return serverhost
+}
+func GetGRPCPort() string {
+        grpcport := "50051"
+        if os.Getenv("GRPC_PORT") != "" {
+                grpcport = os.Getenv("GRPC_PORT")
+        } else if  config.Config.Server.GRPCPort != "" {
+                grpcport = config.Config.Server.GRPCPort
+        }
+        return grpcport
+}
+func GetMasterKey() string {
+        key := "secretkey"
+        if os.Getenv("MASTER_KEY") != "" {
+                key = os.Getenv("MASTER_KEY")
+        } else if  config.Config.Server.MasterKey != "" {
+                key = config.Config.Server.MasterKey
+        }
+        return key
+}
+func GetAllowedOrigin() string {
+        allowedorigin := "*"
+        if os.Getenv("CORS_ALLOWED_ORIGIN") != "" {
+                allowedorigin = os.Getenv("CORS_ALLOWED_ORIGIN")
+        } else if  config.Config.Server.AllowedOrigin != "" {
+                allowedorigin = config.Config.Server.AllowedOrigin
+        }
+        return allowedorigin
+}
+func IsRestBackend() bool {
+        isrest := true
+        if os.Getenv("REST_BACKEND") != "" {
+		if os.Getenv("REST_BACKEND") == "off" {
+			isrest = false
+		}
+	} else if config.Config.Server.RestBackend != "" {
+		if config.Config.Server.RestBackend == "off" {
+			isrest = false
+		}
+       }
+       return isrest
+}
+func IsAgentBackend() bool {
+        isagent := true
+        if os.Getenv("AGENT_BACKEND") != "" {
+                if os.Getenv("AGENT_BACKEND") == "off" {
+                        isagent = false
+                }
+        } else if config.Config.Server.AgentBackend != "" {
+                if config.Config.Server.AgentBackend == "off" {
+                        isagent = false
+                }
+       }
+       return isagent
+}
+func IsClientMode() bool {
+        isclient := true
+        if os.Getenv("CLIENT_MODE") != "" {
+                if os.Getenv("CLIENT_MODE") == "off" {
+                        isclient = false
+                }
+        } else if config.Config.Server.ClientMode != "" {
+                if config.Config.Server.ClientMode == "off" {
+                        isclient = false
+                }
+       }
+       return isclient
+}
+func IsDNSMode() bool {
+        isdns := true
+        if os.Getenv("DNS_MODE") != "" {
+                if os.Getenv("DNS_MODE") == "off" {
+                        isdns = false
+                }
+        } else if config.Config.Server.DNSMode != "" {
+                if config.Config.Server.DNSMode == "off" {
+                        isdns = false
+                }
+       }
+       return isdns
+}
+func DisableRemoteIPCheck() bool {
+        disabled := false
+        if os.Getenv("DISABLE_REMOTE_IP_CHECK") != "" {
+                if os.Getenv("DISABLE_REMOTE_IP_CHECK") == "on" {
+                        disabled = true
+                }
+        } else if config.Config.Server.DisableRemoteIPCheck != "" {
+                if config.Config.Server.DisableRemoteIPCheck == "on" {
+                        disabled= true
+                }
+       }
+       return disabled
+}
+func GetPublicIP() (string, error) {
+
+        endpoint := ""
+        var err error
+
+        iplist := []string{"http://ip.server.gravitl.com", "https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
+        for _, ipserver := range iplist {
+                resp, err := http.Get(ipserver)
+                if err != nil {
+                        continue
+                }
+                defer resp.Body.Close()
+                if resp.StatusCode == http.StatusOK {
+                        bodyBytes, err := ioutil.ReadAll(resp.Body)
+                        if err != nil {
+                                continue
+                        }
+                        endpoint = string(bodyBytes)
+                        break
+                }
+
+        }
+        if err == nil && endpoint == "" {
+                err =  errors.New("Public Address Not Found.")
+        }
+        return endpoint, err
+}

+ 104 - 8
serverctl/serverctl.go

@@ -2,17 +2,65 @@ package serverctl
 
 import (
         "fmt"
-  "github.com/gravitl/netmaker/functions"
+	"github.com/gravitl/netmaker/functions"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mongoconn"
+	"github.com/gravitl/netmaker/servercfg"
 	"io"
+	"time"
+	"context"
 	"errors"
-	"net/http"
         "os"
         "os/exec"
 )
 
+func CreateDefaultNetwork() (bool, error) {
 
-func DownloadNetclient() error {
+        fmt.Println("Creating default network...")
+
+        iscreated := false
+        exists, err := functions.NetworkExists("default")
+
+        if exists || err != nil {
+                fmt.Println("Default network already exists. Skipping...")
+                return iscreated, err
+        } else {
+
+        var network models.Network
+
+        network.NetID = "default"
+        network.AddressRange = "10.10.10.0/24"
+        network.DisplayName = "default"
+        network.SetDefaults()
+        network.SetNodesLastModified()
+        network.SetNetworkLastModified()
+        network.KeyUpdateTimeStamp = time.Now().Unix()
+        priv := false
+        network.IsLocal = &priv
+        network.KeyUpdateTimeStamp = time.Now().Unix()
+        allow := true
+        network.AllowManualSignUp = &allow
 
+        fmt.Println("Creating default network.")
+
+        collection := mongoconn.Client.Database("netmaker").Collection("networks")
+        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+
+        // insert our network into the network table
+        _, err = collection.InsertOne(ctx, network)
+        defer cancel()
+
+        }
+        if err == nil {
+                iscreated = true
+        }
+        return iscreated, err
+
+
+}
+
+func DownloadNetclient() error {
+	/*
 	// Get the data
 	resp, err := http.Get("https://github.com/gravitl/netmaker/releases/download/latest/netclient")
 	if err != nil {
@@ -23,16 +71,58 @@ func DownloadNetclient() error {
 
 	// Create the file
 	out, err := os.Create("/etc/netclient/netclient")
+        */
+        if !FileExists("/etc/netclient/netclient") {
+		_, err := copy("./netclient/netclient", "/etc/netclient/netclient")
 	if err != nil {
                 fmt.Println("could not create /etc/netclient")
 		return err
 	}
-	defer out.Close()
+	}
+	//defer out.Close()
 
 	// Write the body to file
-	_, err = io.Copy(out, resp.Body)
-	return err
+	//_, err = io.Copy(out, resp.Body)
+	return nil
+}
+
+func FileExists(f string) bool {
+    info, err := os.Stat(f)
+    if os.IsNotExist(err) {
+        return false
+    }
+    return !info.IsDir()
 }
+
+func copy(src, dst string) (int64, error) {
+        sourceFileStat, err := os.Stat(src)
+        if err != nil {
+                return 0, err
+        }
+
+        if !sourceFileStat.Mode().IsRegular() {
+                return 0, fmt.Errorf("%s is not a regular file", src)
+        }
+
+        source, err := os.Open(src)
+        if err != nil {
+                return 0, err
+        }
+        defer source.Close()
+
+        destination, err := os.Create(dst)
+        if err != nil {
+                return 0, err
+        }
+        defer destination.Close()
+        nBytes, err := io.Copy(destination, source)
+        err = os.Chmod(dst, 0755)
+        if err != nil {
+                fmt.Println(err)
+        }
+        return nBytes, err
+}
+
 func RemoveNetwork(network string) (bool, error) {
 	_, err := os.Stat("/etc/netclient/netclient")
         if err != nil {
@@ -50,7 +140,13 @@ func RemoveNetwork(network string) (bool, error) {
 }
 
 func AddNetwork(network string) (bool, error) {
-	_, err := os.Stat("/etc/netclient")
+	pubip, err := servercfg.GetPublicIP()
+        if err != nil {
+                fmt.Println("could not get public IP.")
+                return false, err
+        }
+
+	_, err = os.Stat("/etc/netclient")
         if os.IsNotExist(err) {
                 os.Mkdir("/etc/netclient", 744)
         } else if err != nil {
@@ -78,7 +174,7 @@ func AddNetwork(network string) (bool, error) {
                 return false, err
         }
 	fmt.Println("Client is ready. Running install.")
-	out, err := exec.Command("/etc/netclient/netclient","-c","install","-t",token,"-name","netmaker").Output()
+	out, err := exec.Command("/etc/netclient/netclient","-c","install","-t",token,"-name","netmaker","-ip4",pubip).Output()
         fmt.Println(string(out))
 	if err != nil {
                 return false, errors.New(string(out) + err.Error())

+ 0 - 15
test/api_test.go

@@ -2,7 +2,6 @@ package main
 
 import (
 	"bytes"
-	"context"
 	"encoding/json"
 	"io/ioutil"
 	"net/http"
@@ -46,20 +45,6 @@ func TestMain(m *testing.M) {
 	var waitgroup sync.WaitGroup
 	waitgroup.Add(1)
 	go controller.HandleRESTRequests(&waitgroup)
-	var gconf models.GlobalConfig
-	gconf.ServerGRPC = "localhost:8081"
-	gconf.PortGRPC = "50051"
-	//err := SetGlobalConfig(gconf)
-	collection := mongoconn.Client.Database("netmaker").Collection("config")
-	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
-	defer cancel()
-	//create, _, err := functions.GetGlobalConfig()
-	_, err := collection.InsertOne(ctx, gconf)
-	if err != nil {
-		panic("could not create config store")
-	}
-
-	//wait for http server to start
 	time.Sleep(time.Second * 1)
 	os.Exit(m.Run())
 }