Why can a port can be accessible from outside although it is not in firewall open ports on centos 7?

Solution 1:

Docker installs its own firewall rules directly into the kernel of the host server when you publish a port, without using the abstraction layer user-friendly firewall management tools, such as firewalld footnote 1and the associated firewall-cmd (or similarly ufw or Shorewall and others) provide.

Since docker doesn't use them any rules docker creates typically won't be shown when you only use those tools to inspect your firewall.

To see what rules Docker (or any other application that creates its own rules) actually creates in your firewall you will need to to use the more low level iptables and/or iptables-save commands that will show the actual live configuration in the kernel.

Try

 [sudo] iptables -L -v -n --line-numbers 

and

[sudo] iptables -L -v -n -t nat --line-numbers

or use

[sudo] iptables-save

Usually the firewall rules Docker creates will have precedent because they are inserted before the rules managed by your user-friendly firewall management tool.

I run a docker with a springboot program listening on port 8080, which is mapped to 9182 of the host machine, 9182 is not in the opening ports list, but I can still access the web server through http://<HOST_MACHINE_IP>:9182, what is wrong?

Nothing is wrong.

That is exactly what you instructed Docker to do when you created a published port:

Published ports
By default, when you create a container, it does not publish any of its ports to the outside world. To make a port available to services outside of Docker, or to Docker containers which are not connected to the container’s network, use the --publish or -p flag. This creates a firewall rule which maps a container port to a port on the Docker host.

https://docs.docker.com/config/containers/container-networking/

To add more access controls on a port published by Docker requires creating your own rules in the DOCKER-USER iptables chain as documented here: https://docs.docker.com/network/iptables/


footnote 1 Since docker 20.10.0 docker should intgrate with firewalld according to the documentation here: https://docs.docker.com/network/iptables/#integration-with-firewalld

Solution 2:

None of the answers really explain the cause.

As said HermanB, Docker creates its own rules... but not anywhere!

There are two chains where the filter table is important for input traffic: INPUT and FORWARD

  • Firewalld uses the INPUT filter table for its rules.

  • Docker creates routings in PREROUTING chain's DNAT table. That has for consequence to route the packets to the FORWARD chain and not INPUT chain.

Therefore, all the traffic supposed to be consumed by Docker containers "bypass" the firewall.

Searching "firewalld docker" on serverfault will give you tens of similar questions.

Solution:

Having to manually add iptables rules defeats the purpose of Firewalld. That's a shame Docker can't work with Firewalld properly. Nevertheless, I believe we can do something much cleaner by telling Firewalld to apply the same rules in the FORWARD chain AND place the Firewalld's custom chains before the Docker's chains.

Currently, the Firewalld custom chains (FORWARD_direct, FORWARD_IN_ZONES, FORWARD_OUT_ZONES) come after the Docker custom chains (DOCKER-USER, DOCKER-ISOLATION-STAGE-1, DOCKER).

  • iptables -vL -t filter
  • https://github.com/firewalld/firewalld/issues/461