Adds rules outside of DOCKER
chain, unlike documented
#44816
Labels
area/networking
kind/bug
Bugs are bugs. The cause may or may not be known at triage time so debugging may be needed.
status/0-triage
Description
The documentation says:
This suggests to me that all rules that docker adds are added to this
DOCKER
chain (which is jumped to from theFORWARD
chain) and the main chains would only be modified to jump to thisDOCKER
chain.However, in practice, docker also adds rules directly to the
FORWARD
chain in thefilter
table andPOSTROUTING
in thenat
table. This makes it a lot harder to apply iptables firewalling rules in addition to the rules created by docker, because it is hard to identify the docker-created rules, because reloading rules by flushing and re-adding rules also flushes the docker rules.In fact, looking at the current behavior, I really cannot see a reliable and clean way to use additional firewalling rules with docker, especially if
POSTROUTING
rules are needed.If docker would add all of its rules to its own chains (and only add simple and predictable rules to the main chains to jump to its own chains), other firewall software can be configured to not flush the docker chains and preserve the (now easy to detect) docker rules in the main chains when reloading, or duplicate these (now simple, predictable and static) jump-to-docker rules in their own config. The latter gives the third-party software even more control over ordering its rules relative to the docker-generated rules.
Another advantage of adding all docker rules to its own chains, is that it is potentially also easier for docker itself to reload its rules (since it can just flush its own chains, I'm suspecting it now has to remove its own specific rules from the main chains).
A second approach to interoperability would be to have third-party firewall software add all of its rules to the
DOCKER-USER
chain, so it can just flush and refill that chain without interfering with docker's rules. However, this chain is currently only created for theFORWARD
chain, instead of for all chains. It would be good if that would be created for all chains as well, which is requested in #40544. I believe that issue and this issue would be good to both solve, since both approaches have their own value.History
I suspect (but have not looked in the git history) that the original design might have been to put all rules in a
DOCKER
chain, and have aDOCKER-USER
chain for user rules, but perhaps later additions either did not realize this policy when adding new rules to theFORWARD
chain instead of theDOCKER
chain (or perhaps a specific ordering of rules was needed and it was easier to add rules toFORWARD
directly than creating a subchain inside theDOCKER
chain). Similarly when adding rules toPOSTROUTING
. This is just a guess, though.Implementation
To properly implement the behavior suggested by the documentation, a single
DOCKER
chain is probably not enough, since then (if all main chains jump to the singleDOCKER
chain) it is no longer possible to detect the original chain a packet came in. Currently, in thenat
table this already happens (bothPREROUTING
andOUTPUT
jump to the sameDOCKER
chain), but that is probably intentional to allow sharing rules between both chains. However, this is limits future expansion, since any rules added to theDOCKER
chain are now necessarily shared betweenPREROUTING
andOUTPUT
.Instead, it seems like docker should create multiple chains, e.g.
DOCKER-FORWARD
,DOCKER-INPUT
,DOCKER-POSTROUTING
, etc. and then insert a jump to each of these from the corresponding main chain. Inside these docker-specific chains, docker has all the freedom to add the rules it needs, including jumping to the sameDOCKER
chain to share rules between multiple chains (maybe that chain should be renamed, though) or using subchains for splitting static rules from dynamic rules to make it easier to manage rules on e.g. reload.Similarly, the
DOCKER-USER
chain should be duplicate for each main rule, e.g.DOCKER-USER-INPUT
,DOCKER-USER-FORWARD
, etc. Or maybe it could be renamed to something more explicit likeBEFORE-DOCKER-FORWARD
to make the ordering more explicit (maybe also addAFTER-DOCKER-FORWARD
for more control over ordering)?Reproduce
Install docker, show iptables rules generated (including all chain headers so you can see in which chain each rule is):
This returns (I manually removed some libvirt chains that are not relevant here):
In particular not these non-static (depends on interface names) and non-trivial rules added to the
FORWARD
chain:And this rule added to
POSTROUTING
:These are all with some docker containers running, but none of them exposing any ports on the host (so no DNAT rules are added to the
DOCKER
chain).Expected behavior
No response
docker version
docker info
Additional Info
Note that this is essentially the same issue as docker/cli#3698, which was posted to the wrong repo but never reposted after being closed there.
The text was updated successfully, but these errors were encountered: