diff --git a/go.mod b/go.mod index ef45d207..9b75fc9d 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( golang.org/x/oauth2 v0.3.0 golang.org/x/sys v0.3.0 // indirect golang.org/x/text v0.5.0 // indirect - golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c + golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c // indirect golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220324164955-056925b7df31 google.golang.org/protobuf v1.28.1 // indirect gopkg.in/yaml.v3 v3.0.1 @@ -29,7 +29,7 @@ require ( require ( filippo.io/edwards25519 v1.0.0 github.com/c-robinson/iplib v1.0.6 - github.com/go-ping/ping v1.1.0 // indirect + github.com/go-ping/ping v1.1.0 github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0 ) @@ -42,8 +42,8 @@ require ( ) require ( - github.com/gravitl/netclient v0.0.0-20230114051017-65ecaeffca09 github.com/guumaster/tablewriter v0.0.10 + github.com/kr/pretty v0.3.1 github.com/matryer/is v1.4.0 github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.6.1 @@ -53,7 +53,9 @@ require ( cloud.google.com/go/compute/metadata v0.2.1 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/kr/text v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect ) diff --git a/go.sum b/go.sum index 6972718d..573411d1 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,6 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gravitl/netclient v0.0.0-20230114051017-65ecaeffca09 h1:T0gLl+i8whnrdwtW91R4u8x8bmqFVfPTU9WfBratkMc= -github.com/gravitl/netclient v0.0.0-20230114051017-65ecaeffca09/go.mod h1:g3q+vhLySW/6smOsWsVy5LrxoW++f+kqiBAp9BM6sbY= github.com/guumaster/tablewriter v0.0.10 h1:A0HD94yMdt4usgxBjoEceNeE0XMJ027euoHAzsPqBQs= github.com/guumaster/tablewriter v0.0.10/go.mod h1:p4FRFhyfo0UD9ZLmMRbbJooTUsxo6b80qZTERVDWrH8= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= @@ -78,6 +76,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -121,6 +120,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f h1:BSnJgAfHzEp7o8PYJ7YfwAVHhqu7BYUTggcn/LGlUWY= github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f/go.mod h1:UW/gxgQwSePTvL1KA8QEHsXeYHP4xkoXgbDdN781p34= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= diff --git a/logic/metrics/metrics.go b/logic/metrics/metrics.go index 08085715..7c671fb3 100644 --- a/logic/metrics/metrics.go +++ b/logic/metrics/metrics.go @@ -3,9 +3,9 @@ package metrics import ( "time" - proxy_metrics "github.com/gravitl/netclient/nmproxy/metrics" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" + proxy_metrics "github.com/gravitl/netmaker/metrics" "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl" ) diff --git a/logic/peers.go b/logic/peers.go index 05f3ee84..b5d20c8f 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -10,7 +10,6 @@ import ( "strings" "time" - proxy_models "github.com/gravitl/netclient/nmproxy/models" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic/acls/nodeacls" @@ -28,10 +27,10 @@ import ( // TODO ========================== // TODO ========================== // revisit this logic with new host/node models. -func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyManagerPayload, error) { - proxyPayload := proxy_models.ProxyManagerPayload{} +func GetPeersForProxy(node *models.Node, onlyPeers bool) (models.ProxyManagerPayload, error) { + proxyPayload := models.ProxyManagerPayload{} var peers []wgtypes.PeerConfig - peerConfMap := make(map[string]proxy_models.PeerConf) + peerConfMap := make(map[string]models.PeerConf) var err error currentPeers, err := GetNetworkNodes(node.Network) if err != nil { @@ -70,7 +69,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyMana logger.Log(1, "failed to relayed nodes: ", node.ID.String(), err.Error()) proxyPayload.IsRelay = false } else { - relayPeersMap := make(map[string]proxy_models.RelayedConf) + relayPeersMap := make(map[string]models.RelayedConf) for _, relayedNode := range relayedNodes { relayedNode := relayedNode payload, err := GetPeersForProxy(&relayedNode, true) @@ -81,7 +80,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyMana } relayedEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayedHost.EndpointIP, host.ListenPort)) if udpErr == nil { - relayPeersMap[host.PublicKey.String()] = proxy_models.RelayedConf{ + relayPeersMap[host.PublicKey.String()] = models.RelayedConf{ RelayedPeerEndpoint: relayedEndpoint, RelayedPeerPubKey: relayedHost.PublicKey.String(), Peers: payload.Peers, @@ -111,7 +110,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyMana if proxyStatus { listenPort = host.ProxyListenPort if listenPort == 0 { - listenPort = proxy_models.NmProxyPort + listenPort = models.NmProxyPort } } else if listenPort == 0 { listenPort = host.ListenPort @@ -136,7 +135,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyMana PersistentKeepaliveInterval: &keepalive, ReplaceAllowedIPs: true, }) - peerConfMap[host.PublicKey.String()] = proxy_models.PeerConf{ + peerConfMap[host.PublicKey.String()] = models.PeerConf{ Address: net.ParseIP(peer.PrimaryAddress()), Proxy: proxyStatus, PublicListenPort: int32(listenPort), @@ -152,7 +151,7 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyMana } relayTo, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayHost.EndpointIP, relayHost.ListenPort)) if err == nil { - peerConfMap[host.PublicKey.String()] = proxy_models.PeerConf{ + peerConfMap[host.PublicKey.String()] = models.PeerConf{ IsRelayed: true, RelayedTo: relayTo, @@ -193,11 +192,11 @@ func GetPeersForProxy(node *models.Node, onlyPeers bool) (proxy_models.ProxyMana } // GetProxyUpdateForHost - gets the proxy update for host -func GetProxyUpdateForHost(host *models.Host) (proxy_models.ProxyManagerPayload, error) { - proxyPayload := proxy_models.ProxyManagerPayload{ - Action: proxy_models.ProxyUpdate, +func GetProxyUpdateForHost(host *models.Host) (models.ProxyManagerPayload, error) { + proxyPayload := models.ProxyManagerPayload{ + Action: models.ProxyUpdate, } - peerConfMap := make(map[string]proxy_models.PeerConf) + peerConfMap := make(map[string]models.PeerConf) if host.IsRelayed { relayHost, err := GetHost(host.RelayedBy) if err == nil { @@ -214,14 +213,14 @@ func GetProxyUpdateForHost(host *models.Host) (proxy_models.ProxyManagerPayload, } if host.IsRelay { relayedHosts := GetRelayedHosts(host) - relayPeersMap := make(map[string]proxy_models.RelayedConf) + relayPeersMap := make(map[string]models.RelayedConf) for _, relayedHost := range relayedHosts { relayedHost := relayedHost payload, err := GetPeerUpdateForHost(&relayedHost) if err == nil { relayedEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayedHost.EndpointIP, getPeerListenPort(&relayedHost))) if udpErr == nil { - relayPeersMap[relayedHost.PublicKey.String()] = proxy_models.RelayedConf{ + relayPeersMap[relayedHost.PublicKey.String()] = models.RelayedConf{ RelayedPeerEndpoint: relayedEndpoint, RelayedPeerPubKey: relayedHost.PublicKey.String(), Peers: payload.Peers, @@ -254,10 +253,10 @@ func GetProxyUpdateForHost(host *models.Host) (proxy_models.ProxyManagerPayload, if err != nil { continue } - var currPeerConf proxy_models.PeerConf + var currPeerConf models.PeerConf var found bool if currPeerConf, found = peerConfMap[peerHost.PublicKey.String()]; !found { - currPeerConf = proxy_models.PeerConf{ + currPeerConf = models.PeerConf{ Proxy: peerHost.ProxyEnabled, PublicListenPort: int32(getPeerListenPort(peerHost)), } @@ -788,7 +787,7 @@ func getExtPeers(node *models.Node) ([]wgtypes.PeerConfig, []models.IDandAddr, e } -func getExtPeersForProxy(node *models.Node, proxyPeerConf map[string]proxy_models.PeerConf) ([]wgtypes.PeerConfig, map[string]proxy_models.PeerConf, error) { +func getExtPeersForProxy(node *models.Node, proxyPeerConf map[string]models.PeerConf) ([]wgtypes.PeerConfig, map[string]models.PeerConf, error) { var peers []wgtypes.PeerConfig host, err := GetHost(node.HostID.String()) if err != nil { @@ -838,7 +837,7 @@ func getExtPeersForProxy(node *models.Node, proxyPeerConf map[string]proxy_model ReplaceAllowedIPs: true, AllowedIPs: allowedips, } - extConf := proxy_models.PeerConf{ + extConf := models.PeerConf{ IsExtClient: true, Address: net.ParseIP(extPeer.Address), } diff --git a/metrics/metrics.go b/metrics/metrics.go new file mode 100644 index 00000000..eb4b5f40 --- /dev/null +++ b/metrics/metrics.go @@ -0,0 +1,111 @@ +package metrics + +import ( + "fmt" + "sync" + "time" + + "github.com/go-ping/ping" + "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/models" +) + +// lock for metrics map +var metricsMapLock = &sync.RWMutex{} + +// metrics data map +var metricsPeerMap = make(map[string]map[string]*models.ProxyMetric) + +// GetMetricByServer - get metric data of peers by server +func GetMetricByServer(server string) map[string]*models.ProxyMetric { + metricsMapLock.RLock() + defer metricsMapLock.RUnlock() + if _, ok := metricsPeerMap[server]; !ok { + return nil + } + return metricsPeerMap[server] +} + +// GetMetric - fetches the metric data for the peer +func GetMetric(server, peerKey string) models.ProxyMetric { + metric := models.ProxyMetric{} + peerMetricMap := GetMetricByServer(server) + metricsMapLock.RLock() + defer metricsMapLock.RUnlock() + if peerMetricMap == nil { + return metric + } + if m, ok := peerMetricMap[peerKey]; ok && m != nil { + metric = *m + } + return metric +} + +// UpdateMetric - updates metric data for the peer +func UpdateMetric(server, peerKey string, metric *models.ProxyMetric) { + metricsMapLock.Lock() + defer metricsMapLock.Unlock() + if metricsPeerMap[server] == nil { + metricsPeerMap[server] = make(map[string]*models.ProxyMetric) + } + metricsPeerMap[server][peerKey] = metric +} + +// UpdateMetricByPeer - updates metrics data by peer public key +func UpdateMetricByPeer(peerKey string, metric *models.ProxyMetric, onlyTraffic bool) { + metricsMapLock.Lock() + defer metricsMapLock.Unlock() + for server, peerKeyMap := range metricsPeerMap { + if peerMetric, ok := peerKeyMap[peerKey]; ok { + peerMetric.TrafficRecieved += metric.TrafficRecieved + peerMetric.TrafficSent += metric.TrafficSent + if !onlyTraffic { + peerMetric.LastRecordedLatency = metric.LastRecordedLatency + } + + metricsPeerMap[server][peerKey] = peerMetric + } + } +} + +// ResetMetricsForPeer - reset metrics for peer +func ResetMetricsForPeer(server, peerKey string) { + metricsMapLock.Lock() + defer metricsMapLock.Unlock() + delete(metricsPeerMap[server], peerKey) +} + +// ResetMetricForNode - resets node level metrics +func ResetMetricForNode(server, peerKey, peerID string) { + metric := GetMetric(server, peerKey) + delete(metric.NodeConnectionStatus, peerID) + UpdateMetric(server, peerKey, &metric) +} + +// MetricCollectionInterval - collection interval for metrics +const MetricCollectionInterval = time.Second * 25 + +// PeerConnectionStatus - get peer connection status by pinging +func PeerConnectionStatus(address string) (connected bool) { + fmt.Println("PINGER ADDR: ", address) + pinger, err := ping.NewPinger(address) + if err != nil { + logger.Log(0, "could not initiliaze ping peer address", address, err.Error()) + connected = false + } else { + pinger.Timeout = time.Second * 2 + err = pinger.Run() + if err != nil { + logger.Log(0, "failed to ping on peer address", address, err.Error()) + return false + } else { + pingStats := pinger.Statistics() + if pingStats.PacketsRecv > 0 { + connected = true + return + } + } + } + + return +} diff --git a/models/mqtt.go b/models/mqtt.go index 5fb1781e..71a203d0 100644 --- a/models/mqtt.go +++ b/models/mqtt.go @@ -1,30 +1,29 @@ package models import ( - proxy_models "github.com/gravitl/netclient/nmproxy/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // PeerUpdate - struct type PeerUpdate struct { - Network string `json:"network" bson:"network" yaml:"network"` - ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"` - ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"` - Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` - DNS string `json:"dns" bson:"dns" yaml:"dns"` - PeerIDs PeerMap `json:"peerids" bson:"peerids" yaml:"peerids"` - ProxyUpdate proxy_models.ProxyManagerPayload `json:"proxy_update" bson:"proxy_update" yaml:"proxy_update"` + Network string `json:"network" bson:"network" yaml:"network"` + ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"` + ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"` + Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` + DNS string `json:"dns" bson:"dns" yaml:"dns"` + PeerIDs PeerMap `json:"peerids" bson:"peerids" yaml:"peerids"` + ProxyUpdate ProxyManagerPayload `json:"proxy_update" bson:"proxy_update" yaml:"proxy_update"` } // HostPeerUpdate - struct for host peer updates type HostPeerUpdate struct { - Host Host `json:"host" bson:"host" yaml:"host"` - ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"` - ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"` - Network map[string]NetworkInfo `json:"network" bson:"network" yaml:"network"` - Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` - PeerIDs HostPeerMap `json:"peerids" bson:"peerids" yaml:"peerids"` - ProxyUpdate proxy_models.ProxyManagerPayload `json:"proxy_update" bson:"proxy_update" yaml:"proxy_update"` + Host Host `json:"host" bson:"host" yaml:"host"` + ServerVersion string `json:"serverversion" bson:"serverversion" yaml:"serverversion"` + ServerAddrs []ServerAddr `json:"serveraddrs" bson:"serveraddrs" yaml:"serveraddrs"` + Network map[string]NetworkInfo `json:"network" bson:"network" yaml:"network"` + Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` + PeerIDs HostPeerMap `json:"peerids" bson:"peerids" yaml:"peerids"` + ProxyUpdate ProxyManagerPayload `json:"proxy_update" bson:"proxy_update" yaml:"proxy_update"` } // NetworkInfo - struct for network info diff --git a/models/proxy.go b/models/proxy.go new file mode 100644 index 00000000..ae8bfd99 --- /dev/null +++ b/models/proxy.go @@ -0,0 +1,68 @@ +package models + +import ( + "net" + "time" + + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +// ProxyAction - type for proxy action +type ProxyAction string + +const ( + // default proxy port + NmProxyPort = 51722 + // PersistentKeepaliveInterval - default keepalive for wg peer + DefaultPersistentKeepaliveInterval = time.Duration(time.Second * 20) + + // ProxyUpdate - constant for proxy update action + ProxyUpdate ProxyAction = "PROXY_UPDATE" + // ProxyDeletePeers - constant for proxy delete peers action + ProxyDeletePeers ProxyAction = "PROXY_DELETE" + // ProxyDeleteAllPeers - constant for proxy delete all peers action + ProxyDeleteAllPeers ProxyAction = "PROXY_DELETE_ALL" + // NoProxy - constant for no ProxyAction + NoProxy ProxyAction = "NO_PROXY" +) + +// RelayedConf - struct relayed peers config +type RelayedConf struct { + RelayedPeerEndpoint *net.UDPAddr `json:"relayed_peer_endpoint"` + RelayedPeerPubKey string `json:"relayed_peer_pub_key"` + Peers []wgtypes.PeerConfig `json:"relayed_peers"` +} + +// PeerConf - struct for peer config in the network +type PeerConf struct { + Proxy bool `json:"proxy"` + PublicListenPort int32 `json:"public_listen_port"` + IsExtClient bool `json:"is_ext_client"` + Address net.IP `json:"address"` + ExtInternalIp net.IP `json:"ext_internal_ip"` + IsRelayed bool `json:"is_relayed"` + RelayedTo *net.UDPAddr `json:"relayed_to"` +} + +// ProxyManagerPayload - struct for proxy manager payload +type ProxyManagerPayload struct { + Action ProxyAction `json:"action"` + InterfaceName string `json:"interface_name"` + Server string `json:"server"` + //WgAddr string `json:"wg_addr"` + Peers []wgtypes.PeerConfig `json:"peers"` + PeerMap map[string]PeerConf `json:"peer_map"` + IsIngress bool `json:"is_ingress"` + IsRelayed bool `json:"is_relayed"` + RelayedTo *net.UDPAddr `json:"relayed_to"` + IsRelay bool `json:"is_relay"` + RelayedPeerConf map[string]RelayedConf `json:"relayed_conf"` +} + +// Metric - struct for metric data +type ProxyMetric struct { + NodeConnectionStatus map[string]bool `json:"node_connection_status"` + LastRecordedLatency uint64 `json:"last_recorded_latency"` + TrafficSent int64 `json:"traffic_sent"` // stored in MB + TrafficRecieved int64 `json:"traffic_recieved"` // stored in MB +} diff --git a/mq/publishers.go b/mq/publishers.go index 652dab7e..08d6c7e1 100644 --- a/mq/publishers.go +++ b/mq/publishers.go @@ -6,7 +6,6 @@ import ( "fmt" "time" - proxy_models "github.com/gravitl/netclient/nmproxy/models" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" @@ -46,7 +45,7 @@ func PublishSingleHostUpdate(host *models.Host) error { if err != nil { return err } - proxyUpdate.Action = proxy_models.ProxyUpdate + proxyUpdate.Action = models.ProxyUpdate peerUpdate.ProxyUpdate = proxyUpdate }