diff --git a/logic/peers.go b/logic/peers.go index e733c7ef..6104a651 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -16,6 +16,7 @@ import ( "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" + "golang.org/x/exp/slices" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -494,6 +495,11 @@ func GetPeerUpdateForRelayedNode(node *models.Node, udppeers map[string]string) } func getEgressIPs(node, peer *models.Node) []net.IPNet { + //check for internet gateway + internetGateway := false + if slices.Contains(peer.EgressGatewayRanges, "0.0.0.0/0") || slices.Contains(peer.EgressGatewayRanges, "::0") { + internetGateway = true + } allowedips := []net.IPNet{} for _, iprange := range peer.EgressGatewayRanges { // go through each cidr for egress gateway _, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr @@ -501,13 +507,13 @@ func getEgressIPs(node, peer *models.Node) []net.IPNet { logger.Log(1, "could not parse gateway IP range. Not adding ", iprange) continue // if can't parse CIDR } - nodeEndpointArr := strings.Split(peer.Endpoint, ":") // getting the public ip of node - if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) { // ensuring egress gateway range does not contain endpoint of node + nodeEndpointArr := strings.Split(peer.Endpoint, ":") // getting the public ip of node + if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) && !internetGateway { // ensuring egress gateway range does not contain endpoint of node logger.Log(2, "egress IP range of ", iprange, " overlaps with ", node.Endpoint, ", omitting") continue // skip adding egress range if overlaps with node's ip } // TODO: Could put in a lot of great logic to avoid conflicts / bad routes - if ipnet.Contains(net.ParseIP(node.LocalAddress)) { // ensuring egress gateway range does not contain public ip of node + if ipnet.Contains(net.ParseIP(node.LocalAddress)) && !internetGateway { // ensuring egress gateway range does not contain public ip of node logger.Log(2, "egress IP range of ", iprange, " overlaps with ", node.LocalAddress, ", omitting") continue // skip adding egress range if overlaps with node's local ip } diff --git a/logic/server.go b/logic/server.go index ffe056c6..4dca4ce1 100644 --- a/logic/server.go +++ b/logic/server.go @@ -12,6 +12,7 @@ import ( "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" + "golang.org/x/exp/slices" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -206,6 +207,11 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri nodes, err := GetNetworkNodes(serverNode.Network) if err == nil { for _, node := range nodes { + //if egress ranges is internet (0.0.0.0/0 or ::/0) remove as don't want server to use internet gateway + if node.IsEgressGateway == "yes" && (slices.Contains(node.EgressGatewayRanges, "0.0.0.0/0") || slices.Contains(node.EgressGatewayRanges, "::/0")) { + logger.Log(0, "skipping internet gateway for server") + continue + } if node.IsEgressGateway == "yes" && !IsLocalServer(&node) { gateways = append(gateways, node.EgressGatewayRanges...) } diff --git a/models/node.go b/models/node.go index 6edd0199..06ccc9da 100644 --- a/models/node.go +++ b/models/node.go @@ -71,19 +71,20 @@ type Node struct { RelayAddrs []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"` IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"` // IsStatic - refers to if the Endpoint is set manually or dynamically - IsStatic string `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"` - UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"` - DNSOn string `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"` - IsServer string `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"` - Action string `json:"action" bson:"action" yaml:"action"` - IsLocal string `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"` - LocalRange string `json:"localrange" bson:"localrange" yaml:"localrange"` - IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"` - OS string `json:"os" bson:"os" yaml:"os"` - MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"` - Version string `json:"version" bson:"version" yaml:"version"` - Server string `json:"server" bson:"server" yaml:"server"` - TrafficKeys TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"` + IsStatic string `json:"isstatic" bson:"isstatic" yaml:"isstatic" validate:"checkyesorno"` + UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"` + DNSOn string `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"` + IsServer string `json:"isserver" bson:"isserver" yaml:"isserver" validate:"checkyesorno"` + Action string `json:"action" bson:"action" yaml:"action"` + IsLocal string `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"` + LocalRange string `json:"localrange" bson:"localrange" yaml:"localrange"` + IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"` + OS string `json:"os" bson:"os" yaml:"os"` + MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"` + Version string `json:"version" bson:"version" yaml:"version"` + Server string `json:"server" bson:"server" yaml:"server"` + TrafficKeys TrafficKeys `json:"traffickeys" bson:"traffickeys" yaml:"traffickeys"` + InternetGateway string `json:"internetgateway" bson:"internetgateway" yaml:"internetgateway"` } // NodesArray - used for node sorting diff --git a/netclient/functions/mqhandlers.go b/netclient/functions/mqhandlers.go index 8b56fc77..c68ed07a 100644 --- a/netclient/functions/mqhandlers.go +++ b/netclient/functions/mqhandlers.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "net" "os" "runtime" "strings" @@ -208,11 +209,27 @@ func UpdatePeers(client mqtt.Client, msg mqtt.Message) { } file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf" - err = wireguard.UpdateWgPeers(file, peerUpdate.Peers) + internetGateway, err := wireguard.UpdateWgPeers(file, peerUpdate.Peers) if err != nil { logger.Log(0, "error updating wireguard peers"+err.Error()) return } + //check if internet gateway has changed + oldGateway, err := net.ResolveUDPAddr("udp", cfg.Node.InternetGateway) + if err != nil || (oldGateway == &net.UDPAddr{}) { + oldGateway = nil + } + if (internetGateway == nil && oldGateway != nil) || (internetGateway != nil && internetGateway != oldGateway) { + cfg.Node.InternetGateway = internetGateway.String() + if err := config.ModNodeConfig(&cfg.Node); err != nil { + logger.Log(0, "failed to save internet gateway", err.Error()) + } + if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, file); err != nil { + logger.Log(0, "error applying internet gateway", err.Error()) + } + UpdateLocalListenPort(&cfg) + return + } queryAddr := cfg.Node.PrimaryAddress() //err = wireguard.SyncWGQuickConf(cfg.Node.Interface, file) diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 79473fd9..438a19cd 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -319,7 +319,6 @@ func ApplyConf(node *models.Node, ifacename string, confPath string) error { } // WriteWgConfig - creates a wireguard config file -//func WriteWgConfig(cfg *config.ClientConfig, privateKey string, peers []wgtypes.PeerConfig) error { func WriteWgConfig(node *models.Node, privateKey string, peers []wgtypes.PeerConfig) error { options := ini.LoadOptions{ AllowNonUniqueSections: true, @@ -382,14 +381,15 @@ func WriteWgConfig(node *models.Node, privateKey string, peers []wgtypes.PeerCon } // UpdateWgPeers - updates the peers of a network -func UpdateWgPeers(file string, peers []wgtypes.PeerConfig) error { +func UpdateWgPeers(file string, peers []wgtypes.PeerConfig) (*net.UDPAddr, error) { + var internetGateway *net.UDPAddr options := ini.LoadOptions{ AllowNonUniqueSections: true, AllowShadows: true, } wireguard, err := ini.LoadSources(options, file) if err != nil { - return err + return internetGateway, err } //delete the peers sections as they are going to be replaced wireguard.DeleteSection(section_peers) @@ -408,6 +408,9 @@ func UpdateWgPeers(file string, peers []wgtypes.PeerConfig) error { } } wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) + if strings.Contains(allowedIPs, "0.0.0.0/0") || strings.Contains(allowedIPs, "::/0") { + internetGateway = peer.Endpoint + } } if peer.Endpoint != nil { wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) @@ -417,9 +420,9 @@ func UpdateWgPeers(file string, peers []wgtypes.PeerConfig) error { } } if err := wireguard.SaveTo(file); err != nil { - return err + return internetGateway, err } - return nil + return internetGateway, nil } // UpdateWgInterface - updates the interface section of a wireguard config file