Browse Source

collect metrics through proxy between peers

Abhishek Kondur 2 years ago
parent
commit
a2941df5a0

+ 4 - 2
nm-proxy/common/common.go

@@ -15,11 +15,13 @@ var IsRelayed bool
 var IsServer bool
 var InterfaceName string
 
-var WgIFaceMap = make(map[string]models.WgIfaceConf)
+var WgIfaceMap = models.WgIfaceConf{
+	PeerMap: make(map[string]*models.ConnConfig),
+}
 
 var PeerKeyHashMap = make(map[string]models.RemotePeer)
 
-var WgIfaceKeyMap = make(map[string]models.RemotePeer)
+//var WgIfaceKeyMap = make(map[string]models.RemotePeer)
 
 var RelayPeerMap = make(map[string]map[string]models.RemotePeer)
 

+ 15 - 25
nm-proxy/manager/manager.go

@@ -13,7 +13,6 @@ import (
 	"github.com/gravitl/netmaker/nm-proxy/common"
 	"github.com/gravitl/netmaker/nm-proxy/models"
 	peerpkg "github.com/gravitl/netmaker/nm-proxy/peer"
-	"github.com/gravitl/netmaker/nm-proxy/proxy"
 	"github.com/gravitl/netmaker/nm-proxy/wg"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 )
@@ -99,8 +98,8 @@ func (m *ManagerAction) DeleteInterface() {
 			return
 		}
 	}
-	if wgProxyConf, ok := common.WgIFaceMap[m.Payload.InterfaceName]; ok {
-		cleanUpInterface(wgProxyConf)
+	if common.WgIfaceMap.Iface.Name == m.Payload.InterfaceName {
+		cleanUpInterface()
 	}
 
 }
@@ -139,12 +138,12 @@ func (m *ManagerAction) RelayPeers() {
 	}
 }
 
-func cleanUpInterface(ifaceConf models.WgIfaceConf) {
-	log.Println("########------------>  CLEANING UP: ", ifaceConf.Iface.Name)
-	for _, peerI := range ifaceConf.PeerMap {
+func cleanUpInterface() {
+	log.Println("########------------>  CLEANING UP: ", common.WgIfaceMap.Iface.Name)
+	for _, peerI := range common.WgIfaceMap.PeerMap {
 		peerI.StopConn()
 	}
-	delete(common.WgIFaceMap, ifaceConf.Iface.Name)
+	common.WgIfaceMap.PeerMap = make(map[string]*models.ConnConfig)
 }
 
 func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
@@ -169,9 +168,8 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 		log.Println("Failed init new interface: ", err)
 		return nil, err
 	}
-	var wgProxyConf models.WgIfaceConf
-	var ok bool
-	if wgProxyConf, ok = common.WgIFaceMap[m.Payload.InterfaceName]; !ok {
+
+	if common.WgIfaceMap.Iface == nil {
 		for i := len(m.Payload.Peers) - 1; i >= 0; i-- {
 			if !m.Payload.PeerMap[m.Payload.Peers[i].PublicKey.String()].Proxy {
 				log.Println("-----------> skipping peer, proxy is off: ", m.Payload.Peers[i].PublicKey)
@@ -182,8 +180,11 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 				continue
 			}
 		}
+		common.WgIfaceMap.Iface = wgIface.Device
+		common.WgIfaceMap.IfaceKeyHash = fmt.Sprintf("%x", md5.Sum([]byte(wgIface.Device.PublicKey.String())))
 		return wgIface, nil
 	}
+	wgProxyConf := common.WgIfaceMap
 	if m.Payload.IsRelay {
 		m.RelayPeers()
 	}
@@ -191,7 +192,7 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 	// check if node is getting relayed
 	if common.IsRelayed != m.Payload.IsRelayed {
 		common.IsRelayed = m.Payload.IsRelayed
-		cleanUpInterface(wgProxyConf)
+		cleanUpInterface()
 		return wgIface, nil
 	}
 
@@ -199,7 +200,7 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 	// check if listen port has changed
 	if wgIface.Device.ListenPort != wgProxyConf.Iface.ListenPort {
 		// reset proxy for this interface
-		cleanUpInterface(wgProxyConf)
+		cleanUpInterface()
 		return wgIface, nil
 	}
 	// check device conf different from proxy
@@ -320,7 +321,7 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 
 	// sync dev peers with new update
 
-	common.WgIFaceMap[m.Payload.InterfaceName] = wgProxyConf
+	common.WgIfaceMap = wgProxyConf
 
 	log.Println("CLEANED UP..........")
 	return wgIface, nil
@@ -335,16 +336,6 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 	}
 
 	log.Printf("wg: %+v\n", wgInterface)
-	wgListenAddr, err := proxy.GetInterfaceListenAddr(wgInterface.Port)
-	if err != nil {
-		log.Println("failed to get wg listen addr: ", err)
-		return err
-	}
-	common.WgIfaceKeyMap[fmt.Sprintf("%x", md5.Sum([]byte(wgInterface.Device.PublicKey.String())))] = models.RemotePeer{
-		PeerKey:   wgInterface.Device.PublicKey.String(),
-		Interface: wgInterface.Name,
-		Endpoint:  wgListenAddr,
-	}
 	for _, peerI := range m.Payload.Peers {
 
 		peerConf := m.Payload.PeerMap[peerI.PublicKey.String()]
@@ -434,7 +425,6 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 			peerConf.IsExtClient, peerConf.IsAttachedExtClient, relayedTo)
 	}
 	log.Printf("------> PEERHASHMAP: %+v\n", common.PeerKeyHashMap)
