From 81c896b22a4e97adeb53ae801823a50d9d5e0006 Mon Sep 17 00:00:00 2001 From: cameronts Date: Mon, 1 Aug 2022 11:12:25 -0700 Subject: [PATCH 01/14] Add nftables support. --- logic/gateway.go | 75 ++++++++++++++++++++++++++++++++++++------------ logic/util.go | 5 ++++ 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 4e129251..ada4dba7 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -33,14 +33,28 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postUpCmd := "" postDownCmd := "" if node.OS == "linux" { - postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " - postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" - postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " - postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" + // nftables only supported on Linux + if IsNFTablesPresent() { + // assumes chains eg FORWARD and POSTROUTING already exist + postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - if node.EgressGatewayNatEnabled == "yes" { - postUpCmd += "; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE" - postDownCmd += "; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE" + if node.EgressGatewayNatEnabled == "yes" { + postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" + postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" + } + } else { + postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " + postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" + postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " + postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" + + if node.EgressGatewayNatEnabled == "yes" { + postUpCmd += "; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE" + postDownCmd += "; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE" + } } } if node.OS == "freebsd" { @@ -119,12 +133,23 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.PostDown = "" if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules if node.OS == "linux" { - node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " - node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " - node.PostUp += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" - node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; " - node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; " - node.PostDown += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + // nftables only supported on Linux + if IsNFTablesPresent() { + // assumes chains eg FORWARD and POSTROUTING already exist + node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ; " + node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" + node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" + node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade " + } else { + node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " + node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " + node.PostUp += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" + node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; " + node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; " + node.PostDown += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + } } if node.OS == "freebsd" { node.PostUp = "" @@ -151,6 +176,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { // CreateIngressGateway - creates an ingress gateway func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { + var postUpCmd, postDownCmd string node, err := GetNodeByID(nodeid) if node.OS != "linux" { // add in darwin later return models.Node{}, errors.New(node.OS + " is unsupported for ingress gateways") @@ -166,12 +192,23 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { } node.IsIngressGateway = "yes" node.IngressGatewayRange = network.AddressRange - postUpCmd := "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " - postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " - postUpCmd += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" - postDownCmd := "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; " - postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; " - postDownCmd += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + if IsNFTablesPresent() { + // assumes chains eg FORWARD and POSTROUTING already exist + postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" + postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" + } else { + postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " + postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " + postUpCmd += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" + postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; " + postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; " + postDownCmd += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + } + if node.PostUp != "" { if !strings.Contains(node.PostUp, postUpCmd) { postUpCmd = node.PostUp + "; " + postUpCmd diff --git a/logic/util.go b/logic/util.go index af68afbd..8f94736e 100644 --- a/logic/util.go +++ b/logic/util.go @@ -19,6 +19,11 @@ import ( "github.com/gravitl/netmaker/netclient/ncutils" ) +// nfTablesPresent - returns true if nftables is present, false otherwise +func IsNFTablesPresent() bool { + return FileExists("/etc/nftables.conf") +} + // IsBase64 - checks if a string is in base64 format // This is used to validate public keys (make sure they're base64 encoded like all public keys should be). func IsBase64(s string) bool { From 1b01914c52daff0a8d12b32ad2acbe9a07f4ae65 Mon Sep 17 00:00:00 2001 From: cameronts Date: Mon, 1 Aug 2022 15:52:49 -0700 Subject: [PATCH 02/14] Added logging for nftables handling. --- logic/gateway.go | 6 ++++++ logic/util.go | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/logic/gateway.go b/logic/gateway.go index ada4dba7..216a059a 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -36,6 +36,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro // nftables only supported on Linux if IsNFTablesPresent() { // assumes chains eg FORWARD and POSTROUTING already exist + logger.Log(3, "creating egress gateway using nftables") postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " @@ -46,6 +47,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" } } else { + logger.Log(3, "creating egress gateway using iptables") postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " @@ -136,6 +138,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { // nftables only supported on Linux if IsNFTablesPresent() { // assumes chains eg FORWARD and POSTROUTING already exist + logger.Log(3, "deleting egress gateway using nftables") node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ; " @@ -143,6 +146,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade " } else { + logger.Log(3, "deleting egress gateway using iptables") node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " node.PostUp += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" @@ -194,6 +198,7 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { node.IngressGatewayRange = network.AddressRange if IsNFTablesPresent() { // assumes chains eg FORWARD and POSTROUTING already exist + logger.Log(3, "creating ingress gateway using nftables") postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" @@ -201,6 +206,7 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" } else { + logger.Log(3, "creating ingress gateway using iptables") postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " postUpCmd += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" diff --git a/logic/util.go b/logic/util.go index 8f94736e..61800cf9 100644 --- a/logic/util.go +++ b/logic/util.go @@ -21,7 +21,11 @@ import ( // nfTablesPresent - returns true if nftables is present, false otherwise func IsNFTablesPresent() bool { - return FileExists("/etc/nftables.conf") + var nftFound bool + + nftFound = FileExists("/etc/nftables.conf") + logger.Log(3, "nftables found:", nftFound) + return nftFound } // IsBase64 - checks if a string is in base64 format From 903a7a65c818e3aa2cd72cd1bc3f61f7a45ff160 Mon Sep 17 00:00:00 2001 From: cameronts Date: Mon, 1 Aug 2022 16:52:30 -0700 Subject: [PATCH 03/14] Fix nftFound handling in logger.Log call. --- logic/util.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/logic/util.go b/logic/util.go index 61800cf9..cc8caa5a 100644 --- a/logic/util.go +++ b/logic/util.go @@ -6,17 +6,17 @@ import ( "encoding/base64" "encoding/json" "fmt" - "math/big" - "math/rand" - "net" - "os" - "strings" - "time" - "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/ncutils" + "math/big" + "math/rand" + "net" + "os" + "strconv" + "strings" + "time" ) // nfTablesPresent - returns true if nftables is present, false otherwise @@ -24,7 +24,7 @@ func IsNFTablesPresent() bool { var nftFound bool nftFound = FileExists("/etc/nftables.conf") - logger.Log(3, "nftables found:", nftFound) + logger.Log(3, "nftables found:", strconv.FormatBool(nftFound)) return nftFound } From e6d7c956696ac8c6dac1a44187c2c3abebb2d5bb Mon Sep 17 00:00:00 2001 From: cameronts Date: Tue, 2 Aug 2022 15:01:45 -0700 Subject: [PATCH 04/14] Add netclient detection of nftables. --- logic/gateway.go | 6 ++--- logic/nodes.go | 1 + logic/util.go | 10 -------- models/node.go | 36 ++++++++++++++++++----------- netclient/functions/join.go | 10 ++++++++ netclient/ncutils/netclientutils.go | 10 ++++++++ 6 files changed, 46 insertions(+), 27 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 216a059a..19fe08ac 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -34,7 +34,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postDownCmd := "" if node.OS == "linux" { // nftables only supported on Linux - if IsNFTablesPresent() { + if node.IsNFTablesPresent == "yes" { // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating egress gateway using nftables") postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " @@ -136,7 +136,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules if node.OS == "linux" { // nftables only supported on Linux - if IsNFTablesPresent() { + if node.IsNFTablesPresent == "yes" { // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "deleting egress gateway using nftables") node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " @@ -196,7 +196,7 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { } node.IsIngressGateway = "yes" node.IngressGatewayRange = network.AddressRange - if IsNFTablesPresent() { + if node.IsNFTablesPresent == "yes" { // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating ingress gateway using nftables") postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " diff --git a/logic/nodes.go b/logic/nodes.go index 66b47be5..d5123ffe 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -427,6 +427,7 @@ func SetNodeDefaults(node *models.Node) { node.SetDefaultIngressGateway() node.SetDefaulIsPending() node.SetDefaultMTU() + node.SetDefaultNFTablesPresent() node.SetDefaultIsRelayed() node.SetDefaultIsRelay() node.SetDefaultIsDocker() diff --git a/logic/util.go b/logic/util.go index cc8caa5a..a780c373 100644 --- a/logic/util.go +++ b/logic/util.go @@ -14,20 +14,10 @@ import ( "math/rand" "net" "os" - "strconv" "strings" "time" ) -// nfTablesPresent - returns true if nftables is present, false otherwise -func IsNFTablesPresent() bool { - var nftFound bool - - nftFound = FileExists("/etc/nftables.conf") - logger.Log(3, "nftables found:", strconv.FormatBool(nftFound)) - return nftFound -} - // IsBase64 - checks if a string is in base64 format // This is used to validate public keys (make sure they're base64 encoded like all public keys should be). func IsBase64(s string) bool { diff --git a/models/node.go b/models/node.go index 6edd0199..fc242d24 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"` + IsNFTablesPresent string `json:"isnftablespresent" bson:"isnftablespresent" yaml:"isnftablespresent"` } // NodesArray - used for node sorting @@ -119,6 +120,13 @@ func (node *Node) SetDefaultMTU() { } } +// Node.SetDefaultNFTablesPresent - sets default for nftables check +func (node *Node) SetDefaultNFTablesPresent() { + if node.IsNFTablesPresent == "" { + node.IsNFTablesPresent = "no" + } +} + // Node.SetDefaulIsPending - sets ispending default func (node *Node) SetDefaulIsPending() { if node.IsPending == "" { @@ -254,7 +262,7 @@ func (node *Node) SetDefaultName() { } // Node.Fill - fills other node data into calling node data if not set on calling node -func (newNode *Node) Fill(currentNode *Node) { +func (newNode *Node) Fill(currentNode *Node) { // TODO add new field for nftables present newNode.ID = currentNode.ID if newNode.Address == "" { diff --git a/netclient/functions/join.go b/netclient/functions/join.go index 1d69fcfd..2c3aae97 100644 --- a/netclient/functions/join.go +++ b/netclient/functions/join.go @@ -114,7 +114,17 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error { if ncutils.IsFreeBSD() { cfg.Node.UDPHolePunch = "no" + cfg.Node.IsNFTablesPresent = "no" // nftables not supported by FreeBSD } + + if cfg.Node.IsNFTablesPresent == "" { + if ncutils.IsNFTablesPresent() { + cfg.Node.IsNFTablesPresent = "yes" + } else { + cfg.Node.IsNFTablesPresent = "no" + } + } + // make sure name is appropriate, if not, give blank name cfg.Node.Name = formatName(cfg.Node) cfg.Node.OS = runtime.GOOS diff --git a/netclient/ncutils/netclientutils.go b/netclient/ncutils/netclientutils.go index 72a4bb72..63b23c84 100644 --- a/netclient/ncutils/netclientutils.go +++ b/netclient/ncutils/netclientutils.go @@ -109,6 +109,16 @@ func GetWireGuard() string { return "wg" } +// IsNFTablesPresent - returns true if nftables is present, false otherwise. +// Does not consider OS, up to the caller to determine if the OS supports nftables/whether this check is valid. +func IsNFTablesPresent() bool { + var nftFound bool + + nftFound = FileExists("/etc/nftables.conf") + logger.Log(3, "nftables found:", strconv.FormatBool(nftFound)) + return nftFound +} + // IsKernel - checks if running kernel WireGuard func IsKernel() bool { //TODO From 766084d6a390c4216e4e4849369d1046b0a4b0e0 Mon Sep 17 00:00:00 2001 From: cameronts Date: Tue, 2 Aug 2022 15:58:39 -0700 Subject: [PATCH 05/14] Add check for nftables on daemon start. --- netclient/functions/mqpublish.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/netclient/functions/mqpublish.go b/netclient/functions/mqpublish.go index 4f90f2ed..425ed5ae 100644 --- a/netclient/functions/mqpublish.go +++ b/netclient/functions/mqpublish.go @@ -43,6 +43,16 @@ func checkin() { var nodeCfg config.ClientConfig nodeCfg.Network = network nodeCfg.ReadConfig() + // check for nftables present if on Linux + if ncutils.IsLinux() { + if ncutils.IsNFTablesPresent() { + nodeCfg.Node.IsNFTablesPresent = "yes" + } else { + nodeCfg.Node.IsNFTablesPresent = "no" + } + } else { + nodeCfg.Node.IsNFTablesPresent = "no" + } if nodeCfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() if err != nil { From eab23b7022040264c8ff802be906d29e983a84b3 Mon Sep 17 00:00:00 2001 From: cameronts Date: Wed, 3 Aug 2022 11:36:16 -0700 Subject: [PATCH 06/14] Modified ingress deletion handling to preserve egress gateway if present. Removed ingress from FreeBSD as not supported. --- logic/gateway.go | 56 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 19fe08ac..80a4a6ef 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -134,6 +134,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.PostUp = "" node.PostDown = "" if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules + // still have an ingress gateway so preserve it if node.OS == "linux" { // nftables only supported on Linux if node.IsNFTablesPresent == "yes" { @@ -155,12 +156,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.PostDown += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" } } - if node.OS == "freebsd" { - node.PostUp = "" - node.PostDown = "ipfw delete 64000 ; " - node.PostDown += "ipfw delete 65534 ; " - node.PostDown += "kldunload ipfw_nat ipfw" - } + // no need to preserve ingress gateway on FreeBSD as ingress is not supported on that OS } node.SetLastModified() @@ -257,12 +253,60 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error if err = DeleteGatewayExtClients(node.ID, networkName); err != nil { return models.Node{}, err } + logger.Log(3, "deleting ingress gateway") node.UDPHolePunch = network.DefaultUDPHolePunch node.LastModified = time.Now().Unix() node.IsIngressGateway = "no" node.IngressGatewayRange = "" + if node.IsEgressGateway == "yes" { // check if node is still an egress gateway before completely deleting postdown/up rules + // still have an egress gateway so preserve it + if node.OS == "linux" { + // nftables only supported on Linux + if node.IsNFTablesPresent == "yes" { + // preserve egress gateway via the setup that createegressgateway used + // assumes chains eg FORWARD and POSTROUTING already exist + logger.Log(3, "deleting ingress gateway: nftables in use") + node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostDown += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + + if node.EgressGatewayNatEnabled == "yes" { + node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" + node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" + } + } else { + // preserve egress gateway via the setup that createegressgateway used + logger.Log(3, "deleting ingress gateway: iptables in use") + node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " + node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" + node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " + node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" + + if node.EgressGatewayNatEnabled == "yes" { + node.PostUp += "; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" + node.PostDown += "; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + } + } + } + // preserve egress gateway via the setup that createegressgateway used + if node.OS == "freebsd" { + node.PostUp = "kldload ipfw ipfw_nat ; " + node.PostUp += "ipfw disable one_pass ; " + node.PostUp += "ipfw nat 1 config if " + node.Interface + " same_ports unreg_only reset ; " + node.PostUp += "ipfw add 64000 reass all from any to any in ; " + node.PostUp += "ipfw add 64000 nat 1 ip from any to any in via " + node.Interface + " ; " + node.PostUp += "ipfw add 64000 check-state ; " + node.PostUp += "ipfw add 64000 nat 1 ip from any to any out via " + node.Interface + " ; " + node.PostUp += "ipfw add 65534 allow ip from any to any ; " + node.PostDown = "ipfw delete 64000 ; " + node.PostDown += "ipfw delete 65534 ; " + node.PostDown += "kldunload ipfw_nat ipfw" + } + } + data, err := json.Marshal(&node) if err != nil { return models.Node{}, err From 7c2fce3a55835fe791ba14364709c8aa38f63e94 Mon Sep 17 00:00:00 2001 From: cameronts Date: Wed, 3 Aug 2022 12:18:04 -0700 Subject: [PATCH 07/14] Change to expandable switch-based firewall detection. --- logic/gateway.go | 67 +++++++++++++++++--------------- models/node.go | 36 +++++++++-------- netclient/functions/join.go | 8 ++-- netclient/functions/mqpublish.go | 8 ++-- 4 files changed, 64 insertions(+), 55 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 80a4a6ef..317482d9 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -33,8 +33,9 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postUpCmd := "" postDownCmd := "" if node.OS == "linux" { - // nftables only supported on Linux - if node.IsNFTablesPresent == "yes" { + switch node.FirewallInUse { + case models.FIREWALL_NFTABLES: + // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating egress gateway using nftables") postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " @@ -46,7 +47,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" } - } else { + default: // iptables assumed logger.Log(3, "creating egress gateway using iptables") postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" @@ -136,8 +137,9 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules // still have an ingress gateway so preserve it if node.OS == "linux" { - // nftables only supported on Linux - if node.IsNFTablesPresent == "yes" { + switch node.FirewallInUse { + case models.FIREWALL_NFTABLES: + // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "deleting egress gateway using nftables") node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " @@ -146,7 +148,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade " - } else { + default: logger.Log(3, "deleting egress gateway using iptables") node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " @@ -192,7 +194,9 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { } node.IsIngressGateway = "yes" node.IngressGatewayRange = network.AddressRange - if node.IsNFTablesPresent == "yes" { + switch node.FirewallInUse { + case models.FIREWALL_NFTABLES: + // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating ingress gateway using nftables") postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " @@ -201,7 +205,7 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" - } else { + default: logger.Log(3, "creating ingress gateway using iptables") postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " @@ -262,33 +266,32 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error if node.IsEgressGateway == "yes" { // check if node is still an egress gateway before completely deleting postdown/up rules // still have an egress gateway so preserve it - if node.OS == "linux" { + switch node.FirewallInUse { + case models.FIREWALL_NFTABLES: // nftables only supported on Linux - if node.IsNFTablesPresent == "yes" { - // preserve egress gateway via the setup that createegressgateway used - // assumes chains eg FORWARD and POSTROUTING already exist - logger.Log(3, "deleting ingress gateway: nftables in use") - node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - node.PostDown += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + // preserve egress gateway via the setup that createegressgateway used + // assumes chains eg FORWARD and POSTROUTING already exist + logger.Log(3, "deleting ingress gateway: nftables in use") + node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostDown += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - if node.EgressGatewayNatEnabled == "yes" { - node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" - node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" - } - } else { - // preserve egress gateway via the setup that createegressgateway used - logger.Log(3, "deleting ingress gateway: iptables in use") - node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " - node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" - node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " - node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" + if node.EgressGatewayNatEnabled == "yes" { + node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" + node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" + } + default: + // preserve egress gateway via the setup that createegressgateway used + logger.Log(3, "deleting ingress gateway: iptables in use") + node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " + node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" + node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " + node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" - if node.EgressGatewayNatEnabled == "yes" { - node.PostUp += "; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" - node.PostDown += "; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" - } + if node.EgressGatewayNatEnabled == "yes" { + node.PostUp += "; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" + node.PostDown += "; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" } } // preserve egress gateway via the setup that createegressgateway used diff --git a/models/node.go b/models/node.go index fc242d24..e0266927 100644 --- a/models/node.go +++ b/models/node.go @@ -28,6 +28,10 @@ const ( NODE_NOOP = "noop" // NODE_FORCE_UPDATE - indicates a node should pull all changes NODE_FORCE_UPDATE = "force" + // FIREWALL_IPTABLES - indicates that iptables is the firewall in use + FIREWALL_IPTABLES = "iptables" + // FIREWALL_NFTABLES - indicates nftables is in use (Linux only) + FIREWALL_NFTABLES = "nftables" ) var seededRand *rand.Rand = rand.New( @@ -71,20 +75,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"` - IsNFTablesPresent string `json:"isnftablespresent" bson:"isnftablespresent" yaml:"isnftablespresent"` + 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"` + FirewallInUse string `json:"firewallinuse" bson:"firewallinuse" yaml:"firewallinuse"` } // NodesArray - used for node sorting @@ -122,8 +126,8 @@ func (node *Node) SetDefaultMTU() { // Node.SetDefaultNFTablesPresent - sets default for nftables check func (node *Node) SetDefaultNFTablesPresent() { - if node.IsNFTablesPresent == "" { - node.IsNFTablesPresent = "no" + if node.FirewallInUse == "" { + node.FirewallInUse = FIREWALL_IPTABLES // default to iptables } } diff --git a/netclient/functions/join.go b/netclient/functions/join.go index 2c3aae97..09ca176a 100644 --- a/netclient/functions/join.go +++ b/netclient/functions/join.go @@ -114,14 +114,14 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error { if ncutils.IsFreeBSD() { cfg.Node.UDPHolePunch = "no" - cfg.Node.IsNFTablesPresent = "no" // nftables not supported by FreeBSD + cfg.Node.FirewallInUse = models.FIREWALL_IPTABLES // nftables not supported by FreeBSD } - if cfg.Node.IsNFTablesPresent == "" { + if cfg.Node.FirewallInUse == "" { if ncutils.IsNFTablesPresent() { - cfg.Node.IsNFTablesPresent = "yes" + cfg.Node.FirewallInUse = models.FIREWALL_NFTABLES } else { - cfg.Node.IsNFTablesPresent = "no" + cfg.Node.FirewallInUse = models.FIREWALL_IPTABLES } } diff --git a/netclient/functions/mqpublish.go b/netclient/functions/mqpublish.go index 425ed5ae..eaddfab8 100644 --- a/netclient/functions/mqpublish.go +++ b/netclient/functions/mqpublish.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/gravitl/netmaker/models" "net" "os" "strconv" @@ -46,12 +47,13 @@ func checkin() { // check for nftables present if on Linux if ncutils.IsLinux() { if ncutils.IsNFTablesPresent() { - nodeCfg.Node.IsNFTablesPresent = "yes" + nodeCfg.Node.FirewallInUse = models.FIREWALL_NFTABLES } else { - nodeCfg.Node.IsNFTablesPresent = "no" + nodeCfg.Node.FirewallInUse = models.FIREWALL_IPTABLES } } else { - nodeCfg.Node.IsNFTablesPresent = "no" + // defaults to iptables for now, may need another default for non-Linux OSes + nodeCfg.Node.FirewallInUse = models.FIREWALL_IPTABLES } if nodeCfg.Node.IsStatic != "yes" { extIP, err := ncutils.GetPublicIP() From 2ddbfabec754ab3cded170f6eced8af09a765f87 Mon Sep 17 00:00:00 2001 From: Christopher Blaha Date: Wed, 3 Aug 2022 23:34:22 -0400 Subject: [PATCH 08/14] rm netmaker-server.sh --- scripts/netmaker-server.sh | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 scripts/netmaker-server.sh diff --git a/scripts/netmaker-server.sh b/scripts/netmaker-server.sh deleted file mode 100644 index edd8cf10..00000000 --- a/scripts/netmaker-server.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -set -e - -mkdir -p /etc/netmaker/config/environments -wget -O /etc/netmaker/netmaker https://github.com/gravitl/netmaker/releases/download/latest/netmaker -chmod +x /etc/netmaker/netmaker - -cat >/etc/netmaker/config/environments/dev.yaml</etc/systemd/system/netmaker.service< Date: Fri, 5 Aug 2022 05:07:00 -0700 Subject: [PATCH 09/14] Added chain creation for nftables. --- controllers/config/dnsconfig/netmaker.hosts | 3 ++- logic/gateway.go | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/controllers/config/dnsconfig/netmaker.hosts b/controllers/config/dnsconfig/netmaker.hosts index 45eab425..655eaef6 100644 --- a/controllers/config/dnsconfig/netmaker.hosts +++ b/controllers/config/dnsconfig/netmaker.hosts @@ -1 +1,2 @@ -10.0.0.2 testnode.skynet myhost.skynet +10.0.0.1 testnode.skynet +10.0.0.2 myhost.skynet diff --git a/logic/gateway.go b/logic/gateway.go index 317482d9..799f1474 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -38,12 +38,18 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating egress gateway using nftables") - postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + // down commands don't remove as removal of the rules leaves an empty chain while + // removing the chain with rules in it would remove all rules in that section (not safe + // if there are remaining rules on the host that need to stay). In practice the chain is removed + // when non-empty even though the removal of a non-empty chain should not be possible per nftables wiki. + postUpCmd = "nft add chain filter FORWARD ; " + postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " if node.EgressGatewayNatEnabled == "yes" { + postUpCmd += "nft add chain filter POSTROUTING ; " postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" } @@ -142,8 +148,10 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "deleting egress gateway using nftables") - node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostUp = "nft add chain filter FORWARD ; " + node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + node.PostUp += "nft add chain filter POSTROUTING ; " node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ; " node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" @@ -199,8 +207,10 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating ingress gateway using nftables") - postUpCmd = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + postUpCmd = "nft add chain filter FORWARD ; " + postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + postUpCmd += "nft add chain filter POSTROUTING ; " postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " @@ -272,12 +282,14 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error // preserve egress gateway via the setup that createegressgateway used // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "deleting ingress gateway: nftables in use") - node.PostUp = "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " + node.PostUp = "nft add chain filter FORWARD ; " + node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " node.PostDown += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " if node.EgressGatewayNatEnabled == "yes" { + node.PostUp += "nft add chain filter POSTROUTING ; " node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" } From aeca559a8a48c53a1d9d4d68f00eade4fc48976f Mon Sep 17 00:00:00 2001 From: cameronts Date: Sat, 6 Aug 2022 15:00:20 -0700 Subject: [PATCH 10/14] Update code handling of firewall commands and add more logging. --- logic/gateway.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index 799f1474..c5306228 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -32,12 +32,13 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro node.EgressGatewayNatEnabled = gateway.NatEnabled postUpCmd := "" postDownCmd := "" + logger.Log(3, "creating egress gateway firewall in use is '", node.FirewallInUse, "'") if node.OS == "linux" { switch node.FirewallInUse { case models.FIREWALL_NFTABLES: // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist - logger.Log(3, "creating egress gateway using nftables") + logger.Log(3, "creating egress gateway nftables is present") // down commands don't remove as removal of the rules leaves an empty chain while // removing the chain with rules in it would remove all rules in that section (not safe // if there are remaining rules on the host that need to stay). In practice the chain is removed @@ -54,7 +55,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" } default: // iptables assumed - logger.Log(3, "creating egress gateway using iptables") + logger.Log(3, "creating egress gateway nftables is not present") postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " @@ -140,6 +141,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.EgressGatewayRanges = []string{} node.PostUp = "" node.PostDown = "" + logger.Log(3, "deleting egress gateway firewall in use is '", node.FirewallInUse, "'") if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules // still have an ingress gateway so preserve it if node.OS == "linux" { @@ -147,7 +149,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { case models.FIREWALL_NFTABLES: // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist - logger.Log(3, "deleting egress gateway using nftables") + logger.Log(3, "deleting egress gateway nftables is present") node.PostUp = "nft add chain filter FORWARD ; " node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " @@ -157,7 +159,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade " default: - logger.Log(3, "deleting egress gateway using iptables") + logger.Log(3, "deleting egress gateway nftables is not present") node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " node.PostUp += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" @@ -202,11 +204,12 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { } node.IsIngressGateway = "yes" node.IngressGatewayRange = network.AddressRange + logger.Log(3, "creating ingress gateway firewall in use is '", node.FirewallInUse, "'") switch node.FirewallInUse { case models.FIREWALL_NFTABLES: // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist - logger.Log(3, "creating ingress gateway using nftables") + logger.Log(3, "creating ingress gateway nftables is present") postUpCmd = "nft add chain filter FORWARD ; " postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " @@ -216,7 +219,7 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" default: - logger.Log(3, "creating ingress gateway using iptables") + logger.Log(3, "creating ingress gateway using nftables is not present") postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " postUpCmd += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" @@ -274,6 +277,10 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error node.IsIngressGateway = "no" node.IngressGatewayRange = "" + // default to removing postup and postdown + node.PostUp = "" + node.PostDown = "" + logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGatway is", node.IsEgressGateway) if node.IsEgressGateway == "yes" { // check if node is still an egress gateway before completely deleting postdown/up rules // still have an egress gateway so preserve it switch node.FirewallInUse { @@ -281,7 +288,7 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error // nftables only supported on Linux // preserve egress gateway via the setup that createegressgateway used // assumes chains eg FORWARD and POSTROUTING already exist - logger.Log(3, "deleting ingress gateway: nftables in use") + logger.Log(3, "deleting ingress gateway: nftables is in use") node.PostUp = "nft add chain filter FORWARD ; " node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " @@ -295,7 +302,7 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error } default: // preserve egress gateway via the setup that createegressgateway used - logger.Log(3, "deleting ingress gateway: iptables in use") + logger.Log(3, "deleting ingress gateway: nftables is not in use") node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " From f4d19f5606120b8651fa19c4b5df10d731614745 Mon Sep 17 00:00:00 2001 From: cameronts Date: Sat, 6 Aug 2022 15:40:40 -0700 Subject: [PATCH 11/14] Change method used for detecting nftables from looking for nftables.conf (not always there) to looking for nft executable (there upon apt install nft). --- netclient/ncutils/netclientutils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netclient/ncutils/netclientutils.go b/netclient/ncutils/netclientutils.go index 63b23c84..883fa608 100644 --- a/netclient/ncutils/netclientutils.go +++ b/netclient/ncutils/netclientutils.go @@ -114,7 +114,7 @@ func GetWireGuard() string { func IsNFTablesPresent() bool { var nftFound bool - nftFound = FileExists("/etc/nftables.conf") + nftFound = FileExists("/usr/sbin/nft") logger.Log(3, "nftables found:", strconv.FormatBool(nftFound)) return nftFound } From a6660bb377f4cb270c894cd4fde1558076a5a186 Mon Sep 17 00:00:00 2001 From: cameronts Date: Sun, 7 Aug 2022 19:22:54 -0700 Subject: [PATCH 12/14] Pull firewall command building to separate functions for easier maintenance/reuse. Change DeleteIngressGateway's approach to preserving the egress gateway (if present). --- logic/gateway.go | 180 ++++++++++++++++++++++------------------------- models/node.go | 71 ++++++++++--------- 2 files changed, 121 insertions(+), 130 deletions(-) diff --git a/logic/gateway.go b/logic/gateway.go index c5306228..6e02dc0d 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -3,6 +3,7 @@ package logic import ( "encoding/json" "errors" + "fmt" "strings" "time" @@ -30,6 +31,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro node.IsEgressGateway = "yes" node.EgressGatewayRanges = gateway.Ranges node.EgressGatewayNatEnabled = gateway.NatEnabled + node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway postUpCmd := "" postDownCmd := "" logger.Log(3, "creating egress gateway firewall in use is '", node.FirewallInUse, "'") @@ -43,28 +45,11 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro // removing the chain with rules in it would remove all rules in that section (not safe // if there are remaining rules on the host that need to stay). In practice the chain is removed // when non-empty even though the removal of a non-empty chain should not be possible per nftables wiki. - postUpCmd = "nft add chain filter FORWARD ; " - postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " + postUpCmd, postDownCmd = firewallNFTCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled) - if node.EgressGatewayNatEnabled == "yes" { - postUpCmd += "nft add chain filter POSTROUTING ; " - postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" - postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" - } default: // iptables assumed logger.Log(3, "creating egress gateway nftables is not present") - postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " - postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" - postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " - postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" - - if node.EgressGatewayNatEnabled == "yes" { - postUpCmd += "; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE" - postDownCmd += "; iptables -t nat -D POSTROUTING -o " + gateway.Interface + " -j MASQUERADE" - } + postUpCmd, postDownCmd = firewallIPTablesCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled) } } if node.OS == "freebsd" { @@ -139,8 +124,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.IsEgressGateway = "no" node.EgressGatewayRanges = []string{} - node.PostUp = "" - node.PostDown = "" + node.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone logger.Log(3, "deleting egress gateway firewall in use is '", node.FirewallInUse, "'") if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules // still have an ingress gateway so preserve it @@ -150,22 +134,10 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "deleting egress gateway nftables is present") - node.PostUp = "nft add chain filter FORWARD ; " - node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - node.PostUp += "nft add chain filter POSTROUTING ; " - node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ; " - node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" - node.PostDown += "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ;" - node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade " + node.PostUp, node.PostDown = firewallNFTCommandsCreateIngress(node.Interface) default: logger.Log(3, "deleting egress gateway nftables is not present") - node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " - node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " - node.PostUp += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" - node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; " - node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; " - node.PostDown += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + node.PostUp, node.PostDown = firewallIPTablesCommandsCreateIngress(node.Interface) } } // no need to preserve ingress gateway on FreeBSD as ingress is not supported on that OS @@ -210,22 +182,10 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) { // nftables only supported on Linux // assumes chains eg FORWARD and POSTROUTING already exist logger.Log(3, "creating ingress gateway nftables is present") - postUpCmd = "nft add chain filter FORWARD ; " - postUpCmd += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - postUpCmd += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - postUpCmd += "nft add chain filter POSTROUTING ; " - postUpCmd += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" - postDownCmd = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - postDownCmd += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - postDownCmd += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade" + postUpCmd, postDownCmd = firewallNFTCommandsCreateIngress(node.Interface) default: logger.Log(3, "creating ingress gateway using nftables is not present") - postUpCmd = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT ; " - postUpCmd += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT ; " - postUpCmd += "iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" - postDownCmd = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT ; " - postDownCmd += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT ; " - postDownCmd += "iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" + postUpCmd, postDownCmd = firewallIPTablesCommandsCreateIngress(node.Interface) } if node.PostUp != "" { @@ -280,52 +240,12 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error // default to removing postup and postdown node.PostUp = "" node.PostDown = "" - logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGatway is", node.IsEgressGateway) - if node.IsEgressGateway == "yes" { // check if node is still an egress gateway before completely deleting postdown/up rules - // still have an egress gateway so preserve it - switch node.FirewallInUse { - case models.FIREWALL_NFTABLES: - // nftables only supported on Linux - // preserve egress gateway via the setup that createegressgateway used - // assumes chains eg FORWARD and POSTROUTING already exist - logger.Log(3, "deleting ingress gateway: nftables is in use") - node.PostUp = "nft add chain filter FORWARD ; " - node.PostUp += "nft add rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - node.PostUp += "nft add rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - node.PostDown = "nft delete rule ip filter FORWARD iifname " + node.Interface + " counter accept ; " - node.PostDown += "nft delete rule ip filter FORWARD oifname " + node.Interface + " counter accept ; " - - if node.EgressGatewayNatEnabled == "yes" { - node.PostUp += "nft add chain filter POSTROUTING ; " - node.PostUp += "nft add rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" - node.PostDown += "nft delete rule ip nat POSTROUTING oifname " + node.Interface + " counter masquerade ;" - } - default: - // preserve egress gateway via the setup that createegressgateway used - logger.Log(3, "deleting ingress gateway: nftables is not in use") - node.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; " - node.PostUp += "iptables -A FORWARD -o " + node.Interface + " -j ACCEPT" - node.PostDown = "iptables -D FORWARD -i " + node.Interface + " -j ACCEPT; " - node.PostDown += "iptables -D FORWARD -o " + node.Interface + " -j ACCEPT" - - if node.EgressGatewayNatEnabled == "yes" { - node.PostUp += "; iptables -t nat -A POSTROUTING -o " + node.Interface + " -j MASQUERADE" - node.PostDown += "; iptables -t nat -D POSTROUTING -o " + node.Interface + " -j MASQUERADE" - } - } - // preserve egress gateway via the setup that createegressgateway used - if node.OS == "freebsd" { - node.PostUp = "kldload ipfw ipfw_nat ; " - node.PostUp += "ipfw disable one_pass ; " - node.PostUp += "ipfw nat 1 config if " + node.Interface + " same_ports unreg_only reset ; " - node.PostUp += "ipfw add 64000 reass all from any to any in ; " - node.PostUp += "ipfw add 64000 nat 1 ip from any to any in via " + node.Interface + " ; " - node.PostUp += "ipfw add 64000 check-state ; " - node.PostUp += "ipfw add 64000 nat 1 ip from any to any out via " + node.Interface + " ; " - node.PostUp += "ipfw add 65534 allow ip from any to any ; " - node.PostDown = "ipfw delete 64000 ; " - node.PostDown += "ipfw delete 65534 ; " - node.PostDown += "kldunload ipfw_nat ipfw" + logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGateway is", node.IsEgressGateway) + if node.EgressGatewayRequest.NodeID != "" { + _, err := CreateEgressGateway(node.EgressGatewayRequest) + if err != nil { + logger.Log(0, fmt.Sprintf("failed to create egress gateway on node [%s] on network [%s]: %v", + node.EgressGatewayRequest.NodeID, node.EgressGatewayRequest.NetID, err)) } } @@ -357,3 +277,73 @@ func DeleteGatewayExtClients(gatewayID string, networkName string) error { } return nil } + +// firewallNFTCommandsCreateIngress - used to centralize firewall command maintenance for creating an ingress gateway using the nftables firewall. +func firewallNFTCommandsCreateIngress(networkInterface string) (string, string) { + postUp := "nft add table ip filter ; " + postUp += "nft add chain ip filter FORWARD ; " + postUp += "nft add rule ip filter FORWARD iifname " + networkInterface + " counter accept ; " + postUp += "nft add rule ip filter FORWARD oifname " + networkInterface + " counter accept ; " + postUp += "nft add table nat ; " + postUp += "nft add chain nat POSTROUTING ; " + postUp += "nft add rule ip nat POSTROUTING oifname " + networkInterface + " counter masquerade" + + // doesn't remove potentially empty tables or chains + postDown := "nft delete rule ip filter FORWARD iifname " + networkInterface + " counter accept ; " + postDown += "nft delete rule ip filter FORWARD oifname " + networkInterface + " counter accept ; " + postDown += "nft delete rule ip nat POSTROUTING oifname " + networkInterface + " counter masquerade" + + return postUp, postDown +} + +// firewallNFTCommandsCreateEgress - used to centralize firewall command maintenance for creating an egress gateway using the nftables firewall. +func firewallNFTCommandsCreateEgress(networkInterface string, gatewayInterface string, egressNatEnabled string) (string, string) { + postUp := "nft add table ip filter ; " + postUp += "nft add chain ip filter FORWARD ; " + postUp += "nft add rule ip filter FORWARD iifname " + networkInterface + " counter accept ; " + postUp += "nft add rule ip filter FORWARD oifname " + networkInterface + " counter accept ; " + + postDown := "nft delete rule ip filter FORWARD iifname " + networkInterface + " counter accept ; " + postDown += "nft delete rule ip filter FORWARD oifname " + networkInterface + " counter accept ; " + + if egressNatEnabled == "yes" { + postUp += "nft add table nat ; " + postUp += "nft add chain nat POSTROUTING ; " + postUp += "nft add rule ip nat POSTROUTING oifname " + gatewayInterface + " counter masquerade ;" + + postDown += "nft delete rule ip nat POSTROUTING oifname " + gatewayInterface + " counter masquerade ;" + } + + return postUp, postDown +} + +// firewallIPTablesCommandsCreateIngress - used to centralize firewall command maintenance for creating an ingress gateway using the iptables firewall. +func firewallIPTablesCommandsCreateIngress(networkInterface string) (string, string) { + postUp := "iptables -A FORWARD -i " + networkInterface + " -j ACCEPT ; " + postUp += "iptables -A FORWARD -o " + networkInterface + " -j ACCEPT ; " + postUp += "iptables -t nat -A POSTROUTING -o " + networkInterface + " -j MASQUERADE" + + // doesn't remove potentially empty tables or chains + postDown := "iptables -D FORWARD -i " + networkInterface + " -j ACCEPT ; " + postDown += "iptables -D FORWARD -o " + networkInterface + " -j ACCEPT ; " + postDown += "iptables -t nat -D POSTROUTING -o " + networkInterface + " -j MASQUERADE" + + return postUp, postDown +} + +// firewallIPTablesCommandsCreateEgress - used to centralize firewall command maintenance for creating an egress gateway using the iptables firewall. +func firewallIPTablesCommandsCreateEgress(networkInterface string, gatewayInterface string, egressNatEnabled string) (string, string) { + + postUp := "iptables -A FORWARD -i " + networkInterface + " -j ACCEPT; " + postUp += "iptables -A FORWARD -o " + networkInterface + " -j ACCEPT" + postDown := "iptables -D FORWARD -i " + networkInterface + " -j ACCEPT; " + postDown += "iptables -D FORWARD -o " + networkInterface + " -j ACCEPT" + + if egressNatEnabled == "yes" { + postUp += "; iptables -t nat -A POSTROUTING -o " + gatewayInterface + " -j MASQUERADE" + postDown += "; iptables -t nat -D POSTROUTING -o " + gatewayInterface + " -j MASQUERADE" + } + + return postUp, postDown + +} diff --git a/models/node.go b/models/node.go index e0266927..5f84e59f 100644 --- a/models/node.go +++ b/models/node.go @@ -39,41 +39,42 @@ var seededRand *rand.Rand = rand.New( // Node - struct for node model type Node struct { - ID string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5" validate:"id_unique` - Address string `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"` - Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"` - LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"` - Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"` - NetworkSettings Network `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"` - ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"` - LocalListenPort int32 `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"` - PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"` - Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"` - PostUp string `json:"postup" bson:"postup" yaml:"postup"` - PostDown string `json:"postdown" bson:"postdown" yaml:"postdown"` - AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"` - PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"` - IsHub string `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"` - AccessKey string `json:"accesskey" bson:"accesskey" yaml:"accesskey"` - Interface string `json:"interface" bson:"interface" yaml:"interface"` - LastModified int64 `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"` - ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"` - LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"` - LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"` - MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress"` - Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"` - Network string `json:"network" bson:"network" yaml:"network" validate:"network_exists"` - IsRelayed string `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"` - IsPending string `json:"ispending" bson:"ispending" yaml:"ispending"` - IsRelay string `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"` - IsDocker string `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"` - IsK8S string `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"` - IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"` - IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"` - EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"` - EgressGatewayNatEnabled string `json:"egressgatewaynatenabled" bson:"egressgatewaynatenabled" yaml:"egressgatewaynatenabled"` - RelayAddrs []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"` - IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"` + ID string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" validate:"required,min=5" validate:"id_unique` + Address string `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"` + Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"` + LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"` + Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"` + NetworkSettings Network `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"` + ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"` + LocalListenPort int32 `json:"locallistenport" bson:"locallistenport" yaml:"locallistenport" validate:"numeric,min=0,max=65535"` + PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"` + Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"` + PostUp string `json:"postup" bson:"postup" yaml:"postup"` + PostDown string `json:"postdown" bson:"postdown" yaml:"postdown"` + AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"` + PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"` + IsHub string `json:"ishub" bson:"ishub" yaml:"ishub" validate:"checkyesorno"` + AccessKey string `json:"accesskey" bson:"accesskey" yaml:"accesskey"` + Interface string `json:"interface" bson:"interface" yaml:"interface"` + LastModified int64 `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"` + ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"` + LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"` + LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"` + MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress"` + Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"` + Network string `json:"network" bson:"network" yaml:"network" validate:"network_exists"` + IsRelayed string `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"` + IsPending string `json:"ispending" bson:"ispending" yaml:"ispending"` + IsRelay string `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"` + IsDocker string `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"` + IsK8S string `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"` + IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"` + IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"` + EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"` + EgressGatewayNatEnabled string `json:"egressgatewaynatenabled" bson:"egressgatewaynatenabled" yaml:"egressgatewaynatenabled"` + EgressGatewayRequest EgressGatewayRequest `json:"egressgatewayrequest" bson:"egressgatewayrequest" yaml:"egressgatewayrequest"` + 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"` From e190bff8076a74ed49618e83b646a4de5164e570 Mon Sep 17 00:00:00 2001 From: cameronts Date: Sun, 7 Aug 2022 20:28:10 -0700 Subject: [PATCH 13/14] Fix failing test. --- logic/gateway.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/logic/gateway.go b/logic/gateway.go index 6e02dc0d..f7944edb 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -125,6 +125,10 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node.IsEgressGateway = "no" node.EgressGatewayRanges = []string{} node.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone + // needed in case we don't preserve a gateway (i.e., no ingress to preserve) + node.PostUp = "" + node.PostDown = "" + logger.Log(3, "deleting egress gateway firewall in use is '", node.FirewallInUse, "'") if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules // still have an ingress gateway so preserve it @@ -240,6 +244,7 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, error // default to removing postup and postdown node.PostUp = "" node.PostDown = "" + logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGateway is", node.IsEgressGateway) if node.EgressGatewayRequest.NodeID != "" { _, err := CreateEgressGateway(node.EgressGatewayRequest) From 82d8d4ff1e88ab6f718a32f96cd0809f251ed43b Mon Sep 17 00:00:00 2001 From: cameronts Date: Mon, 8 Aug 2022 13:02:32 -0700 Subject: [PATCH 14/14] Rearrange imports per PR comments. --- logic/util.go | 9 +++++---- netclient/functions/mqpublish.go | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/logic/util.go b/logic/util.go index a780c373..af68afbd 100644 --- a/logic/util.go +++ b/logic/util.go @@ -6,16 +6,17 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/gravitl/netmaker/database" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/ncutils" "math/big" "math/rand" "net" "os" "strings" "time" + + "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/netclient/ncutils" ) // IsBase64 - checks if a string is in base64 format diff --git a/netclient/functions/mqpublish.go b/netclient/functions/mqpublish.go index eaddfab8..d72fc349 100644 --- a/netclient/functions/mqpublish.go +++ b/netclient/functions/mqpublish.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/gravitl/netmaker/models" "net" "os" "strconv" @@ -14,6 +13,7 @@ import ( "github.com/cloverstd/tcping/ping" "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/auth" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/ncutils"