Check ipt options before looking for ip6t

iptables package has a function `detectIptables()` called to initialize
some local variables. Since v20.10.0, it first looks for iptables bin,
then ip6tables and finally it checks what iptables flags are available
(including -C). It early exits when ip6tables isn't available, and
doesn't execute the last check.

To remove port mappings (eg. when a container stops/dies), Docker
first checks if those NAT rules exist and then deletes them. However, in
the particular case where there's no ip6tables bin available, iptables
`-C` flag is considered unavailable and thus it looks for NAT rules by
using some substring matching. This substring matching then fails
because `iptables -t nat -S POSTROUTING` dumps rules in a slighly format
than what's expected.

For instance, here's what `iptables -t nat -S POSTROUTING` dumps:

```
-A POSTROUTING -s 172.18.0.2/32 -d 172.18.0.2/32 -p tcp -m tcp --dport 9999 -j MASQUERADE
```

And here's what Docker looks for:

```
POSTROUTING -p tcp -s 172.18.0.2 -d 172.18.0.2 --dport 9999 -j MASQUERADE
```

Because of that, those rules are considered non-existant by Docker and
thus never deleted. To fix that, this change reorders the code in
`detectIptables()`.

Fixes #42127.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
This commit is contained in:
Albin Kerouanton 2021-12-06 01:03:14 +01:00
parent f6848ae321
commit af7236f85a
No known key found for this signature in database
GPG key ID: 630B8E1DCBDB1864

View file

@ -116,11 +116,7 @@ func detectIptables() {
return
}
iptablesPath = path
path, err = exec.LookPath("ip6tables")
if err != nil {
return
}
ip6tablesPath = path
supportsXlock = exec.Command(iptablesPath, "--wait", "-L", "-n").Run() == nil
mj, mn, mc, err := GetVersion()
if err != nil {
@ -128,6 +124,13 @@ func detectIptables() {
return
}
supportsCOpt = supportsCOption(mj, mn, mc)
path, err = exec.LookPath("ip6tables")
if err != nil {
return
} else {
ip6tablesPath = path
}
}
func initDependencies() {