Browse Source

Pull firewall command building to separate functions for easier maintenance/reuse. Change DeleteIngressGateway's approach to preserving the egress gateway (if present).

cameronts 3 years ago
parent
commit
a6660bb377
2 changed files with 122 additions and 131 deletions
  1. 86 96
      logic/gateway.go
  2. 36 35
      models/node.go

+ 86 - 96
logic/gateway.go

@@ -3,6 +3,7 @@ package logic
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
+	"fmt"
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
@@ -30,6 +31,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 	node.IsEgressGateway = "yes"
 	node.IsEgressGateway = "yes"
 	node.EgressGatewayRanges = gateway.Ranges
 	node.EgressGatewayRanges = gateway.Ranges
 	node.EgressGatewayNatEnabled = gateway.NatEnabled
 	node.EgressGatewayNatEnabled = gateway.NatEnabled
+	node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
 	postUpCmd := ""
 	postUpCmd := ""
 	postDownCmd := ""
 	postDownCmd := ""
 	logger.Log(3, "creating egress gateway firewall in use is '", node.FirewallInUse, "'")
 	logger.Log(3, "creating egress gateway firewall in use is '", node.FirewallInUse, "'")
@@ -43,28 +45,11 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 			// removing the chain with rules in it would remove all rules in that section (not safe
 			// removing the chain with rules in it would remove all rules in that section (not safe
 			// if there are remaining rules on the host that need to stay).  In practice the chain is removed
 			// if there are remaining rules on the host that need to stay).  In practice the chain is removed
 			// when non-empty even though the removal of a non-empty chain should not be possible per nftables wiki.
 			// when non-empty even though the removal of a non-empty chain should not be possible per nftables wiki.
-			postUpCmd = "nft add chain filter FORWARD ; "
-			postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-			postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-			postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-			postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-
-			if node.EgressGatewayNatEnabled == "yes" {
-				postUpCmd += "nft add chain filter POSTROUTING ; "
-				postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;"
-				postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;"
-			}
+			postUpCmd, postDownCmd = firewallNFTCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled)
+
 		default: // iptables assumed
 		default: // iptables assumed
 			logger.Log(3, "creating egress gateway nftables is not present")
 			logger.Log(3, "creating egress gateway nftables is not present")
-			postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; "
-			postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT"
-			postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; "
-			postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT"
-
-			if node.EgressGatewayNatEnabled == "yes" {
-				postUpCmd += "; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
-				postDownCmd += "; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
-			}
+			postUpCmd, postDownCmd = firewallIPTablesCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled)
 		}
 		}
 	}
 	}
 	if node.OS == "freebsd" {
 	if node.OS == "freebsd" {
@@ -139,8 +124,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
 
 
 	node.IsEgressGateway = "no"
 	node.IsEgressGateway = "no"
 	node.EgressGatewayRanges = []string{}
 	node.EgressGatewayRanges = []string{}
-	node.PostUp = ""
-	node.PostDown = ""
+	node.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone
 	logger.Log(3, "deleting egress gateway firewall in use is '", node.FirewallInUse, "'")
 	logger.Log(3, "deleting egress gateway firewall in use is '", node.FirewallInUse, "'")
 	if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules
 	if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules
 		// still have an ingress gateway so preserve it
 		// still have an ingress gateway so preserve it
@@ -150,22 +134,10 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
 				// nftables only supported on Linux
 				// nftables only supported on Linux
 				// assumes chains eg FORWARD and POSTROUTING already exist
 				// assumes chains eg FORWARD and POSTROUTING already exist
 				logger.Log(3, "deleting egress gateway nftables is present")
 				logger.Log(3, "deleting egress gateway nftables is present")
-				node.PostUp = "nft add chain filter FORWARD ; "
-				node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-				node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-				node.PostUp += "nft add chain filter POSTROUTING ; "
-				node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ; "
-				node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;"
-				node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;"
-				node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade "
+				node.PostUp, node.PostDown = firewallNFTCommandsCreateIngress(node.Interface)
 			default:
 			default:
 				logger.Log(3, "deleting egress gateway nftables is not present")
 				logger.Log(3, "deleting egress gateway nftables is not present")
-				node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; "
-				node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; "
-				node.PostUp += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
-				node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; "
-				node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; "
-				node.PostDown += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
+				node.PostUp, node.PostDown = firewallIPTablesCommandsCreateIngress(node.Interface)
 			}
 			}
 		}
 		}
 		// no need to preserve ingress gateway on FreeBSD as ingress is not supported on that OS
 		// no need to preserve ingress gateway on FreeBSD as ingress is not supported on that OS
