From 1f92d06d7ca930cfbe8aa54958c731e30447c4a8 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 18 Jan 2023 15:55:24 -0500 Subject: [PATCH 01/13] check host ports on join --- controllers/node.go | 3 +++ logic/hosts.go | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/controllers/node.go b/controllers/node.go index e121979a..8f4a255b 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -579,6 +579,9 @@ func createNode(w http.ResponseWriter, r *http.Request) { // consume password before hashing for mq client creation hostPassword := data.Host.HostPass data.Node.Server = servercfg.GetServer() + if !logic.HostExists(&data.Host) { + logic.CheckHostPorts(&data.Host) + } if err := logic.CreateHost(&data.Host); err != nil { if errors.Is(err, logic.ErrHostExists) { logger.Log(3, "host exists .. no need to create") diff --git a/logic/hosts.go b/logic/hosts.go index 8ebdaaa6..d9d791b4 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -315,3 +315,53 @@ func GetRelatedHosts(hostID string) []models.Host { } return relatedHosts } + +// CheckHostPort checks host endpoints to ensures that hosts on the same server +// with the same endpoint have different listen ports +// in the case of 64535 hosts or more with same endpoint, ports will not be changed +func CheckHostPorts(h *models.Host) { + listenPort := h.ListenPort + proxyPort := h.ProxyListenPort + count := 0 + reset := false + hosts, err := GetAllHosts() + if err != nil { + return + } + for _, host := range hosts { + if host.EndpointIP.Equal(h.EndpointIP) { + if host.ListenPort == h.ListenPort || host.ProxyListenPort == h.ProxyListenPort { + updateListenPorts(h) + count++ + //protect against endless recursion + if count > 64535 { + reset = true + break + } + CheckHostPorts(h) + } + } + } + if reset { + h.ListenPort = listenPort + h.ProxyListenPort = proxyPort + } +} + +// HostExists - checks if given host already exists +func HostExists(h *models.Host) bool { + _, err := GetHost(h.ID.String()) + if (err != nil && !database.IsEmptyRecord(err)) || (err == nil) { + return true + } + return false +} + +func updateListenPorts(h *models.Host) { + h.ListenPort++ + h.ProxyListenPort++ + if h.ListenPort > 65535 || h.ProxyListenPort > 65535 { + h.ListenPort = 1000 + h.ProxyListenPort = 1001 + } +} From 9edb541388c035999018bb9c63e40d247725449a Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 18 Jan 2023 16:27:44 -0500 Subject: [PATCH 02/13] remove localrange --- cli/cmd/network/create.go | 2 -- cli/cmd/network/flags.go | 1 - cli/cmd/network/update.go | 2 -- controllers/network.go | 14 ++------ controllers/network_test.go | 8 ----- logic/accesskeys.go | 5 --- logic/hosts.go | 4 --- logic/networks.go | 65 +++---------------------------------- models/accessToken.go | 5 ++- models/api_host.go | 14 +------- models/host.go | 2 +- models/network.go | 3 +- models/network_test.go | 9 ----- models/node.go | 10 +----- serverctl/serverctl.go | 2 +- swagger.yaml | 6 ---- 16 files changed, 14 insertions(+), 138 deletions(-) diff --git a/cli/cmd/network/create.go b/cli/cmd/network/create.go index 724d4d14..10615eed 100644 --- a/cli/cmd/network/create.go +++ b/cli/cmd/network/create.go @@ -53,7 +53,6 @@ var networkCreateCmd = &cobra.Command{ if allowManualSignUp { network.AllowManualSignUp = "yes" } - network.LocalRange = localRange network.DefaultExtClientDNS = defaultExtClientDNS network.DefaultMTU = int32(defaultMTU) } @@ -74,7 +73,6 @@ func init() { networkCreateCmd.Flags().StringVar(&defaultInterface, "interface", "", "Name of the network interface") networkCreateCmd.Flags().StringVar(&defaultPostUp, "post_up", "", "Commands to run after server is up `;` separated") networkCreateCmd.Flags().StringVar(&defaultPostDown, "post_down", "", "Commands to run after server is down `;` separated") - networkCreateCmd.Flags().StringVar(&localRange, "local_range", "", "Local CIDR range") networkCreateCmd.Flags().StringVar(&defaultExtClientDNS, "ext_client_dns", "", "IPv4 address of DNS server to be used by external clients") networkCreateCmd.Flags().IntVar(&defaultListenPort, "listen_port", 51821, "Default wireguard port each node will attempt to use") networkCreateCmd.Flags().IntVar(&nodeLimit, "node_limit", 999999999, "Maximum number of nodes that can be associated with this network") diff --git a/cli/cmd/network/flags.go b/cli/cmd/network/flags.go index 2c158f2a..38c1448d 100644 --- a/cli/cmd/network/flags.go +++ b/cli/cmd/network/flags.go @@ -16,7 +16,6 @@ var ( defaultPostDown string defaultKeepalive int allowManualSignUp bool - localRange string defaultExtClientDNS string defaultMTU int ) diff --git a/cli/cmd/network/update.go b/cli/cmd/network/update.go index 98717b29..e171487b 100644 --- a/cli/cmd/network/update.go +++ b/cli/cmd/network/update.go @@ -56,7 +56,6 @@ var networkUpdateCmd = &cobra.Command{ if allowManualSignUp { network.AllowManualSignUp = "yes" } - network.LocalRange = localRange network.DefaultExtClientDNS = defaultExtClientDNS network.DefaultMTU = int32(defaultMTU) } @@ -75,7 +74,6 @@ func init() { networkUpdateCmd.Flags().StringVar(&defaultInterface, "interface", "", "Name of the network interface") networkUpdateCmd.Flags().StringVar(&defaultPostUp, "post_up", "", "Commands to run after server is up `;` separated") networkUpdateCmd.Flags().StringVar(&defaultPostDown, "post_down", "", "Commands to run after server is down `;` separated") - networkUpdateCmd.Flags().StringVar(&localRange, "local_range", "", "Local CIDR range") networkUpdateCmd.Flags().StringVar(&defaultExtClientDNS, "ext_client_dns", "", "IPv4 address of DNS server to be used by external clients") networkUpdateCmd.Flags().IntVar(&defaultListenPort, "listen_port", 0, "Default wireguard port each node will attempt to use") networkUpdateCmd.Flags().IntVar(&nodeLimit, "node_limit", 0, "Maximum number of nodes that can be associated with this network") diff --git a/controllers/network.go b/controllers/network.go index 6dbdd6ae..026186a8 100644 --- a/controllers/network.go +++ b/controllers/network.go @@ -191,7 +191,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { newNetwork.DefaultPostUp = network.DefaultPostUp } - rangeupdate4, rangeupdate6, localrangeupdate, holepunchupdate, groupsDelta, userDelta, err := logic.UpdateNetwork(&network, &newNetwork) + rangeupdate4, rangeupdate6, holepunchupdate, groupsDelta, userDelta, err := logic.UpdateNetwork(&network, &newNetwork) if err != nil { logger.Log(0, r.Header.Get("user"), "failed to update network: ", err.Error()) @@ -237,17 +237,7 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { return } } - if localrangeupdate { - err = logic.UpdateNetworkLocalAddresses(network.NetID) - if err != nil { - logger.Log(0, r.Header.Get("user"), - fmt.Sprintf("failed to update network [%s] local addresses: %v", - network.NetID, err.Error())) - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) - return - } - } - if rangeupdate4 || rangeupdate6 || localrangeupdate || holepunchupdate { + if rangeupdate4 || rangeupdate6 || holepunchupdate { nodes, err := logic.GetNetworkNodes(network.NetID) if err != nil { logger.Log(0, r.Header.Get("user"), diff --git a/controllers/network_test.go b/controllers/network_test.go index 7814c7f9..06f1a2f2 100644 --- a/controllers/network_test.go +++ b/controllers/network_test.go @@ -271,14 +271,6 @@ func TestValidateNetwork(t *testing.T) { }, errMessage: "Field validation for 'DefaultKeepalive' failed on the 'max' tag", }, - { - testname: "InvalidLocalRange", - network: models.Network{ - NetID: "skynet", - LocalRange: "192.168.0.1", - }, - errMessage: "Field validation for 'LocalRange' failed on the 'cidr' tag", - }, } for _, tc := range cases { t.Run(tc.testname, func(t *testing.T) { diff --git a/logic/accesskeys.go b/logic/accesskeys.go index b3f9ebc0..376d633f 100644 --- a/logic/accesskeys.go +++ b/logic/accesskeys.go @@ -40,10 +40,6 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models return models.AccessKey{}, errors.New("duplicate AccessKey Name") } } - privAddr := "" - if network.IsLocal != "" { - privAddr = network.LocalRange - } netID := network.NetID @@ -52,7 +48,6 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models accessToken.APIConnString = servercfg.GetAPIConnString() accessToken.ClientConfig.Network = netID accessToken.ClientConfig.Key = accesskey.Value - accessToken.ClientConfig.LocalRange = privAddr tokenjson, err := json.Marshal(accessToken) if err != nil { diff --git a/logic/hosts.go b/logic/hosts.go index d9d791b4..737375c8 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -117,10 +117,6 @@ func UpdateHost(newHost, currentHost *models.Host) { newHost.Name = currentHost.Name } - if newHost.LocalRange.String() != currentHost.LocalRange.String() { - newHost.LocalRange = currentHost.LocalRange - } - if newHost.MTU == 0 { newHost.MTU = currentHost.MTU } diff --git a/logic/networks.go b/logic/networks.go index 2823bc99..ae8b22d1 100644 --- a/logic/networks.go +++ b/logic/networks.go @@ -298,60 +298,6 @@ func UniqueAddress6(networkName string, reverse bool) (net.IP, error) { return add, errors.New("ERROR: No unique IPv6 addresses available. Check network subnet") } -// GetLocalIP - gets the local ip -func GetLocalIP(node models.Node) string { - var local string - ifaces, err := net.Interfaces() - if err != nil { - return local - } - host, err := GetHost(node.HostID.String()) - if err != nil { - return local - } - localrange := host.LocalRange - found := false - for _, i := range ifaces { - if i.Flags&net.FlagUp == 0 { - continue // interface down - } - if i.Flags&net.FlagLoopback != 0 { - continue // loopback interface - } - addrs, err := i.Addrs() - if err != nil { - return local - } - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - if !found { - ip = v.IP - local = ip.String() - if node.IsLocal { - found = localrange.Contains(ip) - } else { - found = true - } - } - case *net.IPAddr: - if !found { - ip = v.IP - local = ip.String() - if node.IsLocal { - found = localrange.Contains(ip) - - } else { - found = true - } - } - } - } - } - return local -} - // UpdateNetworkLocalAddresses - updates network localaddresses func UpdateNetworkLocalAddresses(networkName string) error { @@ -517,14 +463,13 @@ func IsNetworkNameUnique(network *models.Network) (bool, error) { } // UpdateNetwork - updates a network with another network's fields -func UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) (bool, bool, bool, bool, []string, []string, error) { +func UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) (bool, bool, bool, []string, []string, error) { if err := ValidateNetwork(newNetwork, true); err != nil { - return false, false, false, false, nil, nil, err + return false, false, false, nil, nil, err } if newNetwork.NetID == currentNetwork.NetID { hasrangeupdate4 := newNetwork.AddressRange != currentNetwork.AddressRange hasrangeupdate6 := newNetwork.AddressRange6 != currentNetwork.AddressRange6 - localrangeupdate := newNetwork.LocalRange != currentNetwork.LocalRange hasholepunchupdate := newNetwork.DefaultUDPHolePunch != currentNetwork.DefaultUDPHolePunch groupDelta := append(StringDifference(newNetwork.ProSettings.AllowedGroups, currentNetwork.ProSettings.AllowedGroups), StringDifference(currentNetwork.ProSettings.AllowedGroups, newNetwork.ProSettings.AllowedGroups)...) @@ -532,14 +477,14 @@ func UpdateNetwork(currentNetwork *models.Network, newNetwork *models.Network) ( StringDifference(currentNetwork.ProSettings.AllowedUsers, newNetwork.ProSettings.AllowedUsers)...) data, err := json.Marshal(newNetwork) if err != nil { - return false, false, false, false, nil, nil, err + return false, false, false, nil, nil, err } newNetwork.SetNetworkLastModified() err = database.Insert(newNetwork.NetID, string(data), database.NETWORKS_TABLE_NAME) - return hasrangeupdate4, hasrangeupdate6, localrangeupdate, hasholepunchupdate, groupDelta, userDelta, err + return hasrangeupdate4, hasrangeupdate6, hasholepunchupdate, groupDelta, userDelta, err } // copy values - return false, false, false, false, nil, nil, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.") + return false, false, false, nil, nil, errors.New("failed to update network " + newNetwork.NetID + ", cannot change netid.") } // GetNetwork - gets a network from database diff --git a/models/accessToken.go b/models/accessToken.go index 61cd3a08..c3c4c0bf 100644 --- a/models/accessToken.go +++ b/models/accessToken.go @@ -8,7 +8,6 @@ type AccessToken struct { // ClientConfig - the config of the client type ClientConfig struct { - Network string `json:"network"` - Key string `json:"key"` - LocalRange string `json:"localrange"` + Network string `json:"network"` + Key string `json:"key"` } diff --git a/models/api_host.go b/models/api_host.go index 427e0876..c6306d93 100644 --- a/models/api_host.go +++ b/models/api_host.go @@ -13,7 +13,6 @@ type ApiHost struct { Debug bool `json:"debug"` IsStatic bool `json:"isstatic"` ListenPort int `json:"listenport"` - LocalRange string `json:"localrange"` LocalListenPort int `json:"locallistenport"` ProxyListenPort int `json:"proxy_listen_port"` MTU int `json:"mtu" yaml:"mtu"` @@ -50,10 +49,7 @@ func (h *Host) ConvertNMHostToAPI() *ApiHost { } a.IsStatic = h.IsStatic a.ListenPort = h.ListenPort - a.LocalRange = h.LocalRange.String() - if isEmptyAddr(a.LocalRange) { - a.LocalRange = "" - } + a.LocalListenPort = h.LocalListenPort a.MTU = h.MTU a.MacAddress = h.MacAddress.String() a.Name = h.Name @@ -106,14 +102,6 @@ func (a *ApiHost) ConvertAPIHostToNMHost(currentHost *Host) *Host { h.RelayedHosts = a.RelayedHosts h.IsRelay = a.IsRelay h.IsRelayed = a.IsRelayed - if len(a.LocalRange) > 0 { - _, localRange, err := net.ParseCIDR(a.LocalRange) - if err == nil { - h.LocalRange = *localRange - } - } else if !isEmptyAddr(currentHost.LocalRange.String()) { - h.LocalRange = currentHost.LocalRange - } h.ProxyEnabled = a.ProxyEnabled h.IsDefault = a.IsDefault diff --git a/models/host.go b/models/host.go index 30b0b8fc..4938aacd 100644 --- a/models/host.go +++ b/models/host.go @@ -25,8 +25,8 @@ type Host struct { Debug bool `json:"debug" yaml:"debug"` ListenPort int `json:"listenport" yaml:"listenport"` LocalAddress net.IPNet `json:"localaddress" yaml:"localaddress"` - LocalRange net.IPNet `json:"localrange" yaml:"localrange"` PublicListenPort int `json:"public_listen_port" yaml:"public_listen_port"` + LocalListenPort int `json:"locallistenport" yaml:"locallistenport"` ProxyListenPort int `json:"proxy_listen_port" yaml:"proxy_listen_port"` MTU int `json:"mtu" yaml:"mtu"` PublicKey wgtypes.Key `json:"publickey" yaml:"publickey"` diff --git a/models/network.go b/models/network.go index 3442e84d..7eb67d2a 100644 --- a/models/network.go +++ b/models/network.go @@ -7,7 +7,7 @@ import ( ) // Network Struct - contains info for a given unique network -//At some point, need to replace all instances of Name with something else like Identifier +// At some point, need to replace all instances of Name with something else like Identifier type Network struct { AddressRange string `json:"addressrange" bson:"addressrange" validate:"omitempty,cidrv4"` AddressRange6 string `json:"addressrange6" bson:"addressrange6" validate:"omitempty,cidrv6"` @@ -26,7 +26,6 @@ type Network struct { IsIPv4 string `json:"isipv4" bson:"isipv4" validate:"checkyesorno"` IsIPv6 string `json:"isipv6" bson:"isipv6" validate:"checkyesorno"` IsPointToSite string `json:"ispointtosite" bson:"ispointtosite" validate:"checkyesorno"` - LocalRange string `json:"localrange" bson:"localrange" validate:"omitempty,cidr"` DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"` DefaultExtClientDNS string `json:"defaultextclientdns" bson:"defaultextclientdns"` DefaultMTU int32 `json:"defaultmtu" bson:"defaultmtu"` diff --git a/models/network_test.go b/models/network_test.go index f093f8d0..bd79398d 100644 --- a/models/network_test.go +++ b/models/network_test.go @@ -13,13 +13,4 @@ package models // assert.Equal(t, "NetID is not editable", err.Error()) // t.Log(err, Range, local) // }) -// t.Run("LocalRange", func(t *testing.T) { -// var networkupdate models.Network -// //NetID needs to be set as it will be in updateNetwork -// networkupdate.NetID = "skynet" -// networkupdate.LocalRange = "192.168.0.1/24" -// Range, local, err := network.Update(&networkupdate) -// assert.Nil(t, err) -// t.Log(err, Range, local) -// }) //} diff --git a/models/node.go b/models/node.go index 14f625d9..a0945b64 100644 --- a/models/node.go +++ b/models/node.go @@ -150,7 +150,6 @@ type LegacyNode struct { IsServer string `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"` Action string `json:"action" bson:"action" yaml:"action"` IsLocal string `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"` - LocalRange string `json:"localrange" bson:"localrange" yaml:"localrange"` IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"` OS string `json:"os" bson:"os" yaml:"os"` MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"` @@ -495,13 +494,7 @@ func (ln *LegacyNode) ConvertToNewNode() (*Host, *Node) { host.HostPass = ln.Password host.Name = ln.Name host.ListenPort = int(ln.ListenPort) - if _, cidr, err := net.ParseCIDR(ln.LocalAddress); err == nil { - host.LocalRange = *cidr - } else { - if _, cidr, err := net.ParseCIDR(ln.LocalRange); err == nil { - host.LocalRange = *cidr - } - } + host.LocalListenPort = int(ln.LocalListenPort) host.ProxyListenPort = int(ln.ProxyListenPort) host.MTU = int(ln.MTU) host.PublicKey, _ = wgtypes.ParseKey(ln.PublicKey) @@ -594,7 +587,6 @@ func (n *Node) Legacy(h *Host, s *ServerConfig, net *Network) *LegacyNode { l.DNSOn = formatBool(n.DNSOn) l.Action = n.Action l.IsLocal = formatBool(n.IsLocal) - l.LocalRange = h.LocalRange.String() l.IPForwarding = formatBool(h.IPForwarding) l.OS = h.OS l.MTU = int32(h.MTU) diff --git a/serverctl/serverctl.go b/serverctl/serverctl.go index 42cd4b4e..242c5031 100644 --- a/serverctl/serverctl.go +++ b/serverctl/serverctl.go @@ -85,7 +85,7 @@ func setNetworkDefaults() error { } } else { network.SetDefaults() - _, _, _, _, _, _, err = logic.UpdateNetwork(&network, &network) + _, _, _, _, _, err = logic.UpdateNetwork(&network, &network) if err != nil { logger.Log(0, "could not set defaults on network", network.NetID) } diff --git a/swagger.yaml b/swagger.yaml index de95f8ea..fe81f6b3 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -291,9 +291,6 @@ definitions: ispointtosite: type: string x-go-name: IsPointToSite - localrange: - type: string - x-go-name: LocalRange netid: type: string x-go-name: NetID @@ -432,9 +429,6 @@ definitions: format: int32 type: integer x-go-name: LocalListenPort - localrange: - type: string - x-go-name: LocalRange macaddress: type: string x-go-name: MacAddress From e77bd39f44c5e0d6bf9c0fbd155af1a22038f3e7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 20 Jan 2023 06:04:50 -0500 Subject: [PATCH 03/13] remove localaddress from host --- models/host.go | 1 - 1 file changed, 1 deletion(-) diff --git a/models/host.go b/models/host.go index 4938aacd..e6efd1a1 100644 --- a/models/host.go +++ b/models/host.go @@ -24,7 +24,6 @@ type Host struct { Interface string `json:"interface" yaml:"interface"` Debug bool `json:"debug" yaml:"debug"` ListenPort int `json:"listenport" yaml:"listenport"` - LocalAddress net.IPNet `json:"localaddress" yaml:"localaddress"` PublicListenPort int `json:"public_listen_port" yaml:"public_listen_port"` LocalListenPort int `json:"locallistenport" yaml:"locallistenport"` ProxyListenPort int `json:"proxy_listen_port" yaml:"proxy_listen_port"` From 74750ca04590a89e921fb88b89fe05fac516fa21 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 18 Jan 2023 17:41:06 -0500 Subject: [PATCH 04/13] review comments --- logic/hosts.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/logic/hosts.go b/logic/hosts.go index 737375c8..9a71ed47 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "github.com/google/uuid" "github.com/gravitl/netmaker/database" @@ -326,11 +327,12 @@ func CheckHostPorts(h *models.Host) { } for _, host := range hosts { if host.EndpointIP.Equal(h.EndpointIP) { - if host.ListenPort == h.ListenPort || host.ProxyListenPort == h.ProxyListenPort { + if host.ListenPort == h.ListenPort || host.ProxyListenPort == h.ProxyListenPort || + host.ListenPort == h.ProxyListenPort || host.ProxyListenPort == h.ListenPort { updateListenPorts(h) count++ //protect against endless recursion - if count > 64535 { + if count > (math.MaxInt16 - 1000) { reset = true break } @@ -356,7 +358,7 @@ func HostExists(h *models.Host) bool { func updateListenPorts(h *models.Host) { h.ListenPort++ h.ProxyListenPort++ - if h.ListenPort > 65535 || h.ProxyListenPort > 65535 { + if h.ListenPort > math.MaxInt16 || h.ProxyListenPort > math.MaxInt16 { h.ListenPort = 1000 h.ProxyListenPort = 1001 } From e314f6fb9eaab6f80e0d92a7faf21d65ae442d95 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Wed, 18 Jan 2023 17:46:27 -0500 Subject: [PATCH 05/13] skip self when interating through hosts --- logic/hosts.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/logic/hosts.go b/logic/hosts.go index 9a71ed47..57cfab7b 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -326,6 +326,10 @@ func CheckHostPorts(h *models.Host) { return } for _, host := range hosts { + if host.ID == h.ID { + //skip self + continue + } if host.EndpointIP.Equal(h.EndpointIP) { if host.ListenPort == h.ListenPort || host.ProxyListenPort == h.ProxyListenPort || host.ListenPort == h.ProxyListenPort || host.ProxyListenPort == h.ListenPort { From 62cd313bd67357240cd3de544dac1d4724f818e7 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Thu, 19 Jan 2023 15:52:03 -0500 Subject: [PATCH 06/13] test/update ports separately --- logic/host_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++ logic/hosts.go | 50 +++++++++++++++++++++---------------- 2 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 logic/host_test.go diff --git a/logic/host_test.go b/logic/host_test.go new file mode 100644 index 00000000..75ff7a16 --- /dev/null +++ b/logic/host_test.go @@ -0,0 +1,62 @@ +package logic + +import ( + "net" + "testing" + + "github.com/google/uuid" + "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/models" + "github.com/matryer/is" +) + +func TestCheckPorts(t *testing.T) { + database.InitializeDatabase() + h := models.Host{ + ID: uuid.New(), + EndpointIP: net.ParseIP("192.168.1.1"), + ListenPort: 51821, + ProxyListenPort: maxPort, + } + testHost := models.Host{ + ID: uuid.New(), + EndpointIP: net.ParseIP("192.168.1.1"), + ListenPort: 51830, + ProxyListenPort: 51730, + } + CreateHost(&h) + t.Run("no change", func(t *testing.T) { + is := is.New(t) + CheckHostPorts(&testHost) + is.Equal(testHost.ListenPort, 51830) + is.Equal(testHost.ProxyListenPort, 51730) + }) + t.Run("same listen port", func(t *testing.T) { + is := is.New(t) + testHost.ListenPort = 51821 + CheckHostPorts(&testHost) + is.Equal(testHost.ListenPort, 51822) + is.Equal(testHost.ProxyListenPort, 51730) + }) + t.Run("same proxy port", func(t *testing.T) { + is := is.New(t) + testHost.ProxyListenPort = 65535 + CheckHostPorts(&testHost) + is.Equal(testHost.ListenPort, 51822) + is.Equal(testHost.ProxyListenPort, minPort) + }) + t.Run("listenport equals proxy port", func(t *testing.T) { + is := is.New(t) + testHost.ListenPort = maxPort + CheckHostPorts(&testHost) + is.Equal(testHost.ListenPort, minPort) + is.Equal(testHost.ProxyListenPort, minPort+1) + }) + t.Run("proxyport equals listenport", func(t *testing.T) { + is := is.New(t) + testHost.ProxyListenPort = 51821 + CheckHostPorts(&testHost) + is.Equal(testHost.ListenPort, minPort) + is.Equal(testHost.ProxyListenPort, 51822) + }) +} diff --git a/logic/hosts.go b/logic/hosts.go index 57cfab7b..01227b0a 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "math" "github.com/google/uuid" "github.com/gravitl/netmaker/database" @@ -21,6 +20,11 @@ var ( ErrInvalidHostID error = errors.New("invalid host id") ) +const ( + maxPort = 1<<16 - 1 + minPort = 1025 +) + // GetAllHosts - returns all hosts in flat list or error func GetAllHosts() ([]models.Host, error) { currHostMap, err := GetHostsMap() @@ -317,13 +321,21 @@ func GetRelatedHosts(hostID string) []models.Host { // with the same endpoint have different listen ports // in the case of 64535 hosts or more with same endpoint, ports will not be changed func CheckHostPorts(h *models.Host) { - listenPort := h.ListenPort - proxyPort := h.ProxyListenPort + h.ListenPort = checkPort(h, h.ListenPort) + h.ProxyListenPort = checkPort(h, h.ProxyListenPort) + // rerun if ports were set to same value + if h.ListenPort == h.ProxyListenPort { + updatePort(&h.ProxyListenPort) + h.ProxyListenPort = checkPort(h, h.ProxyListenPort) + } +} + +func checkPort(h *models.Host, p int) int { + currentPort := h.ListenPort count := 0 - reset := false hosts, err := GetAllHosts() if err != nil { - return + return currentPort } for _, host := range hosts { if host.ID == h.ID { @@ -331,23 +343,19 @@ func CheckHostPorts(h *models.Host) { continue } if host.EndpointIP.Equal(h.EndpointIP) { - if host.ListenPort == h.ListenPort || host.ProxyListenPort == h.ProxyListenPort || - host.ListenPort == h.ProxyListenPort || host.ProxyListenPort == h.ListenPort { - updateListenPorts(h) + if p == host.ListenPort || p == host.ProxyListenPort { + updatePort(&p) count++ //protect against endless recursion - if count > (math.MaxInt16 - 1000) { - reset = true - break + if count > maxPort-minPort { + logger.Log(0, "hit max interations in checkport") + return currentPort } - CheckHostPorts(h) + p = checkPort(h, p) } } } - if reset { - h.ListenPort = listenPort - h.ProxyListenPort = proxyPort - } + return p } // HostExists - checks if given host already exists @@ -359,11 +367,9 @@ func HostExists(h *models.Host) bool { return false } -func updateListenPorts(h *models.Host) { - h.ListenPort++ - h.ProxyListenPort++ - if h.ListenPort > math.MaxInt16 || h.ProxyListenPort > math.MaxInt16 { - h.ListenPort = 1000 - h.ProxyListenPort = 1001 +func updatePort(p *int) { + *p++ + if *p > maxPort { + *p = minPort } } From d0af730042c90f34d8cef4d5088202bf8e3848c2 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Thu, 19 Jan 2023 18:11:13 -0500 Subject: [PATCH 07/13] review comments --- logic/hosts.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/logic/hosts.go b/logic/hosts.go index 01227b0a..f6f30467 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -331,7 +331,7 @@ func CheckHostPorts(h *models.Host) { } func checkPort(h *models.Host, p int) int { - currentPort := h.ListenPort + currentPort := p count := 0 hosts, err := GetAllHosts() if err != nil { @@ -361,10 +361,7 @@ func checkPort(h *models.Host, p int) int { // HostExists - checks if given host already exists func HostExists(h *models.Host) bool { _, err := GetHost(h.ID.String()) - if (err != nil && !database.IsEmptyRecord(err)) || (err == nil) { - return true - } - return false + return (err != nil && !database.IsEmptyRecord(err)) || (err == nil) } func updatePort(p *int) { From c528110541b4654af829691931d43260a8e95c6e Mon Sep 17 00:00:00 2001 From: Abhishek Kondur Date: Tue, 17 Jan 2023 14:43:16 +0530 Subject: [PATCH 08/13] handle update host logic in mq handler --- mq/handlers.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mq/handlers.go b/mq/handlers.go index 271cb376..527e411a 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -141,7 +141,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) { logger.Log(1, "error unmarshaling payload ", err.Error()) return } - logger.Log(0, "recieved host update for host: ", id) + logger.Log(0, fmt.Sprintf("recieved host update: %+v\n", hostUpdate)) var sendPeerUpdate bool switch hostUpdate.Action { case models.UpdateHost: @@ -168,6 +168,12 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) { logger.Log(0, "failed to pulish peer update: ", err.Error()) } } + if sendPeerUpdate { + err := PublishPeerUpdate() + if err != nil { + logger.Log(0, "failed to pulish peer update: ", err.Error()) + } + } // if servercfg.Is_EE && ifaceDelta { // if err = logic.EnterpriseResetAllPeersFailovers(currentHost.ID.String(), currentHost.Network); err != nil { // logger.Log(1, "failed to reset failover list during node update", currentHost.ID.String(), currentHost.Network) From 63f18f539e44245ecfb5bcc00fd33bed707b4890 Mon Sep 17 00:00:00 2001 From: Abhishek Kondur Date: Wed, 18 Jan 2023 02:03:19 +0530 Subject: [PATCH 09/13] GRA-985: rm locallistenport, added proxy public listen port field --- logic/peers.go | 1 - models/node.go | 1 - 2 files changed, 2 deletions(-) diff --git a/logic/peers.go b/logic/peers.go index 14b6cb91..c0de16ee 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -252,7 +252,6 @@ func GetProxyUpdateForHost(host *models.Host) (proxy_models.ProxyManagerPayload, if err != nil { continue } - var currPeerConf proxy_models.PeerConf var found bool if currPeerConf, found = peerConfMap[peerHost.PublicKey.String()]; !found { diff --git a/models/node.go b/models/node.go index a0945b64..e60de275 100644 --- a/models/node.go +++ b/models/node.go @@ -494,7 +494,6 @@ func (ln *LegacyNode) ConvertToNewNode() (*Host, *Node) { host.HostPass = ln.Password host.Name = ln.Name host.ListenPort = int(ln.ListenPort) - host.LocalListenPort = int(ln.LocalListenPort) host.ProxyListenPort = int(ln.ProxyListenPort) host.MTU = int(ln.MTU) host.PublicKey, _ = wgtypes.ParseKey(ln.PublicKey) From e790b87d81724bfec2913925d2db97a875e2335a Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 20 Jan 2023 08:47:41 -0500 Subject: [PATCH 10/13] add rebase change --- models/api_host.go | 1 - 1 file changed, 1 deletion(-) diff --git a/models/api_host.go b/models/api_host.go index c6306d93..b6a1ef9c 100644 --- a/models/api_host.go +++ b/models/api_host.go @@ -49,7 +49,6 @@ func (h *Host) ConvertNMHostToAPI() *ApiHost { } a.IsStatic = h.IsStatic a.ListenPort = h.ListenPort - a.LocalListenPort = h.LocalListenPort a.MTU = h.MTU a.MacAddress = h.MacAddress.String() a.Name = h.Name From dc58c2c6371df14312b7565627bfa7a2ac9d7262 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 20 Jan 2023 11:15:06 -0500 Subject: [PATCH 11/13] more efficient check for free ports --- logic/hosts.go | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/logic/hosts.go b/logic/hosts.go index f6f30467..94db3311 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -321,41 +321,22 @@ func GetRelatedHosts(hostID string) []models.Host { // with the same endpoint have different listen ports // in the case of 64535 hosts or more with same endpoint, ports will not be changed func CheckHostPorts(h *models.Host) { - h.ListenPort = checkPort(h, h.ListenPort) - h.ProxyListenPort = checkPort(h, h.ProxyListenPort) - // rerun if ports were set to same value - if h.ListenPort == h.ProxyListenPort { - updatePort(&h.ProxyListenPort) - h.ProxyListenPort = checkPort(h, h.ProxyListenPort) - } -} - -func checkPort(h *models.Host, p int) int { - currentPort := p - count := 0 + portsInUse := make(map[int]bool) hosts, err := GetAllHosts() if err != nil { - return currentPort + return } for _, host := range hosts { - if host.ID == h.ID { - //skip self - continue - } - if host.EndpointIP.Equal(h.EndpointIP) { - if p == host.ListenPort || p == host.ProxyListenPort { - updatePort(&p) - count++ - //protect against endless recursion - if count > maxPort-minPort { - logger.Log(0, "hit max interations in checkport") - return currentPort - } - p = checkPort(h, p) - } - } + portsInUse[host.ListenPort] = true + portsInUse[host.ProxyListenPort] = true + } + // iterate until port is not found or max iteration is reached + for i := 0; portsInUse[h.ListenPort] && i < maxPort-minPort+1; i++ { + updatePort(&h.ListenPort) + } + for i := 0; portsInUse[h.ProxyListenPort] && i < maxPort-minPort+1; i++ { + updatePort(&h.ProxyListenPort) } - return p } // HostExists - checks if given host already exists From 5423a458c3bcef3b5f168eb8ca1f3b843f5935d0 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Fri, 20 Jan 2023 13:29:19 -0500 Subject: [PATCH 12/13] review comments --- logic/hosts.go | 7 +++++++ models/host.go | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/logic/hosts.go b/logic/hosts.go index 94db3311..ccfcc053 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -327,6 +327,13 @@ func CheckHostPorts(h *models.Host) { return } for _, host := range hosts { + if host.ID == h.ID { + //skip self + continue + } + if !host.EndpointIP.Equal(h.EndpointIP) { + continue + } portsInUse[host.ListenPort] = true portsInUse[host.ProxyListenPort] = true } diff --git a/models/host.go b/models/host.go index e6efd1a1..743ce431 100644 --- a/models/host.go +++ b/models/host.go @@ -25,7 +25,6 @@ type Host struct { Debug bool `json:"debug" yaml:"debug"` ListenPort int `json:"listenport" yaml:"listenport"` PublicListenPort int `json:"public_listen_port" yaml:"public_listen_port"` - LocalListenPort int `json:"locallistenport" yaml:"locallistenport"` ProxyListenPort int `json:"proxy_listen_port" yaml:"proxy_listen_port"` MTU int `json:"mtu" yaml:"mtu"` PublicKey wgtypes.Key `json:"publickey" yaml:"publickey"` From 1a739e666074b711211004848743d6c9d831c4b3 Mon Sep 17 00:00:00 2001 From: Matthew R Kasun Date: Sun, 22 Jan 2023 17:32:53 -0500 Subject: [PATCH 13/13] log level changed for hostUpdate --- mq/handlers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mq/handlers.go b/mq/handlers.go index 527e411a..eb078375 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -141,7 +141,7 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) { logger.Log(1, "error unmarshaling payload ", err.Error()) return } - logger.Log(0, fmt.Sprintf("recieved host update: %+v\n", hostUpdate)) + logger.Log(3, fmt.Sprintf("recieved host update: %+v\n", hostUpdate)) var sendPeerUpdate bool switch hostUpdate.Action { case models.UpdateHost: