Skip to content

Commit

Permalink
NET-940: Inet Gws (#2828)
Browse files Browse the repository at this point in the history
* internet gws apis

* add validate check for inet request

* add default gw changes to peer update

* update json tag

* add OS checks for inet gws

* add set defaul gw pro func

* allow disable and enable inet gw

* add inet handlers to pro

* add fields to api node

* add inet allowed ips

* add default gw to pull

* unset node inet details on deletion

* unset internet gw on network nodes

* unset inet gw fix

* unset inet gw fix

* send default gw ip

* fix inet node endpoint

* add default gw endpoint ip to pull resp

* validate after unset gws

* add inet client peer allowedips to inet node

* validate after unset gws

* fix allowed ips for inet peer and gw node

* fix allowed ips for inet peer and gw node

* fix allowed ips for inet peer and gw node

* fix allowed ips for inet peer and gw node

* fix inet gw and relayed conflict

* fix inet gw and relayed conflict

* fix update req

* fix update inet gw api

* when inet gw is peer ignore other allowedIps

* test relay

* revert test relay

* revert inet peer update changes

* channel internet traffic of relayed node to relay's inetgw

* channel internet traffic of relayed node to relay's inetgw

* channel internet traffic of relayed node to relay's inetgw

* add check for relayed node

* add inet info to peer update

* add inet info to peer update

* fix update node to persist inet info

* fix go tests

* egress ranges with inet gw fix

* egress ranges with inet gw fix

* disallow node acting using inet gw to act as inet gw

* add check to validate inet gw

* fix typos

* add firewall check

* set inetgw on ingress req on community

* set inetgw to false on community on ingress del
  • Loading branch information
abhishek9686 authored Feb 28, 2024
1 parent fd95e80 commit 0638dca
Show file tree
Hide file tree
Showing 17 changed files with 445 additions and 96 deletions.
2 changes: 1 addition & 1 deletion controllers/config/dnsconfig/Corefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
skynet {
. {
reload 15s
hosts /root/dnsconfig/netmaker.hosts {
fallthrough
Expand Down
2 changes: 1 addition & 1 deletion controllers/ext_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) {
gwendpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), host.ListenPort)
}
var newAllowedIPs string
if logic.IsInternetGw(gwnode) {
if logic.IsInternetGw(gwnode) || gwnode.InternetGwID != "" {
egressrange := "0.0.0.0/0"
if gwnode.Address6.IP != nil && client.Address6 != "" {
egressrange += "," + "::/0"
Expand Down
3 changes: 3 additions & 0 deletions controllers/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ func pull(w http.ResponseWriter, r *http.Request) {
HostNetworkInfo: hPU.HostNetworkInfo,
EgressRoutes: hPU.EgressRoutes,
FwUpdate: hPU.FwUpdate,
ChangeDefaultGw: hPU.ChangeDefaultGw,
DefaultGwIp: hPU.DefaultGwIp,
IsInternetGw: hPU.IsInternetGw,
}

logger.Log(1, hostID, "completed a pull")
Expand Down
47 changes: 21 additions & 26 deletions controllers/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ func getNode(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
nodeid := params["nodeid"]

node, err := validateParams(nodeid, params["network"])
node, err := logic.ValidateParams(nodeid, params["network"])
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
Expand Down Expand Up @@ -402,9 +402,9 @@ func getNode(w http.ResponseWriter, r *http.Request) {
func createEgressGateway(w http.ResponseWriter, r *http.Request) {
var gateway models.EgressGatewayRequest
var params = mux.Vars(r)
node, err := validateParams(params["nodeid"], params["network"])
node, err := logic.ValidateParams(params["nodeid"], params["network"])
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "bad request"))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
w.Header().Set("Content-Type", "application/json")
Expand Down Expand Up @@ -453,9 +453,9 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
nodeid := params["nodeid"]
netid := params["network"]
node, err := validateParams(nodeid, netid)
node, err := logic.ValidateParams(nodeid, netid)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "bad request"))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
node, err = logic.DeleteEgressGateway(netid, nodeid)
Expand Down Expand Up @@ -497,9 +497,9 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
nodeid := params["nodeid"]
netid := params["network"]
node, err := validateParams(nodeid, netid)
node, err := logic.ValidateParams(nodeid, netid)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "bad request"))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
var request models.IngressRequest
Expand Down Expand Up @@ -540,9 +540,9 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
nodeid := params["nodeid"]
netid := params["network"]
node, err := validateParams(nodeid, netid)
node, err := logic.ValidateParams(nodeid, netid)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "bad request"))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
node, removedClients, err := logic.DeleteIngressGateway(nodeid)
Expand Down Expand Up @@ -618,9 +618,9 @@ func updateNode(w http.ResponseWriter, r *http.Request) {

//start here
nodeid := params["nodeid"]
currentNode, err := validateParams(nodeid, params["network"])
currentNode, err := logic.ValidateParams(nodeid, params["network"])
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "bad request"))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
var newData models.ApiNode
Expand All @@ -636,6 +636,14 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
return
}
newNode := newData.ConvertToServerNode(&currentNode)
if newNode.IsInternetGateway != currentNode.IsInternetGateway {
if newNode.IsInternetGateway {
logic.SetInternetGw(newNode, models.InetNodeReq{})
} else {
logic.UnsetInternetGw(newNode)
}

}
relayUpdate := logic.RelayUpdates(&currentNode, newNode)
_, err = logic.GetHost(newNode.HostID.String())
if err != nil {
Expand Down Expand Up @@ -695,9 +703,9 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
// get params
var params = mux.Vars(r)
var nodeid = params["nodeid"]
node, err := validateParams(nodeid, params["network"])
node, err := logic.ValidateParams(nodeid, params["network"])
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "bad request"))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
forceDelete := r.URL.Query().Get("force") == "true"
Expand All @@ -716,16 +724,3 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"])
go mq.PublishMqUpdatesForDeletedNode(node, !fromNode, gwClients)
}

