Explorar el Código

initial functions

0xdcarns hace 2 años
padre
commit
759512ef1f
Se han modificado 4 ficheros con 210 adiciones y 126 borrados
  1. 5 3
      logic/hosts.go
  2. 14 0
      logic/nodes.go
  3. 117 123
      logic/peers.go
  4. 74 0
      mq/publishers.go

+ 5 - 3
logic/hosts.go

@@ -345,18 +345,20 @@ func GetHostNetworks(hostID string) []string {
 func GetRelatedHosts(hostID string) []models.Host {
 	relatedHosts := []models.Host{}
 	networks := GetHostNetworks(hostID)
-	networkMap := make(map[string]struct{})
+	networkMap := make(map[string]struct{}, len(networks))
 	for _, network := range networks {
 		networkMap[network] = struct{}{}
 	}
 	hosts, err := GetAllHosts()
 	if err == nil {
-		for _, host := range hosts {
+		for i := range hosts {
+			host := hosts[i]
 			if host.ID.String() == hostID {
 				continue
 			}
 			networks := GetHostNetworks(host.ID.String())
-			for _, network := range networks {
+			for j := range networks {
+				network := networks[j]
 				if _, ok := networkMap[network]; ok {
 					relatedHosts = append(relatedHosts, host)
 					break

+ 14 - 0
logic/nodes.go

@@ -30,6 +30,20 @@ const (
 	NodePurgeCheckTime = time.Second * 30
 )
 
+// GetNodesByHost - retrieves associated nodes of a host
+func GetNodesByHost(h *models.Host) []models.Node {
+	var hostNodes = []models.Node{}
+	for i := range h.Nodes {
+		nodeID := h.Nodes[i]
+		hostNode, err := GetNodeByID(nodeID)
+		if err != nil {
+			continue
+		}
+		hostNodes = append(hostNodes, hostNode)
+	}
+	return hostNodes
+}
+
 // GetNetworkNodes - gets the nodes of a network
 func GetNetworkNodes(network string) ([]models.Node, error) {
 	allnodes, err := GetAllNodes()

+ 117 - 123
logic/peers.go

@@ -409,7 +409,7 @@ func GetPeerUpdateForHost(ctx context.Context, network string, hostToSend *model
 
 // GetPeerUpdateForSingleHost - gets the consolidated peer update a single a host <-> host
 // from all networks
-func GetPeerUpdateForSingleHost(ctx context.Context,
+func GetPeerUpdateForSingleHost(
 	network string,
 	hostToSend, updatedHost *models.Host,
 	updatedHostNodes []models.Node,
@@ -436,141 +436,135 @@ func GetPeerUpdateForSingleHost(ctx context.Context,
 			nodePeerMap = make(map[string]models.PeerRouteInfo)
 		}
 		for _, peer := range updatedHostNodes {
-			select {
-			case <-ctx.Done():
-				logger.Log(2, "cancelled peer update for host", hostToSend.Name, hostToSend.ID.String())
-				return models.HostPeerUpdate{}, fmt.Errorf("peer update cancelled")
-			default:
-				peer := peer
-				if peer.ID.String() == node.ID.String() {
-					logger.Log(2, "peer update, skipping self")
-					//skip yourself
-					continue
-				}
-				var peerConfig wgtypes.PeerConfig
-				peerConfig.PublicKey = updatedHost.PublicKey
-				peerConfig.PersistentKeepaliveInterval = &peer.PersistentKeepalive
-				peerConfig.ReplaceAllowedIPs = true
-				peerConfig.Endpoint = &net.UDPAddr{
-					IP:   updatedHost.EndpointIP,
-					Port: GetPeerListenPort(updatedHost),
-				}
+			peer := peer
+			if peer.ID.String() == node.ID.String() {
+				logger.Log(2, "peer update, skipping self")
+				//skip yourself
+				continue
+			}
+			var peerConfig wgtypes.PeerConfig
+			peerConfig.PublicKey = updatedHost.PublicKey
+			peerConfig.PersistentKeepaliveInterval = &peer.PersistentKeepalive
+			peerConfig.ReplaceAllowedIPs = true
+			peerConfig.Endpoint = &net.UDPAddr{
+				IP:   updatedHost.EndpointIP,
+				Port: GetPeerListenPort(updatedHost),
+			}
 
-				allowedips := GetAllowedIPs(&node, &peer, nil)
-				if peer.IsIngressGateway {
-					for _, entry := range peer.IngressGatewayRange {
-						_, cidr, err := net.ParseCIDR(string(entry))
-						if err == nil {
-							allowedips = append(allowedips, *cidr)
-						}
+			allowedips := GetAllowedIPs(&node, &peer, nil)
+			if peer.IsIngressGateway {
+				for _, entry := range peer.IngressGatewayRange {
+					_, cidr, err := net.ParseCIDR(string(entry))
+					if err == nil {
+						allowedips = append(allowedips, *cidr)
 					}
 				}
-				if peer.IsEgressGateway {
-					allowedips = append(allowedips, getEgressIPs(&node, &peer)...)
-				}
-				if peer.Action != models.NODE_DELETE &&
-					!peer.PendingDelete &&
-					peer.Connected &&
-					nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(peer.ID.String())) &&
-					(deletedNode == nil || (deletedNode != nil && peer.ID.String() != deletedNode.ID.String())) {
-					peerConfig.AllowedIPs = allowedips // only append allowed IPs if valid connection
-				}
+			}
+			if peer.IsEgressGateway {
+				allowedips = append(allowedips, getEgressIPs(&node, &peer)...)
+			}
+			if peer.Action != models.NODE_DELETE &&
+				!peer.PendingDelete &&
+				peer.Connected &&
+				nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(peer.ID.String())) &&
+				(deletedNode == nil || (deletedNode != nil && peer.ID.String() != deletedNode.ID.String())) {
+				peerConfig.AllowedIPs = allowedips // only append allowed IPs if valid connection
+			}
 
-				if node.IsIngressGateway || node.IsEgressGateway {
-					if peer.IsIngressGateway { // if the peer is also an ingress gateway, we need the routes
-						_, extPeerIDAndAddrs, err := getExtPeers(&peer)
-						if err == nil {
-							for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
-								extPeerIdAndAddr := extPeerIdAndAddr
-								nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
-									PeerAddr: net.IPNet{
-										IP:   net.ParseIP(extPeerIdAndAddr.Address),
-										Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
-									},
-									PeerKey: extPeerIdAndAddr.ID,
-									Allow:   true,
-									ID:      extPeerIdAndAddr.ID,
-								}
+			if node.IsIngressGateway || node.IsEgressGateway {
+				if peer.IsIngressGateway { // if the peer is also an ingress gateway, we need the routes
+					_, extPeerIDAndAddrs, err := getExtPeers(&peer)
+					if err == nil {
+						for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
+							extPeerIdAndAddr := extPeerIdAndAddr
+							nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
+								PeerAddr: net.IPNet{
+									IP:   net.ParseIP(extPeerIdAndAddr.Address),
+									Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
+								},
+								PeerKey: extPeerIdAndAddr.ID,
+								Allow:   true,
+								ID:      extPeerIdAndAddr.ID,
 							}
 						}
 					}
-					if node.IsIngressGateway && peer.IsEgressGateway { // if current node is an ingress on host
-						// and peer is egress, need to inform the clients of the egress ranges
-						hostPeerUpdate.IngressInfo.EgressRanges = append(hostPeerUpdate.IngressInfo.EgressRanges,
-							peer.EgressGatewayRanges...)
-					}
-					nodePeerMap[updatedHost.PublicKey.String()] = models.PeerRouteInfo{
-						PeerAddr: net.IPNet{
-							IP:   net.ParseIP(peer.PrimaryAddress()),
-							Mask: getCIDRMaskFromAddr(peer.PrimaryAddress()),
-						},
-						PeerKey: updatedHost.PublicKey.String(),
-						Allow:   true,
-						ID:      peer.ID.String(),
-					}
 				}
-
-				peerProxyPort := GetProxyListenPort(updatedHost)
-				var nodePeer wgtypes.PeerConfig
-				if _, ok := hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()]; !ok {
-					hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()] = make(map[string]models.IDandAddr)
-					hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, peerConfig)
-					peerIndexMap[updatedHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
-					hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()][peer.ID.String()] = models.IDandAddr{
-						ID:              peer.ID.String(),
-						Address:         peer.PrimaryAddress(),
-						Name:            updatedHost.Name,
-						Network:         peer.Network,
-						ProxyListenPort: peerProxyPort,
-					}
-					hostPeerUpdate.HostNetworkInfo[updatedHost.PublicKey.String()] = models.HostNetworkInfo{
-						Interfaces:      updatedHost.Interfaces,
-						ProxyListenPort: peerProxyPort,
-					}
-					nodePeer = peerConfig
-				} else {
-					peerAllowedIPs := hostPeerUpdate.Peers[peerIndexMap[updatedHost.PublicKey.String()]].AllowedIPs
-					peerAllowedIPs = append(peerAllowedIPs, allowedips...)
-					hostPeerUpdate.Peers[peerIndexMap[updatedHost.PublicKey.String()]].AllowedIPs = peerAllowedIPs
-					hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()][peer.ID.String()] = models.IDandAddr{
-						ID:              peer.ID.String(),
-						Address:         peer.PrimaryAddress(),
-						Name:            updatedHost.Name,
-						Network:         peer.Network,
-						ProxyListenPort: GetProxyListenPort(updatedHost),
-					}
-					hostPeerUpdate.HostNetworkInfo[updatedHost.PublicKey.String()] = models.HostNetworkInfo{
-						Interfaces:      updatedHost.Interfaces,
-						ProxyListenPort: peerProxyPort,
-					}
-					nodePeer = hostPeerUpdate.Peers[peerIndexMap[updatedHost.PublicKey.String()]]
+				if node.IsIngressGateway && peer.IsEgressGateway { // if current node is an ingress on host
+					// and peer is egress, need to inform the clients of the egress ranges
+					hostPeerUpdate.IngressInfo.EgressRanges = append(hostPeerUpdate.IngressInfo.EgressRanges,
+						peer.EgressGatewayRanges...)
 				}
-
-				if node.Network == network { // add to peers map for metrics
-					hostPeerUpdate.PeerIDs[updatedHost.PublicKey.String()] = models.IDandAddr{
-						ID:              peer.ID.String(),
-						Address:         peer.PrimaryAddress(),
-						Name:            updatedHost.Name,
-						Network:         peer.Network,
-						ProxyListenPort: updatedHost.ProxyListenPort,
-					}
-					hostPeerUpdate.NodePeers = append(hostPeerUpdate.NodePeers, nodePeer)
+				nodePeerMap[updatedHost.PublicKey.String()] = models.PeerRouteInfo{
+					PeerAddr: net.IPNet{
+						IP:   net.ParseIP(peer.PrimaryAddress()),
+						Mask: getCIDRMaskFromAddr(peer.PrimaryAddress()),
+					},
+					PeerKey: updatedHost.PublicKey.String(),
+					Allow:   true,
+					ID:      peer.ID.String(),
 				}
 			}
-			if node.IsIngressGateway {
-				getIngressNodeAllowedIPs(network, &node, &hostPeerUpdate, nodePeerMap)
+
+			peerProxyPort := GetProxyListenPort(updatedHost)
+			var nodePeer wgtypes.PeerConfig
+			if _, ok := hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()]; !ok {
+				hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()] = make(map[string]models.IDandAddr)
+				hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, peerConfig)
+				peerIndexMap[updatedHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
+				hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()][peer.ID.String()] = models.IDandAddr{
+					ID:              peer.ID.String(),
+					Address:         peer.PrimaryAddress(),
+					Name:            updatedHost.Name,
+					Network:         peer.Network,
+					ProxyListenPort: peerProxyPort,
+				}
+				hostPeerUpdate.HostNetworkInfo[updatedHost.PublicKey.String()] = models.HostNetworkInfo{
+					Interfaces:      updatedHost.Interfaces,
+					ProxyListenPort: peerProxyPort,
+				}
+				nodePeer = peerConfig
+			} else {
+				peerAllowedIPs := hostPeerUpdate.Peers[peerIndexMap[updatedHost.PublicKey.String()]].AllowedIPs
+				peerAllowedIPs = append(peerAllowedIPs, allowedips...)
+				hostPeerUpdate.Peers[peerIndexMap[updatedHost.PublicKey.String()]].AllowedIPs = peerAllowedIPs
+				hostPeerUpdate.HostPeerIDs[updatedHost.PublicKey.String()][peer.ID.String()] = models.IDandAddr{
+					ID:              peer.ID.String(),
+					Address:         peer.PrimaryAddress(),
+					Name:            updatedHost.Name,
+					Network:         peer.Network,
+					ProxyListenPort: GetProxyListenPort(updatedHost),
+				}
+				hostPeerUpdate.HostNetworkInfo[updatedHost.PublicKey.String()] = models.HostNetworkInfo{
+					Interfaces:      updatedHost.Interfaces,
+					ProxyListenPort: peerProxyPort,
+				}
+				nodePeer = hostPeerUpdate.Peers[peerIndexMap[updatedHost.PublicKey.String()]]
 			}
-			if node.IsEgressGateway {
-				hostPeerUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
-					EgressID: node.ID.String(),
-					Network:  node.PrimaryNetworkRange(),
-					EgressGwAddr: net.IPNet{
-						IP:   net.ParseIP(node.PrimaryAddress()),
-						Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
-					},
-					GwPeers:     nodePeerMap,
-					EgressGWCfg: node.EgressGatewayRequest,
+
+			if node.Network == network { // add to peers map for metrics
+				hostPeerUpdate.PeerIDs[updatedHost.PublicKey.String()] = models.IDandAddr{
+					ID:              peer.ID.String(),
+					Address:         peer.PrimaryAddress(),
+					Name:            updatedHost.Name,
+					Network:         peer.Network,
+					ProxyListenPort: updatedHost.ProxyListenPort,
 				}
+				hostPeerUpdate.NodePeers = append(hostPeerUpdate.NodePeers, nodePeer)
+			}
+		}
+		if node.IsIngressGateway {
+			getIngressNodeAllowedIPs(network, &node, &hostPeerUpdate, nodePeerMap)
+		}
+		if node.IsEgressGateway {
+			hostPeerUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
+				EgressID: node.ID.String(),
+				Network:  node.PrimaryNetworkRange(),
+				EgressGwAddr: net.IPNet{
+					IP:   net.ParseIP(node.PrimaryAddress()),
+					Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
+				},
+				GwPeers:     nodePeerMap,
+				EgressGWCfg: node.EgressGatewayRequest,
 			}
 		}
 	}

+ 74 - 0
mq/publishers.go

@@ -24,6 +24,9 @@ func PublishPeerUpdate() error {
 		logger.Log(1, "err getting all hosts", err.Error())
 		return err
 	}
+	// Get nodes of host that was updated
+	// Go through all affected hosts
+	// publish peer update with single peer
 	logic.ResetPeerUpdateContext()
 	for _, host := range hosts {
 		host := host
@@ -78,6 +81,77 @@ func PublishDeletedClientPeerUpdate(delClient *models.ExtClient) error {
 	return err
 }
 
+// PublishPeerUpdateForClient - publishes a peer update to affected host on behalf of a client's Host
+func PublishPeerUpdateForClient(network string, c *models.ExtClient, deleted bool) error {
+	h := logic.GetHostByNodeID(c.IngressGatewayID)
+	if h == nil {
+		return fmt.Errorf("could not find host for client %s", c.ClientID)
+	}
+	var deletedClient *models.ExtClient
+	if deleted {
+		deletedClient = c
+	}
+	return PublishPeerUpdateForHost(
+		network,
+		h,
+		nil,
+		deletedClient,
+	)
+}
+
+// PublishPeerUpdateForNode - publishes a peer update to affected host on behalf of a node's Host
+func PublishPeerUpdateForNode(network string, n *models.Node, deleted bool) error {
+	h, err := logic.GetHost(n.HostID.String())
+	if err != nil {
+		return err
+	}
+	var deletedNode *models.Node
+	if deleted {
+		deletedNode = n
+	}
+	return PublishPeerUpdateForHost(
+		network,
+		h,
+		deletedNode,
+		nil,
+	)
+}
+
+// PublishPeerUpdateForHost - publishes a peer update to affected hosts on behalf of an updated host
+func PublishPeerUpdateForHost(network string, updatedHost *models.Host, deletedNode *models.Node, deletedClient *models.ExtClient) error {
+
+	hostsToSend := logic.GetRelatedHosts(updatedHost.ID.String())
+	currentHostNodes := logic.GetNodesByHost(updatedHost)
+	serverConf := servercfg.GetServerConfig()
+	for i := range hostsToSend {
+		hostToSend := hostsToSend[i]
+		peerUpdate, err := logic.GetPeerUpdateForSingleHost(
+			network,
+			&hostToSend,
+			updatedHost,
+			currentHostNodes,
+			deletedNode,
+			deletedClient,
+		)
+		if err != nil {
+			logger.Log(0, "failed to send peer update to host", hostToSend.Name, hostToSend.ID.String(), err.Error())
+		}
+		data, err := json.Marshal(&peerUpdate)
+		if err != nil {
+			logger.Log(0, "failed to send peer update to host", hostToSend.Name, hostToSend.ID.String(), err.Error())
+			continue
+		}
+		if err = publish(&hostToSend,
+			fmt.Sprintf("peers/host/%s/%s", hostToSend.ID.String(), serverConf.Server),
+			data,
+		); err != nil {
+			logger.Log(0, "failed to send peer update to host", hostToSend.Name, hostToSend.ID.String(), err.Error())
+		}
+	}
+
+	return nil
+}
+
 // PublishSingleHostPeerUpdate --- determines and publishes a peer update to one host
 func PublishSingleHostPeerUpdate(ctx context.Context, host *models.Host, deletedNode *models.Node, deletedClient *models.ExtClient) error {