I agree, and tools that try to make something complex (nftables) simple and easy to use (UFW, Firewalld) should make that possible.
Different lists are a powerful nftables feature that is used in many system services and applications for things like routing and specialized forwarding. You can't just disable that without breaking tons of software.
Instead, tools like UFW should make it clear which ports are or aren't open and what firewall rules actually apply to the current system. They exist to save users from nftables and eBPF programming, and they should work as advertised.
Ufw advertises itself with "Ufw stands for Uncomplicated Firewall, and is program for managing a netfilter firewall" not "Ufw stands for Uncomplicated Firewall, which lets you add some firewall rules but doesn't manage all of them so you need to be extra careful if you use it."
The real problem is that iptables rules aren't composable. In this thread alone there are several tools that add iptables rules (kubernetes, docker, ufw) and they are just dumped without regards to each other.
I disagree that we need more tooling. We need better tooling. Docker and Kubernetes adding network filters makes total sense, they're useless without forwarding packets between devices.
UFW, on the other hand, pretends to make firewalls simple and easy to use when they're really not. I'm not expecting UFW to start managing Docker's/K8s'/libvirtd's firewall rules, I'm just expecting them to add a section of "ports opened by other applications" that show the open ports that UFW can't control.
Set `{"iptables": false}` in daemon.json (or pass `--iptables=false` to the daemon) and it won't do it. The defaults are convenient enshittification for your casual security-ignorant developer.
I'm not sure how much this routing is really needed. I use nftables instead of iptables, so I told Docker to not touch anything.
I'm gradually getting rid of Docker (NixOS containers powered by systemd-nspawn are more convenient for me at the moment), so I don't have any fancy networking for it - but I still run it. I have a bunch of static nftables rules for the bridge (`iifname "docker0" ct state established,related counter accept` etc.) so the containers can access what they need. And then Docker uses docker-proxy for the exposed ports (paired with appropriate firewall rules when it's not on `lo`, where I have an umbrella `iif "lo" accept`) and it seem to works just fine.
By enabling port forwarding and exposing, you're essentially asking docker to configure the host for it. It's likely a surprising behaviour, but seems like ufw has a bug if you have multiple chains and groups instead of just the default one.
> It does not bypasses them, it uses the firewall to add forwarding rules to the container.
... yes, it adds a forwarding rule. Which skips over the rest of my firewall rules. One might even say that it bypasses them.
> By enabling port forwarding and exposing, you're essentially asking docker to configure the host for it.
No, I'm asking docker to listen on that port and pass it through to the container. If I tell nginx to listen on port 80, would you expect it to take that as a "do anything you can to make sure you get port 80, including rewriting the firewall tables to ignore the rule that blocks port 80"?
GP is being annoying and I agree with you for the most part and I feel Docker should have tried to play nicer with the firewall.
That said it is a mistake to consider Docker in the same class as nginx. Docker is a system for telling the Linux kernel how to set up the environments of processes. Doing whatever it can at the absolute lowest level of abstraction the kernel offers is kind of its entire gig.
The reason docker is integrating this way is to easily group the rules it introduced.
> I feel Docker should have tried to play nicer with the firewall.
The problem is on the UFW side not setting up properly when other chains are present. UFW is just a front-end for iptables, and docker integrates with iptables. Can the situation be made better? Likely on the UFW side. https://docs.docker.com/network/packet-filtering-firewalls/#...
The docker behaviour is documented...
UFW seems buggy in that it only operates on set of prefixed groups instead of looking at all the groups in iptables. Now, looking at the UFW code: https://git.launchpad.net/ufw/tree/src/backend_iptables.py?h... it seems to setup it's own chains and ignores everything else. It even filters out all other chains unless they're part of UFW.
Yeah I agree, I guess it should have been up to whoever packages Docker for Ubuntu to make sure it plays nice with the standard Ubuntu tooling. Given how Docker forward Ubuntu itself is, it probably should have made UFW aware of Docker.
That's a fair argument - I disagree, but it's a valid perspective and probably the root of the difference in views. I personally expect docker to be a piece that fits into the system to run containers. If docker expects to effectively be the system at least for things in its domain, then that would explain why it does things that I consider out of its scope. (There's an echo here of the argument about systemd; if you expect systemd to be everything between the kernel and userspace, then of course it includes ex. its own ntpd and cron replacement, whereas if you expect it to be a service manager then every extra function looks like an overreach)
I wouldn't expect Docker to be listening on anything. Docker isn't proxying any traffic into the container, it's just configuring how ports are forwarded from the host to the container.
Not explicitly, no. The flag is `--publish`, not `--publish-regardless-of-firewall-rules`. It looks for all the world like the usual server --listen or --port options unless you happen to know about this little "feature".
The issue is UFW ignoring other firewall rules, Docker just adds itself to iptables, but UFW actively ignores other chains. The bug is on UFW being insecure by design.
Upvoted because you are correct. Calling it a bypass almost implies something more nefarious vs saying docker automatically adds its own forwarding rules.
It's not intended to be nefarious, but it can have bad consequences. I know the docker devs had good intentions to help people expose services, when they introduced this. However, they also "helped" people unwillingly expose services, oops.
Just because it was meant to be useful and harmless doesn't mean they didn't actually bypass the firewall rules by adding their own rules.