diff --git a/libnetwork/resolver_unix.go b/libnetwork/resolver_unix.go index b35009ee74..f4e4ad6184 100644 --- a/libnetwork/resolver_unix.go +++ b/libnetwork/resolver_unix.go @@ -76,7 +76,7 @@ func reexecSetupResolver() { for _, rule := range rules { if iptables.RawCombinedOutputNative(rule...) != nil { - logrus.Errorf("setting up rule failed, %v", rule) + logrus.Errorf("set up rule failed, %v", rule) } } } diff --git a/libnetwork/service_linux.go b/libnetwork/service_linux.go index a97d24b59e..3d61adeb67 100644 --- a/libnetwork/service_linux.go +++ b/libnetwork/service_linux.go @@ -135,8 +135,7 @@ func (n *network) addLBBackend(ip net.IP, lb *loadBalancer) { if ep := sb.getGatewayEndpoint(); ep != nil { gwIP = ep.Iface().Address().IP } - filteredPorts := filterPortConfigs(lb.service.ingressPorts, false) - if err := programIngress(gwIP, filteredPorts, false); err != nil { + if err := programIngress(gwIP, lb.service.ingressPorts, false); err != nil { logrus.Errorf("Failed to add ingress: %v", err) return } @@ -227,8 +226,7 @@ func (n *network) rmLBBackend(ip net.IP, lb *loadBalancer, rmService bool, fullR if ep := sb.getGatewayEndpoint(); ep != nil { gwIP = ep.Iface().Address().IP } - filteredPorts := filterPortConfigs(lb.service.ingressPorts, true) - if err := programIngress(gwIP, filteredPorts, true); err != nil { + if err := programIngress(gwIP, lb.service.ingressPorts, true); err != nil { logrus.Errorf("Failed to delete ingress: %v", err) } } @@ -299,8 +297,10 @@ func filterPortConfigs(ingressPorts []*PortConfig, isDelete bool) []*PortConfig func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) error { addDelOpt := "-I" + rollbackAddDelOpt := "-D" if isDelete { addDelOpt = "-D" + rollbackAddDelOpt = "-I" } ingressMu.Lock() @@ -381,18 +381,35 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro } } - for _, iPort := range ingressPorts { + //Filter the ingress ports until port rules start to be added/deleted + filteredPorts := filterPortConfigs(ingressPorts, isDelete) + rollbackRules := make([][]string, 0, len(filteredPorts)*3) + var portErr error + defer func() { + if portErr != nil && !isDelete { + filterPortConfigs(filteredPorts, !isDelete) + for _, rule := range rollbackRules { + if err := iptables.RawCombinedOutput(rule...); err != nil { + logrus.Warnf("roll back rule failed, %v: %v", rule, err) + } + } + } + }() + + for _, iPort := range filteredPorts { if iptables.ExistChain(ingressChain, iptables.Nat) { rule := strings.Fields(fmt.Sprintf("-t nat %s %s -p %s --dport %d -j DNAT --to-destination %s:%d", addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, gwIP, iPort.PublishedPort)) - if err := iptables.RawCombinedOutput(rule...); err != nil { - errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err) + if portErr = iptables.RawCombinedOutput(rule...); portErr != nil { + errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr) if !isDelete { return fmt.Errorf("%s", errStr) } - logrus.Infof("%s", errStr) } + rollbackRule := strings.Fields(fmt.Sprintf("-t nat %s %s -p %s --dport %d -j DNAT --to-destination %s:%d", rollbackAddDelOpt, + ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, gwIP, iPort.PublishedPort)) + rollbackRules = append(rollbackRules, rollbackRule) } // Filter table rules to allow a published service to be accessible in the local node from.. @@ -400,24 +417,29 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro // 2) unmanaged containers on bridge networks rule := strings.Fields(fmt.Sprintf("%s %s -m state -p %s --sport %d --state ESTABLISHED,RELATED -j ACCEPT", addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort)) - if err := iptables.RawCombinedOutput(rule...); err != nil { - errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err) + if portErr = iptables.RawCombinedOutput(rule...); portErr != nil { + errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr) if !isDelete { return fmt.Errorf("%s", errStr) } logrus.Warnf("%s", errStr) } + rollbackRule := strings.Fields(fmt.Sprintf("%s %s -m state -p %s --sport %d --state ESTABLISHED,RELATED -j ACCEPT", rollbackAddDelOpt, + ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort)) + rollbackRules = append(rollbackRules, rollbackRule) rule = strings.Fields(fmt.Sprintf("%s %s -p %s --dport %d -j ACCEPT", addDelOpt, ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort)) - if err := iptables.RawCombinedOutput(rule...); err != nil { - errStr := fmt.Sprintf("setting up rule failed, %v: %v", rule, err) + if portErr = iptables.RawCombinedOutput(rule...); portErr != nil { + errStr := fmt.Sprintf("set up rule failed, %v: %v", rule, portErr) if !isDelete { return fmt.Errorf("%s", errStr) } - logrus.Warnf("%s", errStr) } + rollbackRule = strings.Fields(fmt.Sprintf("%s %s -p %s --dport %d -j ACCEPT", rollbackAddDelOpt, + ingressChain, strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort)) + rollbackRules = append(rollbackRules, rollbackRule) if err := plumbProxy(iPort, isDelete); err != nil { logrus.Warnf("failed to create proxy for port %d: %v", iPort.PublishedPort, err) @@ -648,7 +670,7 @@ func fwMarker() { for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { - logrus.Errorf("setting up rule failed, %v: %v", rule, err) + logrus.Errorf("set up rule failed, %v: %v", rule, err) os.Exit(8) } } @@ -735,7 +757,7 @@ func redirector() { for _, rule := range rules { if err := iptables.RawCombinedOutputNative(rule...); err != nil { - logrus.Errorf("setting up rule failed, %v: %v", rule, err) + logrus.Errorf("set up rule failed, %v: %v", rule, err) os.Exit(6) } } @@ -752,14 +774,14 @@ func redirector() { } { if !iptables.ExistsNative(iptables.Filter, "INPUT", rule...) { if err := iptables.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil { - logrus.Errorf("setting up rule failed, %v: %v", rule, err) + logrus.Errorf("set up rule failed, %v: %v", rule, err) os.Exit(7) } } rule[0] = "-s" if !iptables.ExistsNative(iptables.Filter, "OUTPUT", rule...) { if err := iptables.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil { - logrus.Errorf("setting up rule failed, %v: %v", rule, err) + logrus.Errorf("set up rule failed, %v: %v", rule, err) os.Exit(8) } }