Don't use ipset

Commit 0546d90 introduced the use of ipset to reduce the number
of rules that need to be processed per-packet, and make the code
a bit simpler.

But, docker's used on embedded kernels compiled without support
for ipset, so the change is too disruptive.

Replace the two ipset rules with a new chain that writes out the
rule's actions long-hand. So ..

This rule:
  -A FORWARD -m set --match-set docker-ext-bridges-v4 dst \
    -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
Is transformed into a per-bridge rule in new chain DOCKER-CT:
  -A DOCKER-FORWARD -j DOCKER-CT
  -A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
  -A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

And:
  -A FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER
Is transformed into a per-bridge rule in new chain DOCKER-BRIDGE:
  -A DOCKER-FORWARD -j DOCKER-BRIDGE
  -A DOCKER-BRIDGE -o docker0 -j DOCKER
  -A DOCKER-BRIDGE -o bridge1 -j DOCKER

Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
Rob Murray
2025-02-24 11:43:00 +00:00
parent 05104991bc
commit 76417bf763
24 changed files with 308 additions and 195 deletions

View File

@@ -20,11 +20,19 @@ Table `filter`:
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-1 (1 references) Chain DOCKER-ISOLATION-STAGE-1 (1 references)
@@ -47,6 +55,8 @@ Table `filter`:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -54,9 +64,11 @@ Table `filter`:
-A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-FORWARD -A FORWARD -j DOCKER-FORWARD
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
@@ -75,7 +87,7 @@ The FORWARD chain's policy shown above is ACCEPT. However:
[1]: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/libnetwork/drivers/bridge/setup_ip_forwarding.go#L44 [1]: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/libnetwork/drivers/bridge/setup_ip_forwarding.go#L44
The FORWARD chain rules are numbered in the output above, they are: The FORWARD chain rules, explained in the order they appear in the output above, are:
1. Unconditional jump to DOCKER-USER. 1. Unconditional jump to DOCKER-USER.
This is set up by libnetwork, in [setupUserChain][10]. This is set up by libnetwork, in [setupUserChain][10].
@@ -91,24 +103,27 @@ the DOCKER-USER chain, for rules that run before DOCKER's).
The DOCKER-FORWARD chain contains the first stage of Docker's filter rules. Initial The DOCKER-FORWARD chain contains the first stage of Docker's filter rules. Initial
rules are inserted at the top of the table, then not touched. Per-network rules rules are inserted at the top of the table, then not touched. Per-network rules
are appended. are appended. The DOCKER-FORWARD chain rules, explained in the order they appear in
the output above, are:
1. Early ACCEPT for any RELATED,ESTABLISHED traffic to a docker bridge. This rule 1. Unconditional jump to DOCKER-CT.
matches against an `ipset` called `docker-ext-bridges-v4` (`v6` for IPv6). The Created during driver initialisation, in `setupIPChains`.
set contains the CIDR address of each docker network, and it is updated as networks
are created and deleted. This rule is created during driver initialisation, in
`setupIPChains`.
2. Unconditional jump to DOCKER-ISOLATION-STAGE-1. 2. Unconditional jump to DOCKER-ISOLATION-STAGE-1.
Also created during driver initialisation, in `setupIPChains`. Also created during driver initialisation, in `setupIPChains`.
3. Jump to DOCKER, for any packet destined for any bridge network, identified by 3. Unconditional jump to DOCKER-BRIDGE.
matching against the `docker-ext-bridge-v[46]` set.
Also created during driver initialisation, in `setupIPChains`. Also created during driver initialisation, in `setupIPChains`.
The DOCKER chain implements per-port/protocol filtering for each container.
4. ACCEPT any packet leaving a network, set up when the network is created, in 4. ACCEPT any packet leaving a network, set up when the network is created, in
`setupIPTablesInternal`. Note that this accepts any packet leaving the `setupIPTablesInternal`. Note that this accepts any packet leaving the
network that's made it through the DOCKER and isolation chains, whether the network that's made it through the DOCKER and isolation chains, whether the
destination is external or another network. destination is external or another network.
The DOCKER-CT chain is an early ACCEPT for any RELATED,ESTABLISHED traffic to a
docker bridge. It contains a conntrack ACCEPT rule for each bridge network.
DOCKER-BRIDGE has a rule for each bridge network, to jump to the DOCKER chain.
The DOCKER chain implements per-port/protocol filtering for each container.
[10]: https://github.com/moby/moby/blob/e05848c0025b67a16aaafa8cdff95d5e2c064105/libnetwork/firewall_linux.go#L50 [10]: https://github.com/moby/moby/blob/e05848c0025b67a16aaafa8cdff95d5e2c064105/libnetwork/firewall_linux.go#L50
[11]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L230-L232 [11]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L230-L232
[12]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L227-L229 [12]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L227-L229

