123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- package logic
- import (
- "encoding/json"
- "errors"
- "fmt"
- "net"
- "github.com/gravitl/netmaker/database"
- "github.com/gravitl/netmaker/logger"
- "github.com/gravitl/netmaker/models"
- "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
- )
- // CreateRelay - creates a relay
- func CreateRelay(relay models.RelayRequest) ([]models.Client, models.Node, error) {
- var relayedClients []models.Client
- node, err := GetNodeByID(relay.NodeID)
- if err != nil {
- return relayedClients, models.Node{}, err
- }
- host, err := GetHost(node.HostID.String())
- if err != nil {
- return relayedClients, models.Node{}, err
- }
- if host.OS != "linux" {
- return relayedClients, models.Node{}, fmt.Errorf("only linux machines can be relay nodes")
- }
- err = ValidateRelay(relay)
- if err != nil {
- return relayedClients, models.Node{}, err
- }
- node.IsRelay = true
- node.RelayedNodes = relay.RelayedNodes
- node.SetLastModified()
- nodeData, err := json.Marshal(&node)
- if err != nil {
- return relayedClients, node, err
- }
- if err = database.Insert(node.ID.String(), string(nodeData), database.NODES_TABLE_NAME); err != nil {
- return relayedClients, models.Node{}, err
- }
- relayedClients = SetRelayedNodes(true, relay.NodeID, relay.RelayedNodes)
- for _, relayed := range relayedClients {
- data, err := json.Marshal(&relayed.Node)
- if err != nil {
- logger.Log(0, "marshalling relayed node", err.Error())
- continue
- }
- if err := database.Insert(relayed.Node.ID.String(), string(data), database.NODES_TABLE_NAME); err != nil {
- logger.Log(0, "inserting relayed node", err.Error())
- continue
- }
- }
- return relayedClients, node, nil
- }
- // SetRelayedNodes- sets and saves node as relayed
- func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Client {
- var returnnodes []models.Client
- for _, id := range relayed {
- node, err := GetNodeByID(id)
- if err != nil {
- logger.Log(0, "setRelayedNodes.GetNodebyID", err.Error())
- continue
- }
- node.IsRelayed = setRelayed
- if node.IsRelayed {
- node.RelayedBy = relay
- } else {
- node.RelayedBy = ""
- }
- node.SetLastModified()
- data, err := json.Marshal(&node)
- if err != nil {
- logger.Log(0, "setRelayedNodes.Marshal", err.Error())
- continue
- }
- if err := database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME); err != nil {
- logger.Log(0, "setRelayedNodes.Insert", err.Error())
- continue
- }
- host, err := GetHost(node.HostID.String())
- if err == nil {
- returnnodes = append(returnnodes, models.Client{
- Host: *host,
- Node: node,
- })
- }
- }
- return returnnodes
- }
- // ValidateRelay - checks if relay is valid
- func ValidateRelay(relay models.RelayRequest) error {
- var err error
- //isIp := functions.IsIpCIDR(gateway.RangeString)
- empty := len(relay.RelayedNodes) == 0
- if empty {
- err = errors.New("relayed nodes cannot be empty")
- }
- return err
- }
- // UpdateRelayed - updates relay nodes
- func UpdateRelayed(relay string, oldNodes []string, newNodes []string) []models.Client {
- _ = SetRelayedNodes(false, relay, oldNodes)
- return SetRelayedNodes(true, relay, newNodes)
- }
- // DeleteRelay - deletes a relay
- func DeleteRelay(network, nodeid string) ([]models.Client, models.Node, error) {
- var returnClients []models.Client
- node, err := GetNodeByID(nodeid)
- if err != nil {
- return returnClients, models.Node{}, err
- }
- returnClients = SetRelayedNodes(false, nodeid, node.RelayedNodes)
- node.IsRelay = false
- node.RelayedNodes = []string{}
- node.SetLastModified()
- data, err := json.Marshal(&node)
- if err != nil {
- return returnClients, models.Node{}, err
- }
- if err = database.Insert(nodeid, string(data), database.NODES_TABLE_NAME); err != nil {
- return returnClients, models.Node{}, err
- }
- return returnClients, node, nil
- }
- func getRelayedAddresses(id string) []net.IPNet {
- addrs := []net.IPNet{}
- node, err := GetNodeByID(id)
- if err != nil {
- logger.Log(0, "getRelayedAddresses: "+err.Error())
- return addrs
- }
- if node.Address.IP != nil {
- node.Address.Mask = net.CIDRMask(32, 32)
- addrs = append(addrs, node.Address)
- }
- if node.Address6.IP != nil {
- node.Address6.Mask = net.CIDRMask(128, 128)
- addrs = append(addrs, node.Address6)
- }
- return addrs
- }
- // peerUpdateForRelayed - returns the peerConfig for a relayed node
- func peerUpdateForRelayed(client *models.Client, peers []models.Client) []wgtypes.PeerConfig {
- peerConfig := []wgtypes.PeerConfig{}
- if !client.Node.IsRelayed {
- logger.Log(0, "GetPeerUpdateForRelayed called for non-relayed node ", client.Host.Name)
- return []wgtypes.PeerConfig{}
- }
- relayNode, err := GetNodeByID(client.Node.RelayedBy)
- if err != nil {
- logger.Log(0, "error retrieving relay node", err.Error())
- return []wgtypes.PeerConfig{}
- }
- host, err := GetHost(relayNode.HostID.String())
- if err != nil {
- return []wgtypes.PeerConfig{}
- }
- relay := models.Client{
- Host: *host,
- Node: relayNode,
- }
- for _, peer := range peers {
- if peer.Host.ID == client.Host.ID {
- continue
- }
- if peer.Host.ID == relay.Host.ID { // add relay as a peer
- update := peerUpdateForRelayedByRelay(client, &relay)
- peerConfig = append(peerConfig, update)
- continue
- }
- update := wgtypes.PeerConfig{
- PublicKey: peer.Host.PublicKey,
- Remove: true,
- }
- peerConfig = append(peerConfig, update)
- }
- return peerConfig
- }
- // peerUpdateForRelayedByRelay - returns the peerConfig for a node relayed by relay
- func peerUpdateForRelayedByRelay(relayed, relay *models.Client) wgtypes.PeerConfig {
- if relayed.Node.RelayedBy != relay.Node.ID.String() {
- logger.Log(0, "peerUpdateForRelayedByRelay called with invalid parameters")
- return wgtypes.PeerConfig{}
- }
- update := wgtypes.PeerConfig{
- PublicKey: relay.Host.PublicKey,
- ReplaceAllowedIPs: true,
- Endpoint: &net.UDPAddr{
- IP: relay.Host.EndpointIP,
- Port: relay.Host.ListenPort,
- },
- PersistentKeepaliveInterval: &relay.Node.PersistentKeepalive,
- }
- if relay.Node.Address.IP != nil {
- relay.Node.Address.Mask = net.CIDRMask(32, 32)
- update.AllowedIPs = append(update.AllowedIPs, relay.Node.Address)
- }
- if relay.Node.Address6.IP != nil {
- relay.Node.Address6.Mask = net.CIDRMask(128, 128)
- update.AllowedIPs = append(update.AllowedIPs, relay.Node.Address6)
- }
- if relay.Node.IsEgressGateway {
- update.AllowedIPs = append(update.AllowedIPs, getEgressIPs(relay)...)
- }
- if relay.Node.IsIngressGateway {
- update.AllowedIPs = append(update.AllowedIPs, getIngressIPs(relay)...)
- }
- peers, err := GetNetworkClients(relay.Node.Network)
- if err != nil {
- logger.Log(0, "error getting network clients", err.Error())
- return update
- }
- for _, peer := range peers {
- if peer.Host.ID == relayed.Host.ID || peer.Host.ID == relay.Host.ID {
- continue
- }
- update.AllowedIPs = append(update.AllowedIPs, AddAllowedIPs(&peer)...)
- }
- return update
- }
- // peerUpdateForRelay - returns the peerConfig for a relay
- func peerUpdateForRelay(relay *models.Client, peers []models.Client) []wgtypes.PeerConfig {
- peerConfig := []wgtypes.PeerConfig{}
- if !relay.Node.IsRelay {
- logger.Log(0, "GetPeerUpdateForRelay called for non-relay node ", relay.Host.Name)
- return []wgtypes.PeerConfig{}
- }
- for _, peer := range peers {
- if peer.Host.ID == relay.Host.ID {
- continue
- }
- update := wgtypes.PeerConfig{
- PublicKey: peer.Host.PublicKey,
- ReplaceAllowedIPs: true,
- Remove: false,
- Endpoint: &net.UDPAddr{
- IP: peer.Host.EndpointIP,
- Port: peer.Host.ListenPort,
- },
- PersistentKeepaliveInterval: &peer.Node.PersistentKeepalive,
- }
- update.AllowedIPs = append(update.AllowedIPs, AddAllowedIPs(&peer)...)
- peerConfig = append(peerConfig, update)
- }
- return peerConfig
- }
|