egress.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. package logic
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "maps"
  7. "net"
  8. "github.com/gravitl/netmaker/db"
  9. "github.com/gravitl/netmaker/models"
  10. "github.com/gravitl/netmaker/schema"
  11. )
  12. func ValidateEgressReq(e *schema.Egress) error {
  13. if e.Network == "" {
  14. return errors.New("network id is empty")
  15. }
  16. _, err := GetNetwork(e.Network)
  17. if err != nil {
  18. return errors.New("failed to get network " + err.Error())
  19. }
  20. if !e.IsInetGw {
  21. if e.Range == "" {
  22. return errors.New("egress range is empty")
  23. }
  24. _, _, err = net.ParseCIDR(e.Range)
  25. if err != nil {
  26. return errors.New("invalid egress range " + err.Error())
  27. }
  28. err = ValidateEgressRange(e.Network, []string{e.Range})
  29. if err != nil {
  30. return errors.New("invalid egress range " + err.Error())
  31. }
  32. } else {
  33. if len(e.Nodes) > 1 {
  34. return errors.New("can only set one internet routing node")
  35. }
  36. acls, _ := ListAclsByNetwork(models.NetworkID(e.Network))
  37. req := models.InetNodeReq{}
  38. eli, _ := (&schema.Egress{Network: e.Network}).ListByNetwork(db.WithContext(context.TODO()))
  39. for k := range e.Nodes {
  40. inetNode, err := GetNodeByID(k)
  41. if err != nil {
  42. return errors.New("invalid routing node " + err.Error())
  43. }
  44. // check if node is acting as egress gw already
  45. GetNodeEgressInfo(&inetNode, eli, acls)
  46. if err := ValidateInetGwReq(inetNode, req, false); err != nil {
  47. return err
  48. }
  49. }
  50. }
  51. if len(e.Nodes) != 0 {
  52. for k := range e.Nodes {
  53. _, err := GetNodeByID(k)
  54. if err != nil {
  55. return errors.New("invalid routing node " + err.Error())
  56. }
  57. }
  58. }
  59. return nil
  60. }
  61. func DoesNodeHaveAccessToEgress(node *models.Node, e *schema.Egress, acls []models.Acl) bool {
  62. nodeTags := maps.Clone(node.Tags)
  63. nodeTags[models.TagID(node.ID.String())] = struct{}{}
  64. if !e.IsInetGw {
  65. nodeTags[models.TagID("*")] = struct{}{}
  66. }
  67. if !e.IsInetGw {
  68. defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
  69. if defaultDevicePolicy.Enabled {
  70. return true
  71. }
  72. }
  73. for _, acl := range acls {
  74. if !acl.Enabled {
  75. continue
  76. }
  77. srcVal := ConvAclTagToValueMap(acl.Src)
  78. if !e.IsInetGw && acl.AllowedDirection == models.TrafficDirectionBi {
  79. if _, ok := srcVal["*"]; ok {
  80. return true
  81. }
  82. }
  83. for _, dstI := range acl.Dst {
  84. if !e.IsInetGw && dstI.ID == models.NodeTagID && dstI.Value == "*" {
  85. return true
  86. }
  87. if dstI.ID == models.EgressID && dstI.Value == e.ID {
  88. e := schema.Egress{ID: dstI.Value}
  89. err := e.Get(db.WithContext(context.TODO()))
  90. if err != nil {
  91. continue
  92. }
  93. if node.IsStatic {
  94. if _, ok := srcVal[node.StaticNode.ClientID]; ok {
  95. return true
  96. }
  97. } else {
  98. if _, ok := srcVal[node.ID.String()]; ok {
  99. return true
  100. }
  101. }
  102. for tagID := range nodeTags {
  103. if _, ok := srcVal[tagID.String()]; ok {
  104. return true
  105. }
  106. }
  107. }
  108. }
  109. }
  110. return false
  111. }
  112. func AddEgressInfoToPeerByAccess(node, targetNode *models.Node, eli []schema.Egress, acls []models.Acl, isDefaultPolicyActive bool) {
  113. req := models.EgressGatewayRequest{
  114. NodeID: targetNode.ID.String(),
  115. NetID: targetNode.Network,
  116. }
  117. defer func() {
  118. if targetNode.Mutex != nil {
  119. targetNode.Mutex.Lock()
  120. }
  121. IsNodeUsingInternetGw(targetNode, acls)
  122. if targetNode.Mutex != nil {
  123. targetNode.Mutex.Unlock()
  124. }
  125. }()
  126. for _, e := range eli {
  127. if !e.Status || e.Network != targetNode.Network {
  128. continue
  129. }
  130. if !isDefaultPolicyActive || e.IsInetGw {
  131. if !DoesNodeHaveAccessToEgress(node, &e, acls) {
  132. if node.IsRelayed && node.RelayedBy == targetNode.ID.String() {
  133. if !DoesNodeHaveAccessToEgress(targetNode, &e, acls) {
  134. continue
  135. }
  136. } else {
  137. continue
  138. }
  139. }
  140. }
  141. if metric, ok := e.Nodes[targetNode.ID.String()]; ok {
  142. if e.IsInetGw {
  143. targetNode.EgressDetails.IsInternetGateway = true
  144. targetNode.EgressDetails.InetNodeReq = models.InetNodeReq{
  145. InetNodeClientIDs: GetInetClientsFromAclPolicies(e.ID),
  146. }
  147. req.Ranges = append(req.Ranges, "0.0.0.0/0")
  148. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  149. Network: "0.0.0.0/0",
  150. Nat: true,
  151. RouteMetric: 256,
  152. })
  153. req.Ranges = append(req.Ranges, "::/0")
  154. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  155. Network: "::/0",
  156. Nat: true,
  157. RouteMetric: 256,
  158. })
  159. } else {
  160. m64, err := metric.(json.Number).Int64()
  161. if err != nil {
  162. m64 = 256
  163. }
  164. m := uint32(m64)
  165. req.Ranges = append(req.Ranges, e.Range)
  166. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  167. Network: e.Range,
  168. Nat: e.Nat,
  169. RouteMetric: m,
  170. })
  171. }
  172. }
  173. }
  174. if targetNode.Mutex != nil {
  175. targetNode.Mutex.Lock()
  176. }
  177. if len(req.Ranges) > 0 {
  178. targetNode.EgressDetails.IsEgressGateway = true
  179. targetNode.EgressDetails.EgressGatewayRanges = req.Ranges
  180. targetNode.EgressDetails.EgressGatewayRequest = req
  181. } else {
  182. targetNode.EgressDetails = models.EgressDetails{}
  183. }
  184. if targetNode.Mutex != nil {
  185. targetNode.Mutex.Unlock()
  186. }
  187. }
  188. // TODO
  189. func GetNetworkEgressInfo(network models.NetworkID, acls []models.Acl) (egressNodes map[string]models.Node) {
  190. eli, _ := (&schema.Egress{Network: network.String()}).ListByNetwork(db.WithContext(context.TODO()))
  191. egressNodes = make(map[string]models.Node)
  192. var err error
  193. for _, e := range eli {
  194. if !e.Status || e.Nodes == nil {
  195. continue
  196. }
  197. for nodeID, metric := range e.Nodes {
  198. targetNode, ok := egressNodes[nodeID]
  199. if !ok {
  200. targetNode, err = GetNodeByID(nodeID)
  201. if err != nil {
  202. continue
  203. }
  204. }
  205. req := models.EgressGatewayRequest{
  206. NodeID: targetNode.ID.String(),
  207. NetID: targetNode.Network,
  208. }
  209. IsNodeUsingInternetGw(&targetNode, acls)
  210. if e.IsInetGw {
  211. targetNode.EgressDetails.IsInternetGateway = true
  212. targetNode.EgressDetails.InetNodeReq = models.InetNodeReq{
  213. InetNodeClientIDs: GetInetClientsFromAclPolicies(e.ID),
  214. }
  215. req.Ranges = append(req.Ranges, "0.0.0.0/0")
  216. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  217. Network: "0.0.0.0/0",
  218. Nat: true,
  219. RouteMetric: 256,
  220. })
  221. req.Ranges = append(req.Ranges, "::/0")
  222. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  223. Network: "::/0",
  224. Nat: true,
  225. RouteMetric: 256,
  226. })
  227. } else {
  228. m64, err := metric.(json.Number).Int64()
  229. if err != nil {
  230. m64 = 256
  231. }
  232. m := uint32(m64)
  233. req.Ranges = append(req.Ranges, e.Range)
  234. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  235. Network: e.Range,
  236. Nat: e.Nat,
  237. RouteMetric: m,
  238. })
  239. }
  240. if targetNode.Mutex != nil {
  241. targetNode.Mutex.Lock()
  242. }
  243. if len(req.Ranges) > 0 {
  244. targetNode.EgressDetails.IsEgressGateway = true
  245. targetNode.EgressDetails.EgressGatewayRanges = append(targetNode.EgressDetails.EgressGatewayRanges, req.Ranges...)
  246. targetNode.EgressDetails.EgressGatewayRequest.Ranges = append(targetNode.EgressDetails.EgressGatewayRequest.Ranges, req.Ranges...)
  247. targetNode.EgressDetails.EgressGatewayRequest.RangesWithMetric = append(targetNode.EgressDetails.EgressGatewayRequest.RangesWithMetric,
  248. req.RangesWithMetric...)
  249. targetNode.EgressDetails.EgressGatewayRequest = req
  250. egressNodes[targetNode.ID.String()] = targetNode
  251. }
  252. if targetNode.Mutex != nil {
  253. targetNode.Mutex.Unlock()
  254. }
  255. }
  256. }
  257. return
  258. }
  259. func GetNodeEgressInfo(targetNode *models.Node, eli []schema.Egress, acls []models.Acl) {
  260. req := models.EgressGatewayRequest{
  261. NodeID: targetNode.ID.String(),
  262. NetID: targetNode.Network,
  263. }
  264. defer func() {
  265. if targetNode.Mutex != nil {
  266. targetNode.Mutex.Lock()
  267. }
  268. IsNodeUsingInternetGw(targetNode, acls)
  269. if targetNode.Mutex != nil {
  270. targetNode.Mutex.Unlock()
  271. }
  272. }()
  273. for _, e := range eli {
  274. if !e.Status || e.Network != targetNode.Network {
  275. continue
  276. }
  277. if metric, ok := e.Nodes[targetNode.ID.String()]; ok {
  278. if e.IsInetGw {
  279. targetNode.EgressDetails.IsInternetGateway = true
  280. targetNode.EgressDetails.InetNodeReq = models.InetNodeReq{
  281. InetNodeClientIDs: GetInetClientsFromAclPolicies(e.ID),
  282. }
  283. req.Ranges = append(req.Ranges, "0.0.0.0/0")
  284. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  285. Network: "0.0.0.0/0",
  286. Nat: true,
  287. RouteMetric: 256,
  288. })
  289. req.Ranges = append(req.Ranges, "::/0")
  290. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  291. Network: "::/0",
  292. Nat: true,
  293. RouteMetric: 256,
  294. })
  295. } else {
  296. m64, err := metric.(json.Number).Int64()
  297. if err != nil {
  298. m64 = 256
  299. }
  300. m := uint32(m64)
  301. req.Ranges = append(req.Ranges, e.Range)
  302. req.RangesWithMetric = append(req.RangesWithMetric, models.EgressRangeMetric{
  303. Network: e.Range,
  304. Nat: e.Nat,
  305. RouteMetric: m,
  306. })
  307. }
  308. }
  309. }
  310. if targetNode.Mutex != nil {
  311. targetNode.Mutex.Lock()
  312. }
  313. if len(req.Ranges) > 0 {
  314. targetNode.EgressDetails.IsEgressGateway = true
  315. targetNode.EgressDetails.EgressGatewayRanges = req.Ranges
  316. targetNode.EgressDetails.EgressGatewayRequest = req
  317. } else {
  318. targetNode.EgressDetails = models.EgressDetails{}
  319. }
  320. if targetNode.Mutex != nil {
  321. targetNode.Mutex.Unlock()
  322. }
  323. }
  324. func RemoveNodeFromEgress(node models.Node) {
  325. egs, _ := (&schema.Egress{
  326. Network: node.Network,
  327. }).ListByNetwork(db.WithContext(context.TODO()))
  328. for _, egI := range egs {
  329. if _, ok := egI.Nodes[node.ID.String()]; ok {
  330. delete(egI.Nodes, node.ID.String())
  331. egI.Update(db.WithContext(context.TODO()))
  332. }
  333. }
  334. }
  335. func GetEgressRanges(netID models.NetworkID) (map[string][]string, map[string]struct{}, error) {
  336. resultMap := make(map[string]struct{})
  337. nodeEgressMap := make(map[string][]string)
  338. networkNodes, err := GetNetworkNodes(netID.String())
  339. if err != nil {
  340. return nil, nil, err
  341. }
  342. for _, currentNode := range networkNodes {
  343. if currentNode.Network != netID.String() {
  344. continue
  345. }
  346. if currentNode.EgressDetails.IsEgressGateway { // add the egress gateway range(s) to the result
  347. if len(currentNode.EgressDetails.EgressGatewayRanges) > 0 {
  348. nodeEgressMap[currentNode.ID.String()] = currentNode.EgressDetails.EgressGatewayRanges
  349. for _, egressRangeI := range currentNode.EgressDetails.EgressGatewayRanges {
  350. resultMap[egressRangeI] = struct{}{}
  351. }
  352. }
  353. }
  354. }
  355. extclients, _ := GetNetworkExtClients(netID.String())
  356. for _, extclient := range extclients {
  357. if len(extclient.ExtraAllowedIPs) > 0 {
  358. nodeEgressMap[extclient.ClientID] = extclient.ExtraAllowedIPs
  359. for _, extraAllowedIP := range extclient.ExtraAllowedIPs {
  360. resultMap[extraAllowedIP] = struct{}{}
  361. }
  362. }
  363. }
  364. return nodeEgressMap, resultMap, nil
  365. }