View File

@@ -18,16 +18,26 @@ The filter table is:
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DROP 0 -- !docker_gwbridge docker_gwbridge 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker_gwbridge docker_gwbridge 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * docker_gwbridge 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * docker_gwbridge 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 DROP 0 -- docker_gwbridge docker_gwbridge 0.0.0.0/0 0.0.0.0/0 5 0 0 DROP 0 -- docker_gwbridge docker_gwbridge 0.0.0.0/0 0.0.0.0/0
6 0 0 ACCEPT 0 -- docker_gwbridge !docker_gwbridge 0.0.0.0/0 0.0.0.0/0 6 0 0 ACCEPT 0 -- docker_gwbridge !docker_gwbridge 0.0.0.0/0 0.0.0.0/0
@@ -60,6 +70,8 @@ The filter table is:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-INGRESS -N DOCKER-INGRESS
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
@@ -70,9 +82,13 @@ The filter table is:
-A FORWARD -j DOCKER-FORWARD -A FORWARD -j DOCKER-FORWARD
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i docker_gwbridge -o docker_gwbridge -j DROP -A DOCKER ! -i docker_gwbridge -o docker_gwbridge -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o docker_gwbridge -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o docker_gwbridge -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i docker_gwbridge -o docker_gwbridge -j DROP -A DOCKER-FORWARD -i docker_gwbridge -o docker_gwbridge -j DROP
-A DOCKER-FORWARD -i docker_gwbridge ! -o docker_gwbridge -j ACCEPT -A DOCKER-FORWARD -i docker_gwbridge ! -o docker_gwbridge -j ACCEPT

View File

@@ -35,11 +35,19 @@ The filter table is updated as follows:
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 ACCEPT 0 -- bridgeICC bridgeICC 0.0.0.0/0 0.0.0.0/0 5 0 0 ACCEPT 0 -- bridgeICC bridgeICC 0.0.0.0/0 0.0.0.0/0
6 0 0 DROP 0 -- bridgeNoICC bridgeNoICC 0.0.0.0/0 0.0.0.0/0 6 0 0 DROP 0 -- bridgeNoICC bridgeNoICC 0.0.0.0/0 0.0.0.0/0
@@ -68,6 +76,8 @@ The filter table is updated as follows:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -75,9 +85,11 @@ The filter table is updated as follows:
-A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-FORWARD -A FORWARD -j DOCKER-FORWARD
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridgeICC -o bridgeICC -j ACCEPT -A DOCKER-FORWARD -i bridgeICC -o bridgeICC -j ACCEPT
-A DOCKER-FORWARD -i bridgeNoICC -o bridgeNoICC -j DROP -A DOCKER-FORWARD -i bridgeNoICC -o bridgeNoICC -j DROP

View File

@@ -23,17 +23,27 @@ The filter and nat tables are identical to [nat mode][0]:
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80 1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80
2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0 5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0
@@ -56,6 +66,8 @@ The filter and nat tables are identical to [nat mode][0]:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -65,9 +77,13 @@ The filter and nat tables are identical to [nat mode][0]:
-A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT -A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i bridge1 -o bridge1 -j DROP -A DOCKER ! -i bridge1 -o bridge1 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o bridge1 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridge1 -j ACCEPT -A DOCKER-FORWARD -i bridge1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2

View File

@@ -21,16 +21,26 @@ The filter table is:
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 1 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 ACCEPT 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 2 0 0 ACCEPT 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0 5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0
@@ -56,6 +66,8 @@ The filter table is:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -64,9 +76,13 @@ The filter table is:
-A FORWARD -j DOCKER-FORWARD -A FORWARD -j DOCKER-FORWARD
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i bridge1 -o bridge1 -j ACCEPT -A DOCKER ! -i bridge1 -o bridge1 -j ACCEPT
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o bridge1 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridge1 -j ACCEPT -A DOCKER-FORWARD -i bridge1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2

View File

