Skip to content

Commit

Permalink
Merge pull request #798 from LimeHat/main
Browse files Browse the repository at this point in the history
Replace error with a warning when iptables fails
  • Loading branch information
hellt authored Feb 23, 2022
2 parents c6ff217 + c1294c7 commit 40bb9b8
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 16 deletions.
12 changes: 10 additions & 2 deletions docs/manual/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ mgmt:

If the existing bridge has already been addressed with IPv4/6 address, containerlab will respect this address and use it in the IPAM configuration blob of the docker network.

If there is no existing IPv4/6 address defined for the custom bridge, Docker will assign the first interface from the subnet associated with the bridge.
If there is no existing IPv4/6 address defined for the custom bridge, docker will assign the first interface from the subnet associated with the bridge.

It is possible to set the desired gateway IP (that is the IP assigned to the bridge) with the `ipv4-gw/ipv6-gw` setting under `mgmt` container:

Expand Down Expand Up @@ -230,7 +230,15 @@ topology:
# your regular topology definition
```

1. When set to `false`, containerlab will not touch iptables rules. On most docker installation this will result in restricted external access.
1. When set to `false`, containerlab will not touch iptables rules. On most docker installations this will result in restricted external access.

???error "'missing DOCKER-USER iptables chain' error"
Containerlab will throw an error "missing DOCKER-USER iptables chain" when this chain is not found. This error is typically caused by two factors

1. Old docker version installed. Typically seen on Centos systems. Minimum required docker version is 17.06.
2. Docker is installed incorrectly. It is recommended to follow the [official installation procedures](https://docs.docker.com/engine/install/) by selecting "Installation per distro" menu option.

When docker is correctly installed, additional iptables chains will become available and the error will not appear.

### connection details
When containerlab needs to create the management network, it asks the docker daemon to do this. Docker will fulfill the request and will create a network with the underlying linux bridge interface backing it. The bridge interface name is generated by the docker daemon, but it is easy to find it:
Expand Down
12 changes: 10 additions & 2 deletions runtime/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,12 @@ func (d *DockerRuntime) postCreateNetActions() (err error) {
if err != nil {
log.Warnf("failed to disable TX checksum offloading for the %s bridge interface: %v", d.mgmt.Bridge, err)
}
err = d.installIPTablesFwdRule()
if err != nil {
log.Warnf("%v", err)
}

return d.installIPTablesFwdRule()
return nil
}

// DeleteNet deletes a docker bridge
Expand Down Expand Up @@ -269,8 +273,12 @@ func (d *DockerRuntime) DeleteNet(ctx context.Context) (err error) {

// bridge name associated with the network
br := "br-" + nres.ID[:12]
err = d.deleteIPTablesFwdRule(br)
if err != nil {
log.Warnf("%v", err)
}

return d.deleteIPTablesFwdRule(br)
return nil
}

// CreateContainer creates a docker container (but does not start it)
Expand Down
32 changes: 20 additions & 12 deletions runtime/docker/iptables.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,22 @@ func (d *DockerRuntime) installIPTablesFwdRule() (err error) {
log.Debugf("found iptables forwarding rule targeting the bridge %q. Skipping creation of the forwarding rule.", d.mgmt.Bridge)
return err
}

if err != nil {
return err
// non nil error typically means that DOCKER-USER chain doesn't exist
// this happens with old docker installations (centos7 hello) from default repos
return fmt.Errorf("missing DOCKER-USER iptables chain. See http://containerlab.srlinux.dev/manual/network/#external-access")
}

cmd := fmt.Sprintf(iptAllowCmd, d.mgmt.Bridge)

_, err = exec.Command("iptables", strings.Split(cmd, " ")...).Output()
log.Debugf("Installing iptables rules for bridge %q", d.mgmt.Bridge)

stdOutErr, err := exec.Command("iptables", strings.Split(cmd, " ")...).CombinedOutput()
if err != nil {
return
log.Warnf("Iptables install stdout/stderr result is: %s", stdOutErr)
return fmt.Errorf("unable to install iptables rules: %w", err)
}

return err
return nil
}

// deleteIPTablesFwdRule deletes `allow` rule installed with InstallIPTablesFwdRule when the bridge interface doesn't exist anymore
Expand All @@ -60,11 +63,16 @@ func (d *DockerRuntime) deleteIPTablesFwdRule(br string) (err error) {
}

// first check if a rule exists before trying to delete it
res, _ := exec.Command("iptables", strings.Split(iptCheckCmd, " ")...).Output()
res, err := exec.Command("iptables", strings.Split(iptCheckCmd, " ")...).Output()
if !bytes.Contains(res, []byte(d.mgmt.Bridge)) {
log.Debug("external access iptables rule doesn't exist. Skipping deletion")
return nil
}
if err != nil {
// non nil error typically means that DOCKER-USER chain doesn't exist
// this happens with old docker installations (centos7 hello) from default repos
return fmt.Errorf("missing DOCKER-USER iptables chain. See http://containerlab.srlinux.dev/manual/network/#external-access")
}

_, err = utils.BridgeByName(br)
if err == nil {
Expand All @@ -73,11 +81,11 @@ func (d *DockerRuntime) deleteIPTablesFwdRule(br string) (err error) {
}

cmd := fmt.Sprintf(iptDelCmd, br)

_, err = exec.Command("iptables", strings.Split(cmd, " ")...).Output()
log.Debugf("Removing clab iptables rules for bridge %q", br)
stdOutErr, err := exec.Command("iptables", strings.Split(cmd, " ")...).CombinedOutput()
if err != nil {
return
log.Warnf("Iptables delete stdout/stderr result is: %s", stdOutErr)
return fmt.Errorf("unable to delete iptables rules: %w", err)
}

return err
return nil
}

0 comments on commit 40bb9b8

Please sign in to comment.