gateway.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. package logic
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "slices"
  7. "sort"
  8. "time"
  9. "github.com/google/uuid"
  10. "github.com/gravitl/netmaker/database"
  11. "github.com/gravitl/netmaker/logger"
  12. "github.com/gravitl/netmaker/models"
  13. "github.com/gravitl/netmaker/servercfg"
  14. "golang.org/x/exp/slog"
  15. )
  16. var (
  17. IPv4Network = "0.0.0.0/0"
  18. IPv6Network = "::/0"
  19. )
  20. // IsInternetGw - checks if node is acting as internet gw
  21. func IsInternetGw(node models.Node) bool {
  22. return node.IsInternetGateway
  23. }
  24. // GetInternetGateways - gets all the nodes that are internet gateways
  25. func GetInternetGateways() ([]models.Node, error) {
  26. nodes, err := GetAllNodes()
  27. if err != nil {
  28. return nil, err
  29. }
  30. igs := make([]models.Node, 0)
  31. for _, node := range nodes {
  32. if node.IsInternetGateway {
  33. igs = append(igs, node)
  34. }
  35. }
  36. return igs, nil
  37. }
  38. // GetAllIngresses - gets all the nodes that are ingresses
  39. func GetAllIngresses() ([]models.Node, error) {
  40. nodes, err := GetAllNodes()
  41. if err != nil {
  42. return nil, err
  43. }
  44. ingresses := make([]models.Node, 0)
  45. for _, node := range nodes {
  46. if node.IsIngressGateway {
  47. ingresses = append(ingresses, node)
  48. }
  49. }
  50. return ingresses, nil
  51. }
  52. // GetAllEgresses - gets all the nodes that are egresses
  53. func GetAllEgresses() ([]models.Node, error) {
  54. nodes, err := GetAllNodes()
  55. if err != nil {
  56. return nil, err
  57. }
  58. egresses := make([]models.Node, 0)
  59. for _, node := range nodes {
  60. if node.EgressDetails.IsEgressGateway {
  61. egresses = append(egresses, node)
  62. }
  63. }
  64. return egresses, nil
  65. }
  66. // CreateEgressGateway - creates an egress gateway
  67. func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) {
  68. node, err := GetNodeByID(gateway.NodeID)
  69. if err != nil {
  70. return models.Node{}, err
  71. }
  72. host, err := GetHost(node.HostID.String())
  73. if err != nil {
  74. return models.Node{}, err
  75. }
  76. if host.OS != "linux" { // support for other OS to be added
  77. return models.Node{}, errors.New(host.OS + " is unsupported for egress gateways")
  78. }
  79. if host.FirewallInUse == models.FIREWALL_NONE {
  80. return models.Node{}, errors.New("please install iptables or nftables on the device")
  81. }
  82. if len(gateway.RangesWithMetric) == 0 && len(gateway.Ranges) > 0 {
  83. for _, rangeI := range gateway.Ranges {
  84. gateway.RangesWithMetric = append(gateway.RangesWithMetric, models.EgressRangeMetric{
  85. Network: rangeI,
  86. RouteMetric: 256,
  87. })
  88. }
  89. }
  90. for i := len(gateway.Ranges) - 1; i >= 0; i-- {
  91. // check if internet gateway IPv4
  92. if gateway.Ranges[i] == "0.0.0.0/0" || gateway.Ranges[i] == "::/0" {
  93. // remove inet range
  94. gateway.Ranges = append(gateway.Ranges[:i], gateway.Ranges[i+1:]...)
  95. continue
  96. }
  97. normalized, err := NormalizeCIDR(gateway.Ranges[i])
  98. if err != nil {
  99. return models.Node{}, err
  100. }
  101. gateway.Ranges[i] = normalized
  102. }
  103. rangesWithMetric := []string{}
  104. for i := len(gateway.RangesWithMetric) - 1; i >= 0; i-- {
  105. if gateway.RangesWithMetric[i].Network == "0.0.0.0/0" || gateway.RangesWithMetric[i].Network == "::/0" {
  106. // remove inet range
  107. gateway.RangesWithMetric = append(gateway.RangesWithMetric[:i], gateway.RangesWithMetric[i+1:]...)
  108. continue
  109. }
  110. normalized, err := NormalizeCIDR(gateway.RangesWithMetric[i].Network)
  111. if err != nil {
  112. return models.Node{}, err
  113. }
  114. gateway.RangesWithMetric[i].Network = normalized
  115. rangesWithMetric = append(rangesWithMetric, gateway.RangesWithMetric[i].Network)
  116. if gateway.RangesWithMetric[i].RouteMetric <= 0 || gateway.RangesWithMetric[i].RouteMetric > 999 {
  117. gateway.RangesWithMetric[i].RouteMetric = 256
  118. }
  119. }
  120. sort.Strings(gateway.Ranges)
  121. sort.Strings(rangesWithMetric)
  122. if !slices.Equal(gateway.Ranges, rangesWithMetric) {
  123. return models.Node{}, errors.New("invalid ranges")
  124. }
  125. if gateway.NatEnabled == "" {
  126. gateway.NatEnabled = "yes"
  127. }
  128. err = ValidateEgressGateway(gateway)
  129. if err != nil {
  130. return models.Node{}, err
  131. }
  132. if gateway.Ranges == nil {
  133. gateway.Ranges = make([]string, 0)
  134. }
  135. node.EgressDetails.IsEgressGateway = true
  136. node.EgressDetails.EgressGatewayRanges = gateway.Ranges
  137. node.EgressDetails.EgressGatewayNatEnabled = models.ParseBool(gateway.NatEnabled)
  138. node.EgressDetails.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
  139. node.SetLastModified()
  140. if err = UpsertNode(&node); err != nil {
  141. return models.Node{}, err
  142. }
  143. return node, nil
  144. }
  145. // ValidateEgressGateway - validates the egress gateway model
  146. func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
  147. return nil
  148. }
  149. // DeleteEgressGateway - deletes egress from node
  150. func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
  151. node, err := GetNodeByID(nodeid)
  152. if err != nil {
  153. return models.Node{}, err
  154. }
  155. node.EgressDetails.IsEgressGateway = false
  156. node.EgressDetails.EgressGatewayRanges = []string{}
  157. node.EgressDetails.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone
  158. node.SetLastModified()
  159. if err = UpsertNode(&node); err != nil {
  160. return models.Node{}, err
  161. }
  162. return node, nil
  163. }
  164. // CreateIngressGateway - creates an ingress gateway
  165. func CreateIngressGateway(netid string, nodeid string, ingress models.IngressRequest) (models.Node, error) {
  166. node, err := GetNodeByID(nodeid)
  167. if err != nil {
  168. return models.Node{}, err
  169. }
  170. if node.IsRelayed {
  171. return models.Node{}, errors.New("gateway cannot be created on a relayed node")
  172. }
  173. host, err := GetHost(node.HostID.String())
  174. if err != nil {
  175. return models.Node{}, err
  176. }
  177. if host.OS != "linux" {
  178. return models.Node{}, errors.New("gateway can only be created on linux based node")
  179. }
  180. network, err := GetParentNetwork(netid)
  181. if err != nil {
  182. return models.Node{}, err
  183. }
  184. node.IsIngressGateway = true
  185. node.IsGw = true
  186. SetAutoRelay(&node)
  187. node.IsInternetGateway = ingress.IsInternetGateway
  188. node.IngressGatewayRange = network.AddressRange
  189. node.IngressGatewayRange6 = network.AddressRange6
  190. node.IngressDNS = ingress.ExtclientDNS
  191. if node.IsInternetGateway && node.IngressDNS == "" {
  192. node.IngressDNS = "1.1.1.1"
  193. }
  194. node.IngressPersistentKeepalive = 20
  195. if ingress.PersistentKeepalive != 0 {
  196. node.IngressPersistentKeepalive = ingress.PersistentKeepalive
  197. }
  198. node.IngressMTU = 1420
  199. if ingress.MTU != 0 {
  200. node.IngressMTU = ingress.MTU
  201. }
  202. if servercfg.IsPro {
  203. if _, exists := FailOverExists(node.Network); exists {
  204. ResetFailedOverPeer(&node)
  205. }
  206. ResetAutoRelayedPeer(&node)
  207. }
  208. node.SetLastModified()
  209. node.Metadata = ingress.Metadata
  210. if node.Metadata == "" {
  211. node.Metadata = "This host can be used for remote access"
  212. }
  213. if node.Tags == nil {
  214. node.Tags = make(map[models.TagID]struct{})
  215. }
  216. node.Tags[models.TagID(fmt.Sprintf("%s.%s", netid, models.GwTagName))] = struct{}{}
  217. err = UpsertNode(&node)
  218. if err != nil {
  219. return models.Node{}, err
  220. }
  221. err = SetNetworkNodesLastModified(netid)
  222. return node, err
  223. }
  224. // GetIngressGwUsers - lists the users having to access to ingressGW
  225. func GetIngressGwUsers(node models.Node) (models.IngressGwUsers, error) {
  226. gwUsers := models.IngressGwUsers{
  227. NodeID: node.ID.String(),
  228. Network: node.Network,
  229. }
  230. users, err := GetUsers()
  231. if err != nil {
  232. return gwUsers, err
  233. }
  234. for _, user := range users {
  235. if user.PlatformRoleID != models.SuperAdminRole && user.PlatformRoleID != models.AdminRole {
  236. gwUsers.Users = append(gwUsers.Users, user)
  237. }
  238. }
  239. return gwUsers, nil
  240. }
  241. // DeleteIngressGateway - deletes an ingress gateway
  242. func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error) {
  243. removedClients := []models.ExtClient{}
  244. node, err := GetNodeByID(nodeid)
  245. if err != nil {
  246. return models.Node{}, removedClients, err
  247. }
  248. clients, err := GetExtClientsByID(nodeid, node.Network)
  249. if err != nil && !database.IsEmptyRecord(err) {
  250. return models.Node{}, removedClients, err
  251. }
  252. removedClients = clients
  253. // delete ext clients belonging to ingress gateway
  254. if err = DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil {
  255. return models.Node{}, removedClients, err
  256. }
  257. logger.Log(3, "deleting ingress gateway")
  258. node.LastModified = time.Now().UTC()
  259. node.IsIngressGateway = false
  260. delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName)))
  261. node.IngressGatewayRange = ""
  262. node.Metadata = ""
  263. err = UpsertNode(&node)
  264. if err != nil {
  265. return models.Node{}, removedClients, err
  266. }
  267. err = SetNetworkNodesLastModified(node.Network)
  268. return node, removedClients, err
  269. }
  270. // DeleteGatewayExtClients - deletes ext clients based on gateway (mac) of ingress node and network
  271. func DeleteGatewayExtClients(gatewayID string, networkName string) error {
  272. currentExtClients, err := GetNetworkExtClients(networkName)
  273. if database.IsEmptyRecord(err) {
  274. return nil
  275. }
  276. if err != nil {
  277. return err
  278. }
  279. for _, extClient := range currentExtClients {
  280. if extClient.IngressGatewayID == gatewayID {
  281. if err = DeleteExtClient(networkName, extClient.ClientID, false); err != nil {
  282. logger.Log(1, "failed to remove ext client", extClient.ClientID)
  283. continue
  284. }
  285. }
  286. }
  287. return nil
  288. }
  289. // IsUserAllowedAccessToExtClient - checks if user has permission to access extclient
  290. func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bool {
  291. if username == MasterUser {
  292. return true
  293. }
  294. user, err := GetUser(username)
  295. if err != nil {
  296. return false
  297. }
  298. if user.UserName != client.OwnerID {
  299. return false
  300. }
  301. return true
  302. }
  303. func ValidateInetGwReq(inetNode models.Node, req models.InetNodeReq, update bool) error {
  304. inetHost, err := GetHost(inetNode.HostID.String())
  305. if err != nil {
  306. return err
  307. }
  308. if inetHost.FirewallInUse == models.FIREWALL_NONE {
  309. return errors.New("iptables or nftables needs to be installed")
  310. }
  311. if inetNode.InternetGwID != "" {
  312. return fmt.Errorf("node %s is using a internet gateway already", inetHost.Name)
  313. }
  314. if inetNode.IsRelayed {
  315. return fmt.Errorf("node %s is being relayed", inetHost.Name)
  316. }
  317. for _, clientNodeID := range req.InetNodeClientIDs {
  318. clientNode, err := GetNodeByID(clientNodeID)
  319. if err != nil {
  320. return err
  321. }
  322. if clientNode.IsFailOver {
  323. return errors.New("failover node cannot be set to use internet gateway")
  324. }
  325. clientHost, err := GetHost(clientNode.HostID.String())
  326. if err != nil {
  327. return err
  328. }
  329. if clientHost.IsDefault {
  330. return errors.New("default host cannot be set to use internet gateway")
  331. }
  332. if clientHost.OS != models.OS_Types.Linux && clientHost.OS != models.OS_Types.Windows {
  333. return errors.New("can only attach linux or windows machine to a internet gateway")
  334. }
  335. if clientNode.IsInternetGateway {
  336. return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
  337. }
  338. if update {
  339. if clientNode.InternetGwID != "" && clientNode.InternetGwID != inetNode.ID.String() {
  340. return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
  341. }
  342. } else {
  343. if clientNode.InternetGwID != "" {
  344. return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
  345. }
  346. }
  347. if clientNode.FailedOverBy != uuid.Nil {
  348. ResetFailedOverPeer(&clientNode)
  349. }
  350. if clientNode.AutoRelayedBy != uuid.Nil {
  351. ResetAutoRelayedPeer(&clientNode)
  352. }
  353. if clientNode.IsRelayed && clientNode.RelayedBy != inetNode.ID.String() {
  354. return fmt.Errorf("node %s is being relayed", clientHost.Name)
  355. }
  356. for _, nodeID := range clientHost.Nodes {
  357. node, err := GetNodeByID(nodeID)
  358. if err != nil {
  359. continue
  360. }
  361. if node.InternetGwID != "" && node.InternetGwID != inetNode.ID.String() {
  362. return errors.New("nodes on same host cannot use different internet gateway")
  363. }
  364. }
  365. }
  366. return nil
  367. }
  368. // SetInternetGw - sets the node as internet gw based on flag bool
  369. func SetInternetGw(node *models.Node, req models.InetNodeReq) {
  370. node.IsInternetGateway = true
  371. node.InetNodeReq = req
  372. for _, clientNodeID := range req.InetNodeClientIDs {
  373. clientNode, err := GetNodeByID(clientNodeID)
  374. if err != nil {
  375. continue
  376. }
  377. clientNode.InternetGwID = node.ID.String()
  378. UpsertNode(&clientNode)
  379. }
  380. }
  381. func UnsetInternetGw(node *models.Node) {
  382. nodes, err := GetNetworkNodes(node.Network)
  383. if err != nil {
  384. slog.Error("failed to get network nodes", "network", node.Network, "error", err)
  385. return
  386. }
  387. for _, clientNode := range nodes {
  388. if node.ID.String() == clientNode.InternetGwID {
  389. clientNode.InternetGwID = ""
  390. UpsertNode(&clientNode)
  391. }
  392. }
  393. node.IsInternetGateway = false
  394. node.InetNodeReq = models.InetNodeReq{}
  395. }
  396. func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
  397. if relay.InternetGwID != "" {
  398. relayedHost, err := GetHost(relayed.HostID.String())
  399. if err != nil {
  400. return peerUpdate
  401. }
  402. peerUpdate.ChangeDefaultGw = true
  403. peerUpdate.DefaultGwIp = relay.Address.IP
  404. if peerUpdate.DefaultGwIp == nil || relayedHost.EndpointIP == nil {
  405. peerUpdate.DefaultGwIp = relay.Address6.IP
  406. }
  407. }
  408. return peerUpdate
  409. }
  410. func SetDefaultGw(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
  411. if node.InternetGwID != "" {
  412. inetNode, err := GetNodeByID(node.InternetGwID)
  413. if err != nil {
  414. return peerUpdate
  415. }
  416. host, err := GetHost(node.HostID.String())
  417. if err != nil {
  418. return peerUpdate
  419. }
  420. peerUpdate.ChangeDefaultGw = true
  421. peerUpdate.DefaultGwIp = inetNode.Address.IP
  422. if peerUpdate.DefaultGwIp == nil || host.EndpointIP == nil {
  423. peerUpdate.DefaultGwIp = inetNode.Address6.IP
  424. }
  425. }
  426. return peerUpdate
  427. }
  428. // GetAllowedIpForInetNodeClient - get inet cidr for node using a inet gw
  429. func GetAllowedIpForInetNodeClient(node, peer *models.Node) []net.IPNet {
  430. var allowedips = []net.IPNet{}
  431. if peer.Address.IP != nil {
  432. _, ipnet, _ := net.ParseCIDR(IPv4Network)
  433. allowedips = append(allowedips, *ipnet)
  434. }
  435. if peer.Address6.IP != nil {
  436. _, ipnet, _ := net.ParseCIDR(IPv6Network)
  437. allowedips = append(allowedips, *ipnet)
  438. }
  439. return allowedips
  440. }