ip6tables fails during network creation when com.docker.network.host_ipv4 bridge option is set #46445
Closed
Description
Description
With IPv6 and the experimental ip6tables
option enabled in the daemon, creating an IPv6-enabled bridge network with the com.docker.network.host_ipv4
option set fails with:
Error response from daemon: Failed to Setup IP tables: Unable to enable NAT rule: (iptables failed: ip6tables --wait -t nat -I POSTROUTING -s fd01::/64 ! -o br-f15cb6308dee -j SNAT --to-source 192.168.0.2: ip6tables v1.8.7 (legacy): Bad IP address "192.168.0.2"
Try `ip6tables -h' or 'ip6tables --help' for more information.
(exit status 2))
This is because the IPv4 address is used when setting up both the IPv4 rules and the IPv6 rules:
moby/libnetwork/drivers/bridge/setup_ip_tables_linux.go
Lines 160 to 165 in 6ce5aa1
Reproduce
dockerd --ipv6 --fixed-cidr-v6=fd00::/64 --experimental --ip6tables
docker network create -d bridge --ipv6 --subnet fd01::/64 --opt com.docker.network.host_ipv4=192.168.0.2 test-network
Expected behavior
Docker should create a bridge network with IPv4 SNAT (to the given IP) and IPv6 masquerade.
docker version
Client: Docker Engine - Community
Version: 24.0.6
API version: 1.43
Go version: go1.20.7
Git commit: ed223bc
Built: Mon Sep 4 12:31:44 2023
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 24.0.6
API version: 1.43 (minimum version 1.12)
Go version: go1.20.7
Git commit: 1a79695
Built: Mon Sep 4 12:31:44 2023
OS/Arch: linux/amd64
Experimental: true
containerd:
Version: 1.6.22
GitCommit: 8165feabfdfe38c65b599c4993d227328c231fca
runc:
Version: 1.1.8
GitCommit: v1.1.8-0-g82f18fe
docker-init:
Version: 0.19.0
GitCommit: de40ad0
docker info
Client: Docker Engine - Community
Version: 24.0.6
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.11.2
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.21.0
Path: /usr/libexec/docker/cli-plugins/docker-compose
Server:
Containers: 5
Running: 5
Paused: 0
Stopped: 0
Images: 1159
Server Version: 24.0.6
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 8165feabfdfe38c65b599c4993d227328c231fca
runc version: v1.1.8-0-g82f18fe
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.2.0-26-generic
Operating System: Ubuntu 22.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 23.46GiB
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: true
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
Default Address Pools:
Base: 172.17.0.0/16, Size: 24
Base: 172.18.0.0/15, Size: 23
Base: 172.20.0.0/14, Size: 22
Base: 172.24.0.0/13, Size: 21
Base: fd01::/64, Size: 64
Additional Info
The following change should fix it (I'll open a new pull request once I write a regression test):
diff --git a/libnetwork/drivers/bridge/setup_ip_tables_linux.go b/libnetwork/drivers/bridge/setup_ip_tables_linux.go
index c98781f3b0..5d2289014b 100644
--- a/libnetwork/drivers/bridge/setup_ip_tables_linux.go
+++ b/libnetwork/drivers/bridge/setup_ip_tables_linux.go
@@ -157,11 +157,15 @@ func (n *bridgeNetwork) setupIPTables(ipVersion iptables.IPVersion, maskedAddr *
return setupInternalNetworkRules(config.BridgeName, maskedAddr, config.EnableICC, false)
})
} else {
- if err = setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
+ hostIP := config.HostIP
+ if ipVersion != iptables.IPv4 {
+ hostIP = nil
+ }
+ if err = setupIPTablesInternal(hostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
}
n.registerIptCleanFunc(func() error {
- return setupIPTablesInternal(config.HostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
+ return setupIPTablesInternal(hostIP, config.BridgeName, maskedAddr, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
})
natChain, filterChain, _, _, err := n.getDriverChains(ipVersion)
if err != nil {
Activity