Browse Source

add ip6table rules for gateways

Matthew R. Kasun 2 years ago
parent
commit
ea3a1933e1
4 changed files with 77 additions and 30 deletions
  1. 52 21
      logic/gateway.go
  2. 17 0
      logic/util.go
  3. 1 1
      models/node.go
  4. 7 8
      models/structs.go

+ 52 - 21
logic/gateway.go

@@ -37,6 +37,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 	node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway
 	postUpCmd := ""
 	postDownCmd := ""
+	ipv4, ipv6 := getNetworkProtocols(gateway.Ranges)
 	logger.Log(3, "creating egress gateway firewall in use is '", node.FirewallInUse, "'")
 	if node.OS == "linux" {
 		switch node.FirewallInUse {
@@ -52,7 +53,7 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, erro
 
 		default: // iptables assumed
 			logger.Log(3, "creating egress gateway nftables is not present")
-			postUpCmd, postDownCmd = firewallIPTablesCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled)
+			postUpCmd, postDownCmd = firewallIPTablesCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled, ipv4, ipv6)
 		}
 	}
 	if node.OS == "freebsd" {
@@ -180,7 +181,9 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) {
 		return models.Node{}, err
 	}
 	node.IsIngressGateway = "yes"
-	node.IngressGatewayRange = network.AddressRange
+	node.IngressGatewayRange = append(node.IngressGatewayRange, network.AddressRange)
+	node.IngressGatewayRange = append(node.IngressGatewayRange, network.AddressRange6)
+	ipv4, ipv6 = getNetworkProtocols(node.IngressGatewayRange)
 	logger.Log(3, "creating ingress gateway firewall in use is '", node.FirewallInUse, "'")
 	switch node.FirewallInUse {
 	case models.FIREWALL_NFTABLES:
@@ -190,7 +193,7 @@ func CreateIngressGateway(netid string, nodeid string) (models.Node, error) {
 		postUpCmd, postDownCmd = firewallNFTCommandsCreateIngress(node.Interface)
 	default:
 		logger.Log(3, "creating ingress gateway using nftables is not present")
-		postUpCmd, postDownCmd = firewallIPTablesCommandsCreateIngress(node.Interface)
+		postUpCmd, postDownCmd = firewallIPTablesCommandsCreateIngress(node.Interface, ipv4, ipv6)
 	}
 
 	if node.PostUp != "" {
@@ -331,33 +334,61 @@ func firewallNFTCommandsCreateEgress(networkInterface string, gatewayInterface s
 }
 
 // firewallIPTablesCommandsCreateIngress - used to centralize firewall command maintenance for creating an ingress gateway using the iptables firewall.
-func firewallIPTablesCommandsCreateIngress(networkInterface string) (string, string) {
-	// spacing around ; is important for later parsing of postup/postdown in wireguard/common.go
-	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"
+func firewallIPTablesCommandsCreateIngress(networkInterface string, ipv4, ipv6 bool) (string, string) {
+	postUp := ""
+	postDown := ""
+	if ipv4 {
+		// spacing around ; is important for later parsing of postup/postdown in wireguard/common.go
+		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"
+		// 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"
+	}
+	if ipv6 {
+		// spacing around ; is important for later parsing of postup/postdown in wireguard/common.go
+		postUp += "ip6tables -A FORWARD -i " + networkInterface + " -j ACCEPT ; "
+		postUp += "ip6tables -A FORWARD -o " + networkInterface + " -j ACCEPT ; "
+		postUp += "ip6tables -t nat -A POSTROUTING -o " + networkInterface + " -j MASQUERADE"
 
+		// doesn't remove potentially empty tables or chains
+		postDown += "ip6tables -D FORWARD -i " + networkInterface + " -j ACCEPT ; "
+		postDown += "ip6tables -D FORWARD -o " + networkInterface + " -j ACCEPT ; "
+		postDown += "ip6tables -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) {
+func firewallIPTablesCommandsCreateEgress(networkInterface string, gatewayInterface string, egressNatEnabled string, ipv4, ipv6 bool) (string, string) {
 	// spacing around ; is important for later parsing of postup/postdown in wireguard/common.go
-	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"
+	postUp := ""
+	postDown := ""
+	if ipv4 {
+		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"
+		}
 	}
+	if ipv6 {
+		postUp += "ip6tables -A FORWARD -i " + networkInterface + " -j ACCEPT ; "
+		postUp += "ip6tables -A FORWARD -o " + networkInterface + " -j ACCEPT"
+		postDown += "ip6tables -D FORWARD -i " + networkInterface + " -j ACCEPT ; "
+		postDown += "ip6tables -D FORWARD -o " + networkInterface + " -j ACCEPT"
 
+		if egressNatEnabled == "yes" {
+			postUp += " ; ip6tables -t nat -A POSTROUTING -o " + gatewayInterface + " -j MASQUERADE"
+			postDown += " ; ip6tables -t nat -D POSTROUTING -o " + gatewayInterface + " -j MASQUERADE"
+		}
+	}
 	return postUp, postDown
 
 }

+ 17 - 0
logic/util.go

@@ -169,3 +169,20 @@ func ShouldPublishPeerPorts(serverNode *models.Node) bool {
 	}
 	return false
 }
+
+func getNetworkProtocols(cidrs []string) (bool, bool) {
+	ipv4 := false
+	ipv6 := false
+	for _, cidr := range cidrs {
+		ip, _, err := net.ParseCIDR(cidr)
+		if err != nil {
+			continue
+		}
+		if ip.To4() == nil {
+			ipv6 = true
+		} else {
+			ipv4 = true
+		}
+	}
+	return ipv4, ipv6
+}

+ 1 - 1
models/node.go

@@ -76,7 +76,7 @@ type Node struct {
 	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"`
+	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"`

+ 7 - 8
models/structs.go

@@ -146,14 +146,13 @@ type ExtPeersResponse struct {
 
 // EgressGatewayRequest - egress gateway request
 type EgressGatewayRequest struct {
-	NodeID      string   `json:"nodeid" bson:"nodeid"`
-	NetID       string   `json:"netid" bson:"netid"`
-	RangeString string   `json:"rangestring" bson:"rangestring"`
-	NatEnabled  string   `json:"natenabled" bson:"natenabled"`
-	Ranges      []string `json:"ranges" bson:"ranges"`
-	Interface   string   `json:"interface" bson:"interface"`
-	PostUp      string   `json:"postup" bson:"postup"`
-	PostDown    string   `json:"postdown" bson:"postdown"`
+	NodeID     string   `json:"nodeid" bson:"nodeid"`
+	NetID      string   `json:"netid" bson:"netid"`
+	NatEnabled string   `json:"natenabled" bson:"natenabled"`
+	Ranges     []string `json:"ranges" bson:"ranges"`
+	Interface  string   `json:"interface" bson:"interface"`
+	PostUp     string   `json:"postup" bson:"postup"`
+	PostDown   string   `json:"postdown" bson:"postdown"`
 }
 
 // RelayRequest - relay request struct