>

Docker ports being exposed to Internet

Docker ports being exposed to Internet

When I began setting up my Docker containers ports to be accessed through Nginx, I faced an annoying problem. Even though my firewall (UFW, in this case) was correctly configured to deny direct access to the containers ports, somehow, the firewall rules were bypassed.

The solution for this problem was quite simple and it can even be found in the official docker documentation. The problem was how I had set the the container variable ports in the docker compose file.

In the docker compose file, when you want to share some port, you can either choose by the keyword expose or ports.

If you want to open the ports of your containers, to be accessed for services running on the host machine, then you should use the ports keyword.
If you want to open the ports of your containers, to be accessed ONLY for containers on the same network, then you should use expose.

Contextualizing my use case, my current infrastructure uses both the docker compose and docker swarm environments.

The above solution works pretty well for containers launched by docker compse up. Unfortnely, I only have one container launched in that way (a instance of swagger-ui). All the remaining containers are orchestrhed within a docker swarm.

Solution for Docker Swarm

By default, the docker swarm binds the node ports on 0.0.0.0, allowing any IP to connect to the containers within the swarm. This behavior is expected and makes sense since docker swarm was designed to allow external nodes to ingress the swarm.

Therefore, even with the expose keywords being used and UFW correctly configured to deny direct access to the ports, the microservices running within the swarm remain exposing their ports to the internet through {domain}:{port}.

But why this is a problem? In this particular project I am using Kong as API gateway. It's easy to setup and until now I am pretty satisfied with it, in addition, I can enable plugins for some functionalities e.g., requesting an api key to access the endopints, provided by key-auth plugin.

The kong is set by default to run on port 8000 to expose my API endopints, and it is not a problem to expose this port to internet. However, the Kong service also provides access to port 80001, to setup available routes and access plugin's configurations, including key-auth. And that is the problem.

By accessing {domain}:{8001}/key-auths all my API keys are listed. For me, this is a no-go. In that case, I could simply remove the port exposure by deleting it from the docker-compose. But I wanted something better.

Unfortunately, the replacement of the ports keyword with the expose keyword do not work in a swarm environment.

Therefore, it is necessary to ensure that docker will not bypass UFW configurations. The majority of solutions that I found deals directly with iptables, which is something I did not touch yet. Fortunely, I found the answer below from tsuna (link follows directly to the github thread).

docker and ufw serious problems · Issue #4737 · moby/moby
Having installed ufw and blocking all incoming traffic by default (sudo ufw default deny) by running docker images that map the ports to my host machine, these mapped docker ports are accessible fr…

All I needed to do was to edit the file /etc/ufw/after.rules with the excerpt below and reload ufw.

# Put Docker behind UFW

:DOCKER-USER - [0:0]
:ufw-user-input - [0:0]

-A DOCKER-USER -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-USER -m conntrack --ctstate INVALID -j DROP
-A DOCKER-USER -i eth0 -j ufw-user-input
-A DOCKER-USER -i eth0 -j DROP
COMMIT
sudo ufw reload

That is no container exposing their ports to the internet anymore, at least I open the ports manually in UFW.