@@ -210,22 +182,10 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) {
 		// nftables only supported on Linux
 		// nftables only supported on Linux
 		// assumes chains eg FORWARD and POSTROUTING already exist
 		// assumes chains eg FORWARD and POSTROUTING already exist
 		logger.Log(3, "creating ingress gateway nftables is present")
 		logger.Log(3, "creating ingress gateway nftables is present")
-		postUpCmd = "nft add chain filter FORWARD ; "
-		postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-		postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-		postUpCmd += "nft add chain filter POSTROUTING ; "
-		postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade"
-		postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-		postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-		postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade"
+		postUpCmd, postDownCmd = firewallNFTCommandsCreateIngress(node.Interface)
 	default:
 	default:
 		logger.Log(3, "creating ingress gateway using nftables is not present")
 		logger.Log(3, "creating ingress gateway using nftables is not present")
-		postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; "
-		postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; "
-		postUpCmd += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
-		postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; "
-		postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; "
-		postDownCmd += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
+		postUpCmd, postDownCmd = firewallIPTablesCommandsCreateIngress(node.Interface)
 	}
 	}
 
 
 	if node.PostUp != "" {
 	if node.PostUp != "" {
@@ -280,52 +240,12 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error
 	// default to removing postup and postdown
 	// default to removing postup and postdown
 	node.PostUp = ""
 	node.PostUp = ""
 	node.PostDown = ""
 	node.PostDown = ""
-	logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGatway is", node.IsEgressGateway)
-	if node.IsEgressGateway == "yes" { // check if node is still an egress gateway before completely deleting postdown/up rules
-		// still have an egress gateway so preserve it
-		switch node.FirewallInUse {
-		case models.FIREWALL_NFTABLES:
-			// nftables only supported on Linux
-			// preserve egress gateway via the setup that createegressgateway used
-			// assumes chains eg FORWARD and POSTROUTING already exist
-			logger.Log(3, "deleting ingress gateway: nftables is in use")
-			node.PostUp = "nft add chain filter FORWARD ; "
-			node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-			node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-			node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; "
-			node.PostDown += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; "
-
-			if node.EgressGatewayNatEnabled == "yes" {
-				node.PostUp += "nft add chain filter POSTROUTING ; "
-				node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;"
-				node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;"
-			}
-		default:
-			// preserve egress gateway via the setup that createegressgateway used
-			logger.Log(3, "deleting ingress gateway: nftables is not in use")
-			node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; "
-			node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT"
-			node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; "
-			node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT"
-
-			if node.EgressGatewayNatEnabled == "yes" {
-				node.PostUp += "; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE"
-				node.PostDown += "; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE"
-			}
-		}
-		// preserve egress gateway via the setup that createegressgateway used
-		if node.OS == "freebsd" {
-			node.PostUp = "kldload ipfw ipfw_nat ; "
-			node.PostUp += "ipfw disable one_pass ; "
-			node.PostUp += "ipfw nat 1 config if " + node.Interface + " same_ports unreg_only reset ; "
-			node.PostUp += "ipfw add 64000 reass all from any to any in ; "
-			node.PostUp += "ipfw add 64000 nat 1 ip from any to any in via " + node.Interface + " ; "
-			node.PostUp += "ipfw add 64000 check-state ; "
-			node.PostUp += "ipfw add 64000 nat 1 ip from any to any out via " + node.Interface + " ; "
-			node.PostUp += "ipfw add 65534 allow ip from any to any ; "
-			node.PostDown = "ipfw delete 64000 ; "
-			node.PostDown += "ipfw delete 65534 ; "
-			node.PostDown += "kldunload ipfw_nat ipfw"
+	logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGateway is", node.IsEgressGateway)
+	if node.EgressGatewayRequest.NodeID != "" {
+		_, err := CreateEgressGateway(node.EgressGatewayRequest)
+		if err != nil {
+			logger.Log(0, fmt.Sprintf("failed to create egress gateway on node [%s] on network [%s]: %v",
+				node.EgressGatewayRequest.NodeID, node.EgressGatewayRequest.NetID, err))
 		}
 		}
 	}
 	}
 
 
@@ -357,3 +277,73 @@ func DeleteGatewayExtClients(gatewayID string, networkName string) error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+
+// firewallNFTCommandsCreateIngress - used to centralize firewall command maintenance for creating an ingress gateway using the nftables firewall.
+func firewallNFTCommandsCreateIngress(networkInterface string) (string, string) {
+	postUp := "nft add table ip filter ; "
+	postUp += "nft add chain ip filter FORWARD ; "
+	postUp += "nft add rule ip filter FORWARD iifname " + networkInterface + " counter accept ; "
+	postUp += "nft add rule ip filter FORWARD oifname " + networkInterface + " counter accept ; "
+	postUp += "nft add table nat ; "
+	postUp += "nft add chain nat POSTROUTING ; "
+	postUp += "nft add rule ip nat POSTROUTING oifname " + networkInterface + " counter masquerade"
+
+	// doesn't remove potentially empty tables or chains
+	postDown := "nft delete rule ip filter FORWARD iifname " + networkInterface + " counter accept ; "
+	postDown += "nft delete rule ip filter FORWARD oifname " + networkInterface + " counter accept ; "
+	postDown += "nft delete rule ip nat POSTROUTING oifname " + networkInterface + " counter masquerade"
+
+	return postUp, postDown
+}
+
+// firewallNFTCommandsCreateEgress - used to centralize firewall command maintenance for creating an egress gateway using the nftables firewall.
+func firewallNFTCommandsCreateEgress(networkInterface string, gatewayInterface string, egressNatEnabled string) (string, string) {
+	postUp := "nft add table ip filter ; "
+	postUp += "nft add chain ip filter FORWARD ; "
+	postUp += "nft add rule ip filter FORWARD iifname " + networkInterface + " counter accept ; "
+	postUp += "nft add rule ip filter FORWARD oifname " + networkInterface + " counter accept ; "
+
+	postDown := "nft delete rule ip filter FORWARD iifname " + networkInterface + " counter accept ; "
+	postDown += "nft delete rule ip filter FORWARD oifname " + networkInterface + " counter accept ; "
+
+	if egressNatEnabled == "yes" {
+		postUp += "nft add table nat ; "
+		postUp += "nft add chain nat POSTROUTING ; "
+		postUp += "nft add rule ip nat POSTROUTING oifname " + gatewayInterface + " counter masquerade ;"
+
+		postDown += "nft delete rule ip nat POSTROUTING oifname " + gatewayInterface + " counter masquerade ;"
+	}
+
+	return postUp, postDown
+}
+
+// firewallIPTablesCommandsCreateIngress - used to centralize firewall command maintenance for creating an ingress gateway using the iptables firewall.
+func firewallIPTablesCommandsCreateIngress(networkInterface string) (string, string) {
+	postUp := "iptables -A FORWARD -i " + networkInterface + " -j ACCEPT ; "
+	postUp += "iptables -A FORWARD -o " + networkInterface + " -j ACCEPT ; "
+	postUp += "iptables -t nat -A POSTROUTING -o " + networkInterface + " -j MASQUERADE"
+
+	// doesn't remove potentially empty tables or chains
+	postDown := "iptables -D FORWARD -i " + networkInterface + " -j ACCEPT ; "
+	postDown += "iptables -D FORWARD -o " + networkInterface + " -j ACCEPT ; "
+	postDown += "iptables -t nat -D POSTROUTING -o " + networkInterface + " -j MASQUERADE"
+
+	return postUp, postDown
+}
+
+// firewallIPTablesCommandsCreateEgress - used to centralize firewall command maintenance for creating an egress gateway using the iptables firewall.
+func firewallIPTablesCommandsCreateEgress(networkInterface string, gatewayInterface string, egressNatEnabled string) (string, string) {
+
+	postUp := "iptables -A FORWARD -i " + networkInterface + " -j ACCEPT; "
+	postUp += "iptables -A FORWARD -o " + networkInterface + " -j ACCEPT"
+	postDown := "iptables -D FORWARD -i " + networkInterface + " -j ACCEPT; "
+	postDown += "iptables -D FORWARD -o " + networkInterface + " -j ACCEPT"
+
+	if egressNatEnabled == "yes" {
+		postUp += "; iptables -t nat -A POSTROUTING -o " + gatewayInterface + " -j MASQUERADE"
+		postDown += "; iptables -t nat -D POSTROUTING -o " + gatewayInterface + " -j MASQUERADE"
+	}
+
+	return postUp, postDown
+
+}

+ 36 - 35
models/node.go

@@ -39,41 +39,42 @@ var seededRand *rand.Rand = rand.New(
 
 
 // Node - struct for node model
 // Node - struct for node model
 type Node struct {
 type Node struct {
-	ID                      string   `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5" validate:"id_unique`
-	Address                 string   `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
-	Address6                string   `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
-	LocalAddress            string   `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
-	Name                    string   `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"`
-	NetworkSettings         Network  `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
-	ListenPort              int32    `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
-	LocalListenPort         int32    `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"`
-	PublicKey               string   `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
-	Endpoint                string   `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
-	PostUp                  string   `json:"postup" bson:"postup" yaml:"postup"`
-	PostDown                string   `json:"postdown" bson:"postdown" yaml:"postdown"`
-	AllowedIPs              []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
-	PersistentKeepalive     int32    `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
-	IsHub                   string   `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"`
-	AccessKey               string   `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
-	Interface               string   `json:"interface" bson:"interface" yaml:"interface"`
-	LastModified            int64    `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
-	ExpirationDateTime      int64    `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
-	LastPeerUpdate          int64    `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
-	LastCheckIn             int64    `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
-	MacAddress              string   `json:"macaddress" bson:"macaddress" yaml:"macaddress"`
-	Password                string   `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
-	Network                 string   `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
-	IsRelayed               string   `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
-	IsPending               string   `json:"ispending" bson:"ispending" yaml:"ispending"`
-	IsRelay                 string   `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"`
-	IsDocker                string   `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"`
-	IsK8S                   string   `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"`
-	IsEgressGateway         string   `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
-	IsIngressGateway        string   `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
-	EgressGatewayRanges     []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
-	EgressGatewayNatEnabled string   `json:"egressgatewaynatenabled" bson:"egressgatewaynatenabled" yaml:"egressgatewaynatenabled"`
-	RelayAddrs              []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"`
-	IngressGatewayRange     string   `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
+	ID                      string               `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5" validate:"id_unique`
+	Address                 string               `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
+	Address6                string               `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
+	LocalAddress            string               `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
+	Name                    string               `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"`
+	NetworkSettings         Network              `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
+	ListenPort              int32                `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
+	LocalListenPort         int32                `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"`
+	PublicKey               string               `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
+	Endpoint                string               `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
+	PostUp                  string               `json:"postup" bson:"postup" yaml:"postup"`
+	PostDown                string               `json:"postdown" bson:"postdown" yaml:"postdown"`
+	AllowedIPs              []string             `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
+	PersistentKeepalive     int32                `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
+	IsHub                   string               `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"`
+	AccessKey               string               `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
+	Interface               string               `json:"interface" bson:"interface" yaml:"interface"`
+	LastModified            int64                `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
+	ExpirationDateTime      int64                `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
+	LastPeerUpdate          int64                `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
+	LastCheckIn             int64                `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
+	MacAddress              string               `json:"macaddress" bson:"macaddress" yaml:"macaddress"`
+	Password                string               `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
+	Network                 string               `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
+	IsRelayed               string               `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
+	IsPending               string               `json:"ispending" bson:"ispending" yaml:"ispending"`
+	IsRelay                 string               `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"`
+	IsDocker                string               `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"`
+	IsK8S                   string               `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"`
+	IsEgressGateway         string               `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
+	IsIngressGateway        string               `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
+	EgressGatewayRanges     []string             `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
+	EgressGatewayNatEnabled string               `json:"egressgatewaynatenabled" bson:"egressgatewaynatenabled" yaml:"egressgatewaynatenabled"`
+	EgressGatewayRequest    EgressGatewayRequest `json:"egressgatewayrequest" bson:"egressgatewayrequest" yaml:"egressgatewayrequest"`
+	RelayAddrs              []string             `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"`
+	IngressGatewayRange     string               `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
 	// IsStatic - refers to if the Endpoint is set manually or dynamically
 	// IsStatic - refers to if the Endpoint is set manually or dynamically
 	IsStatic      string      `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"`
 	IsStatic      string      `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"`
 	UDPHolePunch  string      `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
 	UDPHolePunch  string      `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`