It no longer needs to be moved to the top of the filter-FORWARD
chain after creating a new bridge network. But, it does need to
be rearranged after setting up Swarm ingress.
Similarly, the jump to DOCKER-INGRESS no longer needs to be
shuffled back to the top of the FORWARD chain after adding a
new network.
Signed-off-by: Rob Murray <rob.murray@docker.com>
| ... | ... |
@@ -854,10 +854,6 @@ func (daemon *Daemon) initNetworkController(cfg *config.Config, activeSandboxes |
| 854 | 854 |
return err |
| 855 | 855 |
} |
| 856 | 856 |
|
| 857 |
- if err := daemon.netController.SetupUserChains(); err != nil {
|
|
| 858 |
- log.G(context.TODO()).WithError(err).Warnf("initNetworkController")
|
|
| 859 |
- } |
|
| 860 |
- |
|
| 861 | 857 |
// Set HostGatewayIP to the default bridge's IP if it is empty |
| 862 | 858 |
setHostGatewayIP(daemon.netController, cfg) |
| 863 | 859 |
return nil |
| ... | ... |
@@ -168,7 +168,7 @@ func New(cfgOptions ...config.Option) (*Controller, error) {
|
| 168 | 168 |
return nil, err |
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 |
- setupArrangeUserFilterRule(c) |
|
| 171 |
+ c.setupUserChains() |
|
| 172 | 172 |
return c, nil |
| 173 | 173 |
} |
| 174 | 174 |
|
| ... | ... |
@@ -700,30 +700,9 @@ addToStore: |
| 700 | 700 |
} |
| 701 | 701 |
} |
| 702 | 702 |
|
| 703 |
- if c.isSwarmNode() {
|
|
| 704 |
- c.mu.Lock() |
|
| 705 |
- arrangeIngressFilterRule() |
|
| 706 |
- c.mu.Unlock() |
|
| 707 |
- } |
|
| 708 |
- |
|
| 709 |
- if err := c.SetupUserChains(); err != nil {
|
|
| 710 |
- log.G(context.TODO()).WithError(err).Warnf("Controller.NewNetwork %s:", name)
|
|
| 711 |
- } |
|
| 712 |
- |
|
| 713 | 703 |
return nw, nil |
| 714 | 704 |
} |
| 715 | 705 |
|
| 716 |
-// Sets up the DOCKER-USER chain for each iptables version (IPv4, IPv6) that's |
|
| 717 |
-// enabled in the controller's configuration. |
|
| 718 |
-func (c *Controller) SetupUserChains() error {
|
|
| 719 |
- for _, ipVersion := range c.enabledIptablesVersions() {
|
|
| 720 |
- if err := setupUserChain(ipVersion); err != nil {
|
|
| 721 |
- return err |
|
| 722 |
- } |
|
| 723 |
- } |
|
| 724 |
- return nil |
|
| 725 |
-} |
|
| 726 |
- |
|
| 727 | 706 |
var joinCluster NetworkWalker = func(nw *Network) bool {
|
| 728 | 707 |
if nw.configOnly {
|
| 729 | 708 |
return false |
| ... | ... |
@@ -2,6 +2,7 @@ package libnetwork |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"context" |
| 5 |
+ "errors" |
|
| 5 | 6 |
"fmt" |
| 6 | 7 |
|
| 7 | 8 |
"github.com/containerd/log" |
| ... | ... |
@@ -10,24 +11,24 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
const userChain = "DOCKER-USER" |
| 12 | 12 |
|
| 13 |
-var ctrl *Controller |
|
| 14 |
- |
|
| 15 |
-func setupArrangeUserFilterRule(c *Controller) {
|
|
| 16 |
- ctrl = c |
|
| 17 |
- iptables.OnReloaded(arrangeUserFilterRule) |
|
| 18 |
-} |
|
| 19 |
- |
|
| 20 |
-// arrangeUserFilterRule sets up the DOCKER-USER chain for each iptables version |
|
| 21 |
-// (IPv4, IPv6) that's enabled in the controller's configuration. |
|
| 22 |
-func arrangeUserFilterRule() {
|
|
| 23 |
- if ctrl == nil {
|
|
| 24 |
- return |
|
| 25 |
- } |
|
| 26 |
- for _, ipVersion := range ctrl.enabledIptablesVersions() {
|
|
| 27 |
- if err := setupUserChain(ipVersion); err != nil {
|
|
| 28 |
- log.G(context.TODO()).WithError(err).Warn("arrangeUserFilterRule")
|
|
| 13 |
+// Sets up the DOCKER-USER chain for each iptables version (IPv4, IPv6) that's |
|
| 14 |
+// enabled in the controller's configuration. |
|
| 15 |
+func (c *Controller) setupUserChains() {
|
|
| 16 |
+ setup := func() error {
|
|
| 17 |
+ var errs []error |
|
| 18 |
+ for _, ipVersion := range c.enabledIptablesVersions() {
|
|
| 19 |
+ errs = append(errs, setupUserChain(ipVersion)) |
|
| 29 | 20 |
} |
| 21 |
+ return errors.Join(errs...) |
|
| 22 |
+ } |
|
| 23 |
+ if err := setup(); err != nil {
|
|
| 24 |
+ log.G(context.Background()).WithError(err).Warn("configuring " + userChain)
|
|
| 30 | 25 |
} |
| 26 |
+ iptables.OnReloaded(func() {
|
|
| 27 |
+ if err := setup(); err != nil {
|
|
| 28 |
+ log.G(context.Background()).WithError(err).Warn("configuring " + userChain + " on firewall reload")
|
|
| 29 |
+ } |
|
| 30 |
+ }) |
|
| 31 | 31 |
} |
| 32 | 32 |
|
| 33 | 33 |
// setupUserChain sets up the DOCKER-USER chain for the given [iptables.IPVersion]. |
| ... | ... |
@@ -69,7 +69,7 @@ func TestUserChain(t *testing.T) {
|
| 69 | 69 |
_, err = iptable6.Raw("-A", fwdChainName, "-j", "DROP")
|
| 70 | 70 |
assert.Check(t, err) |
| 71 | 71 |
} |
| 72 |
- arrangeUserFilterRule() |
|
| 72 |
+ c.setupUserChains() |
|
| 73 | 73 |
|
| 74 | 74 |
golden.Assert(t, getRules(t, iptable4, fwdChainName), |
| 75 | 75 |
fmt.Sprintf("TestUserChain_iptables-%v_append-%v_fwdafter4", tc.iptables, tc.append))
|
| ... | ... |
@@ -363,7 +363,10 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 363 | 363 |
if err := iptable.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
|
| 364 | 364 |
return fmt.Errorf("failed to add jump rule to %s in filter table forward chain: %v", ingressChain, err)
|
| 365 | 365 |
} |
| 366 |
- arrangeUserFilterRule() |
|
| 366 |
+ // The jump to DOCKER-USER needs to be before the jump to DOCKER-INGRESS. |
|
| 367 |
+ if err := setupUserChain(iptables.IPv4); err != nil {
|
|
| 368 |
+ log.G(context.TODO()).Warnf("Failed to restore "+userChain+" after creating "+ingressChain+": %v", err)
|
|
| 369 |
+ } |
|
| 367 | 370 |
} |
| 368 | 371 |
|
| 369 | 372 |
oifName, err := findOIFName(gwIP) |
| ... | ... |
@@ -452,26 +455,6 @@ func programIngress(gwIP net.IP, ingressPorts []*PortConfig, isDelete bool) erro |
| 452 | 452 |
return nil |
| 453 | 453 |
} |
| 454 | 454 |
|
| 455 |
-// In the filter table FORWARD chain the first rule should be to jump to |
|
| 456 |
-// DOCKER-USER so the user is able to filter packet first. |
|
| 457 |
-// The second rule should be jump to INGRESS-CHAIN. |
|
| 458 |
-// This chain has the rules to allow access to the published ports for swarm tasks |
|
| 459 |
-// from local bridge networks and docker_gwbridge (ie:taks on other swarm networks) |
|
| 460 |
-func arrangeIngressFilterRule() {
|
|
| 461 |
- // TODO IPv6 support |
|
| 462 |
- iptable := iptables.GetIptable(iptables.IPv4) |
|
| 463 |
- if iptable.ExistChain(ingressChain, iptables.Filter) {
|
|
| 464 |
- if iptable.Exists(iptables.Filter, "FORWARD", "-j", ingressChain) {
|
|
| 465 |
- if err := iptable.RawCombinedOutput("-D", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 466 |
- log.G(context.TODO()).Warnf("failed to delete jump rule to ingressChain in filter table: %v", err)
|
|
| 467 |
- } |
|
| 468 |
- } |
|
| 469 |
- if err := iptable.RawCombinedOutput("-I", "FORWARD", "-j", ingressChain); err != nil {
|
|
| 470 |
- log.G(context.TODO()).Warnf("failed to add jump rule to ingressChain in filter table: %v", err)
|
|
| 471 |
- } |
|
| 472 |
- } |
|
| 473 |
-} |
|
| 474 |
- |
|
| 475 | 455 |
func findOIFName(ip net.IP) (string, error) {
|
| 476 | 456 |
nlh := ns.NlHandle() |
| 477 | 457 |
|
| ... | ... |
@@ -1,4 +1,5 @@ |
| 1 | 1 |
-P FORWARD ACCEPT |
| 2 |
+-A FORWARD -j DOCKER-USER |
|
| 2 | 3 |
-A FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT |
| 3 | 4 |
-A FORWARD -j DOCKER-ISOLATION-STAGE-1 |
| 4 | 5 |
-A FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER |
| ... | ... |
@@ -1,4 +1,5 @@ |
| 1 | 1 |
-P FORWARD ACCEPT |
| 2 |
+-A FORWARD -j DOCKER-USER |
|
| 2 | 3 |
-A FORWARD -m set --match-set docker-ext-bridges-v6 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT |
| 3 | 4 |
-A FORWARD -j DOCKER-ISOLATION-STAGE-1 |
| 4 | 5 |
-A FORWARD -m set --match-set docker-ext-bridges-v6 dst -j DOCKER |
| ... | ... |
@@ -1,4 +1,5 @@ |
| 1 | 1 |
-P FORWARD ACCEPT |
| 2 |
+-A FORWARD -j DOCKER-USER |
|
| 2 | 3 |
-A FORWARD -m set --match-set docker-ext-bridges-v4 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT |
| 3 | 4 |
-A FORWARD -j DOCKER-ISOLATION-STAGE-1 |
| 4 | 5 |
-A FORWARD -m set --match-set docker-ext-bridges-v4 dst -j DOCKER |
| ... | ... |
@@ -1,4 +1,5 @@ |
| 1 | 1 |
-P FORWARD ACCEPT |
| 2 |
+-A FORWARD -j DOCKER-USER |
|
| 2 | 3 |
-A FORWARD -m set --match-set docker-ext-bridges-v6 dst -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT |
| 3 | 4 |
-A FORWARD -j DOCKER-ISOLATION-STAGE-1 |
| 4 | 5 |
-A FORWARD -m set --match-set docker-ext-bridges-v6 dst -j DOCKER |