-	log.Printf("-------> WgKeyHashMap: %+v\n", common.WgIfaceKeyMap)
-	log.Printf("-------> WgIFaceMap: %+v\n", common.WgIFaceMap)
+	log.Printf("-------> WgIFaceMap: %+v\n", common.WgIfaceMap)
 	return nil
 }

+ 24 - 2
nm-proxy/metrics/metrics.go

@@ -1,7 +1,10 @@
 package metrics
 
 import (
+	"encoding/json"
+	"os"
 	"sync"
+	"time"
 )
 
 /*
@@ -10,12 +13,31 @@ import (
 */
 
 type Metric struct {
-	LastRecordedLatency int64
+	LastRecordedLatency uint64
 	ConnectionStatus    bool
 	TrafficSent         uint64
 	TrafficRecieved     uint64
 }
 
-var MetricsMapLock *sync.RWMutex
+var MetricsMapLock = &sync.Mutex{}
 
 var MetricsMap = make(map[string]Metric)
+
+func init() {
+	go func() {
+		for {
+			time.Sleep(1 * time.Minute)
+			PrintMetrics()
+		}
+	}()
+}
+
+func PrintMetrics() {
+
+	data, err := json.MarshalIndent(MetricsMap, "", " ")
+	if err != nil {
+		return
+	}
+	os.WriteFile("/tmp/metrics.json", data, 0755)
+
+}

+ 3 - 2
nm-proxy/models/peer.go

@@ -41,6 +41,7 @@ type ExtClientPeer struct {
 }
 
 type WgIfaceConf struct {
-	Iface   *wgtypes.Device
-	PeerMap map[string]*ConnConfig
+	Iface        *wgtypes.Device
+	IfaceKeyHash string
+	PeerMap      map[string]*ConnConfig
 }

+ 35 - 14
nm-proxy/packet/packet.go

