From cb610cbaa0a5ae1b047ec0f64f8b15b35df61ef3 Mon Sep 17 00:00:00 2001 From: davidefalcone1 Date: Mon, 28 Jun 2021 18:17:18 +0200 Subject: [PATCH] Fixed some issues regarding ExternalCIDR traffic This PR adds ExternalCIDR network to WireGuard configuration (allowedIPs, the networks allowed to enter into a wg tunnel) and modifies the iptables module to allow the traffic toward ExternalCIDR of a remote cluster to correctly trigger the right SNAT rule. --- pkg/liqonet/iptables/iptables.go | 5 ++- pkg/liqonet/iptables/iptables_test.go | 55 ++++++++------------------ pkg/liqonet/tunnel/wireguard/driver.go | 33 +++++++++------- 3 files changed, 38 insertions(+), 55 deletions(-) diff --git a/pkg/liqonet/iptables/iptables.go b/pkg/liqonet/iptables/iptables.go index 3cd33d41ed..cfd1d6e067 100644 --- a/pkg/liqonet/iptables/iptables.go +++ b/pkg/liqonet/iptables/iptables.go @@ -707,7 +707,7 @@ func getChainRulesPerCluster(tep *netv1alpha1.TunnelEndpoint) (map[string][]IPTa } clusterID := tep.Spec.ClusterID localRemappedPodCIDR, remotePodCIDR := utils.GetPodCIDRS(tep) - localRemappedExternalCIDR, _ := utils.GetExternalCIDRS(tep) + localRemappedExternalCIDR, remoteExternalCIDR := utils.GetExternalCIDRS(tep) // Init chain rules chainRules := make(map[string][]IPTableRule) @@ -719,7 +719,8 @@ func getChainRulesPerCluster(tep *netv1alpha1.TunnelEndpoint) (map[string][]IPTa // For these rules, source in not necessary since // the remotePodCIDR is unique in home cluster chainRules[liqonetPostroutingChain] = append(chainRules[liqonetPostroutingChain], - IPTableRule{"-d", remotePodCIDR, "-j", getClusterPostRoutingChain(clusterID)}) + IPTableRule{"-d", remotePodCIDR, "-j", getClusterPostRoutingChain(clusterID)}, + IPTableRule{"-d", remoteExternalCIDR, "-j", getClusterPostRoutingChain(clusterID)}) chainRules[liqonetInputChain] = append(chainRules[liqonetInputChain], IPTableRule{"-d", remotePodCIDR, "-j", getClusterInputChain(clusterID)}) chainRules[liqonetForwardingChain] = append(chainRules[liqonetForwardingChain], diff --git a/pkg/liqonet/iptables/iptables_test.go b/pkg/liqonet/iptables/iptables_test.go index 1e98c9ab64..70b5156f54 100644 --- a/pkg/liqonet/iptables/iptables_test.go +++ b/pkg/liqonet/iptables/iptables_test.go @@ -149,13 +149,15 @@ var _ = Describe("iptables", func() { // Check existence of rule in LIQO-POSTROUTING chain postRoutingRules, err := h.ListRulesInChain(liqonetPostroutingChain) - expectedRule := fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, getClusterPostRoutingChain(tep.Spec.ClusterID)) - Expect(expectedRule).To(Equal(postRoutingRules[0])) + expectedRules := []string{ + fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, getClusterPostRoutingChain(tep.Spec.ClusterID)), + fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATExternalCIDR, getClusterPostRoutingChain(tep.Spec.ClusterID))} + Expect(postRoutingRules).To(ContainElements(expectedRules)) // Check existence of rules in LIQO-PREROUTING chain // Rule for NAT-ting the PodCIDR should not be present preRoutingRules, err := h.ListRulesInChain(liqonetPreroutingChain) - expectedRule = fmt.Sprintf("-s %s -d %s -j %s", tep.Status.RemoteNATPodCIDR, tep.Status.LocalNATExternalCIDR, + expectedRule := fmt.Sprintf("-s %s -d %s -j %s", tep.Status.RemoteNATPodCIDR, tep.Status.LocalNATExternalCIDR, getClusterPreRoutingMappingChain(tep.Spec.ClusterID)) Expect(expectedRule).To(Equal(preRoutingRules[0])) @@ -180,12 +182,14 @@ var _ = Describe("iptables", func() { // Check existence of rule in LIQO-PREROUTING chain postRoutingRules, err := h.ListRulesInChain(liqonetPostroutingChain) - expectedRule := fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, getClusterPostRoutingChain(tep.Spec.ClusterID)) - Expect(expectedRule).To(Equal(postRoutingRules[0])) + expectedRules := []string{ + fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, getClusterPostRoutingChain(tep.Spec.ClusterID)), + fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATExternalCIDR, getClusterPostRoutingChain(tep.Spec.ClusterID))} + Expect(postRoutingRules).To(ContainElements(expectedRules)) // Check existence of rule in LIQO-FORWARD chain forwardRules, err := h.ListRulesInChain(liqonetForwardingChain) - expectedRule = fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, getClusterForwardChain(tep.Spec.ClusterID)) + expectedRule := fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, getClusterForwardChain(tep.Spec.ClusterID)) Expect(expectedRule).To(Equal(forwardRules[0])) // Check existence of rule in LIQO-INPUT chain @@ -195,7 +199,7 @@ var _ = Describe("iptables", func() { // Check existence of rule in LIQO-PREROUTING chain preRoutingRules, err := h.ListRulesInChain(liqonetPreroutingChain) - expectedRules := []string{ + expectedRules = []string{ fmt.Sprintf("-s %s -d %s -j %s", tep.Status.RemoteNATPodCIDR, tep.Status.LocalNATPodCIDR, getClusterPreRoutingChain(tep.Spec.ClusterID)), fmt.Sprintf("-s %s -d %s -j %s", tep.Status.RemoteNATPodCIDR, tep.Status.LocalNATExternalCIDR, @@ -267,37 +271,12 @@ var _ = Describe("iptables", func() { Expect(err).To(BeNil()) newPostRoutingRules, err := h.ListRulesInChain(liqonetPostroutingChain) - // Check if new rule has been added. - expectedRule := fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, clusterPostRoutingChain) - Expect(expectedRule).To(Equal(newPostRoutingRules[0])) - - // Check if outdated rule has been removed - Expect(newPostRoutingRules).ToNot(ContainElement(outdatedRule)) - }) - }) - - Context("If there are already some rules in chains but they are not in new rules", func() { - It(`should remove existing rules that are not in the set of new rules and add new rules`, func() { - err := h.EnsureChainRulesPerCluster(tep) - Expect(err).To(BeNil()) - - clusterPostRoutingChain := strings.Join([]string{liqonetPostroutingClusterChainPrefix, strings.Split(tep.Spec.ClusterID, "-")[0]}, "") - - // Get rule that will be removed - postRoutingRules, err := h.ListRulesInChain(liqonetPostroutingChain) - outdatedRule := postRoutingRules[0] - - // Modify resource - tep.Status.RemoteNATPodCIDR = remoteNATPodCIDRValue - - // Second call - err = h.EnsureChainRulesPerCluster(tep) - Expect(err).To(BeNil()) - newPostRoutingRules, err := h.ListRulesInChain(liqonetPostroutingChain) - - // Check if new rule has been added. - expectedRule := fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, clusterPostRoutingChain) - Expect(expectedRule).To(Equal(newPostRoutingRules[0])) + // Check if new rules has been added. + expectedRules := []string{ + fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATPodCIDR, clusterPostRoutingChain), + fmt.Sprintf("-d %s -j %s", tep.Status.RemoteNATExternalCIDR, clusterPostRoutingChain), + } + Expect(newPostRoutingRules).To(ContainElements(expectedRules)) // Check if outdated rule has been removed Expect(newPostRoutingRules).ToNot(ContainElement(outdatedRule)) diff --git a/pkg/liqonet/tunnel/wireguard/driver.go b/pkg/liqonet/tunnel/wireguard/driver.go index 70e9ecceae..fd0486a9e1 100644 --- a/pkg/liqonet/tunnel/wireguard/driver.go +++ b/pkg/liqonet/tunnel/wireguard/driver.go @@ -24,6 +24,7 @@ import ( netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1" "github.com/liqotech/liqo/pkg/liqonet/tunnel" + "github.com/liqotech/liqo/pkg/liqonet/utils" ) const ( @@ -144,7 +145,7 @@ func (w *Wireguard) Init() error { // ConnectToEndpoint connects to a remote cluster described by the given tep. func (w *Wireguard) ConnectToEndpoint(tep *netv1alpha1.TunnelEndpoint) (*netv1alpha1.Connection, error) { // parse allowed IPs. - allowedIPs, err := getAllowedIPs(tep) + allowedIPs, stringAllowedIPs, err := getAllowedIPs(tep) if err != nil { return newConnectionOnError(err.Error()), err } @@ -165,7 +166,7 @@ func (w *Wireguard) ConnectToEndpoint(tep *netv1alpha1.TunnelEndpoint) (*netv1al oldCon, found := w.connections[tep.Spec.ClusterID] if found { // check if the peer configuration is updated. - if allowedIPs.String() == oldCon.PeerConfiguration[AllowedIPs] && remoteKey.String() == oldCon.PeerConfiguration[PublicKey] && + if stringAllowedIPs == oldCon.PeerConfiguration[AllowedIPs] && remoteKey.String() == oldCon.PeerConfiguration[PublicKey] && endpoint.IP.String() == oldCon.PeerConfiguration[EndpointIP] && strconv.Itoa(endpoint.Port) == oldCon.PeerConfiguration[ListeningPort] { return oldCon, nil } @@ -193,7 +194,7 @@ func (w *Wireguard) ConnectToEndpoint(tep *netv1alpha1.TunnelEndpoint) (*netv1al Endpoint: endpoint, PersistentKeepaliveInterval: &ka, ReplaceAllowedIPs: true, - AllowedIPs: []net.IPNet{*allowedIPs}, + AllowedIPs: allowedIPs, }} err = w.client.ConfigureDevice(DeviceName, wgtypes.Config{ @@ -208,7 +209,7 @@ func (w *Wireguard) ConnectToEndpoint(tep *netv1alpha1.TunnelEndpoint) (*netv1al Status: netv1alpha1.Connected, StatusMessage: "Cluster peer connected", PeerConfiguration: map[string]string{ListeningPort: strconv.Itoa(endpoint.Port), EndpointIP: endpoint.IP.String(), - AllowedIPs: allowedIPs.String(), PublicKey: remoteKey.String()}, + AllowedIPs: stringAllowedIPs, PublicKey: remoteKey.String()}, } w.connections[tep.Spec.ClusterID] = c klog.V(4).Infof("Done connecting cluster peer %s@%s", tep.Spec.ClusterID, endpoint.String()) @@ -314,20 +315,22 @@ func (w *Wireguard) setWGLink() error { return nil } -func getAllowedIPs(tep *netv1alpha1.TunnelEndpoint) (*net.IPNet, error) { - var remoteSubnet string - // check if the remote podCIDR has been remapped. - if tep.Status.RemoteNATPodCIDR != "None" { - remoteSubnet = tep.Status.RemoteNATPodCIDR - } else { - remoteSubnet = tep.Spec.PodCIDR - } +// Function that receives a TunnelEndpoint resource and extracts +// wireguard allowedIPs. They are returned as []net.IPNet and +// as a string (to accommodate comparison/storing on TEP resource). +func getAllowedIPs(tep *netv1alpha1.TunnelEndpoint) ([]net.IPNet, string, error) { + _, remotePodCIDR := utils.GetPodCIDRS(tep) + _, remoteExternalCIDR := utils.GetExternalCIDRS(tep) - _, cidr, err := net.ParseCIDR(remoteSubnet) + _, podCIDR, err := net.ParseCIDR(remotePodCIDR) + if err != nil { + return nil, "", fmt.Errorf("unable to parse podCIDR %s for cluster %s: %w", remotePodCIDR, tep.Spec.ClusterID, err) + } + _, externalCIDR, err := net.ParseCIDR(remoteExternalCIDR) if err != nil { - return nil, fmt.Errorf("unable to parse podCIDR %s for cluster %s: %w", remoteSubnet, tep.Spec.ClusterID, err) + return nil, "", fmt.Errorf("unable to parse externalCIDR %s for cluster %s: %w", remoteExternalCIDR, tep.Spec.ClusterID, err) } - return cidr, nil + return []net.IPNet{*podCIDR, *externalCIDR}, fmt.Sprintf("%s,%s", remotePodCIDR, remoteExternalCIDR), nil } func getKey(tep *netv1alpha1.TunnelEndpoint) (*wgtypes.Key, error) {