peers.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package logic
  2. import (
  3. "log"
  4. "net"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "github.com/gravitl/netmaker/logger"
  9. "github.com/gravitl/netmaker/models"
  10. "github.com/gravitl/netmaker/netclient/ncutils"
  11. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  12. )
  13. // GetPeerUpdate - gets a wireguard peer config for each peer of a node
  14. func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) {
  15. var peerUpdate models.PeerUpdate
  16. var peers []wgtypes.PeerConfig
  17. var serverNodeAddresses = []models.ServerAddr{}
  18. currentPeers, err := GetPeers(node)
  19. if err != nil {
  20. return models.PeerUpdate{}, err
  21. }
  22. // begin translating netclient logic
  23. /*
  24. Go through netclient code and put below
  25. */
  26. // #1 Set Keepalive values: set_keepalive
  27. // #2 Set local address: set_local - could be a LOT BETTER and fix some bugs with additional logic
  28. // #3 Set allowedips: set_allowedips
  29. for _, peer := range currentPeers {
  30. if peer.ID == node.ID {
  31. //skip yourself
  32. continue
  33. }
  34. pubkey, err := wgtypes.ParseKey(peer.PublicKey)
  35. if err != nil {
  36. return models.PeerUpdate{}, err
  37. }
  38. if node.Endpoint == peer.Endpoint {
  39. //peer is on same network
  40. // set_local
  41. if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" {
  42. peer.Endpoint = peer.LocalAddress
  43. } else {
  44. continue
  45. }
  46. }
  47. endpoint := peer.Endpoint + ":" + strconv.FormatInt(int64(peer.ListenPort), 10)
  48. address, err := net.ResolveUDPAddr("udp", endpoint)
  49. if err != nil {
  50. return models.PeerUpdate{}, err
  51. }
  52. // set_allowedips
  53. allowedips := GetAllowedIPs(node, &peer)
  54. var keepalive time.Duration
  55. if node.PersistentKeepalive != 0 {
  56. // set_keepalive
  57. keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(node.PersistentKeepalive), 10) + "s")
  58. }
  59. var peerData = wgtypes.PeerConfig{
  60. PublicKey: pubkey,
  61. Endpoint: address,
  62. ReplaceAllowedIPs: true,
  63. AllowedIPs: allowedips,
  64. PersistentKeepaliveInterval: &keepalive,
  65. }
  66. peers = append(peers, peerData)
  67. if peer.IsServer == "yes" {
  68. serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{ID: peer.ID, IsLeader: IsLeader(&peer), Address: peer.Address})
  69. }
  70. }
  71. if node.IsIngressGateway == "yes" {
  72. extPeers, err := getExtPeers(node)
  73. if err == nil {
  74. peers = append(peers, extPeers...)
  75. } else {
  76. log.Println("ERROR RETRIEVING EXTERNAL PEERS", err)
  77. }
  78. }
  79. peerUpdate.Network = node.Network
  80. peerUpdate.Peers = peers
  81. peerUpdate.ServerAddrs = serverNodeAddresses
  82. /*
  83. End translation of netclient code
  84. */
  85. return peerUpdate, nil
  86. }
  87. func getExtPeers(node *models.Node) ([]wgtypes.PeerConfig, error) {
  88. var peers []wgtypes.PeerConfig
  89. extPeers, err := GetExtPeersList(node)
  90. if err != nil {
  91. return peers, err
  92. }
  93. for _, extPeer := range extPeers {
  94. pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
  95. if err != nil {
  96. logger.Log(1, "error parsing ext pub key:", err.Error())
  97. continue
  98. }
  99. if node.PublicKey == extPeer.PublicKey {
  100. continue
  101. }
  102. var peer wgtypes.PeerConfig
  103. var peeraddr = net.IPNet{
  104. IP: net.ParseIP(extPeer.Address),
  105. Mask: net.CIDRMask(32, 32),
  106. }
  107. var allowedips []net.IPNet
  108. allowedips = append(allowedips, peeraddr)
  109. if extPeer.Address6 != "" {
  110. var addr6 = net.IPNet{
  111. IP: net.ParseIP(extPeer.Address6),
  112. Mask: net.CIDRMask(128, 128),
  113. }
  114. allowedips = append(allowedips, addr6)
  115. }
  116. peer = wgtypes.PeerConfig{
  117. PublicKey: pubkey,
  118. ReplaceAllowedIPs: true,
  119. AllowedIPs: allowedips,
  120. }
  121. peers = append(peers, peer)
  122. }
  123. return peers, nil
  124. }
  125. // GetAllowedIPs - calculates the wireguard allowedip field for a peer of a node based on the peer and node settings
  126. func GetAllowedIPs(node, peer *models.Node) []net.IPNet {
  127. var allowedips []net.IPNet
  128. var peeraddr = net.IPNet{
  129. IP: net.ParseIP(peer.Address),
  130. Mask: net.CIDRMask(32, 32),
  131. }
  132. dualstack := false
  133. allowedips = append(allowedips, peeraddr)
  134. // handle manually set peers
  135. for _, allowedIp := range peer.AllowedIPs {
  136. if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil {
  137. nodeEndpointArr := strings.Split(node.Endpoint, ":")
  138. if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != peer.Address { // don't need to add an allowed ip that already exists..
  139. allowedips = append(allowedips, *ipnet)
  140. }
  141. } else if appendip := net.ParseIP(allowedIp); appendip != nil && allowedIp != peer.Address {
  142. ipnet := net.IPNet{
  143. IP: net.ParseIP(allowedIp),
  144. Mask: net.CIDRMask(32, 32),
  145. }
  146. allowedips = append(allowedips, ipnet)
  147. }
  148. }
  149. // handle egress gateway peers
  150. if peer.IsEgressGateway == "yes" {
  151. //hasGateway = true
  152. ranges := peer.EgressGatewayRanges
  153. for _, iprange := range ranges { // go through each cidr for egress gateway
  154. _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr
  155. if err != nil {
  156. ncutils.PrintLog("could not parse gateway IP range. Not adding "+iprange, 1)
  157. continue // if can't parse CIDR
  158. }
  159. nodeEndpointArr := strings.Split(peer.Endpoint, ":") // getting the public ip of node
  160. if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain endpoint of node
  161. ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.Endpoint+", omitting", 2)
  162. continue // skip adding egress range if overlaps with node's ip
  163. }
  164. // TODO: Could put in a lot of great logic to avoid conflicts / bad routes
  165. if ipnet.Contains(net.ParseIP(node.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node
  166. ncutils.PrintLog("egress IP range of "+iprange+" overlaps with "+node.LocalAddress+", omitting", 2)
  167. continue // skip adding egress range if overlaps with node's local ip
  168. }
  169. if err != nil {
  170. log.Println("ERROR ENCOUNTERED SETTING GATEWAY")
  171. } else {
  172. allowedips = append(allowedips, *ipnet)
  173. }
  174. }
  175. }
  176. if peer.Address6 != "" && dualstack {
  177. var addr6 = net.IPNet{
  178. IP: net.ParseIP(peer.Address6),
  179. Mask: net.CIDRMask(128, 128),
  180. }
  181. allowedips = append(allowedips, addr6)
  182. }
  183. return allowedips
  184. }