Why is firewalld allowing public traffic to my non-public ports, bound to Docker containers?

Solution 1:

Well, it turns out that the problem stems from the fact that I'm using Docker for my internal ports. In order to simplify the process of getting containers to talk to the world and each other, Docker made the choice to take a large amount of control over your firewalls/networking. This means that if you don't want your containers to be publicly accessible AND you need to control public access via the firewall on the same machine as your Docker daemon, you need to configure your firewalls slightly differently. Docker has some official documentation on how to do this. Basically, you have the following options:

  • Set up a separate machine just for your firewall. This would probably be the easiest, since Docker and your firewall wouldn't have to share resources.
  • Add your iptables rules to the DOCKER-USER chain (this is more of an answer for iptables users; I'm not sure how to get firewalld to replicate this approach)
  • Disable the whole thing by setting iptables=false in your Docker service config. (this blog post discusses this option)

I also found a post that I thought was a nice variation on the DOCKER-USER chain option. Basically, you create an iptables.conf file that you can load without a flush using iptables-restore -n. Unfortunately, it's an iptables solution, not a firewalld solution.

One of the hard parts of diagnosing this issue was that I would run a script to modify the firewall to match what I wanted, and that would work until I restarted the machine or started up the Docker daemon. Docker overwrites the iptables config when it starts up.