func validateParams(nodeid, netid string) (models.Node, error) {
node, err := logic.GetNodeByID(nodeid)
if err != nil {
slog.Error("error fetching node", "node", nodeid, "error", err.Error())
return node, fmt.Errorf("error fetching node during parameter validation: %v", err)
}
if node.Network != netid {
slog.Error("network url param does not match node id", "url nodeid", netid, "node", node.Network)
return node, fmt.Errorf("network url param does not match node network")
}
return node, nil
}
6 changes: 1 addition & 5 deletions controllers/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,7 @@ func TestGetNetworkNodes(t *testing.T) {

func TestValidateEgressGateway(t *testing.T) {
var gateway models.EgressGatewayRequest
t.Run("EmptyRange", func(t *testing.T) {
gateway.Ranges = []string{}
err := logic.ValidateEgressGateway(gateway)
assert.EqualError(t, err, "IP Ranges Cannot Be Empty")
})

t.Run("Success", func(t *testing.T) {
gateway.Ranges = []string{"10.100.100.0/24"}
err := logic.ValidateEgressGateway(gateway)
Expand Down
31 changes: 13 additions & 18 deletions logic/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import (
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
)

var (
// SetInternetGw - sets the node as internet gw based on flag bool
SetInternetGw = func(node *models.Node, flag bool) {
}
// IsInternetGw - checks if node is acting as internet gw
IsInternetGw = func(node models.Node) bool {
return false
}
)
// IsInternetGw - checks if node is acting as internet gw
func IsInternetGw(node models.Node) bool {
return node.IsInternetGateway
}

// GetInternetGateways - gets all the nodes that are internet gateways
func GetInternetGateways() ([]models.Node, error) {
Expand All @@ -27,13 +23,8 @@ func GetInternetGateways() ([]models.Node, error) {
}
igs := make([]models.Node, 0)
for _, node := range nodes {
if !node.IsEgressGateway {
continue
}
for _, ran := range node.EgressGatewayRanges {
if ran == "0.0.0.0/0" {
igs = append(igs, node)
}
if node.IsInternetGateway {
igs = append(igs, node)
}
}
return igs, nil
Expand Down Expand Up @@ -167,7 +158,9 @@ func CreateIngressGateway(netid string, nodeid string, ingress models.IngressReq
return models.Node{}, err
}
node.IsIngressGateway = true
SetInternetGw(&node, ingress.IsInternetGateway)
if !servercfg.IsPro {
node.IsInternetGateway = ingress.IsInternetGateway
}
node.IngressGatewayRange = network.AddressRange
node.IngressGatewayRange6 = network.AddressRange6
node.IngressDNS = ingress.ExtclientDNS
Expand Down Expand Up @@ -223,7 +216,9 @@ func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error
logger.Log(3, "deleting ingress gateway")
node.LastModified = time.Now()
node.IsIngressGateway = false
node.IsInternetGateway = false
if !servercfg.IsPro {
node.IsInternetGateway = false
}
node.IngressGatewayRange = ""
node.Metadata = ""
err = UpsertNode(&node)
Expand Down
30 changes: 30 additions & 0 deletions logic/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,23 @@ func DeleteNode(node *models.Node, purge bool) error {
// unset all the relayed nodes
SetRelayedNodes(false, node.ID.String(), node.RelayedNodes)
}
if node.InternetGwID != "" {
inetNode, err := GetNodeByID(node.InternetGwID)
if err == nil {
clientNodeIDs := []string{}
for _, inetNodeClientID := range inetNode.InetNodeReq.InetNodeClientIDs {
if inetNodeClientID == node.ID.String() {
continue
}
clientNodeIDs = append(clientNodeIDs, inetNodeClientID)
}
inetNode.InetNodeReq.InetNodeClientIDs = clientNodeIDs
UpsertNode(&inetNode)
}
}
if node.IsInternetGateway {
UnsetInternetGw(node)
}

if !purge && !alreadyDeleted {
newnode := *node
Expand Down Expand Up @@ -598,3 +615,16 @@ func SortApiNodes(unsortedNodes []models.ApiNode) {
return unsortedNodes[i].ID < unsortedNodes[j].ID
})
}

func ValidateParams(nodeid, netid string) (models.Node, error) {
node, err := GetNodeByID(nodeid)
if err != nil {
slog.Error("error fetching node", "node", nodeid, "error", err.Error())
return node, fmt.Errorf("error fetching node during parameter validation: %v", err)
}
if node.Network != netid {
slog.Error("network url param does not match node id", "url nodeid", netid, "node", node.Network)
return node, fmt.Errorf("network url param does not match node network")
}
return node, nil
}
65 changes: 45 additions & 20 deletions logic/peers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package logic

import (
"errors"
"fmt"
"net"
"net/netip"

Expand All @@ -28,10 +29,30 @@ var (
GetFailOverPeerIps = func(peer, node *models.Node) []net.IPNet {
return []net.IPNet{}
}

// CreateFailOver - creates failover in a network
CreateFailOver = func(node models.Node) error {
return nil
}

// SetDefaulGw
SetDefaultGw = func(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
return peerUpdate
}
SetDefaultGwForRelayedUpdate = func(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
return peerUpdate
}
// UnsetInternetGw
UnsetInternetGw = func(node *models.Node) {
node.IsInternetGateway = false
}
// SetInternetGw
SetInternetGw = func(node *models.Node, req models.InetNodeReq) {
node.IsInternetGateway = true
}
// GetAllowedIpForInetNodeClient
GetAllowedIpForInetNodeClient = func(node, peer *models.Node) []net.IPNet {
return []net.IPNet{}
}
)

// GetPeerUpdateForHost - gets the consolidated peer update for the host from all networks
Expand Down Expand Up @@ -122,7 +143,10 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
}
continue
}

hostPeerUpdate = SetDefaultGw(node, hostPeerUpdate)
if !hostPeerUpdate.IsInternetGw {
hostPeerUpdate.IsInternetGw = IsInternetGw(node)
}
currentPeers := GetNetworkNodesMemory(allNodes, node.Network)
for _, peer := range currentPeers {
peer := peer
Expand Down Expand Up @@ -164,6 +188,9 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
peerIndexMap[peerHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
continue
}
if node.IsRelayed && node.RelayedBy == peer.ID.String() {
hostPeerUpdate = SetDefaultGwForRelayedUpdate(node, peer, hostPeerUpdate)
}
}

uselocal := false
Expand Down Expand Up @@ -251,18 +278,8 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
logger.Log(1, "error retrieving external clients:", err.Error())
}
}
addedInetGwRanges := false
if node.IsEgressGateway && node.EgressGatewayRequest.NatEnabled == "yes" && len(node.EgressGatewayRequest.Ranges) > 0 {
hostPeerUpdate.FwUpdate.IsEgressGw = true
if IsInternetGw(node) {
hostPeerUpdate.FwUpdate.IsEgressGw = true
egressrange := []string{"0.0.0.0/0"}
if node.Address6.IP != nil {
egressrange = append(egressrange, "::/0")
}
node.EgressGatewayRequest.Ranges = append(node.EgressGatewayRequest.Ranges, egressrange...)
addedInetGwRanges = true
}
hostPeerUpdate.FwUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
EgressID: node.ID.String(),
Network: node.PrimaryNetworkRange(),
Expand All @@ -274,21 +291,21 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
}

}
if IsInternetGw(node) && !addedInetGwRanges {
if IsInternetGw(node) {
hostPeerUpdate.FwUpdate.IsEgressGw = true
egressrange := []string{"0.0.0.0/0"}
if node.Address6.IP != nil {
egressrange = append(egressrange, "::/0")
}
hostPeerUpdate.FwUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
EgressID: node.ID.String(),
hostPeerUpdate.FwUpdate.EgressInfo[fmt.Sprintf("%s-%s", node.ID.String(), "inet")] = models.EgressInfo{
EgressID: fmt.Sprintf("%s-%s", node.ID.String(), "inet"),
Network: node.PrimaryAddressIPNet(),
EgressGwAddr: net.IPNet{
IP: net.ParseIP(node.PrimaryAddress()),
Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
},
EgressGWCfg: models.EgressGatewayRequest{
NodeID: node.ID.String(),
NodeID: fmt.Sprintf("%s-%s", node.ID.String(), "inet"),
NetID: node.Network,
NatEnabled: "yes",
Ranges: egressrange,
Expand Down Expand Up @@ -354,7 +371,17 @@ func GetPeerListenPort(host *models.Host) int {
// GetAllowedIPs - calculates the wireguard allowedip field for a peer of a node based on the peer and node settings
func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet {
var allowedips []net.IPNet
allowedips = getNodeAllowedIPs(peer, node)
if peer.IsInternetGateway && node.InternetGwID == peer.ID.String() {
allowedips = append(allowedips, GetAllowedIpForInetNodeClient(node, peer)...)
return allowedips
}
if node.IsRelayed && node.RelayedBy == peer.ID.String() {
allowedips = append(allowedips, GetAllowedIpsForRelayed(node, peer)...)
if peer.InternetGwID != "" {
return allowedips
}
}
allowedips = append(allowedips, getNodeAllowedIPs(peer, node)...)

// handle ingress gateway peers
if peer.IsIngressGateway {
Expand All @@ -366,9 +393,7 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet
allowedips = append(allowedips, extPeer.AllowedIPs...)
}
}
if node.IsRelayed && node.RelayedBy == peer.ID.String() {
allowedips = append(allowedips, GetAllowedIpsForRelayed(node, peer)...)
}

return allowedips
}

Expand Down
Loading

0 comments on commit 0638dca

Please sign in to comment.