Browse Source

connect to ext client by using handshake packet info

Abhishek Kondur 2 years ago
parent
commit
d0d9bc5ecd

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

@@ -15,6 +15,8 @@ var IsHostNetwork bool
 var IsRelay bool
 var IsIngressGateway bool
 var IsRelayed bool
+var IsServer bool
+var InterfaceName string
 
 const (
 	NmProxyPort = 51722
@@ -74,8 +76,8 @@ type RemotePeer struct {
 }
 
 type ExtClientPeer struct {
-	Endpoint *net.UDPAddr
-	context.CancelFunc
+	CancelFunc context.CancelFunc
+	CommChan   chan *net.UDPAddr
 }
 
 type WgIfaceConf struct {
@@ -93,6 +95,8 @@ var RelayPeerMap = make(map[string]map[string]RemotePeer)
 
 var ExtClientsWaitTh = make(map[string]ExtClientPeer)
 
+var ExtSourceIpMap = make(map[string]RemotePeer)
+
 // RunCmd - runs a local command
 func RunCmd(command string, printerr bool) (string, error) {
 	args := strings.Fields(command)

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

@@ -9,7 +9,6 @@ import (
 	"net"
 	"reflect"
 	"runtime"
-	"time"
 
 	"github.com/gravitl/netmaker/nm-proxy/common"
 	peerpkg "github.com/gravitl/netmaker/nm-proxy/peer"
@@ -163,6 +162,7 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 			log.Println("failed to get real iface: ", err)
 		}
 	}
+	common.InterfaceName = m.Payload.InterfaceName
 	wgIface, err = wg.NewWGIFace(m.Payload.InterfaceName, "127.0.0.1/32", wg.DefaultMTU)
 	if err != nil {
 		log.Println("Failed init new interface: ", err)
@@ -179,6 +179,7 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 					log.Println("falied to update peer: ", err)
 				}
 				m.Payload.Peers = append(m.Payload.Peers[:i], m.Payload.Peers[i+1:]...)
+				continue
 			}
 			if m.Payload.PeerMap[m.Payload.Peers[i].PublicKey.String()].IsAttachedExtClient {
 				if err := wgIface.Update(m.Payload.Peers[i], false); err != nil {
@@ -220,7 +221,7 @@ func (m *ManagerAction) processPayload() (*wg.WGIface, error) {
 					m.Payload.Peers = append(m.Payload.Peers[:i], m.Payload.Peers[i+1:]...)
 
 				}
-				log.Println("----> Skip Processing ExtClient: ", m.Payload.Peers[i].PublicKey.String())
+
 				continue
 			}
 			// check if proxy is off for the peer
@@ -384,12 +385,11 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 			shouldProceed = true
 		}
 		if peerConf.IsExtClient && peerConf.IsAttachedExtClient && shouldProceed {
-			ctx, cancel := context.WithCancel(context.Background())
-			common.ExtClientsWaitTh[peerI.PublicKey.String()] = common.ExtClientPeer{
-				Endpoint:   peerI.Endpoint,
-				CancelFunc: cancel,
-			}
-			go proxy.StartSniffer(ctx, wgInterface.Name, m.Payload.WgAddr, peerConf.Address, wgInterface.Port)
+			// ctx, cancel := context.WithCancel(context.Background())
+			// common.ExtClientsWaitTh[peerI.PublicKey.String()] = common.ExtClientPeer{
+			// 	CancelFunc: cancel,
+			// }
+			//go proxy.StartSniffer(ctx, wgInterface.Name, m.Payload.WgAddr, peerConf.Address, wgInterface.Port)
 		}
 
 		if peerConf.IsExtClient && !peerConf.IsAttachedExtClient {
@@ -422,15 +422,16 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 			go func(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig,
 				isRelayed bool, relayTo *net.UDPAddr, peerConf PeerConf, ingGwAddr string) {
 				addExtClient := false
+				commChan := make(chan *net.UDPAddr, 100)
 				ctx, cancel := context.WithCancel(context.Background())
 				common.ExtClientsWaitTh[peerI.PublicKey.String()] = common.ExtClientPeer{
-					Endpoint:   peer.Endpoint,
 					CancelFunc: cancel,
+					CommChan:   commChan,
 				}
 				defer func() {
 					if addExtClient {
 						log.Println("GOT ENDPOINT for Extclient adding peer...")
-						go proxy.StartSniffer(ctx, wgInterface.Name, ingGwAddr, peerConf.Address, wgInterface.Port)
+						//go proxy.StartSniffer(ctx, wgInterface.Name, ingGwAddr, peerConf.Address, wgInterface.Port)
 						common.PeerKeyHashMap[fmt.Sprintf("%x", md5.Sum([]byte(peer.PublicKey.String())))] = common.RemotePeer{
 							Interface:           wgInterface.Name,
 							PeerKey:             peer.PublicKey.String(),
@@ -438,30 +439,31 @@ func (m *ManagerAction) AddInterfaceToProxy() error {
 							IsAttachedExtClient: peerConf.IsAttachedExtClient,
 							Endpoint:            peer.Endpoint,
 						}
+						common.ExtSourceIpMap[peer.Endpoint.String()] = common.RemotePeer{
+							Interface:           wgInterface.Name,
+							PeerKey:             peer.PublicKey.String(),
+							IsExtClient:         peerConf.IsExtClient,
+							IsAttachedExtClient: peerConf.IsAttachedExtClient,
+							Endpoint:            peer.Endpoint,
+						}
 
 						peerpkg.AddNewPeer(wgInterface, peer, peerConf.Address, isRelayed,
 							peerConf.IsExtClient, peerConf.IsAttachedExtClient, relayedTo)
+
 					}
+					log.Println("Exiting extclient watch Thread for: ", peer.PublicKey.String())
 				}()
 				for {
 					select {
 					case <-ctx.Done():
-						log.Println("Exiting extclient watch Thread for: ", wgInterface.Device.PublicKey.String())
 						return
-					default:
-						wgInterface, err := wg.NewWGIFace(m.Payload.InterfaceName, "127.0.0.1/32", wg.DefaultMTU)
-						if err != nil {
-							log.Println("Failed init new interface: ", err)
+					case endpoint := <-commChan:
+						if endpoint != nil {
+							addExtClient = true
+							peer.Endpoint = endpoint
+							delete(common.ExtClientsWaitTh, peer.PublicKey.String())
 							return
 						}
-						for _, devpeerI := range wgInterface.Device.Peers {
-							if devpeerI.PublicKey.String() == peer.PublicKey.String() && devpeerI.Endpoint != nil {
-								peer.Endpoint = devpeerI.Endpoint
-								addExtClient = true
-								return
-							}
-						}
-						time.Sleep(time.Second * 5)
 					}
 
 				}

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

@@ -21,7 +21,6 @@ import (
 func Start(ctx context.Context, mgmChan chan *manager.ManagerAction, apiServerAddr string) {
 	log.Println("Starting Proxy...")
 	common.IsHostNetwork = (os.Getenv("HOST_NETWORK") == "" || os.Getenv("HOST_NETWORK") == "on")
-
 	hInfo := stun.GetHostInfo(apiServerAddr)
 	stun.Host = hInfo
 	log.Printf("HOSTINFO: %+v", hInfo)

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

@@ -0,0 +1,247 @@
+package packet
+
+import (
+	"bytes"
+	"crypto/hmac"
+	"crypto/subtle"
+	"encoding/base64"
+	"encoding/binary"
+	"encoding/hex"
+	"errors"
+	"hash"
+	"log"
+
+	"github.com/gravitl/netmaker/nm-proxy/wg"
+	"golang.org/x/crypto/blake2s"
+	"golang.org/x/crypto/chacha20poly1305"
+	"golang.org/x/crypto/curve25519"
+	"golang.org/x/crypto/poly1305"
+	"golang.zx2c4.com/wireguard/tai64n"
+)
+
+func init() {
+	InitialChainKey = blake2s.Sum256([]byte(NoiseConstruction))
+	mixHash(&InitialHash, &InitialChainKey, []byte(WGIdentifier))
+}
+func mixKey(dst, c *[blake2s.Size]byte, data []byte) {
+	KDF1(dst, c[:], data)
+}
+
+func mixHash(dst, h *[blake2s.Size]byte, data []byte) {
+	hash, _ := blake2s.New256(nil)
+	hash.Write(h[:])
+	hash.Write(data)
+	hash.Sum(dst[:0])
+	hash.Reset()
+}
+func HMAC1(sum *[blake2s.Size]byte, key, in0 []byte) {
+	mac := hmac.New(func() hash.Hash {
+		h, _ := blake2s.New256(nil)
+		return h
+	}, key)
+	mac.Write(in0)
+	mac.Sum(sum[:0])
+}
+
+func HMAC2(sum *[blake2s.Size]byte, key, in0, in1 []byte) {
+	mac := hmac.New(func() hash.Hash {
+		h, _ := blake2s.New256(nil)
+		return h
+	}, key)
+	mac.Write(in0)
+	mac.Write(in1)
+	mac.Sum(sum[:0])
+}
+
+func KDF1(t0 *[blake2s.Size]byte, key, input []byte) {
+	HMAC1(t0, key, input)
+	HMAC1(t0, t0[:], []byte{0x1})
+}
+
+const (
+	NoiseConstruction = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
+	WGIdentifier      = "WireGuard v1 zx2c4 [email protected]"
+	WGLabelMAC1       = "mac1----"
+	WGLabelCookie     = "cookie--"
+)
+
+const (
+	MessageInitiationType  = 1
+	MessageResponseType    = 2
+	MessageCookieReplyType = 3
+	MessageTransportType   = 4
+)
+const (
+	NoisePublicKeySize    = 32
+	NoisePrivateKeySize   = 32
+	NoisePresharedKeySize = 32
+)
+
+type (
+	NoisePublicKey    [NoisePublicKeySize]byte
+	NoisePrivateKey   [NoisePrivateKeySize]byte
+	NoisePresharedKey [NoisePresharedKeySize]byte
+	NoiseNonce        uint64 // padded to 12-bytes
+)
+
+type MessageInitiation struct {
+	Type      uint32
+	Sender    uint32
+	Ephemeral NoisePublicKey
+	Static    [NoisePublicKeySize + poly1305.TagSize]byte
+	Timestamp [tai64n.TimestampSize + poly1305.TagSize]byte
+	MAC1      [blake2s.Size128]byte
+	MAC2      [blake2s.Size128]byte
+}
+
+var (
+	InitialChainKey [blake2s.Size]byte
+	InitialHash     [blake2s.Size]byte
+	ZeroNonce       [chacha20poly1305.NonceSize]byte
+)
+
+func KDF2(t0, t1 *[blake2s.Size]byte, key, input []byte) {
+	var prk [blake2s.Size]byte
+	HMAC1(&prk, key, input)
+	HMAC1(t0, prk[:], []byte{0x1})
+	HMAC2(t1, prk[:], t0[:], []byte{0x2})
+	setZero(prk[:])
+}
+func setZero(arr []byte) {
+	for i := range arr {
+		arr[i] = 0
+	}
+}
+func isZero(val []byte) bool {
+	acc := 1
+	for _, b := range val {
+		acc &= subtle.ConstantTimeByteEq(b, 0)
+	}
+	return acc == 1
+}
+func uapiCfg(cfg ...string) string {
+	if len(cfg)%2 != 0 {
+		panic("odd number of args to uapiReader")
+	}
+	buf := new(bytes.Buffer)
+	for i, s := range cfg {
+		buf.WriteString(s)
+		sep := byte('\n')
+		if i%2 == 0 {
+			sep = '='
+		}
+		buf.WriteByte(sep)
+	}
+	return buf.String()
+}
+func sharedSecret(sk *NoisePrivateKey, pk NoisePublicKey) (ss [NoisePublicKeySize]byte) {
+	apk := (*[NoisePublicKeySize]byte)(&pk)
+	ask := (*[NoisePrivateKeySize]byte)(sk)
+	curve25519.ScalarMult(&ss, ask, apk)
+	return ss
+}
+
+func ConsumeHandshakeMsg(buf []byte, devicePubKey NoisePublicKey, devicePrivKey NoisePrivateKey) (string, error) {
+
+	var (
+		hash     [blake2s.Size]byte
+		chainKey [blake2s.Size]byte
+	)
+	var err error
+	var msg MessageInitiation
+	reader := bytes.NewReader(buf[:])
+	err = binary.Read(reader, binary.LittleEndian, &msg)
+	if err != nil {
+		log.Println("Failed to decode initiation message")
+		return "", err
+	}
+
+	if msg.Type != MessageInitiationType {
+		return "", errors.New("not handshake initiate message")
+	}
+	log.Println("-----> HandSHAKE MESSAGE")
+	mixHash(&hash, &InitialHash, devicePubKey[:])
+	mixHash(&hash, &hash, msg.Ephemeral[:])
+	mixKey(&chainKey, &InitialChainKey, msg.Ephemeral[:])
+
+	// decrypt static key
+	var peerPK NoisePublicKey
+	var key [chacha20poly1305.KeySize]byte
+	ss := sharedSecret(&devicePrivKey, msg.Ephemeral)
+	if isZero(ss[:]) {
+		return "", errors.New("no secret")
+	}
+	KDF2(&chainKey, &key, chainKey[:], ss[:])
+	aead, _ := chacha20poly1305.New(key[:])
+	_, err = aead.Open(peerPK[:0], ZeroNonce[:], msg.Static[:], hash[:])
+	if err != nil {
+		return "", err
+	}
+	setZero(hash[:])
+	setZero(chainKey[:])
+	return base64.StdEncoding.EncodeToString(peerPK[:]), nil
+}
+
+func loadExactHex(dst []byte, src string) error {
+	slice, err := hex.DecodeString(src)
+	if err != nil {
+		return err
+	}
+	if len(slice) != len(dst) {
+		return errors.New("hex string does not fit the slice")
+	}
+	copy(dst, slice)
+	return nil
+}
+
+func (key NoisePrivateKey) IsZero() bool {
+	var zero NoisePrivateKey
+	return key.Equals(zero)
+}
+
+func (key NoisePrivateKey) Equals(tar NoisePrivateKey) bool {
+	return subtle.ConstantTimeCompare(key[:], tar[:]) == 1
+}
+
+func (key *NoisePrivateKey) FromHex(src string) (err error) {
+	err = loadExactHex(key[:], src)
+	key.clamp()
+	return
+}
+
+func (key *NoisePrivateKey) FromMaybeZeroHex(src string) (err error) {
+	err = loadExactHex(key[:], src)
+	if key.IsZero() {
+		return
+	}
+	key.clamp()
+	return
+}
+func (sk *NoisePrivateKey) clamp() {
+	sk[0] &= 248
+	sk[31] = (sk[31] & 127) | 64
+}
+
+func (key *NoisePublicKey) FromHex(src string) error {
+	return loadExactHex(key[:], src)
+}
+
+func (key NoisePublicKey) IsZero() bool {
+	var zero NoisePublicKey
+	return key.Equals(zero)
+}
+
+func (key NoisePublicKey) Equals(tar NoisePublicKey) bool {
+	return subtle.ConstantTimeCompare(key[:], tar[:]) == 1
+}
+
+func (key *NoisePresharedKey) FromHex(src string) error {
+	return loadExactHex(key[:], src)
+}
+
+func GetDeviceKeys(ifaceName string) (NoisePrivateKey, NoisePublicKey, error) {
+	wgPrivKey := wg.GetWgIfacePrivKey(ifaceName)
+	wgPubKey := wg.GetWgIfacePubKey(ifaceName)
+
+	return wgPrivKey, wgPubKey, nil
+}

+ 10 - 10
nm-proxy/peer/peer.go

@@ -41,8 +41,8 @@ func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig, peerAddr stri
 		LocalKey:    wgInterface.Device.PublicKey.String(),
 		RemoteKey:   peer.PublicKey.String(),
 		WgInterface: wgInterface,
-
-		PeerConf: peer,
+		IsExtClient: isExtClient,
+		PeerConf:    peer,
 	}
 	p := proxy.NewProxy(c)
 	peerPort := common.NmProxyPort
@@ -65,15 +65,15 @@ func AddNewPeer(wgInterface *wg.WGIface, peer *wgtypes.PeerConfig, peerAddr stri
 	}
 	log.Printf("----> Established Remote Conn with RPeer: %s, ----> RAddr: %s", peer.PublicKey, remoteConn.String())
 
-	if !(isExtClient && isAttachedExtClient) {
-		log.Printf("Starting proxy for Peer: %s\n", peer.PublicKey.String())
-		err = p.Start(remoteConn)
-		if err != nil {
-			return err
-		}
-	} else {
-		log.Println("Not Starting Proxy for Attached ExtClient...")
+	// if !(isExtClient && isAttachedExtClient) {
+	log.Printf("Starting proxy for Peer: %s\n", peer.PublicKey.String())
+	err = p.Start(remoteConn)
+	if err != nil {
+		return err
 	}
+	// } else {
+	// 	log.Println("Not Starting Proxy for Attached ExtClient...")
+	// }
 
 	connConf := common.ConnConfig{
 		Key:             peer.PublicKey.String(),

+ 136 - 141
nm-proxy/proxy/proxy.go

@@ -4,13 +4,8 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"log"
 	"net"
-	"time"
 
-	"github.com/google/gopacket"
-	"github.com/google/gopacket/layers"
-	"github.com/google/gopacket/pcap"
 	"github.com/gravitl/netmaker/nm-proxy/common"
 	"github.com/gravitl/netmaker/nm-proxy/wg"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@@ -28,14 +23,14 @@ type Config struct {
 	RemoteKey   string
 	LocalKey    string
 	WgInterface *wg.WGIface
+	IsExtClient bool
 	PeerConf    *wgtypes.PeerConfig
 }
 
 // Proxy -  WireguardProxy proxies
 type Proxy struct {
-	Ctx    context.Context
-	Cancel context.CancelFunc
-
+	Ctx        context.Context
+	Cancel     context.CancelFunc
 	Config     Config
 	RemoteConn *net.UDPAddr
 	LocalConn  net.Conn
@@ -107,136 +102,136 @@ func getBoardCastAddress() ([]net.Addr, error) {
 	return nil, errors.New("couldn't obtain the broadcast addr")
 }
 
-func StartSniffer(ctx context.Context, ifaceName, ingGwAddr, extClientAddr string, port int) {
-	log.Println("Starting Packet Sniffer for iface: ", ifaceName)
-	var (
-		snapshotLen int32 = 1024
-		promiscuous bool  = false
-		err         error
-		timeout     time.Duration = 1 * time.Microsecond
-		handle      *pcap.Handle
-	)
-	// Open device
-	handle, err = pcap.OpenLive(ifaceName, snapshotLen, promiscuous, timeout)
-	if err != nil {
-		log.Println("failed to start sniffer for iface: ", ifaceName, err)
-		return
-	}
-	// if err := handle.SetBPFFilter(fmt.Sprintf("src %s and port %d", extClientAddr, port)); err != nil {
-	// 	log.Println("failed to set bpf filter: ", err)
-	// 	return
-	// }
-	defer handle.Close()
-
-	// var tcp layers.TCP
-	// var icmp layers.ICMPv4
-	// var udp layers.UDP
-	// parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &udp, &tcp, &icmp)
-
-	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
-	for {
-		select {
-		case <-ctx.Done():
-			log.Println("Stopping packet sniffer for iface: ", ifaceName, " port: ", port)
-			return
-		default:
-			packet, err := packetSource.NextPacket()
-			if err == nil {
-				//processPkt(ifaceName, packet)
-				ipLayer := packet.Layer(layers.LayerTypeIPv4)
-				if ipLayer != nil {
-					fmt.Println("IPv4 layer detected.")
-					ip, _ := ipLayer.(*layers.IPv4)
-
-					// IP layer variables:
-					// Version (Either 4 or 6)
-					// IHL (IP Header Length in 32-bit words)
-					// TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
-					// Checksum, SrcIP, DstIP
-					fmt.Println("#########################")
-					fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
-					fmt.Println("Protocol: ", ip.Protocol.String())
-					if (ip.SrcIP.String() == extClientAddr && ip.DstIP.String() != ingGwAddr) ||
-						(ip.DstIP.String() == extClientAddr && ip.SrcIP.String() != ingGwAddr) {
-
-						log.Println("-----> Fowarding PKT From: ", ip.SrcIP, " to: ", ip.DstIP)
-						c, err := net.Dial("ip", ip.DstIP.String())
-						if err == nil {
-							c.Write(ip.Payload)
-							c.Close()
-						} else {
-							log.Println("------> Failed to forward packet from sniffer: ", err)
-
-						}
-					}
-
-					fmt.Println("#########################")
-				}
-			}
-		}
-
-	}
-}
-
-func processPkt(iface string, packet gopacket.Packet) {
-	// Let's see if the packet is an ethernet packet
-	// ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
-	// if ethernetLayer != nil {
-	// 	fmt.Println("Ethernet layer detected.")
-	// 	ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
-	// 	fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
-	// 	fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
-	// 	// Ethernet type is typically IPv4 but could be ARP or other
-	// 	fmt.Println("Ethernet type: ", ethernetPacket.EthernetType)
-	// 	fmt.Println()
-	// }
-
-	// Let's see if the packet is IP (even though the ether type told us)
-	ipLayer := packet.Layer(layers.LayerTypeIPv4)
-	if ipLayer != nil {
-		fmt.Println("IPv4 layer detected.")
-		ip, _ := ipLayer.(*layers.IPv4)
-
-		// IP layer variables:
-		// Version (Either 4 or 6)
-		// IHL (IP Header Length in 32-bit words)
-		// TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
-		// Checksum, SrcIP, DstIP
-		fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
-		fmt.Println("Protocol: ", ip.Protocol)
-		fmt.Println()
-
-	}
-
-	// udpLayer := packet.Layer(layers.LayerTypeUDP)
-	// if udpLayer != nil {
-	// 	udp, _ := udpLayer.(*layers.UDP)
-	// 	fmt.Printf("UDP: From port %d to %d\n", udp.SrcPort, udp.DstPort)
-	// 	fmt.Println()
-	// }
-
-	// // Iterate over all layers, printing out each layer type
-	// fmt.Println("All packet layers:")
-	// for _, layer := range packet.Layers() {
-	// 	fmt.Println("- ", layer.LayerType())
-	// }
-
-	// When iterating through packet.Layers() above,
-	// if it lists Payload layer then that is the same as
-	// this applicationLayer. applicationLayer contains the payload
-	// applicationLayer := packet.ApplicationLayer()
-	// if applicationLayer != nil {
-	// 	fmt.Println("Application layer/Payload found.")
-	// 	fmt.Printf("%s\n", applicationLayer.Payload())
-
-	// 	// Search for a string inside the payload
-	// 	if strings.Contains(string(applicationLayer.Payload()), "HTTP") {
-	// 		fmt.Println("HTTP found!")
-	// 	}
-	// }
-
-	// Check for errors
-	if err := packet.ErrorLayer(); err != nil {
-		fmt.Println("Error decoding some part of the packet:", err)
-	}
-}
+// func StartSniffer(ctx context.Context, ifaceName, ingGwAddr, extClientAddr string, port int) {
+// 	log.Println("Starting Packet Sniffer for iface: ", ifaceName)
+// 	var (
+// 		snapshotLen int32 = 1024
+// 		promiscuous bool  = false
+// 		err         error
+// 		timeout     time.Duration = 1 * time.Microsecond
+// 		handle      *pcap.Handle
+// 	)
+// 	// Open device
+// 	handle, err = pcap.OpenLive(ifaceName, snapshotLen, promiscuous, timeout)
+// 	if err != nil {
+// 		log.Println("failed to start sniffer for iface: ", ifaceName, err)
+// 		return
+// 	}
+// 	// if err := handle.SetBPFFilter(fmt.Sprintf("src %s and port %d", extClientAddr, port)); err != nil {
+// 	// 	log.Println("failed to set bpf filter: ", err)
+// 	// 	return
+// 	// }
+// 	defer handle.Close()
+
+// 	// var tcp layers.TCP
+// 	// var icmp layers.ICMPv4
+// 	// var udp layers.UDP
+// 	// parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &udp, &tcp, &icmp)
+
+// 	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
+// 	for {
+// 		select {
+// 		case <-ctx.Done():
+// 			log.Println("Stopping packet sniffer for iface: ", ifaceName, " port: ", port)
+// 			return
+// 		default:
+// 			packet, err := packetSource.NextPacket()
+// 			if err == nil {
+// 				//processPkt(ifaceName, packet)
+// 				ipLayer := packet.Layer(layers.LayerTypeIPv4)
+// 				if ipLayer != nil {
+// 					fmt.Println("IPv4 layer detected.")
+// 					ip, _ := ipLayer.(*layers.IPv4)
+
+// 					// IP layer variables:
+// 					// Version (Either 4 or 6)
+// 					// IHL (IP Header Length in 32-bit words)
+// 					// TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
+// 					// Checksum, SrcIP, DstIP
+// 					fmt.Println("#########################")
+// 					fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
+// 					fmt.Println("Protocol: ", ip.Protocol.String())
+// 					if (ip.SrcIP.String() == extClientAddr && ip.DstIP.String() != ingGwAddr) ||
+// 						(ip.DstIP.String() == extClientAddr && ip.SrcIP.String() != ingGwAddr) {
+
+// 						log.Println("-----> Fowarding PKT From: ", ip.SrcIP, " to: ", ip.DstIP)
+// 						c, err := net.Dial("ip", ip.DstIP.String())
+// 						if err == nil {
+// 							c.Write(ip.Payload)
+// 							c.Close()
+// 						} else {
+// 							log.Println("------> Failed to forward packet from sniffer: ", err)
+
+// 						}
+// 					}
+
+// 					fmt.Println("#########################")
+// 				}
+// 			}
+// 		}
+
+// 	}
+// }
+
+// func processPkt(iface string, packet gopacket.Packet) {
+// 	// Let's see if the packet is an ethernet packet
+// 	// ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
+// 	// if ethernetLayer != nil {
+// 	// 	fmt.Println("Ethernet layer detected.")
+// 	// 	ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
+// 	// 	fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
+// 	// 	fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
+// 	// 	// Ethernet type is typically IPv4 but could be ARP or other
+// 	// 	fmt.Println("Ethernet type: ", ethernetPacket.EthernetType)
+// 	// 	fmt.Println()
+// 	// }
+
+// 	// Let's see if the packet is IP (even though the ether type told us)
+// 	ipLayer := packet.Layer(layers.LayerTypeIPv4)
+// 	if ipLayer != nil {
+// 		fmt.Println("IPv4 layer detected.")
+// 		ip, _ := ipLayer.(*layers.IPv4)
+
+// 		// IP layer variables:
+// 		// Version (Either 4 or 6)
+// 		// IHL (IP Header Length in 32-bit words)
+// 		// TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
+// 		// Checksum, SrcIP, DstIP
+// 		fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
+// 		fmt.Println("Protocol: ", ip.Protocol)
+// 		fmt.Println()
+
+// 	}
+
+// 	// udpLayer := packet.Layer(layers.LayerTypeUDP)
+// 	// if udpLayer != nil {
+// 	// 	udp, _ := udpLayer.(*layers.UDP)
+// 	// 	fmt.Printf("UDP: From port %d to %d\n", udp.SrcPort, udp.DstPort)
+// 	// 	fmt.Println()
+// 	// }
+
+// 	// // Iterate over all layers, printing out each layer type
+// 	// fmt.Println("All packet layers:")
+// 	// for _, layer := range packet.Layers() {
+// 	// 	fmt.Println("- ", layer.LayerType())
+// 	// }
+
+// 	// When iterating through packet.Layers() above,
+// 	// if it lists Payload layer then that is the same as
+// 	// this applicationLayer. applicationLayer contains the payload
+// 	// applicationLayer := packet.ApplicationLayer()
+// 	// if applicationLayer != nil {
+// 	// 	fmt.Println("Application layer/Payload found.")
+// 	// 	fmt.Printf("%s\n", applicationLayer.Payload())
+
+// 	// 	// Search for a string inside the payload
+// 	// 	if strings.Contains(string(applicationLayer.Payload()), "HTTP") {
+// 	// 		fmt.Println("HTTP found!")
+// 	// 	}
+// 	// }
+
+// 	// Check for errors
+// 	if err := packet.ErrorLayer(); err != nil {
+// 		fmt.Println("Error decoding some part of the packet:", err)
+// 	}
+// }

+ 7 - 3
nm-proxy/proxy/wireguard.go

@@ -59,14 +59,18 @@ func (p *Proxy) ProxyToRemote() {
 				log.Println("ERRR READ: ", err)
 				continue
 			}
+
 			//go func(buf []byte, n int) {
 			ifaceConf := common.WgIFaceMap[p.Config.WgInterface.Name]
 			if peerI, ok := ifaceConf.PeerMap[p.Config.RemoteKey]; ok {
 				var srcPeerKeyHash, dstPeerKeyHash string
-				buf, n, srcPeerKeyHash, dstPeerKeyHash = packet.ProcessPacketBeforeSending(buf, n, peerI.Config.LocalKey, peerI.Config.Key)
-				if err != nil {
-					log.Println("failed to process pkt before sending: ", err)
+				if !p.Config.IsExtClient {
+					buf, n, srcPeerKeyHash, dstPeerKeyHash = packet.ProcessPacketBeforeSending(buf, n, peerI.Config.LocalKey, peerI.Config.Key)
+					if err != nil {
+						log.Println("failed to process pkt before sending: ", err)
+					}
 				}
+
 				log.Printf("PROXING TO REMOTE!!!---> %s >>>>> %s >>>>> %s [[ SrcPeerHash: %s, DstPeerHash: %s ]]\n",
 					p.LocalConn.LocalAddr(), server.NmProxyServer.Server.LocalAddr().String(), p.RemoteConn.String(), srcPeerKeyHash, dstPeerKeyHash)
 			} else {

+ 37 - 15
nm-proxy/server/server.go

@@ -60,11 +60,13 @@ func (p *ProxyServer) Listen(ctx context.Context) {
 				log.Println("RECV ERROR: ", err)
 				continue
 			}
+			orgN := n
 			//go func(buffer []byte, source *net.UDPAddr, n int) {
 
 			var srcPeerKeyHash, dstPeerKeyHash string
 			n, srcPeerKeyHash, dstPeerKeyHash = packet.ExtractInfo(buffer, n)
-			//log.Printf("--------> RECV PKT , [SRCKEYHASH: %s], SourceIP: [%s] \n", srcPeerKeyHash, source.IP.String())
+			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...")
@@ -125,25 +127,45 @@ func (p *ProxyServer) Listen(ctx context.Context) {
 							log.Println("Failed to proxy to Wg local interface: ", err)
 							//continue
 						}
+						continue
 
 					}
 				}
 
 			}
-			// // forward to all interfaces
-			// for _, ifaceCfg := range common.WgIfaceKeyMap {
-			// 	log.Println("###--------> Forwarding Unknown PKT to ", ifaceCfg.Interface)
-			// 	conn, err := net.DialUDP("udp", nil, ifaceCfg.Endpoint)
-			// 	if err == nil {
-			// 		_, err := conn.Write(buffer[:n])
-			// 		if err != nil {
-			// 			log.Println("Failed to forward the unknown pkt to ifcace: ", ifaceCfg.Interface, err)
-			// 		}
-			// 		conn.Close()
-			// 	}
-
-			// }
-			//}(buffer, source, n)
+			if peerInfo, ok := common.ExtSourceIpMap[source.String()]; ok {
+				if ifaceConf, ok := common.WgIFaceMap[peerInfo.Interface]; ok {
+					if peerI, ok := ifaceConf.PeerMap[peerInfo.PeerKey]; ok {
+						log.Printf("PROXING TO LOCAL!!!---> %s <<<< %s <<<<<<<< %s   [[ RECV PKT [SRCKEYHASH: %s], [DSTKEYHASH: %s], SourceIP: [%s] ]]\n",
+							peerI.Proxy.LocalConn.RemoteAddr(), peerI.Proxy.LocalConn.LocalAddr(),
+							fmt.Sprintf("%s:%d", source.IP.String(), source.Port), srcPeerKeyHash, dstPeerKeyHash, source.IP.String())
+						_, err = peerI.Proxy.LocalConn.Write(buffer[:orgN])
+						if err != nil {
+							log.Println("Failed to proxy to Wg local interface: ", err)
+							//continue
+						}
+						continue
+
+					}
+				}
+			}
+			// consume handshake message for ext clients
+			devPriv, devPubkey, err := packet.GetDeviceKeys(common.InterfaceName)
+			if err == nil {
+				peerPubKey, err := packet.ConsumeHandshakeMsg(buffer[:orgN], devPubkey, devPriv)
+				if err != nil {
+					log.Println("---------> @@@ failed to decode HS: ", err)
+				} else {
+					log.Println("--------> Got HandShake from peer: ", peerPubKey, source)
+					if val, ok := common.ExtClientsWaitTh[peerPubKey]; ok {
+						val.CommChan <- source
+					}
+				}
+
+			} else {
+				log.Println("failed to get device keys: ", err)
+			}
+
 		}
 
 	}

+ 19 - 4
nm-proxy/wg/wg.go

@@ -80,18 +80,33 @@ func (w *WGIface) GetWgIface(iface string) error {
 	return nil
 }
 
-func GetWgIfacePubKey(iface string) string {
+func GetWgIfacePubKey(iface string) [32]byte {
 	wgClient, err := wgctrl.New()
 	if err != nil {
 		log.Println("Error fetching pub key: ", iface, err)
-		return ""
+		return [32]byte{}
 	}
 	dev, err := wgClient.Device(iface)
 	if err != nil {
 		log.Println("Error fetching pub key: ", iface, err)
-		return ""
+		return [32]byte{}
 	}
-	return dev.PublicKey.String()
+
+	return dev.PublicKey
+}
+
+func GetWgIfacePrivKey(iface string) [32]byte {
+	wgClient, err := wgctrl.New()
+	if err != nil {
+		log.Println("Error fetching pub key: ", iface, err)
+		return [32]byte{}
+	}
+	dev, err := wgClient.Device(iface)
+	if err != nil {
+		log.Println("Error fetching pub key: ", iface, err)
+		return [32]byte{}
+	}
+	return dev.PrivateKey
 }
 
 // parseAddress parse a string ("1.2.3.4/24") address to WG Address