Browse Source

configure proxy for ext clients

Abhishek Kondur 2 years ago
parent
commit
5d7bf9502b
6 changed files with 178 additions and 57 deletions
  1. 2 2
      logic/gateway.go
  2. 115 40
      logic/peers.go
  3. 12 5
      nm-proxy/common/common.go
  4. 24 9
      nm-proxy/manager/manager.go
  5. 5 1
      nm-proxy/peer/peer.go
  6. 20 0
      nm-proxy/server/server.go

+ 2 - 2
logic/gateway.go

@@ -230,8 +230,8 @@ func CreateIngressGateway(netid string, nodeid string, failover bool) (models.No
 		}
 		}
 	}
 	}
 	node.SetLastModified()
 	node.SetLastModified()
-	node.PostUp = postUpCmd
-	node.PostDown = postDownCmd
+	// node.PostUp = postUpCmd
+	// node.PostDown = postDownCmd
 	node.UDPHolePunch = "no"
 	node.UDPHolePunch = "no"
 	if failover && servercfg.Is_EE {
 	if failover && servercfg.Is_EE {
 		node.Failover = "yes"
 		node.Failover = "yes"

+ 115 - 40
logic/peers.go

@@ -45,6 +45,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (manager.ManagerPayload
 				logger.Log(1, "failed to relayed nodes: ", node.Name, err.Error())
 				logger.Log(1, "failed to relayed nodes: ", node.Name, err.Error())
 				proxyPayload.IsRelay = false
 				proxyPayload.IsRelay = false
 			} else {
 			} else {
+
 				relayPeersMap := make(map[string]manager.RelayedConf)
 				relayPeersMap := make(map[string]manager.RelayedConf)
 				for _, relayedNode := range relayedNodes {
 				for _, relayedNode := range relayedNodes {
 					payload, err := GetPeersForProxy(&relayedNode, true)
 					payload, err := GetPeersForProxy(&relayedNode, true)
@@ -64,6 +65,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (manager.ManagerPayload
 				proxyPayload.RelayedPeerConf = relayPeersMap
 				proxyPayload.RelayedPeerConf = relayPeersMap
 			}
 			}
 		}
 		}
+
 	}
 	}
 
 
 	for _, peer := range currentPeers {
 	for _, peer := range currentPeers {
@@ -109,6 +111,14 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (manager.ManagerPayload
 
 
 		}
 		}
 	}
 	}
+	var extPeers []wgtypes.PeerConfig
+	extPeers, peerConfMap, err = getExtPeersForProxy(node, peerConfMap)
+	if err == nil {
+		peers = append(peers, extPeers...)
+
+	} else if !database.IsEmptyRecord(err) {
+		logger.Log(1, "error retrieving external clients:", err.Error())
+	}
 	proxyPayload.Peers = peers
 	proxyPayload.Peers = peers
 	proxyPayload.PeerMap = peerConfMap
 	proxyPayload.PeerMap = peerConfMap
 	proxyPayload.InterfaceName = node.Interface
 	proxyPayload.InterfaceName = node.Interface
@@ -274,17 +284,17 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
 			serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{IsLeader: IsLeader(&peer), Address: peer.Address})
 			serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{IsLeader: IsLeader(&peer), Address: peer.Address})
 		}
 		}
 	}
 	}
-	if node.IsIngressGateway == "yes" {
-		extPeers, idsAndAddr, err := getExtPeers(node)
-		if err == nil {
-			peers = append(peers, extPeers...)
-			for i := range idsAndAddr {
-				peerMap[idsAndAddr[i].ID] = idsAndAddr[i]
-			}
-		} else if !database.IsEmptyRecord(err) {
-			logger.Log(1, "error retrieving external clients:", err.Error())
+	// if node.IsIngressGateway == "yes" {
+	extPeers, idsAndAddr, err := getExtPeers(node)
+	if err == nil {
+		peers = append(peers, extPeers...)
+		for i := range idsAndAddr {
+			peerMap[idsAndAddr[i].ID] = idsAndAddr[i]
 		}
 		}
+	} else if !database.IsEmptyRecord(err) {
+		logger.Log(1, "error retrieving external clients:", err.Error())
 	}
 	}
