Uncomplicated Firewall (UFW) is not blocking anything when using Docker

49,337

Solution 1

The problem was using the -p flag on containers.

It turns out that Docker makes changes directly on your iptables, which are not shown with ufw status.

Possible solutions are:

  1. Stop using the -p flag. Use docker linking or docker networks instead.

  2. Bind containers locally so they are not exposed outside your machine:

    docker run -p 127.0.0.1:8080:8080 ...

  3. If you insist on using the -p flag, tell docker not to touch your iptables by disabling them in /etc/docker/daemon.json and restarting:

    { "iptables" : false }

I recommend option 1 or 2. Beware that option 3 has side-effects, like containers becoming unable to connect to the internet.

Solution 2

16.04 presents new challenges. I did all the steps as shown Running Docker behind the ufw firewall BUT I could NOT get docker plus UFW to work on 16.04. In other words no matter what I did all docker ports became globally exposed to the internet. Until I found this: How to set Docker 1.12+ to NOT interfere with IPTABLES/FirewallD

I had to create the file /etc/docker/daemon.json and put the following in:

{
    "iptables": false
}

I then issued sudo service docker stop then sudo service docker start FINALLY docker is simply following the appropriate rules in UFW.

Additional data: Docker overrules UFW!

Solution 3

If you're using the init system of systemd (Ubuntu 15.10 and later) edit the /etc/docker/daemon.json (might need to create it if it does not exist), make sure it has iptables key configured:

{   "iptables" : false }

EDIT: this might cause you to lose connection to the internet from inside containers

If you have UFW enabled, verify that you can access the internet from inside containers. if not - you must define DEFAULT_FORWARD_POLICY as ACCEPT on /etc/default/ufw and apply the trick described here: https://stackoverflow.com/a/17498195/507564

Solution 4

In my case I've ended up modifying iptables to allow access to Docker only from specific IPs.

As per ESala's answer:

If you use -p flag on containers Docker makes changes directly to iptables, ignoring the ufw.

Example of records added to iptables by Docker

Routing to 'DOCKER' chain:

-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

Forwarding packets from 'DOCKER' chain to container:

-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 6379 -j DNAT --to-destination 172.17.0.3:6379

You can modify iptables to allow access to DOCKER chain only from specified source IP (e.g. 1.1.1.1):

-A PREROUTING -s 1.1.1.1 -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -s 1.1.1.1 ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER

You may want to use iptables-save > /tmp/iptables.conf and iptables-restore < /tmp/iptables.conf to dump, edit, and restore iptables rules.

Solution 5

A fast workaround is when running Docker and doing the port mapping. You can always do

docker run ...-p 127.0.0.1:<ext pot>:<internal port> ...

to prevent your Docker from being accessed from outside.

Share:
49,337

Related videos on Youtube

ESala
Author by

ESala

Experienced Software Engineer with a demonstrated history of working in the research industry. Strong technical professional with a Master's Degree focused in Industrial Electronics and Automatics from the Technical University of Catalonia (UPC). Currently completing a PhD in Data Science applied to the improvement of the Energy Efficiency of HVAC in Smart Buildings. Skilled in Backend Applications with Java, Kotlin and Spring Framework, and Data Science with Matlab and Python. Interested in Microservices, Reactive Programming, the Internet of Things, Android Development and Electronics.

Updated on September 18, 2022

Comments

  • ESala
    ESala over 1 year

    This is my first time setting up an Ubuntu Server (14.04 LTS) and I am having trouble configuring the firewall (UFW).

    I only need ssh and http, so I am doing this:

    sudo ufw disable
    
    sudo ufw reset
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    
    sudo ufw allow 22/tcp
    sudo ufw allow 80/tcp
    
    sudo ufw enable
    sudo reboot
    

    But I can still connect to databases on other ports of this machine. Any idea about what am I doing wrong?

    EDIT: these databases are on Docker containers. Could this be related? is it overriding my ufw config?

    EDIT2: output of sudo ufw status verbose

    Status: active
    Logging: on (low)
    Default: deny (incoming), allow (outgoing), deny (routed)
    New profiles: skip
    
    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW IN    Anywhere
    80/tcp                     ALLOW IN    Anywhere
    22/tcp (v6)                ALLOW IN    Anywhere (v6)
    80/tcp (v6)                ALLOW IN    Anywhere (v6)
    
    • solsTiCe
      solsTiCe almost 9 years
      what database ? which port ? Are you sure this is the same machine ? what is the output of ufw status
    • ESala
      ESala almost 9 years
      @solsTiCe yes, I am sure it is the same machine. The database is InfluxDB (on a docker container) with ports 8083 and 8086. I added the ufw status verbose output in the question. Thanks.
  • Andreas Reiff
    Andreas Reiff about 8 years
    This is so useful - I was going crazy with being able to access ports I had not allowed in ufw. Using iptables=false breaks a lot though, like containers becoming accessible on localhost, e. g. for reverse proxying. Better to make sure that container listen correct, don't use -p 80:80 but use -p 127.0.0.1:80:80 or different port like 127.0.0.1:3000:80 for reverse proxying with nginx or apache and no port clashes.
  • ESala
    ESala about 8 years
    @AndreasReiff you are right, but lately I have found it best to avoid -p as much as possible. For example, in the case of a reverse proxy I don't map any port for the worker containers, and then put nginx in it's own container with -p 80:80 and a --link to the others. This way there cannot be any port clashes and the only point of access is through nginx.
  • Henk
    Henk about 8 years
    Also check this post for a third precaution you have to take! svenv.nl/unixandlinux/dockerufw
  • orshachar
    orshachar over 7 years
    Important : /etc/default/docker is a configuration file used by the upstart config. If you have moved from upstart to systemd, this file will not be used.
  • ctbrown
    ctbrown over 6 years
    @ESala You should think about un-marking this answer as correct since it is dated.
  • ctbrown
    ctbrown over 6 years
    With Ubuntu 16.04 and Docker version 17.09, this solution breaks outbound connection from the containers. See response askubuntu.com/a/833363/262702 and askubuntu.com/a/954041/262702
  • spencer.sm
    spencer.sm almost 5 years
    Why does it work when using 127.0.0.1 but not with localhost or 0.0.0.0?
  • paleo13
    paleo13 almost 4 years
    This solution worked for me - thank you!
  • Duco
    Duco about 3 years
    Thank you so much! This answer still holds true as of 2021. It was driving me nuts I could access my database from anywhere, but with this answer I finally fixed the problem.
  • Somebody
    Somebody about 3 years
    woah! that's some serious security breach...
  • Y.Terz
    Y.Terz over 2 years
    This doesn't seem right, as according to the documentation, "an ephemeral host port is chosen for the host port". I think it's better to use expose instead.