Docker not subject to firewall?

I am trying to run a few docker containers. Previously, I was running all of my containers with network_mode: "host", and the only way I could access the services running in the containers was to apply a port forward or traffic rule.

I recently tried setting up a custom docker network, so all of my containers are in their own network and address each other by their "hostname"(ie - container name)

Once I did this; I inadvertantly discovered that none of the port forwards and traffic rules were necessary. ALL of the services running in ALL of the containers are exposed to WAN. I even tried setting one of the port forwards to REJECT, and the container was still exposed to WAN. I even tried setting the firewall zone containing my custom docker interface to REJECT/REJECT/REJECT and the container(s) are still exposed to WAN!

Does that seem right? is it expected that docker networks are exposed to WAN and not subject to firewall?

I could run my containers in host network, which does appear to put them behind the firewall, but it seems odd that all containers are simply not subject to the firewall?

Docker expose creates individual forward rules, you can still control that traffic pre/post routing.

i am using docker compose, and i am specifying ports. are you telling me that dockerd is setting up firewall rules per the ports specified in docker compose?

edit: or... do you mean EXPOSE ... in the actual dockerfile definition is used to create firewall rules?

Yes, both ways, you can see them with iptables-nft-ssave or nft list ruleset

I did this:

  1. Don't touch Docker0.
  2. Config firewall Docket0 <===> LAN transparent
  3. All containers IPs refer to router LAN: 192.168.x.1

Then I could access the container by 192.168.x.1:9000 for example for Portainer.

i can access the service running in the container fine: but that is my concern, i can access it even though I have 1) set docker firewall zone to REJECT/REJECT/REJECT AND set a rul to reject port 5000 (for example).

and after all that, i can still access the service.

Those configure last rule in chain, if docker expose installs rules those come before final rule.

1 Like

My docker exposed in my sub network, I do not care it, my main router has its own firewall to reject any illegal access.

my docker contaner is running, forwarded 5000:5000:

# docker ps
CONTAINER ID   IMAGE                                    COMMAND                  CREATED              STATUS          PORTS                                       NAMES
87cadebdf55c   mtconnect/agent:2.3                      "mtcagent run agent.…"   About a minute ago   Up 41 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   agent
bfa8555df215   lscr.io/linuxserver/code-server:latest   "/init"                  17 hours ago         Up 16 hours                                                 code-server

thre is no nft rules at all referencing 5000:

root@OpenWrt:/opt/docker/volumes/code-server/_data/workspace/mxi-fleet-gen# nft list ruleset|  grep 5000
root@OpenWrt:/opt/docker/volumes/code-server/_data/workspace/mxi-fleet-gen# 

...but the service is still accesible from WAN? Im happy if there is a rule generated in the background that is allowing this, but as far as i can tell, docker bridge has punched a huge hole inthe firewall

check iptables-save , the xt bridge hides filter.

im sorry, what is iptables-save?

i guess all im looking for is a way to confirm, through reading config, that my ports are exposed via explicit rule(s) as opposed to just side-stepping the firewall

1 Like

Just bind all the ports of your container to a specific IP address. This should expose the ports only to that IP address instead of all addresses (0.0.0.0/0).

See here:

the following is my iptables list, cmd: iptables -t nat -L

iptables -t nat -L

root@RAX3000M:~#
root@RAX3000M:~#
root@RAX3000M:~# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere !127.0.0.0/8 ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 anywhere
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:1883
MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:8086
MASQUERADE tcp -- 172.17.0.4 172.17.0.4 tcp dpt:3000
MASQUERADE tcp -- 172.17.0.6 172.17.0.6 tcp dpt:9000

Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
DNAT tcp -- anywhere anywhere tcp dpt:1883 to:172.17.0.2:1883
DNAT tcp -- anywhere anywhere tcp dpt:8086 to:172.17.0.3:8086
DNAT tcp -- anywhere anywhere tcp dpt:3000 to:172.17.0.4:3000
DNAT tcp -- anywhere anywhere tcp dpt:9000 to:172.17.0.6:9000
root@RAX3000M:~#

firewall

This is not final setups, still under study.

1 Like

that is helpful. it appears that at least some rules are being added. here is mine, running a service on 5000 and also on 8080.

# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  anywhere            !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        anywhere            
MASQUERADE  all  --  172.18.0.0/16        anywhere            
MASQUERADE  tcp  --  172.18.0.2           172.18.0.2           tcp dpt:8080
MASQUERADE  tcp  --  172.18.0.3           172.18.0.3           tcp dpt:5000

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:8080 to:172.18.0.2:8080
DNAT       tcp  --  anywhere             anywhere             tcp dpt:5000 to:172.18.0.3:5000

and they appear to be removed when the respective container is stopped.

i dont know too much about iptables - the extent of my firewall knowledge is using generic routers and luci to configure firewalls, so i understand concepts but not inner workings. it appears that at minimum these rules are being added dynamically as opposed to some blanket docker pass through, which is good.

hi,

what version of owrt are you using?
have you read /etc/config/dockerd?
because the answer is there: yes, by default a) dockerd wants to control firewall b) it is supporting iptables per design no native nft support (yet) c) docker ports are exposed on all interfaces including WAN. you need to add wan to blocked_interfaces.