@@ -66,11 +66,13 @@ func ConsumeHandshakeInitiationMsg(initiator bool, buf []byte, src *net.UDPAddr,
 
 func CreateMetricPacket(id uint32, sender, reciever wgtypes.Key) ([]byte, error) {
 	msg := MetricMessage{
+		Type:      MessageMetricsType,
 		ID:        id,
 		Sender:    sender,
 		Reciever:  reciever,
 		TimeStamp: time.Now().UnixMilli(),
 	}
+	log.Printf("----------> $$$$$$ CREATED PACKET: %+v\n", msg)
 	var buff [MessageMetricSize]byte
 	writer := bytes.NewBuffer(buff[:0])
 	err := binary.Write(writer, binary.LittleEndian, msg)
@@ -101,26 +103,45 @@ func ProcessPacketBeforeSending(buf []byte, n int, srckey, dstKey string) ([]byt
 
 	srcKeymd5 := md5.Sum([]byte(srckey))
 	dstKeymd5 := md5.Sum([]byte(dstKey))
-	if n > len(buf)-len(srcKeymd5)-len(dstKeymd5) {
-		buf = append(buf, srcKeymd5[:]...)
-		buf = append(buf, dstKeymd5[:]...)
+	m := ProxyMessage{
+		Type:     MessageProxyType,
+		Sender:   srcKeymd5,
+		Reciever: dstKeymd5,
+	}
+	var msgBuffer [MessageProxySize]byte
+	writer := bytes.NewBuffer(msgBuffer[:0])
+	err := binary.Write(writer, binary.LittleEndian, m)
+	if err != nil {
+		log.Println(err)
+	}
+	if n > len(buf)-MessageProxySize {
+		buf = append(buf, msgBuffer[:]...)
+
 	} else {
-		copy(buf[n:n+len(srcKeymd5)], srcKeymd5[:])
-		copy(buf[n+len(srcKeymd5):n+len(srcKeymd5)+len(dstKeymd5)], dstKeymd5[:])
+		copy(buf[n:n+MessageProxySize], msgBuffer[:])
 	}
-	n += len(srcKeymd5)
-	n += len(dstKeymd5)
+	n += MessageProxySize
 
 	return buf, n, fmt.Sprintf("%x", srcKeymd5), fmt.Sprintf("%x", dstKeymd5)
 }
 
-func ExtractInfo(buffer []byte, n int) (int, string, string) {
+func ExtractInfo(buffer []byte, n int) (int, string, string, error) {
 	data := buffer[:n]
-	if len(data) < 32 {
-		return 0, "", ""
+	if len(data) < 36 {
+		return 0, "", "", errors.New("proxy message not found")
+	}
+	var msg ProxyMessage
+	var err error
+	reader := bytes.NewReader(buffer[n-MessageProxySize:])
+	err = binary.Read(reader, binary.LittleEndian, &msg)
+	if err != nil {
+		log.Println("Failed to decode proxy message")
+		return n, "", "", err
+	}
+
+	if msg.Type != MessageProxyType {
+		return n, "", "", errors.New("not a proxy message")
 	}
-	srcKeyHash := data[n-32 : n-16]
-	dstKeyHash := data[n-16:]
-	n -= 32
-	return n, fmt.Sprintf("%x", srcKeyHash), fmt.Sprintf("%x", dstKeyHash)
+	n -= MessageProxySize
+	return n, fmt.Sprintf("%x", msg.Sender), fmt.Sprintf("%x", msg.Reciever), nil
 }

+ 6 - 0
nm-proxy/packet/packet_helper.go

@@ -36,3 +36,9 @@ type MetricMessage struct {
 	Reciever  wgtypes.Key
 	TimeStamp int64
 }
+
+type ProxyMessage struct {
+	Type     uint32
+	Sender   [16]byte
+	Reciever [16]byte
+}

+ 12 - 7
nm-proxy/packet/utils.go

@@ -13,13 +13,18 @@ import (
 const (
 	MessageInitiationType = 1
 	MessageMetricsType    = 5
-	NoisePublicKeySize    = 32
-	NoisePrivateKeySize   = 32
-	MessageMetricSize     = 148
-	NoiseConstruction     = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
-	WGIdentifier          = "WireGuard v1 zx2c4 [email protected]"
-	WGLabelMAC1           = "mac1----"
-	WGLabelCookie         = "cookie--"
+	MessageProxyType      = 6
+
+	NoisePublicKeySize  = 32
+	NoisePrivateKeySize = 32
+
+	MessageMetricSize = 148
+	MessageProxySize  = 36
+
+	NoiseConstruction = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
+	WGIdentifier      = "WireGuard v1 zx2c4 [email protected]"
+	WGLabelMAC1       = "mac1----"
+	WGLabelCookie     = "cookie--"
 )
 
 func mixKey(dst, c *[blake2s.Size]byte, data []byte) {

+ 2 - 12
nm-proxy/peer/peer.go

@@ -19,7 +19,7 @@ func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig, peerAddr stri
 	c := proxy.Config{
 		Port:        peer.Endpoint.Port,
 		LocalKey:    wgInterface.Device.PublicKey,
-		RemoteKey:   peer.PublicKey.String(),
+		RemoteKey:   peer.PublicKey,
 		WgInterface: wgInterface,
 		IsExtClient: isExtClient,
 		PeerConf:    peer,
@@ -66,17 +66,7 @@ func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig, peerAddr stri
 		LocalConn:           p.LocalConn,
 	}
 
-	if _, ok := common.WgIFaceMap[wgInterface.Name]; ok {
-		common.WgIFaceMap[wgInterface.Name].PeerMap[peer.PublicKey.String()] = &connConf
-	} else {
-		ifaceConf := models.WgIfaceConf{
-			Iface:   wgInterface.Device,
-			PeerMap: make(map[string]*models.ConnConfig),
-		}
-
-		common.WgIFaceMap[wgInterface.Name] = ifaceConf
-		common.WgIFaceMap[wgInterface.Name].PeerMap[peer.PublicKey.String()] = &connConf
-	}
+	common.WgIfaceMap.PeerMap[peer.PublicKey.String()] = &connConf
 
 	return nil
 }

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

@@ -20,7 +20,7 @@ type Config struct {
 	Port        int
 	BodySize    int
 	Addr        string
-	RemoteKey   string
+	RemoteKey   wgtypes.Key
 	LocalKey    wgtypes.Key
 	WgInterface *wg.WGIface
 	IsExtClient bool

+ 15 - 12
nm-proxy/proxy/wireguard.go

@@ -28,13 +28,16 @@ func NewProxy(config Config) *Proxy {
 
 // proxyToRemote proxies everything from Wireguard to the RemoteKey peer
 func (p *Proxy) ProxyToRemote() {
-
+	ticker := time.NewTicker(time.Minute)
+	buf := make([]byte, 65000)
 	go func() {
 		<-p.Ctx.Done()
 		log.Println("Closing connection for: ", p.LocalConn.LocalAddr().String())
+		ticker.Stop()
+		buf = nil
 		p.LocalConn.Close()
 	}()
-	buf := make([]byte, 65000)
+
 	for {
 		select {
 		case <-p.Ctx.Done():
@@ -56,14 +59,15 @@ func (p *Proxy) ProxyToRemote() {
 			}
 
 			return
-		case <-time.After(time.Minute):
+		case <-ticker.C:
 			metrics.MetricsMapLock.Lock()
-			metric := metrics.MetricsMap[p.Config.PeerConf.PublicKey.String()]
+			metric := metrics.MetricsMap[p.Config.RemoteKey.String()]
 			metric.ConnectionStatus = false
-			metrics.MetricsMap[p.Config.PeerConf.PublicKey.String()] = metric
+			metrics.MetricsMap[p.Config.RemoteKey.String()] = metric
 			metrics.MetricsMapLock.Unlock()
-			pkt, err := packet.CreateMetricPacket(uuid.New().ID(), p.Config.LocalKey, p.Config.PeerConf.PublicKey)
+			pkt, err := packet.CreateMetricPacket(uuid.New().ID(), p.Config.LocalKey, p.Config.RemoteKey)
 			if err == nil {
+				log.Printf("-----------> ##### $$$$$ SENDING METRIC PACKET TO: %s\n", p.RemoteConn.String())
 				_, err = server.NmProxyServer.Server.WriteToUDP(pkt, p.RemoteConn)
 				if err != nil {
 					log.Println("Failed to send to metric pkt: ", err)
@@ -78,18 +82,17 @@ func (p *Proxy) ProxyToRemote() {
 				continue
 			}
 
-			ifaceConf := common.WgIFaceMap[p.Config.WgInterface.Name]
-			if peerI, ok := ifaceConf.PeerMap[p.Config.RemoteKey]; ok {
+			if _, ok := common.WgIfaceMap.PeerMap[p.Config.RemoteKey.String()]; ok {
 
 				metrics.MetricsMapLock.Lock()
-				metric := metrics.MetricsMap[peerI.Key.String()]
+				metric := metrics.MetricsMap[p.Config.RemoteKey.String()]
 				metric.TrafficSent += uint64(n)
-				metrics.MetricsMap[peerI.Key.String()] = metric
+				metrics.MetricsMap[p.Config.RemoteKey.String()] = metric
 				metrics.MetricsMapLock.Unlock()
 
 				var srcPeerKeyHash, dstPeerKeyHash string
 				if !p.Config.IsExtClient {
-					buf, n, srcPeerKeyHash, dstPeerKeyHash = packet.ProcessPacketBeforeSending(buf, n, ifaceConf.Iface.PublicKey.String(), peerI.Key.String())
+					buf, n, srcPeerKeyHash, dstPeerKeyHash = packet.ProcessPacketBeforeSending(buf, n, common.WgIfaceMap.Iface.PublicKey.String(), p.Config.RemoteKey.String())
 					if err != nil {
 						log.Println("failed to process pkt before sending: ", err)
 					}
@@ -125,7 +128,7 @@ func (p *Proxy) updateEndpoint() error {
 	}
 	// add local proxy connection as a Wireguard peer
 	log.Printf("---> ####### Updating Peer:  %+v\n", p.Config.PeerConf)
-	err = p.Config.WgInterface.UpdatePeer(p.Config.RemoteKey, p.Config.PeerConf.AllowedIPs, wg.DefaultWgKeepAlive,
+	err = p.Config.WgInterface.UpdatePeer(p.Config.RemoteKey.String(), p.Config.PeerConf.AllowedIPs, wg.DefaultWgKeepAlive,
 		udpAddr, p.Config.PeerConf.PresharedKey)
 	if err != nil {
 		return err

+ 103 - 96
nm-proxy/server/server.go

@@ -46,12 +46,12 @@ func (p *ProxyServer) Listen(ctx context.Context) {
 		case <-ctx.Done():
 			log.Println("--------->### Shutting down Proxy.....")
 			// clean up proxy connections
-			for iface, ifaceConf := range common.WgIFaceMap {
-				log.Println("########------------>  CLEANING UP: ", iface)
-				for _, peerI := range ifaceConf.PeerMap {
-					peerI.StopConn()
-				}
+
+			log.Println("########------------>  CLEANING UP Interface ")
+			for _, peerI := range common.WgIfaceMap.PeerMap {
+				peerI.StopConn()
 			}
+
 			// close server connection
 			NmProxyServer.Server.Close()
 			return
@@ -65,62 +65,21 @@ func (p *ProxyServer) Listen(ctx context.Context) {
 			}
 			//go func(buffer []byte, source *net.UDPAddr, n int) {
 			origBufferLen := n
+			fromProxy := true
 			var srcPeerKeyHash, dstPeerKeyHash string
-			n, srcPeerKeyHash, dstPeerKeyHash = packet.ExtractInfo(buffer, n)
-			//log.Printf("--------> RECV PKT , [SRCKEYHASH: %s], SourceIP: [%s] \n", srcPeerKeyHash, source.IP.String())
-
-			if _, ok := common.WgIfaceKeyMap[dstPeerKeyHash]; !ok {
-				// if common.IsIngressGateway {
-				// 	log.Println("----> fowarding PKT to EXT client...")
-				// 	if val, ok := common.PeerKeyHashMap[dstPeerKeyHash]; ok && val.IsAttachedExtClient {
-
-				// 		log.Printf("-------->Forwarding the pkt to extClient  [ SourceIP: %s ], [ SourceKeyHash: %s ], [ DstIP: %s ], [ DstHashKey: %s ] \n",
-				// 			source.String(), srcPeerKeyHash, val.Endpoint.String(), dstPeerKeyHash)
-				// 		_, err = NmProxyServer.Server.WriteToUDP(buffer[:n], val.Endpoint)
-				// 		if err != nil {
-				// 			log.Println("Failed to send to remote: ", err)
-				// 		}
-				// 		continue
-
-				// 	}
-				// }
-
-				if common.IsRelay {
-
-					log.Println("----------> Relaying######")
-					// check for routing map and forward to right proxy
-					if remoteMap, ok := common.RelayPeerMap[srcPeerKeyHash]; ok {
-						if conf, ok := remoteMap[dstPeerKeyHash]; ok {
-							log.Printf("--------> Relaying PKT [ SourceIP: %s:%d ], [ SourceKeyHash: %s ], [ DstIP: %s:%d ], [ DstHashKey: %s ] \n",
-								source.IP.String(), source.Port, srcPeerKeyHash, conf.Endpoint.String(), conf.Endpoint.Port, dstPeerKeyHash)
-							_, err = NmProxyServer.Server.WriteToUDP(buffer[:n+32], conf.Endpoint)
-							if err != nil {
-								log.Println("Failed to send to remote: ", err)
-							}
-							//continue
-						}
-					} else {
-						if remoteMap, ok := common.RelayPeerMap[dstPeerKeyHash]; ok {
-							if conf, ok := remoteMap[dstPeerKeyHash]; ok {
-								log.Printf("--------> Relaying BACK TO RELAYED NODE PKT [ SourceIP: %s ], [ SourceKeyHash: %s ], [ DstIP: %s ], [ DstHashKey: %s ] \n",
-									source.String(), srcPeerKeyHash, conf.Endpoint.String(), dstPeerKeyHash)
-								_, err = NmProxyServer.Server.WriteToUDP(buffer[:n+32], conf.Endpoint)
-								if err != nil {
-									log.Println("Failed to send to remote: ", err)
-								}
-								//continue
-							}
-						}
-
-					}
-
-				}
-
+			n, srcPeerKeyHash, dstPeerKeyHash, err = packet.ExtractInfo(buffer, n)
+			if err != nil {
+				log.Println("proxy message not found: ", err)
+				fromProxy = false
 			}
+			if fromProxy {
+				proxyIncomingPacket(buffer[:], source, n, srcPeerKeyHash, dstPeerKeyHash)
+				continue
 
-			if peerInfo, ok := common.PeerKeyHashMap[srcPeerKeyHash]; ok {
-				if ifaceConf, ok := common.WgIFaceMap[peerInfo.Interface]; ok {
-					if peerI, ok := ifaceConf.PeerMap[peerInfo.PeerKey]; ok {
+			} else {
+				// unknown peer to proxy -> check if extclient and handle it
+				if peerInfo, ok := common.ExtSourceIpMap[source.String()]; ok {
+					if peerI, ok := common.WgIfaceMap.PeerMap[peerInfo.PeerKey]; ok {
 						metrics.MetricsMapLock.Lock()
 						metric := metrics.MetricsMap[peerInfo.PeerKey]
 						metric.TrafficRecieved += uint64(n)
@@ -138,65 +97,113 @@ func (p *ProxyServer) Listen(ctx context.Context) {
 						continue
 
 					}
-				}
 
+				}
 			}
-			if peerInfo, ok := common.ExtSourceIpMap[source.String()]; ok {
-				if ifaceConf, ok := common.WgIFaceMap[peerInfo.Interface]; ok {
-					if peerI, ok := ifaceConf.PeerMap[peerInfo.PeerKey]; ok {
+
+			msgType := binary.LittleEndian.Uint32(buffer[:4])
+			switch msgType {
+			case packet.MessageMetricsType:
+				metricMsg, err := packet.ConsumeMetricPacket(buffer[:origBufferLen])
+				// calc latency
+				if err == nil {
+					log.Printf("------->$$$$$ Recieved Metric Pkt: %+v, FROM:%s\n", metricMsg, source.String())
+					if metricMsg.Sender == common.WgIfaceMap.Iface.PublicKey {
+						latency := time.Now().UnixMilli() - metricMsg.TimeStamp
+						log.Println("----------------> LAtency$$$$$$: ", latency)
 						metrics.MetricsMapLock.Lock()
-						metric := metrics.MetricsMap[peerInfo.PeerKey]
-						metric.TrafficRecieved += uint64(n)
+						metric := metrics.MetricsMap[metricMsg.Reciever.String()]
+						metric.LastRecordedLatency = uint64(latency)
 						metric.ConnectionStatus = true
-						metrics.MetricsMap[peerInfo.PeerKey] = metric
+						metric.TrafficRecieved += uint64(origBufferLen)
+						metrics.MetricsMap[metricMsg.Reciever.String()] = metric
 						metrics.MetricsMapLock.Unlock()
-						log.Printf("PROXING TO LOCAL!!!---> %s <<<< %s <<<<<<<< %s   [[ RECV PKT [SRCKEYHASH: %s], [DSTKEYHASH: %s], SourceIP: [%s] ]]\n",
-							peerI.LocalConn.RemoteAddr(), peerI.LocalConn.LocalAddr(),
-							fmt.Sprintf("%s:%d", source.IP.String(), source.Port), srcPeerKeyHash, dstPeerKeyHash, source.IP.String())
-						_, err = peerI.LocalConn.Write(buffer[:origBufferLen])
+					} else if metricMsg.Reciever == common.WgIfaceMap.Iface.PublicKey {
+						// proxy it back to the sender
+						log.Println("------------> $$$ SENDING back the metric pkt to the source: ", source.String())
+						_, err = NmProxyServer.Server.WriteToUDP(buffer[:origBufferLen], source)
 						if err != nil {
-							log.Println("Failed to proxy to Wg local interface: ", err)
-							//continue
+							log.Println("Failed to send metric packet to remote: ", err)
 						}
-						continue
-
+						metrics.MetricsMapLock.Lock()
+						metric := metrics.MetricsMap[metricMsg.Sender.String()]
+						metric.ConnectionStatus = true
+						metric.TrafficRecieved += uint64(origBufferLen)
+						metrics.MetricsMap[metricMsg.Sender.String()] = metric
+						metrics.MetricsMapLock.Unlock()
 					}
 				}
-			}
-			// unknown peer to proxy -> check if extclient and handle it
 			// consume handshake message for ext clients
-			msgType := binary.LittleEndian.Uint32(buffer[:4])
-			switch msgType {
-			case packet.MessageMetricsType:
-				metricMsg, err := packet.ConsumeMetricPacket(buffer[:origBufferLen])
-				// calc latency
-				if err == nil {
-					latency := time.Now().UnixMilli() - metricMsg.TimeStamp
-					metrics.MetricsMapLock.Lock()
-					metric := metrics.MetricsMap[metricMsg.Reciever.PublicKey().String()]
-					metric.LastRecordedLatency = latency
-					metric.ConnectionStatus = true
-					metric.TrafficRecieved += uint64(origBufferLen)
-					metrics.MetricsMap[metricMsg.Reciever.PublicKey().String()] = metric
-					metrics.MetricsMapLock.Unlock()
+			case packet.MessageInitiationType:
+
+				err := packet.ConsumeHandshakeInitiationMsg(false, buffer[:origBufferLen], source,
+					packet.NoisePublicKey(common.WgIfaceMap.Iface.PublicKey), packet.NoisePrivateKey(common.WgIfaceMap.Iface.PrivateKey))
+				if err != nil {
+					log.Println("---------> @@@ failed to decode HS: ", err)
 				}
 
-			case packet.MessageInitiationType:
+			}
 
-				devPriv, devPubkey, err := packet.GetDeviceKeys(common.InterfaceName)
-				if err == nil {
-					err := packet.ConsumeHandshakeInitiationMsg(false, buffer[:origBufferLen], source, devPubkey, devPriv)
+		}
+
+	}
+}
+
+func proxyIncomingPacket(buffer []byte, source *net.UDPAddr, n int, srcPeerKeyHash, dstPeerKeyHash string) {
+	var err error
+	//log.Printf("--------> RECV PKT , [SRCKEYHASH: %s], SourceIP: [%s] \n", srcPeerKeyHash, source.IP.String())
+
+	if common.WgIfaceMap.IfaceKeyHash != dstPeerKeyHash && common.IsRelay {
+
+		log.Println("----------> Relaying######")
+		// check for routing map and forward to right proxy
+		if remoteMap, ok := common.RelayPeerMap[srcPeerKeyHash]; ok {
+			if conf, ok := remoteMap[dstPeerKeyHash]; ok {
+				log.Printf("--------> Relaying PKT [ SourceIP: %s:%d ], [ SourceKeyHash: %s ], [ DstIP: %s:%d ], [ DstHashKey: %s ] \n",
+					source.IP.String(), source.Port, srcPeerKeyHash, conf.Endpoint.String(), conf.Endpoint.Port, dstPeerKeyHash)
+				_, err = NmProxyServer.Server.WriteToUDP(buffer[:n+packet.MessageProxySize], conf.Endpoint)
+				if err != nil {
+					log.Println("Failed to send to remote: ", err)
+				}
+				return
+			}
+		} else {
+			if remoteMap, ok := common.RelayPeerMap[dstPeerKeyHash]; ok {
+				if conf, ok := remoteMap[dstPeerKeyHash]; ok {
+					log.Printf("--------> Relaying BACK TO RELAYED NODE PKT [ SourceIP: %s ], [ SourceKeyHash: %s ], [ DstIP: %s ], [ DstHashKey: %s ] \n",
+						source.String(), srcPeerKeyHash, conf.Endpoint.String(), dstPeerKeyHash)
+					_, err = NmProxyServer.Server.WriteToUDP(buffer[:n+packet.MessageProxySize], conf.Endpoint)
 					if err != nil {
-						log.Println("---------> @@@ failed to decode HS: ", err)
+						log.Println("Failed to send to remote: ", err)
 					}
-				} else {
-					log.Println("failed to get device keys: ", err)
+					return
 				}
 			}
 
 		}
+	}
+
+	if peerInfo, ok := common.PeerKeyHashMap[srcPeerKeyHash]; ok {
+		if peerI, ok := common.WgIfaceMap.PeerMap[peerInfo.PeerKey]; ok {
+			metrics.MetricsMapLock.Lock()
+			metric := metrics.MetricsMap[peerInfo.PeerKey]
+			metric.TrafficRecieved += uint64(n)
+			metric.ConnectionStatus = true
+			metrics.MetricsMap[peerInfo.PeerKey] = metric
+			metrics.MetricsMapLock.Unlock()
+			log.Printf("PROXING TO LOCAL!!!---> %s <<<< %s <<<<<<<< %s   [[ RECV PKT [SRCKEYHASH: %s], [DSTKEYHASH: %s], SourceIP: [%s] ]]\n",
+				peerI.LocalConn.RemoteAddr(), peerI.LocalConn.LocalAddr(),
+				fmt.Sprintf("%s:%d", source.IP.String(), source.Port), srcPeerKeyHash, dstPeerKeyHash, source.IP.String())
+			_, err = peerI.LocalConn.Write(buffer[:n])
+			if err != nil {
+				log.Println("Failed to proxy to Wg local interface: ", err)
+				//continue
+			}
+			return
+		}
 
 	}
+
 }
 
 // Create - creats a proxy listener