How can I configure my firewall to work with Docker?

7,831

Solution 1

This is not possible in vanilla UFW because of the fact that the interface name is in a constant state of unguessability. In order to set something like this up, a manually defined network should be created. In short, one can use the driver options of Docker's bridge in the compose config to create a custom network. This will look something like:

networks:
    my_bridge:
        driver: bridge
        driver_opts:
            com.docker.network.bridge.name: my-bridge

From here, the bridge config can be added to each service in the compose file:

myimage:
    image: myimage:1.0
    ports:
        - "2580:2580"
    networks:
        - my_bridge

Then, upon next start of the Compose system, the new network will be created with the proper name:

my-bridge Link encap:Ethernet  HWaddr 11:22:33:44:55:66  
      inet addr:172.18.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
      inet6 addr: fe80::42:1122:3344:5566/64 Scope:Link
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:11 errors:0 dropped:0 overruns:0 frame:0
      TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0 
      RX bytes:788 (788.0 B)  TX bytes:695 (695.0 B)

From there, adding UFW rules to allow connection to port 1234 are trivial:

ufw allow in on my-bridge from any to any port 1234

And suddenly, everything works perfectly!

Solution 2

To integrate the accepted answer, you can also use a docker command to create the network outside of docker-compose:

sudo docker network create -d bridge -o com.docker.network.bridge.name=my-bridge my_bridge

After that you can inspect the networks issuing

ip link show

Now, in your compose files you can just re-route the default network or define any network you like remapping it to the already existing one

version: "3"
services:
  test:
    image: nginx:alpine
    ports:
      - "80:80"
networks:
  default:
    external:
      name: my_bridge
Share:
7,831

Related videos on Youtube

Kaz Wolfe
Author by

Kaz Wolfe

Hello. You showed up in my review queue. You will be reviewed and re-tagged if necessary. Failure to comply may result in harm. Yes, I am a wolf. Awoo. IT director for a warehousing company, doing networking, systems, and support. My languages of choice are Java and Python. One of the six people who actually like MongoDB. Self-declared cybersecurity expert. If you need me, swing by the AskUbuntu General Room or contact me on Discord. If you want to talk to me over e-mail for some reason, shoot a message to the below listed address. Please don't spam me. Notable Achievements Wrote WolfBot. And abandoned it. And then went back to working on it. And then archived it to go work on Discord chatbots Played video games Managed to nuke an entire Linux install, live. And then fix it, live. Reddit. Operate DIY Tech, a partnered Discord server. Honestly not much. I'm pretty boring. Contact Information PGP Key: 2588 13F5 3A16 EBB4 (Keybase Enabled) Discord: KazWolfe#2896 E-mail: (username)@linux.com

Updated on September 18, 2022

Comments

  • Kaz Wolfe
    Kaz Wolfe over 1 year

    My computer is hosting an application on port 1234 that should never be accessible from anything but my machine. However, my Docker container (which is running Apache) should be able to access this. Similarly, my Docker container is hosting a number of resources on various ports that should similarly be only accessible from my computer. Now, this is further complicated by the fact that my system uses a bridge for that specific network:

    NETWORK ID          NAME                DRIVER              SCOPE
    4d4b5e752963        bridge              bridge              local               
    c387eb42698a        project_default     bridge              local               
    6818c0eb94bf        host                host                local               
    f7e4ed6c05a2        none                null                local  
    

    This bridge (annoyingly) always has a randomly generated ID that changes each time I restart my Docker Compose setup:

    br-c387eb42698a Link encap:Ethernet  HWaddr 02:42:29:95:fd:2c  
              inet addr:172.18.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
              inet6 addr: fe80::42:29ff:fe95:fd2c/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:405753 errors:0 dropped:0 overruns:0 frame:0
              TX packets:530699 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:85147217 (85.1 MB)  TX bytes:75260996 (75.2 MB)
    

    In short, I need the following:

    • Any host on br-c387eb42698a (or whatever the network name is) to access port 1234 on my local machine (conveniently 172.18.0.1)
    • My machine to be able to access any port on any host on that subnet. (default)
    • The world to never be able to access any port from the subnet or port 1234.

    Ideally, a solution here would work in an IP-agnostic way such that it does not depend on the bridge being on the 172.18.0.0/24 subnet, nor would it break or allow data leaks if I'm connected to a network that happens to contain the 172.18.0.0/24 subnet.

    The easiest thing I can think of would be to use the interface name and set up UFW rules around that, but I can't really do that as my interface is constantly changing.

    How can I do this? While I'd prefer to do this in pure ufw (or iptables if necessary), I'm open to solutions that entail configuring Docker to always assign a persistent ID (or even custom name?) to the bridge interface.

    • Andrea Lazzarotto
      Andrea Lazzarotto about 7 years
      How are you initializing/restarting the container to set up the bridge?
    • Kaz Wolfe
      Kaz Wolfe about 7 years
      @AndreaLazzarotto I'm using Docker Compose being called by a systemd service.
    • Andrea Lazzarotto
      Andrea Lazzarotto about 7 years
      Ok. I was looking at this and it mentions a bridge option that you can pass to docker. Have you tried this approach?
    • Kaz Wolfe
      Kaz Wolfe about 7 years
      @AndreaLazzarotto Thanks for the help, I found something based on what you sent that seems to work for now.