From fc8f0423726df80f93044d65f67ec870d057217a Mon Sep 17 00:00:00 2001 From: Christophe Guillon Date: Mon, 1 Oct 2018 17:25:05 +0200 Subject: [PATCH] Fix bridge connection reset due to invalid packets Add drop of conntrack INVALID packets in input such that invalid packets due to TCP window overflow do not cause a connection reset. Due to some netfilter/conntrack limitations, invalid packets are never treated as NAT'ed but reassigned to the host and considered martians. This causes a RST response from the host and resets the connection. As soon as NAT is setup, for bridge networks for instance, invalid packets have to be dropped in input. The implementation adds a generic DOCKER-INPUT chain prefilled with a rule for dropping invalid packets and a return rule. As soon as some bridge network is setup, the DOCKER-INPUT chain call is inserted in the filter table INPUT chain. Fixes #1090. Signed-off-by: Christophe Guillon --- drivers/bridge/setup_ip_tables.go | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/bridge/setup_ip_tables.go b/drivers/bridge/setup_ip_tables.go index 5865a18f18..764960fa46 100644 --- a/drivers/bridge/setup_ip_tables.go +++ b/drivers/bridge/setup_ip_tables.go @@ -12,7 +12,8 @@ import ( // DockerChain: DOCKER iptable chain name const ( - DockerChain = "DOCKER" + DockerChain = "DOCKER" + DockerInputChain = "DOCKER-INPUT" // Isolation between bridge networks is achieved in two stages by means // of the following two chains in the filter table. The first chain matches // on the source interface being a bridge network's bridge and the @@ -58,6 +59,18 @@ func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainI } }() + _, err = iptables.NewChain(DockerInputChain, iptables.Filter, false) + if err != nil { + return nil, nil, nil, nil, fmt.Errorf("failed to create INPUT chain %s: %v", DockerInputChain, err) + } + defer func() { + if err != nil { + if err := iptables.RemoveExistingChain(DockerInputChain, iptables.Filter); err != nil { + logrus.Warnf("failed on removing iptables INPUT chain %s on cleanup: %v", DockerInputChain, err) + } + } + }() + isolationChain1, err := iptables.NewChain(IsolationChain1, iptables.Filter, false) if err != nil { return nil, nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err) @@ -82,6 +95,10 @@ func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainI } }() + if err := iptables.AddReturnRule(DockerInputChain); err != nil { + return nil, nil, nil, nil, err + } + if err := iptables.AddReturnRule(IsolationChain1); err != nil { return nil, nil, nil, nil, err } @@ -90,6 +107,10 @@ func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainI return nil, nil, nil, nil, err } + if err := iptables.ProgramRule(iptables.Filter, DockerInputChain, iptables.Insert, []string{"-m", "conntrack", "--ctstate", "INVALID", "-j", "DROP"}); err != nil { + return nil, nil, nil, nil, err + } + return natChain, filterChain, isolationChain1, isolationChain2, nil } @@ -149,6 +170,13 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt n.portMapper.SetIptablesChain(natChain, n.getNetworkBridgeName()) } + d.Lock() + err = iptables.EnsureJumpRule("INPUT", DockerInputChain) + d.Unlock() + if err != nil { + return err + } + d.Lock() err = iptables.EnsureJumpRule("FORWARD", IsolationChain1) d.Unlock() @@ -321,10 +349,14 @@ func removeIPChains() { // Remove obsolete rules from default chains iptables.ProgramRule(iptables.Filter, "FORWARD", iptables.Delete, []string{"-j", oldIsolationChain}) + // Remove possibly installed references to chains + iptables.ProgramRule(iptables.Filter, "INPUT", iptables.Delete, []string{"-j", DockerInputChain}) + // Remove chains for _, chainInfo := range []iptables.ChainInfo{ {Name: DockerChain, Table: iptables.Nat}, {Name: DockerChain, Table: iptables.Filter}, + {Name: DockerInputChain, Table: iptables.Filter}, {Name: IsolationChain1, Table: iptables.Filter}, {Name: IsolationChain2, Table: iptables.Filter}, {Name: oldIsolationChain, Table: iptables.Filter},