Browse Source

Add nftables support.

cameronts 3 years ago
parent
commit
81c896b22a
2 changed files with 62 additions and 20 deletions
  1. 57 20
      logic/gateway.go
  2. 5 0
      logic/util.go

+ 57 - 20
logic/gateway.go

@@ -33,14 +33,28 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 	postUpCmd := ""
 	postUpCmd := ""
 	postDownCmd := ""
 	postDownCmd := ""
 	if node.OS == "linux" {
 	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"
-
-		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"
+		// 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 += "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" {
 	if node.OS == "freebsd" {
@@ -119,12 +133,23 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
 	node.PostDown = ""
 	node.PostDown = ""
 	if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules
 	if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules
 		if node.OS == "linux" {
 		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" {
 		if node.OS == "freebsd" {
 			node.PostUp = ""
 			node.PostUp = ""
@@ -151,6 +176,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
 // CreateIngressGateway - creates an ingress gateway
 // CreateIngressGateway - creates an ingress gateway
 func CreateIngressGateway(netid string, nodeid string) (models.Node, error) {
 func CreateIngressGateway(netid string, nodeid string) (models.Node, error) {
 
 
+	var postUpCmd, postDownCmd string
 	node, err := GetNodeByID(nodeid)
 	node, err := GetNodeByID(nodeid)
 	if node.OS != "linux" { // add in darwin later
 	if node.OS != "linux" { // add in darwin later
 		return models.Node{}, errors.New(node.OS + " is unsupported for ingress gateways")
 		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.IsIngressGateway = "yes"
 	node.IngressGatewayRange = network.AddressRange
 	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 node.PostUp != "" {
 		if !strings.Contains(node.PostUp, postUpCmd) {
 		if !strings.Contains(node.PostUp, postUpCmd) {
 			postUpCmd = node.PostUp + "; " + postUpCmd
 			postUpCmd = node.PostUp + "; " + postUpCmd

+ 5 - 0
logic/util.go

@@ -19,6 +19,11 @@ import (
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"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
 // 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).
 // This is used to validate public keys (make sure they're base64 encoded like all public keys should be).
 func IsBase64(s string) bool {
 func IsBase64(s string) bool {