Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add firewalld policy "docker-forwarding". #47745

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

robmry
Copy link
Contributor

@robmry robmry commented Apr 23, 2024

- What I did

Allow forwarding from any firewalld zone to the 'docker' zone.

This makes it possible to use routable IPv6 addresses on a bridge network, with masquerading disabled, and have the host forward packets to it.

- How I did it

Use firewalld's addPolicy method ... ignore a NAME_CONFLICT error (policy already exists), and an unknown-method error (because addPolicy was added in firewalld 0.9.0, older versions don't need the policy). If something else goes wrong, log the error but still reload firewalld - there's no need to regress existing functionality by bailing out early. Being cautious, because we don't have good test coverage for firewalld - errors are only logged anyway, normally at debug level.

- How to verify it

Without this change...

# docker network create --ipv6 --subnet fd02::/64 -o com.docker.network.bridge.enable_ip_masquerade=false nnn6
# docker run --rm -ti --name c1 --network nnn6 -P nginx

(then, on another host)

# ip -6 route add fd02::/64 via fd48:70ba:de62:0:1d00:31c3:c27b:6d1b
# curl 'http://[fd02::2]'
curl: (7) Failed to connect to fd02::2 port 80: Permission denied

Using OpenSUSE (firewalld 2.1.1-1.4)

Policy created (but not the pre-existing zone) on first run with the change ...

INFO[2024-04-23T11:10:48.166745414+01:00] Firewalld: docker zone already exists, returning
INFO[2024-04-23T11:10:48.173292238+01:00] Firewalld: created docker-forwarding policy

The policy ends up here ...

# cat /etc/firewalld/policies/docker-forwarding.xml
<?xml version="1.0" encoding="utf-8"?>
<policy version="1.0" target="ACCEPT">
  <description>allow forwarding to the docker zone</description>
  <ingress-zone name="ANY"/>
  <egress-zone name="docker"/>
</policy>

Repeat the curl test ...

# curl 'http://[fd02::2]'
<!DOCTYPE html>
...

Daemon restart ...

INFO[2024-04-23T11:16:30.394677002+01:00] Firewalld: docker zone already exists, returning
DEBU[2024-04-23T11:16:30.397121661+01:00] Firewalld: docker-forwarding policy already exists

CentOS 7 (firewalld 0.6.3-11.el7) - addPolicy doesn't work, but it isn't needed ...

INFO[2024-04-22T11:26:23.952140185+01:00] Firewalld: docker zone already exists, returning
DEBU[2024-04-22T11:26:23.953287064+01:00] Firewalld: addPolicy docker-forwarding: UnknownMethod

- Description for the changelog

If firewalld is running on the host, create policy `docker-forwarding` to allow forwarding from
any zone to the `docker` zone. This makes it possible to configure a bridge network with a
routable IPv6 address, and no masquerading.

@robmry robmry self-assigned this Apr 23, 2024
@robmry robmry added kind/enhancement Enhancements are not bugs or new features but can improve usability or performance. area/networking impact/changelog impact/documentation area/networking/firewalld labels Apr 23, 2024
@robmry robmry added this to the 27.0.0 milestone Apr 23, 2024
@robmry robmry marked this pull request as ready for review April 23, 2024 12:56
@robmry robmry force-pushed the firewalld_forwarding_policy branch 3 times, most recently from e840a6a to 93149a2 Compare April 24, 2024 14:05
Comment on lines 271 to 274
if derr.Name == "org.fedoraproject.FirewallD1.Exception" && strings.HasPrefix(err.Error(), "NAME_CONFLICT") {
log.G(context.TODO()).Debugf("Firewalld: %s policy already exists", dockerFwdPolicy)
return false, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if derr.Name == "org.fedoraproject.FirewallD1.Exception" && strings.HasPrefix(err.Error(), "NAME_CONFLICT") {
log.G(context.TODO()).Debugf("Firewalld: %s policy already exists", dockerFwdPolicy)
return false, nil
}
if derr.Name == dbusInterface+".Exception" && len(derr.Args) > 0 {
if msg, ok := derr.Args[0].(string); ok && strings.HasPrefix(msg, "NAME_CONFLICT") {
log.G(context.TODO()).Debugf("Firewalld: %s policy already exists", dockerFwdPolicy)
return false, nil
}
}

Probably overkill to unpack the error args, but I was curious how awkward it would be to type-assert. Honestly, it's not too awful with the length check lifted into the outer condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why, when dbus's Error.Error() is already doing it? ...

func (e Error) Error() string {
if len(e.Body) >= 1 {
s, ok := e.Body[0].(string)
if ok {
return s
}
}
return e.Name
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, you know something I didn't.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if derr.Name == "org.fedoraproject.FirewallD1.Exception" && strings.HasPrefix(err.Error(), "NAME_CONFLICT") {
log.G(context.TODO()).Debugf("Firewalld: %s policy already exists", dockerFwdPolicy)
return false, nil
}
if derr.Name == dbusInterface+".Exception" && strings.HasPrefix(err.Error(), "NAME_CONFLICT") {
log.G(context.TODO()).Debugf("Firewalld: %s policy already exists", dockerFwdPolicy)
return false, nil
}

Allow forwarding from any firewalld zone to the 'docker' zone.

This makes it possible to use routable IPv6 addresses on a bridge
network, with masquerading disabled, and have the host forward packets
to it.

Signed-off-by: Rob Murray <rob.murray@docker.com>
@robmry robmry force-pushed the firewalld_forwarding_policy branch from 93149a2 to ff8de5e Compare April 24, 2024 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants