-
Notifications
You must be signed in to change notification settings - Fork 86
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
Best Practices for Docker and UFW #777
Comments
Rootless mode seems also useful as a workaround for this |
Hey @AkihiroSuda, thanks a lot for your suggestion. The only posts I've found referencing rootless mode are using nightly builds so it seems this is an experimental feature at the moment and not ready for production? Are there any official docs and stable builds available? Also would you be able to expand on the pros and cons of rootless vs regular modes or direct me to some articles which explain this clearly? Thanks for your time. Appreciate any insights you might have to offer :) |
Not only for nightly builds
Yes, it is likely to remain experimental until we can complete migration to cgroup2 (around the end of the year)
https://www.slideshare.net/AkihiroSuda/dockercon-2019-hardening-docker-daemon-with-rootless-mode |
Hi guys, I just made a little script that solves the ufw firewall and docker iptables issue. You can take a look at repo here. It's heavily based on chaifeng/ufw-docker's ufw rules, but automates the manual process. All you have to do is run the container with special label |
The only thing that helped me: https://p1ngouin.com/posts/how-to-manage-iptables-rules-with-ufw-and-docker |
I actually like this a lot more than https://github.com/chaifeng/ufw-docker |
Something to be aware of this solution (and every other one I've found so far) is that they're filtering the dest-port after the nat translation has been applied. This means if you have two containers listening on 443 internally but exposed on different external ports, they'll both be open. In my case I have a pub container on 443->443 and an admin container on 443->8443, so none of these workarounds manage to close off that 8443 port. |
@nathan-sav I'm using ufw-docker. You can give container a static ip address and write specific rule for that IP. In that way your problem can be solved. For example, I have multiple mysql containers running on default 3306, exposed on 3306, 3307, 3308 externally, and they all have different ufw rules. Unfortunately containers' ip address must be static, otherwise IP specific rules doesn't make sense. To solve that problem, I started ufw-docker-automated. |
Yeah unfortunately that doesn't work for me, I don't want to manage container ips like that and I don't like the idea of needing a script to watch for IP changes and update rules appropriately. I think I have a better solution in the works, I'll follow up if/once I'm successful :) |
Ok, here's what I came up with and this works much better for me:
It works by tagging the allowed packets in the NAT table and then allowing them later on in the filter table, rather than doing the matching at filter time (when you're dealing with already natted packets). It all fits into /etc/ufw/after.rules:
There might be bugs but so far it seems to work reliably, I've restarted docker/ufw a bunch of times with various combinations of them being enabled at boot. Feedback welcome! |
This is more a fundamental part of iptables than anything to do with docker. It's just because the filter tables come after nat.
Marking is definitely a good workaround (annoying that you can't just drop in nat but such is life). Be careful about |
Agreed, I just mentioned it so other people wouldn't be caught off guard after reading this thead.
Excellent point, I'll see if I can come up with a cleaner way to handle that :) |
Might just be able to do |
I've heard about this problem. So in other words when you do |
Correct. Iptables filtering rules are applied AFTER the nat rules are applied, so iptables first of all maps 8443 -> 443, then the destination port 443 allow rule lets it through. This is why ufw-docker suggests setting manual ips to your containers and putting those ips into the rules. |
@nathan-sav It looks like the Check out |
There's another work around which uses reverse proxy from Nginx or Apache (installed locally) to map ports to containers bind to localhost. However, it adds extra complexities and reduces the flexibilities of using Docker. |
That's essentially what I ended up doing after quickly tiring of fiddling around with UFW after rules and such, with one simple difference. I set up a Nginx reverse proxy directly on the host system with a minimal configuration that does nothing but forward all queries (including request headers) directly to a Traefik container bound to a localhost port. Traefik then works as expected, dynamically forwarding to containers as I bring them up and down as if it were being accessed directly. The difference is that my firewall behaves as expected with straightforward ufw commands as in days of yore. It's working well so far, though I still have to do some fine tuning, like whether to make Nginx the TLS termination proxy or pass that on through to Traefik. I'm inclined to do the former because it suits my particular needs and allows me the flexibility to serve stuff via Nginx directly from the host on another port/virtualhost or whatever. |
As rootless becomes more common, this may solve itself to an extent, but still, gaping security hole for newcomers- this really needs better, sane defaults! |
Exactly. It should have mentioned it somewhere on the documentation. I guess ufw is just one of those firewall solutions out there (though quite popular), and Docker thinks that it is not worth mentioning. |
Reminder to people following: ufw is just an iptables wrapper. The issue is Docker installs its own chain at the very start of iptables, which effectively ignores all of your firewall rules. Putting Dockers chain at the end of iptables, or at least, after ufw's chain could solve this (since ufw has no ability to modify chains other than its own). |
Docker already provides integration with Firewalld, respecting the way Firewalld works. I do not think it would be such a stretch to also support UFW and how UFW works, respecting the hierarchy in iptables. |
This really hasn't been addressed? |
No. At least I see nothing related to this in the last release logs. |
I am new to all this but would |
In 2023 there is still no update AFAIK. |
What about this solution? #690 (comment) This worked for me, simple and easy to implement. |
There is a well known security concern when running Docker on a Ubuntu host that uses UFW as its main firewall: Docker's manipulation of iptables bypasses the rules created by UFW, enabling access by default to containers with ports mapped despite UFW being enabled. Though there are existing methods of securing the network (e.g. binding to 127.0.0.1), the extra security of UFW can be desirable.
See:
Most of these recommend disabling iptables manipulation with
--iptables=false
and manually configuring the rules as necessary.More recently, two other workarounds have surfaced which do not use this flag and seem to be more robust:
These are at least a year old now, and despite the many results it's still not common knowledge as searches continue: https://trends.google.com/trends/explore?q=docker%20ufw&geo=US
It seems that the Docker team isn't interested in addressing this on their end, so the purpose of this issue is to request community feedback, determine best practices, and create a PR to hopefully add something to the documentation.
The text was updated successfully, but these errors were encountered: