Skip to content

Bridge plugin leak ip masq if netns is empty #810

@qkboy

Description

@qkboy

When calling bridge to create a container through nerdctl, if set "ipMasq": true , three iptables rules will be created. These rules are not deleted after the container is deleted, but remain on the system.

:CNI-4f6dd6c08c7e1a901788c768 - [0:0]
-A POSTROUTING -s 10.4.0.29/32 -m comment --comment "name: \"bridge\" id: \"default-237eaf51aa0c1411433db10b2c8dac0f826f87ac6f48c62084ee84c3d9c20384\"" -j CNI-4f6dd6c08c7e1a901788c768
-A CNI-4f6dd6c08c7e1a901788c768 -d 10.4.0.0/24 -m comment --comment "name: \"bridge\" id: \"default-237eaf51aa0c1411433db10b2c8dac0f826f87ac6f48c62084ee84c3d9c20384\"" -j ACCEPT
-A CNI-4f6dd6c08c7e1a901788c768 ! -d 224.0.0.0/4 -m comment --comment "name: \"bridge\" id: \"default-237eaf51aa0c1411433db10b2c8dac0f826f87ac6f48c62084ee84c3d9c20384\"" -j MASQUERADE

The reason is that, nerdctl calling cni Del will put Netns="" into the StdinData.

// The third parameter means Netns path , it's empty
if err := opts.cni.Remove(ctx, opts.fullID, "", namespaceOpts...); err != nil {
	logrus.WithError(err).Errorf("failed to call cni.Remove")
	return err
}

and ctr also do the same action.

defer func() {
	if enableCNI {
		// The third parameter means Netns path , it's empty
		if err := network.Remove(ctx, commands.FullID(ctx, container), ""); err != nil {
			logrus.WithError(err).Error("network review")
		}
	}
	task.Delete(ctx)
}()

But bridge plugin only execute ipamDel() and didn't teardown ip masq when Netns is empty .

	if args.Netns == "" {
		return ipamDel()
	}

In another case, even if Netns is not empty, but the container has stopped. Bridge plugin try to obtain the ip address from container's netns will be fail too. So teardown ip masq will not execute too. The current handling method is to skip.

	// If the device isn't there then don't try to clean up IP masq either.
	var ipnets []*net.IPNet
	err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
		var err error
		ipnets, err = ip.DelLinkByNameAddr(args.IfName)
		if err != nil && err == ip.ErrLinkNotFound {
			return nil
		}
		return err
	})

When nerdctl calls cni Del, the container has been stopped. This problem is difficult to solve on nerdctl or ctr.
Actually, nerdctl or ctr will inserts the network metadata into the prevResult structure of the StdinData.

"prevResult":{"cniVersion":"1.0.0","interfaces":[{"name":"nerdctl0","mac":"12:02:11:fb:08:a7"},{"name":"vethd4a25238","mac":"96:56:42:de:0f:bf"},{"name":"eth0","mac":"6e:af:15:d5:2c:d8","sandbox":"/proc/2538456/ns/net"}],"ips":[{"interface":2,"address":"10.4.0.102/24","gateway":"10.4.0.1"}]

We can solve this problem by getting the IP address from prevResult and adjusting the order of executing ip masq.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions