From ff82f24ccb837adf12fae73069210eb7f3870a75 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 10 Jan 2020 09:10:32 -0500 Subject: [PATCH] Clean up stale egress IP iptables rules on startup --- pkg/network/node/egressip.go | 2 ++ pkg/network/node/iptables.go | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/pkg/network/node/egressip.go b/pkg/network/node/egressip.go index e0fa3666f4..79a2ded39b 100644 --- a/pkg/network/node/egressip.go +++ b/pkg/network/node/egressip.go @@ -87,6 +87,8 @@ func (eip *egressIPWatcher) Synced() { } } } + + eip.iptables.SyncEgressIPRules() } func egressIPLabel(link netlink.Link) (string, error) { diff --git a/pkg/network/node/iptables.go b/pkg/network/node/iptables.go index 2866bb89c5..93ca7ba996 100644 --- a/pkg/network/node/iptables.go +++ b/pkg/network/node/iptables.go @@ -3,7 +3,10 @@ package node import ( + "bytes" "fmt" + "regexp" + "strings" "sync" "time" @@ -288,3 +291,67 @@ func (n *NodeIPTables) DeleteEgressIPRules(egressIP, mark string) error { } return n.ipt.DeleteRule(iptables.TableFilter, iptables.Chain("OPENSHIFT-FIREWALL-ALLOW"), "-d", egressIP, "-m", "conntrack", "--ctstate", "NEW", "-j", "REJECT") } + +var masqRuleRE = regexp.MustCompile(`-A OPENSHIFT-MASQUERADE .* --to-source ([^ ]*)`) +var filterRuleRE = regexp.MustCompile(`-A OPENSHIFT-FIREWALL-ALLOW -d ([^ ]*)/32 .* -j REJECT`) + +func (n *NodeIPTables) findStaleEgressIPRules(table iptables.Table, ruleMatch *regexp.Regexp) (map[string]string, error) { + buf := bytes.NewBuffer(nil) + err := n.ipt.SaveInto(table, buf) + if err != nil { + return nil, err + } + rules := make(map[string]string) + for _, line := range strings.Split(string(buf.Bytes()), "\n") { + match := ruleMatch.FindStringSubmatch(line) + if len(match) != 2 { + continue + } + rules[match[1]] = match[0] + } + + // Delete rules matching current egress IPs + for ip := range n.egressIPs { + delete(rules, ip) + } + return rules, nil +} + +func (n *NodeIPTables) SyncEgressIPRules() { + masqRules, err := n.findStaleEgressIPRules(iptables.TableNAT, masqRuleRE) + if err != nil { + klog.Warningf("Error looking for stale egress IP iptables rules: %v", err) + } + filterRules, err := n.findStaleEgressIPRules(iptables.TableFilter, filterRuleRE) + if err != nil { + klog.Warningf("Error looking for stale egress IP iptables rules: %v", err) + } + + for ip, rule := range masqRules { + klog.V(2).Infof("Deleting iptables masquerade rule for stale egress IP %s", ip) + args := strings.Split(rule, " ") + if len(args) != 12 { + klog.Warningf("Error deleting iptables masquerade rule for stale egress IP %s: unexpected rule format %q", ip, rule) + continue + } + args = args[2:] + err := n.ipt.DeleteRule(iptables.TableNAT, iptables.Chain("OPENSHIFT-MASQUERADE"), args...) + if err != nil { + klog.Warningf("Error deleting iptables masquerade rule for stale egress IP %s: %v", ip, err) + } + } + + for ip, rule := range filterRules { + klog.V(2).Infof("Deleting iptables filter rule for stale egress IP %s", ip) + args := strings.Split(rule, " ") + if len(args) != 10 { + klog.Warningf("Error deleting iptables filter rule for stale egress IP %s: unexpected rule format %q", ip, rule) + continue + } + args = args[2:] + err := n.ipt.DeleteRule(iptables.TableFilter, iptables.Chain("OPENSHIFT-FIREWALL-ALLOW"), args...) + if err != nil { + klog.Warningf("Error deleting iptables filter rule for stale egress IP %s: %v", ip, err) + } + } +}