@@ -21,17 +21,27 @@ The filter table is:
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80 1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80
2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 DROP 0 -- bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 5 0 0 DROP 0 -- bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
6 0 0 ACCEPT 0 -- bridge1 !bridge1 0.0.0.0/0 0.0.0.0/0 6 0 0 ACCEPT 0 -- bridge1 !bridge1 0.0.0.0/0 0.0.0.0/0
@@ -58,6 +68,8 @@ The filter table is:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -67,9 +79,13 @@ The filter table is:
-A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT -A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i bridge1 -o bridge1 -j DROP -A DOCKER ! -i bridge1 -o bridge1 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o bridge1 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridge1 -o bridge1 -j DROP -A DOCKER-FORWARD -i bridge1 -o bridge1 -j DROP
-A DOCKER-FORWARD -i bridge1 ! -o bridge1 -j ACCEPT -A DOCKER-FORWARD -i bridge1 ! -o bridge1 -j ACCEPT
@@ -84,7 +100,7 @@ The filter table is:
By comparison with [ICC=true][1]: By comparison with [ICC=true][1]:
- Rules 6 and 7 replace the accept rule for outgoing packets. - DOCKER-FORWARD rules 6 and 7 replace the accept rule for outgoing packets.
- Rule 6, added by `setIcc`, drops any packet sent from the internal network to itself. - Rule 6, added by `setIcc`, drops any packet sent from the internal network to itself.
- Rule 7, added by `setupIPTablesInternal` accepts any other outgoing packet. - Rule 7, added by `setupIPTablesInternal` accepts any other outgoing packet.

View File

@@ -24,17 +24,27 @@ The filter table is the same as with the userland proxy enabled.
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80 1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80
2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0 5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0
@@ -57,6 +67,8 @@ The filter table is the same as with the userland proxy enabled.
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -66,9 +78,13 @@ The filter table is the same as with the userland proxy enabled.
-A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT -A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i bridge1 -o bridge1 -j DROP -A DOCKER ! -i bridge1 -o bridge1 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o bridge1 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridge1 -j ACCEPT -A DOCKER-FORWARD -i bridge1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2

View File

@@ -21,18 +21,28 @@ The filter table is:
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80 1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80
2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
3 0 0 ACCEPT 1 -- * bridge1 0.0.0.0/0 0.0.0.0/0 3 0 0 ACCEPT 1 -- * bridge1 0.0.0.0/0 0.0.0.0/0
4 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 4 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0 5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0
@@ -60,6 +70,8 @@ The filter table is:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -70,9 +82,13 @@ The filter table is:
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER -o bridge1 -p icmp -j ACCEPT -A DOCKER -o bridge1 -p icmp -j ACCEPT
-A DOCKER ! -i bridge1 -o bridge1 -j DROP -A DOCKER ! -i bridge1 -o bridge1 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o bridge1 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridge1 -j ACCEPT -A DOCKER-FORWARD -i bridge1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-ISOLATION-STAGE-1 -i bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
@@ -115,7 +131,7 @@ needed._
The ICMP rule, as shown by `iptables -L`, looks alarming until you spot that it's The ICMP rule, as shown by `iptables -L`, looks alarming until you spot that it's
for `prot 1`: for `prot 1`:
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80 1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80
2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0

View File

