diff --git a/logic/gateway.go b/logic/gateway.go index b36589f2..291b3013 100644 --- a/logic/gateway.go +++ b/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" + 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 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 } diff --git a/logic/util.go b/logic/util.go index af68afbd..e177cad6 100644 --- a/logic/util.go +++ b/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 +} diff --git a/models/node.go b/models/node.go index 9241116e..d0565dac 100644 --- a/models/node.go +++ b/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"` diff --git a/models/structs.go b/models/structs.go index d0ce6bb7..cde70cc0 100644 --- a/models/structs.go +++ b/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