+	// }
 
 
 	peerUpdate.Network = node.Network
 	peerUpdate.Network = node.Network
 	peerUpdate.ServerVersion = servercfg.Version
 	peerUpdate.ServerVersion = servercfg.Version
@@ -298,7 +308,7 @@ func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
 func getExtPeers(node *models.Node) ([]wgtypes.PeerConfig, []models.IDandAddr, error) {
 func getExtPeers(node *models.Node) ([]wgtypes.PeerConfig, []models.IDandAddr, error) {
 	var peers []wgtypes.PeerConfig
 	var peers []wgtypes.PeerConfig
 	var idsAndAddr []models.IDandAddr
 	var idsAndAddr []models.IDandAddr
-	extPeers, err := GetExtPeersList(node)
+	extPeers, err := GetNetworkExtClients(node.Network)
 	if err != nil {
 	if err != nil {
 		return peers, idsAndAddr, err
 		return peers, idsAndAddr, err
 	}
 	}
@@ -355,42 +365,107 @@ func getExtPeers(node *models.Node) ([]wgtypes.PeerConfig, []models.IDandAddr, e
 
 
 }
 }
 
 
+func getExtPeersForProxy(node *models.Node, proxyPeerConf map[string]manager.PeerConf) ([]wgtypes.PeerConfig, map[string]manager.PeerConf, error) {
+	var peers []wgtypes.PeerConfig
+
+	extPeers, err := GetNetworkExtClients(node.Network)
+	if err != nil {
+		return peers, proxyPeerConf, err
+	}
+	for _, extPeer := range extPeers {
+		pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
+		if err != nil {
+			logger.Log(1, "error parsing ext pub key:", err.Error())
+			continue
+		}
+
+		if node.PublicKey == extPeer.PublicKey {
+			continue
+		}
+
+		var allowedips []net.IPNet
+		var peer wgtypes.PeerConfig
+		if extPeer.Address != "" {
+			var peeraddr = net.IPNet{
+				IP:   net.ParseIP(extPeer.Address),
+				Mask: net.CIDRMask(32, 32),
+			}
+			if peeraddr.IP != nil && peeraddr.Mask != nil {
+				allowedips = append(allowedips, peeraddr)
+			}
+		}
+
+		if extPeer.Address6 != "" {
+			var addr6 = net.IPNet{
+				IP:   net.ParseIP(extPeer.Address6),
+				Mask: net.CIDRMask(128, 128),
+			}
+			if addr6.IP != nil && addr6.Mask != nil {
+				allowedips = append(allowedips, addr6)
+			}
+		}
+
+		peer = wgtypes.PeerConfig{
+			PublicKey:         pubkey,
+			ReplaceAllowedIPs: true,
+			AllowedIPs:        allowedips,
+		}
+
+		extConf := manager.PeerConf{
+			IsExtClient: true,
+		}
+		if extPeer.IngressGatewayID == node.ID {
+			extConf.IsAttachedExtClient = true
+		}
+		ingGatewayUdpAddr, err := net.ResolveUDPAddr("udp", extPeer.IngressGatewayEndpoint)
+		if err == nil {
+			extConf.IngressGatewayEndPoint = ingGatewayUdpAddr
+		}
+
+		proxyPeerConf[peer.PublicKey.String()] = extConf
+
+		peers = append(peers, peer)
+	}
+	return peers, proxyPeerConf, nil
+
+}
+
 // GetAllowedIPs - calculates the wireguard allowedip field for a peer of a node based on the peer and node settings
 // GetAllowedIPs - calculates the wireguard allowedip field for a peer of a node based on the peer and node settings
 func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet {
 func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet {
 	var allowedips []net.IPNet
 	var allowedips []net.IPNet
 	allowedips = getNodeAllowedIPs(peer, node)
 	allowedips = getNodeAllowedIPs(peer, node)
 
 
 	// handle ingress gateway peers
 	// handle ingress gateway peers
-	if peer.IsIngressGateway == "yes" {
-		extPeers, _, err := getExtPeers(peer)
-		if err != nil {
-			logger.Log(2, "could not retrieve ext peers for ", peer.Name, err.Error())
-		}
-		for _, extPeer := range extPeers {
-			allowedips = append(allowedips, extPeer.AllowedIPs...)
-		}
-		// if node is a failover node, add allowed ips from nodes it is handling
-		if peer.Failover == "yes" && metrics.FailoverPeers != nil {
-			// traverse through nodes that need handling
-			logger.Log(3, "peer", peer.Name, "was found to be failover for", node.Name, "checking failover peers...")
-			for k := range metrics.FailoverPeers {
-				// if FailoverNode is me for this node, add allowedips
-				if metrics.FailoverPeers[k] == peer.ID {
-					// get original node so we can traverse the allowed ips
-					nodeToFailover, err := GetNodeByID(k)
-					if err == nil {
-						failoverNodeMetrics, err := GetMetrics(nodeToFailover.ID)
-						if err == nil && failoverNodeMetrics != nil {
-							if len(failoverNodeMetrics.NodeName) > 0 {
-								allowedips = append(allowedips, getNodeAllowedIPs(&nodeToFailover, peer)...)
-								logger.Log(0, "failing over node", nodeToFailover.Name, nodeToFailover.PrimaryAddress(), "to failover node", peer.Name)
-							}
-						}
-					}
-				}
-			}
-		}
-	}
+	// if peer.IsIngressGateway == "yes" {
+	// 	extPeers, _, err := getExtPeers(peer)
+	// 	if err != nil {
+	// 		logger.Log(2, "could not retrieve ext peers for ", peer.Name, err.Error())
+	// 	}
+	// 	for _, extPeer := range extPeers {
+	// 		allowedips = append(allowedips, extPeer.AllowedIPs...)
+	// 	}
+	// 	// if node is a failover node, add allowed ips from nodes it is handling
+	// 	if peer.Failover == "yes" && metrics.FailoverPeers != nil {
+	// 		// traverse through nodes that need handling
+	// 		logger.Log(3, "peer", peer.Name, "was found to be failover for", node.Name, "checking failover peers...")
+	// 		for k := range metrics.FailoverPeers {
+	// 			// if FailoverNode is me for this node, add allowedips
+	// 			if metrics.FailoverPeers[k] == peer.ID {
+	// 				// get original node so we can traverse the allowed ips
+	// 				nodeToFailover, err := GetNodeByID(k)
+	// 				if err == nil {
+	// 					failoverNodeMetrics, err := GetMetrics(nodeToFailover.ID)
+	// 					if err == nil && failoverNodeMetrics != nil {
+	// 						if len(failoverNodeMetrics.NodeName) > 0 {
+	// 							allowedips = append(allowedips, getNodeAllowedIPs(&nodeToFailover, peer)...)
+	// 							logger.Log(0, "failing over node", nodeToFailover.Name, nodeToFailover.PrimaryAddress(), "to failover node", peer.Name)
+	// 						}
+	// 					}
+	// 				}
+	// 			}
+	// 		}
+	// 	}
+	// }
 	// handle relay gateway peers
 	// handle relay gateway peers
 	// if peer.IsRelay == "yes" {
 	// if peer.IsRelay == "yes" {
 	// 	for _, ip := range peer.RelayAddrs {
 	// 	for _, ip := range peer.RelayAddrs {

+ 12 - 5
nm-proxy/common/common.go

@@ -13,6 +13,7 @@ import (
 
 
 var IsHostNetwork bool
 var IsHostNetwork bool
 var IsRelay bool
 var IsRelay bool
+var IsIngressGateway bool
 
 
 const (
 const (
 	NmProxyPort = 51722
 	NmProxyPort = 51722
@@ -30,12 +31,16 @@ type ConnConfig struct {
 	// Key is a public key of a remote peer
 	// Key is a public key of a remote peer
 	Key string
 	Key string
 	// LocalKey is a public key of a local peer
 	// LocalKey is a public key of a local peer
-	LocalKey        string
-	LocalWgPort     int
-	RemoteProxyIP   net.IP
-	RemoteWgPort    int
-	RemoteProxyPort int
+	LocalKey            string
+	LocalWgPort         int
+	RemoteProxyIP       net.IP
+	RemoteWgPort        int
+	RemoteProxyPort     int
+	IsExtClient         bool
+	IsAttachedExtClient bool
+	IngressGateWay      *net.UDPAddr
 }
 }
+
 type Config struct {
 type Config struct {
 	Port         int
 	Port         int
 	BodySize     int
 	BodySize     int
@@ -71,6 +76,8 @@ var WgIfaceKeyMap = make(map[string]struct{})
 
 
 var RelayPeerMap = make(map[string]map[string]RemotePeer)
 var RelayPeerMap = make(map[string]map[string]RemotePeer)
 
 
+var ExtClientsMap = make(map[string]RemotePeer)
+
 // RunCmd - runs a local command
 // RunCmd - runs a local command
 func RunCmd(command string, printerr bool) (string, error) {
 func RunCmd(command string, printerr bool) (string, error) {
 	args := strings.Fields(command)
 	args := strings.Fields(command)

+ 24 - 9
nm-proxy/manager/manager.go

@@ -21,6 +21,7 @@ type ManagerPayload struct {
 	Peers           []wgtypes.PeerConfig   `json:"peers"`
 	Peers           []wgtypes.PeerConfig   `json:"peers"`
 	PeerMap         map[string]PeerConf    `json:"peer_map"`
 	PeerMap         map[string]PeerConf    `json:"peer_map"`
 	IsRelayed       bool                   `json:"is_relayed"`
 	IsRelayed       bool                   `json:"is_relayed"`
+	IsIngress       bool                   `json:"is_ingress"`
 	RelayedTo       *net.UDPAddr           `json:"relayed_to"`
 	RelayedTo       *net.UDPAddr           `json:"relayed_to"`
 	IsRelay         bool                   `json:"is_relay"`
 	IsRelay         bool                   `json:"is_relay"`
 	RelayedPeerConf map[string]RelayedConf `json:"relayed_conf"`
 	RelayedPeerConf map[string]RelayedConf `json:"relayed_conf"`
@@ -31,9 +32,13 @@ type RelayedConf struct {
 	RelayedPeerPubKey   string               `json:"relayed_peer_pub_key"`
 	RelayedPeerPubKey   string               `json:"relayed_peer_pub_key"`
 	Peers               []wgtypes.PeerConfig `json:"relayed_peers"`
 	Peers               []wgtypes.PeerConfig `json:"relayed_peers"`
 }
 }
+
 type PeerConf struct {
 type PeerConf struct {
-	IsRelayed bool         `json:"is_relayed"`
-	RelayedTo *net.UDPAddr `json:"relayed_to"`
+	IsExtClient            bool         `json:"is_ext_client"`
+	IsAttachedExtClient    bool         `json:"is_attached_ext_client"`
+	IngressGatewayEndPoint *net.UDPAddr `json:"ingress_gateway_endpoint"`
+	IsRelayed              bool         `json:"is_relayed"`
+	RelayedTo              *net.UDPAddr `json:"relayed_to"`
 }
 }
 
 
 const (
 const (
@@ -62,6 +67,7 @@ func StartProxyManager(manageChan chan *ManagerAction) {
 				if mI.Payload.IsRelay {
 				if mI.Payload.IsRelay {
 					mI.RelayPeers()
 					mI.RelayPeers()
 				}
 				}
+				mI.ExtClients()
 				err := mI.AddInterfaceToProxy()
 				err := mI.AddInterfaceToProxy()
 				if err != nil {
 				if err != nil {
 					log.Printf("failed to add interface: [%s] to proxy: %v\n  ", mI.Payload.InterfaceName, err)
 					log.Printf("failed to add interface: [%s] to proxy: %v\n  ", mI.Payload.InterfaceName, err)
@@ -84,6 +90,11 @@ func (m *ManagerAction) RelayUpdate() {
 	common.IsRelay = m.Payload.IsRelay
 	common.IsRelay = m.Payload.IsRelay
 }
 }
 
 
+func (m *ManagerAction) ExtClients() {
+	common.IsIngressGateway = m.Payload.IsIngress
+
+}
+
 func (m *ManagerAction) RelayPeers() {
 func (m *ManagerAction) RelayPeers() {
 	common.IsRelay = true
 	common.IsRelay = true
 	for relayedNodePubKey, relayedNodeConf := range m.Payload.RelayedPeerConf {
 	for relayedNodePubKey, relayedNodeConf := range m.Payload.RelayedPeerConf {
@@ -138,7 +149,8 @@ func (m *ManagerAction) UpdatePeerProxy() {
 	}
 	}
 
 
 	for _, peerI := range m.Payload.Peers {
 	for _, peerI := range m.Payload.Peers {
-		if peerI.Endpoint == nil {
+		peerConf := m.Payload.PeerMap[peerI.PublicKey.String()]
+		if peerI.Endpoint == nil && !peerConf.IsExtClient {
 			log.Println("Endpoint nil for peer: ", peerI.PublicKey.String())
 			log.Println("Endpoint nil for peer: ", peerI.PublicKey.String())
 			continue
 			continue
 		}
 		}
@@ -191,7 +203,8 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 	log.Printf("wg: %+v\n", wgInterface)
 	log.Printf("wg: %+v\n", wgInterface)
 
 
 	for _, peerI := range m.Payload.Peers {
 	for _, peerI := range m.Payload.Peers {
-		if peerI.Endpoint == nil {
+		peerConf := m.Payload.PeerMap[peerI.PublicKey.String()]
+		if peerI.Endpoint == nil && !peerConf.IsExtClient {
 			log.Println("Endpoint nil for peer: ", peerI.PublicKey.String())
 			log.Println("Endpoint nil for peer: ", peerI.PublicKey.String())
 			continue
 			continue
 		}
 		}
@@ -199,19 +212,21 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 			Interface: ifaceName,
 			Interface: ifaceName,
 			PeerKey:   peerI.PublicKey.String(),
 			PeerKey:   peerI.PublicKey.String(),
 		}
 		}
+
 		var isRelayed bool
 		var isRelayed bool
 		var relayedTo *net.UDPAddr
 		var relayedTo *net.UDPAddr
 		if m.Payload.IsRelayed {
 		if m.Payload.IsRelayed {
 			isRelayed = true
 			isRelayed = true
 			relayedTo = m.Payload.RelayedTo
 			relayedTo = m.Payload.RelayedTo
 		} else {
 		} else {
-			if val, ok := m.Payload.PeerMap[peerI.PublicKey.String()]; ok {
-				isRelayed = val.IsRelayed
-				relayedTo = val.RelayedTo
-			}
+
+			isRelayed = peerConf.IsRelayed
+			relayedTo = peerConf.RelayedTo
+
 		}
 		}
 
 
-		peerpkg.AddNewPeer(wgInterface, &peerI, isRelayed, relayedTo)
+		peerpkg.AddNewPeer(wgInterface, &peerI, isRelayed,
+			peerConf.IsExtClient, peerConf.IngressGatewayEndPoint, relayedTo)
 	}
 	}
 	log.Printf("------> PEERHASHMAP: %+v\n", common.PeerKeyHashMap)
 	log.Printf("------> PEERHASHMAP: %+v\n", common.PeerKeyHashMap)
 	return nil
 	return nil

+ 5 - 1
nm-proxy/peer/peer.go

@@ -33,7 +33,8 @@ type ConnConfig struct {
 	RemoteProxyPort int
 	RemoteProxyPort int
 }
 }
 
 
-func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig, isRelayed bool, relayTo *net.UDPAddr) error {
+func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig,
+	isRelayed, isExtClient bool, ingGateway, relayTo *net.UDPAddr) error {
 
 
 	c := proxy.Config{
 	c := proxy.Config{
 		Port:        peer.Endpoint.Port,
 		Port:        peer.Endpoint.Port,
@@ -48,7 +49,10 @@ func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig, isRelayed boo
 	if isRelayed {
 	if isRelayed {
 		//go server.NmProxyServer.KeepAlive(peer.Endpoint.IP.String(), common.NmProxyPort)
 		//go server.NmProxyServer.KeepAlive(peer.Endpoint.IP.String(), common.NmProxyPort)
 		peerEndpoint = relayTo.IP.String()
 		peerEndpoint = relayTo.IP.String()
+	} else if isExtClient {
+		peerEndpoint = ingGateway.IP.String()
 	}
 	}
+
 	remoteConn, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", peerEndpoint, common.NmProxyPort))
 	remoteConn, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", peerEndpoint, common.NmProxyPort))
 	if err != nil {
 	if err != nil {
 		return err
 		return err

+ 20 - 0
nm-proxy/server/server.go

@@ -62,6 +62,26 @@ func (p *ProxyServer) Listen(ctx context.Context) {
 			var srcPeerKeyHash, dstPeerKeyHash string
 			var srcPeerKeyHash, dstPeerKeyHash string
 			n, srcPeerKeyHash, dstPeerKeyHash = packet.ExtractInfo(buffer, n)
 			n, srcPeerKeyHash, dstPeerKeyHash = packet.ExtractInfo(buffer, n)
 			//log.Printf("--------> RECV PKT [DSTPORT: %d], [SRCKEYHASH: %s], SourceIP: [%s] \n", localWgPort, srcPeerKeyHash, source.IP.String())
 			//log.Printf("--------> RECV PKT [DSTPORT: %d], [SRCKEYHASH: %s], SourceIP: [%s] \n", localWgPort, srcPeerKeyHash, source.IP.String())
+			if common.IsIngressGateway {
+				if peerConf, ok := common.ExtClientsMap[source.IP.String()]; ok {
+					log.Println("Pkt recieved from Ext clients...forward it to all peers")
+					if peers, ok := common.WgIFaceMap[peerConf.Interface]; ok {
+						for _, peerI := range peers {
+							// log.Printf("-------->  Forwading Ext PKT [ SourceIP: %s ], [ SourceKeyHash: %s ], [ DstIP: %s ], [ DstHashKey: %s ] \n",
+							// 	source.String(), srcPeerKeyHash, peerI.Config.RemoteProxyIP, dstPeerKeyHash)
+							out, outN, _, _ := packet.ProcessPacketBeforeSending(buffer[:1500], n-32, peerConf.PeerKey, peerI.Config.Key)
+							_, err = NmProxyServer.Server.WriteToUDP(out[:outN], &net.UDPAddr{
+								IP:   peerI.Config.RemoteProxyIP,
+								Port: peerI.Config.RemoteProxyPort,
+							})
+							if err != nil {
+								log.Println("Failed to send to remote: ", err)
+							}
+						}
+					}
+				}
+			}
+
 			if common.IsRelay && dstPeerKeyHash != "" && srcPeerKeyHash != "" {
 			if common.IsRelay && dstPeerKeyHash != "" && srcPeerKeyHash != "" {
 				if _, ok := common.WgIfaceKeyMap[dstPeerKeyHash]; !ok {
 				if _, ok := common.WgIfaceKeyMap[dstPeerKeyHash]; !ok {