@@ -20,17 +20,27 @@ The filter table is updated as follows:
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references) Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80 1 0 0 ACCEPT 6 -- !bridge1 bridge1 0.0.0.0/0 192.0.2.2 tcp dpt:80
2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP 0 -- !docker0 docker0 0.0.0.0/0 0.0.0.0/0
3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0 3 0 0 DROP 0 -- !bridge1 bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-BRIDGE (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DOCKER 0 -- * docker0 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-CT (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
2 0 0 ACCEPT 0 -- * bridge1 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
Chain DOCKER-FORWARD (1 references) Chain DOCKER-FORWARD (1 references)
num pkts bytes target prot opt in out source destination num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst ctstate RELATED,ESTABLISHED 1 0 0 DOCKER-CT 0 -- * * 0.0.0.0/0 0.0.0.0/0
2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0 2 0 0 DOCKER-ISOLATION-STAGE-1 0 -- * * 0.0.0.0/0 0.0.0.0/0
3 0 0 DOCKER 0 -- * * 0.0.0.0/0 0.0.0.0/0 match-set docker-ext-bridges-v4 dst 3 0 0 DOCKER-BRIDGE 0 -- * * 0.0.0.0/0 0.0.0.0/0
4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0 4 0 0 ACCEPT 0 -- docker0 * 0.0.0.0/0 0.0.0.0/0
5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0 5 0 0 ACCEPT 0 -- bridge1 * 0.0.0.0/0 0.0.0.0/0
@@ -56,6 +66,8 @@ The filter table is updated as follows:
-P FORWARD ACCEPT -P FORWARD ACCEPT
-P OUTPUT ACCEPT -P OUTPUT ACCEPT
-N DOCKER -N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD -N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2 -N DOCKER-ISOLATION-STAGE-2
@@ -65,9 +77,13 @@ The filter table is updated as follows:
-A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT -A DOCKER -d 192.0.2.2/32 ! -i bridge1 -o bridge1 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i bridge1 -o bridge1 -j DROP -A DOCKER ! -i bridge1 -o bridge1 -j DROP
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o bridge1 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o bridge1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i bridge1 -j ACCEPT -A DOCKER-FORWARD -i bridge1 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
@@ -83,6 +99,7 @@ Note that:
- In the DOCKER-FORWARD chain, rule 5 for outgoing traffic from the new network has been - In the DOCKER-FORWARD chain, rule 5 for outgoing traffic from the new network has been
appended to the end of the chain. appended to the end of the chain.
- The DOCKER-CT and DOCKER-FORWARD chains each have a rule for the new network.
- In the DOCKER-ISOLATION chains, rules equivalent to the docker0 rules have - In the DOCKER-ISOLATION chains, rules equivalent to the docker0 rules have
also been inserted for the new bridge. also been inserted for the new bridge.
- In the DOCKER chain, there is an ACCEPT rule for TCP port 80 packets routed - In the DOCKER chain, there is an ACCEPT rule for TCP port 80 packets routed

View File

@@ -24,7 +24,7 @@ The FORWARD chain's policy shown above is ACCEPT. However:
[1]: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/libnetwork/drivers/bridge/setup_ip_forwarding.go#L44 [1]: https://github.com/moby/moby/blob/cff4f20c44a3a7c882ed73934dec6a77246c6323/libnetwork/drivers/bridge/setup_ip_forwarding.go#L44
The FORWARD chain rules are numbered in the output above, they are: The FORWARD chain rules, explained in the order they appear in the output above, are:
1. Unconditional jump to DOCKER-USER. 1. Unconditional jump to DOCKER-USER.
This is set up by libnetwork, in [setupUserChain][10]. This is set up by libnetwork, in [setupUserChain][10].
@@ -40,24 +40,27 @@ the DOCKER-USER chain, for rules that run before DOCKER's).
The DOCKER-FORWARD chain contains the first stage of Docker's filter rules. Initial The DOCKER-FORWARD chain contains the first stage of Docker's filter rules. Initial
rules are inserted at the top of the table, then not touched. Per-network rules rules are inserted at the top of the table, then not touched. Per-network rules
are appended. are appended. The DOCKER-FORWARD chain rules, explained in the order they appear in
the output above, are:
1. Early ACCEPT for any RELATED,ESTABLISHED traffic to a docker bridge. This rule 1. Unconditional jump to DOCKER-CT.
matches against an `ipset` called `docker-ext-bridges-v4` (`v6` for IPv6). The Created during driver initialisation, in `setupIPChains`.
set contains the CIDR address of each docker network, and it is updated as networks
are created and deleted. This rule is created during driver initialisation, in
`setupIPChains`.
2. Unconditional jump to DOCKER-ISOLATION-STAGE-1. 2. Unconditional jump to DOCKER-ISOLATION-STAGE-1.
Also created during driver initialisation, in `setupIPChains`. Also created during driver initialisation, in `setupIPChains`.
3. Jump to DOCKER, for any packet destined for any bridge network, identified by 3. Unconditional jump to DOCKER-BRIDGE.
matching against the `docker-ext-bridge-v[46]` set.
Also created during driver initialisation, in `setupIPChains`. Also created during driver initialisation, in `setupIPChains`.
The DOCKER chain implements per-port/protocol filtering for each container.
4. ACCEPT any packet leaving a network, set up when the network is created, in 4. ACCEPT any packet leaving a network, set up when the network is created, in
`setupIPTablesInternal`. Note that this accepts any packet leaving the `setupIPTablesInternal`. Note that this accepts any packet leaving the
network that's made it through the DOCKER and isolation chains, whether the network that's made it through the DOCKER and isolation chains, whether the
destination is external or another network. destination is external or another network.
The DOCKER-CT chain is an early ACCEPT for any RELATED,ESTABLISHED traffic to a
docker bridge. It contains a conntrack ACCEPT rule for each bridge network.
DOCKER-BRIDGE has a rule for each bridge network, to jump to the DOCKER chain.
The DOCKER chain implements per-port/protocol filtering for each container.
[10]: https://github.com/moby/moby/blob/e05848c0025b67a16aaafa8cdff95d5e2c064105/libnetwork/firewall_linux.go#L50 [10]: https://github.com/moby/moby/blob/e05848c0025b67a16aaafa8cdff95d5e2c064105/libnetwork/firewall_linux.go#L50
[11]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L230-L232 [11]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L230-L232
[12]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L227-L229 [12]: https://github.com/robmry/moby/blob/52c89d467fc5326149e4bbb8903d23589b66ff0d/libnetwork/drivers/bridge/setup_ip_tables_linux.go#L227-L229

View File

@@ -21,7 +21,7 @@ The filter table is:
By comparison with [ICC=true][1]: By comparison with [ICC=true][1]:
- Rules 6 and 7 replace the accept rule for outgoing packets. - DOCKER-FORWARD rules 6 and 7 replace the accept rule for outgoing packets.
- Rule 6, added by `setIcc`, drops any packet sent from the internal network to itself. - Rule 6, added by `setIcc`, drops any packet sent from the internal network to itself.
- Rule 7, added by `setupIPTablesInternal` accepts any other outgoing packet. - Rule 7, added by `setupIPTablesInternal` accepts any other outgoing packet.

View File

@@ -22,6 +22,7 @@ Note that:
- In the DOCKER-FORWARD chain, rule 5 for outgoing traffic from the new network has been - In the DOCKER-FORWARD chain, rule 5 for outgoing traffic from the new network has been
appended to the end of the chain. appended to the end of the chain.
- The DOCKER-CT and DOCKER-FORWARD chains each have a rule for the new network.
- In the DOCKER-ISOLATION chains, rules equivalent to the docker0 rules have - In the DOCKER-ISOLATION chains, rules equivalent to the docker0 rules have
also been inserted for the new bridge. also been inserted for the new bridge.
- In the DOCKER chain, there is an ACCEPT rule for TCP port 80 packets routed - In the DOCKER chain, there is an ACCEPT rule for TCP port 80 packets routed

View File

@@ -31,7 +31,6 @@ import (
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace"
"golang.org/x/sys/unix"
) )
const ( const (
@@ -521,9 +520,6 @@ func (d *driver) configure(option map[string]interface{}) error {
if config.EnableIPTables { if config.EnableIPTables {
removeIPChains(iptables.IPv4) removeIPChains(iptables.IPv4)
if err := setupHashNetIpset(ipsetExtBridges4, unix.AF_INET); err != nil {
return fmt.Errorf("%w (kernel modules ip_set, ip_set_hash_net and netfilter_xt_set are required)", err)
}
if err := setupIPChains(config, iptables.IPv4); err != nil { if err := setupIPChains(config, iptables.IPv4); err != nil {
return err return err
} }
@@ -548,28 +544,21 @@ func (d *driver) configure(option map[string]interface{}) error {
removeIPChains(iptables.IPv6) removeIPChains(iptables.IPv6)
if err := setupHashNetIpset(ipsetExtBridges6, unix.AF_INET6); err != nil { if err := setupIPChains(config, iptables.IPv6); err != nil {
// Continue, IPv4 will work (as below). // If the chains couldn't be set up, it's probably because the kernel has no IPv6
log.G(context.TODO()).WithError(err).Warn( // support, or it doesn't have module ip6_tables loaded. It won't be possible to
"ip6tables is enabled, but cannot set up IPv6 ipset (kernel modules ip_set, ip_set_hash_net and netfilter_xt_set are required)") // create IPv6 networks without enabling ip6_tables in the kernel, or disabling
// ip6tables in the daemon config. But, allow the daemon to start because IPv4
// will work. So, log the problem, and continue.
log.G(context.TODO()).WithError(err).Warn("ip6tables is enabled, but cannot set up ip6tables chains")
} else { } else {
err = setupIPChains(config, iptables.IPv6) // Make sure on firewall reload, first thing being re-played is chains creation
if err != nil { iptables.OnReloaded(func() {
// If the chains couldn't be set up, it's probably because the kernel has no IPv6 log.G(context.TODO()).Debugf("Recreating ip6tables chains on firewall reload")
// support, or it doesn't have module ip6_tables loaded. It won't be possible to if err := setupIPChains(config, iptables.IPv6); err != nil {
// create IPv6 networks without enabling ip6_tables in the kernel, or disabling log.G(context.TODO()).WithError(err).Error("Error reloading ip6tables chains")
// ip6tables in the daemon config. But, allow the daemon to start because IPv4 }
// will work. So, log the problem, and continue. })
log.G(context.TODO()).WithError(err).Warn("ip6tables is enabled, but cannot set up ip6tables chains")
} else {
// Make sure on firewall reload, first thing being re-played is chains creation
iptables.OnReloaded(func() {
log.G(context.TODO()).Debugf("Recreating ip6tables chains on firewall reload")
if err := setupIPChains(config, iptables.IPv6); err != nil {
log.G(context.TODO()).WithError(err).Error("Error reloading ip6tables chains")
}
})
}
} }
} }
@@ -590,19 +579,6 @@ func (d *driver) configure(option map[string]interface{}) error {
return d.initStore() return d.initStore()
} }
func setupHashNetIpset(name string, family uint8) error {
if err := netlink.IpsetCreate(name, "hash:net", netlink.IpsetCreateOptions{
Replace: true,
Family: family,
}); err != nil {
return fmt.Errorf("creating ipset %s: %w", name, err)
}
if err := netlink.IpsetFlush(name); err != nil {
return fmt.Errorf("flushing ipset %s: %w", name, err)
}
return nil
}
func (d *driver) getNetwork(id string) (*bridgeNetwork, error) { func (d *driver) getNetwork(id string) (*bridgeNetwork, error) {
d.Lock() d.Lock()
defer d.Unlock() defer d.Unlock()

View File

@@ -27,7 +27,6 @@ import (
"github.com/docker/docker/libnetwork/types" "github.com/docker/docker/libnetwork/types"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"github.com/vishvananda/netns" "github.com/vishvananda/netns"
"golang.org/x/sys/unix"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/icmd" "gotest.tools/v3/icmd"
@@ -1266,9 +1265,6 @@ func TestCleanupIptableRules(t *testing.T) {
iptables.IPv6: {EnableIP6Tables: true}, iptables.IPv6: {EnableIP6Tables: true},
} }
assert.NilError(t, setupHashNetIpset(ipsetExtBridges4, unix.AF_INET))
assert.NilError(t, setupHashNetIpset(ipsetExtBridges6, unix.AF_INET6))
for _, version := range ipVersions { for _, version := range ipVersions {
err := setupIPChains(configs[version], version) err := setupIPChains(configs[version], version)
assert.NilError(t, err, "version:%s", version) assert.NilError(t, err, "version:%s", version)

View File

@@ -13,13 +13,14 @@ import (
"github.com/docker/docker/libnetwork/iptables" "github.com/docker/docker/libnetwork/iptables"
"github.com/docker/docker/libnetwork/types" "github.com/docker/docker/libnetwork/types"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"github.com/vishvananda/netlink/nl"
) )
// DockerChain: DOCKER iptable chain name // DockerChain: DOCKER iptable chain name
const ( const (
DockerChain = "DOCKER" DockerChain = "DOCKER"
DockerForwardChain = "DOCKER-FORWARD" DockerForwardChain = "DOCKER-FORWARD"
DockerBridgeChain = "DOCKER-BRIDGE"
DockerCTChain = "DOCKER-CT"
// Isolation between bridge networks is achieved in two stages by means // Isolation between bridge networks is achieved in two stages by means
// of the following two chains in the filter table. The first chain matches // of the following two chains in the filter table. The first chain matches
@@ -33,11 +34,6 @@ const (
IsolationChain1 = "DOCKER-ISOLATION-STAGE-1" IsolationChain1 = "DOCKER-ISOLATION-STAGE-1"
IsolationChain2 = "DOCKER-ISOLATION-STAGE-2" IsolationChain2 = "DOCKER-ISOLATION-STAGE-2"
// ipset names for IPv4 and IPv6 bridge subnets that don't belong
// to --internal networks.
ipsetExtBridges4 = "docker-ext-bridges-v4"
ipsetExtBridges6 = "docker-ext-bridges-v6"
) )
// Path to the executable installed in Linux under WSL2 that reports on // Path to the executable installed in Linux under WSL2 that reports on
@@ -92,6 +88,30 @@ func setupIPChains(config configuration, version iptables.IPVersion) (retErr err
} }
}() }()
_, err = iptable.NewChain(DockerBridgeChain, iptables.Filter)
if err != nil {
return fmt.Errorf("failed to create FILTER chain %s: %v", DockerBridgeChain, err)
}
defer func() {
if retErr != nil {
if err := iptable.RemoveExistingChain(DockerBridgeChain, iptables.Filter); err != nil {
log.G(context.TODO()).Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", DockerBridgeChain, err)
}
}
}()
_, err = iptable.NewChain(DockerCTChain, iptables.Filter)
if err != nil {
return fmt.Errorf("failed to create FILTER chain %s: %v", DockerCTChain, err)
}
defer func() {
if retErr != nil {
if err := iptable.RemoveExistingChain(DockerCTChain, iptables.Filter); err != nil {
log.G(context.TODO()).Warnf("failed on removing iptables FILTER chain %s on cleanup: %v", DockerCTChain, err)
}
}
}()
_, err = iptable.NewChain(IsolationChain1, iptables.Filter) _, err = iptable.NewChain(IsolationChain1, iptables.Filter)
if err != nil { if err != nil {
return fmt.Errorf("failed to create FILTER isolation chain: %v", err) return fmt.Errorf("failed to create FILTER isolation chain: %v", err)
@@ -130,14 +150,32 @@ func setupIPChains(config configuration, version iptables.IPVersion) (retErr err
// Make sure the filter-FORWARD chain has rules to accept related packets and // Make sure the filter-FORWARD chain has rules to accept related packets and
// jump to the isolation and docker chains. (Re-)insert at the top of the table, // jump to the isolation and docker chains. (Re-)insert at the top of the table,
// in reverse order. // in reverse order.
ipsetName := ipsetExtBridges4 if err := iptable.EnsureJumpRule("FORWARD", DockerForwardChain); err != nil {
if version == iptables.IPv6 { return err
ipsetName = ipsetExtBridges6
} }
if err := iptable.EnsureJumpRule(DockerForwardChain, DockerBridgeChain); err != nil {
return err
}
if err := iptable.EnsureJumpRule(DockerForwardChain, IsolationChain1); err != nil {
return err
}
if err := iptable.EnsureJumpRule(DockerForwardChain, DockerCTChain); err != nil {
return err
}
if err := mirroredWSL2Workaround(config, version); err != nil {
return err
}
// Delete rules that may have been added to the FORWARD chain by moby 28.0.0. // Delete rules that may have been added to the FORWARD chain by moby 28.0.0.
ipsetName := "docker-ext-bridges-v4"
if version == iptables.IPv6 {
ipsetName = "docker-ext-bridges-v6"
}
if err := iptable.DeleteJumpRule("FORWARD", DockerChain, if err := iptable.DeleteJumpRule("FORWARD", DockerChain,
"-m", "set", "--match-set", ipsetName, "dst"); err != nil { "-m", "set", "--match-set", ipsetName, "dst"); err != nil {
return fmt.Errorf("%w (kernel module netfilter_xt_set is required)", err) log.G(context.TODO()).WithFields(log.Fields{"error": err, "set": ipsetName}).Debug(
"deleting legacy ipset dest match rule")
} }
if err := iptable.DeleteJumpRule("FORWARD", IsolationChain1); err != nil { if err := iptable.DeleteJumpRule("FORWARD", IsolationChain1); err != nil {
return err return err
@@ -146,28 +184,8 @@ func setupIPChains(config configuration, version iptables.IPVersion) (retErr err
"-m", "set", "--match-set", ipsetName, "dst", "-m", "set", "--match-set", ipsetName, "dst",
"-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED",
); err != nil { ); err != nil {
return err log.G(context.TODO()).WithFields(log.Fields{"error": err, "set": ipsetName}).Debug(
} "deleting legacy ipset conntrack rule")
// Create rules in the DockerForward chain.
if err := iptable.EnsureJumpRule("FORWARD", DockerForwardChain); err != nil {
return err
}
if err := iptable.EnsureJumpRule(DockerForwardChain, DockerChain,
"-m", "set", "--match-set", ipsetName, "dst"); err != nil {
return err
}
if err := iptable.EnsureJumpRule(DockerForwardChain, IsolationChain1); err != nil {
return err
}
if err := iptable.EnsureJumpRule(DockerForwardChain, "ACCEPT",
"-m", "set", "--match-set", ipsetName, "dst",
"-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED",
); err != nil {
return err
}
if err := mirroredWSL2Workaround(config, version); err != nil {
return err
} }
return nil return nil
@@ -221,11 +239,6 @@ func (n *bridgeNetwork) setupIPTables(ipVersion iptables.IPVersion, maskedAddr *
// Pickup this configuration option from driver // Pickup this configuration option from driver
hairpinMode := !driverConfig.EnableUserlandProxy hairpinMode := !driverConfig.EnableUserlandProxy
ipsetName := ipsetExtBridges4
if ipVersion == iptables.IPv6 {
ipsetName = ipsetExtBridges6
}
if config.Internal { if config.Internal {
if err = setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, true); err != nil { if err = setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, true); err != nil {
return fmt.Errorf("Failed to Setup IP tables: %w", err) return fmt.Errorf("Failed to Setup IP tables: %w", err)
@@ -260,28 +273,26 @@ func (n *bridgeNetwork) setupIPTables(ipVersion iptables.IPVersion, maskedAddr *
return err return err
} }
cidr, _ := maskedAddr.Mask.Size() ctRule := iptables.Rule{IPVer: ipVersion, Table: iptables.Filter, Chain: DockerCTChain, Args: []string{
if cidr == 0 { "-o", config.BridgeName,
return fmt.Errorf("no CIDR for bridge %s addr %s", config.BridgeName, maskedAddr) "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED",
} "-j", "ACCEPT",
ipsetEntry := &netlink.IPSetEntry{ }}
IP: maskedAddr.IP, if err := appendOrDelChainRule(ctRule, "bridge ct related", true); err != nil {
CIDR: uint8(cidr), return err
}
if err := netlink.IpsetAdd(ipsetName, ipsetEntry); err != nil {
if !errors.Is(err, nl.IPSetError(nl.IPSET_ERR_EXIST)) {
return fmt.Errorf("failed to add bridge %s (%s) to ipset: %w",
config.BridgeName, maskedAddr, err)
}
// Re-adding an IP address to an ipset on firewalld reload is expected, not an error.
log.G(context.TODO()).WithFields(log.Fields{
"ipset": ipsetName,
"bridge": config.BridgeName,
"subnet": maskedAddr,
}).Debug("Subnet was already in the ipset")
} }
n.registerIptCleanFunc(func() error { n.registerIptCleanFunc(func() error {
return netlink.IpsetDel(ipsetName, ipsetEntry) return appendOrDelChainRule(ctRule, "bridge ct related", false)
})
jumpToDockerRule := iptables.Rule{IPVer: ipVersion, Table: iptables.Filter, Chain: DockerBridgeChain, Args: []string{
"-o", config.BridgeName,
"-j", DockerChain,
}}
if err := appendOrDelChainRule(jumpToDockerRule, "jump to docker", true); err != nil {
return err
}
n.registerIptCleanFunc(func() error {
return appendOrDelChainRule(jumpToDockerRule, "jump to docker", false)
}) })
} }
return nil return nil

View File

@@ -16,7 +16,6 @@ import (
"github.com/docker/docker/libnetwork/netlabel" "github.com/docker/docker/libnetwork/netlabel"
"github.com/docker/docker/libnetwork/types" "github.com/docker/docker/libnetwork/types"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"gotest.tools/v3/assert" "gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp" is "gotest.tools/v3/assert/cmp"
) )
@@ -97,22 +96,15 @@ func TestSetupIPChains(t *testing.T) {
createTestBridge(config, br, t) createTestBridge(config, br, t)
assertBridgeConfig(config, br, d, t) assertBridgeConfig(config, br, d, t)
// The purpose of this test is unclear but, now there's an ipset of bridges, it's
// an error to create a bridge that's already been created. That can't happen in
// normal running. So, just flush the set between each step.
assert.NilError(t, netlink.IpsetFlush(ipsetExtBridges4))
config.EnableIPMasquerade = true config.EnableIPMasquerade = true
assertBridgeConfig(config, br, d, t) assertBridgeConfig(config, br, d, t)
assert.NilError(t, netlink.IpsetFlush(ipsetExtBridges4))
config.EnableICC = true config.EnableICC = true
assertBridgeConfig(config, br, d, t) assertBridgeConfig(config, br, d, t)
assert.NilError(t, netlink.IpsetFlush(ipsetExtBridges4))
config.EnableIPMasquerade = false config.EnableIPMasquerade = false
assertBridgeConfig(config, br, d, t) assertBridgeConfig(config, br, d, t)
assert.NilError(t, netlink.IpsetFlush(ipsetExtBridges4))
} }
func getBasicTestConfig() *networkConfiguration { func getBasicTestConfig() *networkConfiguration {
@@ -164,14 +156,10 @@ func assertIPTableChainProgramming(rule iptables.Rule, descr string, t *testing.
func assertChainConfig(d *driver, t *testing.T) { func assertChainConfig(d *driver, t *testing.T) {
var err error var err error
err = setupHashNetIpset(ipsetExtBridges4, unix.AF_INET)
assert.NilError(t, err)
err = setupIPChains(d.config, iptables.IPv4) err = setupIPChains(d.config, iptables.IPv4)
assert.NilError(t, err) assert.NilError(t, err)
if d.config.EnableIP6Tables { if d.config.EnableIP6Tables {
err = setupHashNetIpset(ipsetExtBridges6, unix.AF_INET6)
assert.NilError(t, err)
err = setupIPChains(d.config, iptables.IPv6) err = setupIPChains(d.config, iptables.IPv6)
assert.NilError(t, err) assert.NilError(t, err)
} }
@@ -474,8 +462,6 @@ func TestMirroredWSL2Workaround(t *testing.T) {
restoreWslinfoPath := simulateWSL2MirroredMode(t, tc.loopback0, tc.wslinfoPerm) restoreWslinfoPath := simulateWSL2MirroredMode(t, tc.loopback0, tc.wslinfoPerm)
defer restoreWslinfoPath() defer restoreWslinfoPath()
assert.NilError(t, setupHashNetIpset(ipsetExtBridges4, unix.AF_INET))
config := configuration{EnableIPTables: true} config := configuration{EnableIPTables: true}
if tc.userlandProxy { if tc.userlandProxy {
config.UserlandProxyPath = "some-proxy" config.UserlandProxyPath = "some-proxy"

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE

View File

@@ -1,4 +1,4 @@
-N DOCKER-FORWARD -N DOCKER-FORWARD
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -m set --match-set docker-ext-bridges-v6 dst -j DOCKER -A DOCKER-FORWARD -j DOCKER-BRIDGE