Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
InstanceServices all -- anywhere link-local/16
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:http
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
Hereās my VPS with Ubuntu and Docker. Thereās a testing Nginx container serving the port 80. Based on the FORWARD chain, the rules firstly entered the the DOCKER-USER which is empty. Then it proceed to DOCKER-ISOLATION-STAGE-1 which wrapped with DOCKER-ISOLATION-STAGE-2. In the DOCKER-ISOLATION-STAGE-2 all traffics are dropped. But why the Nginx Welcome page is still reachable? I have read the iptables docs and trying with all LLMs including ChatGPT, Gemini and Claude, but canāt figure it out .
Do you want to learn about iptables or do you have a problem with a container port which shouldnāt be available but it is? By the way Docker Desktop wonāt create iptables rules on your host (or maybe it will, I actually donāt know, but not these) :).
Iām not using the Docker Desktop but the normal Docker for ubuntu servers. I want to learn about the iptables that how Docker are working with it, because the behavior and the rules are not making sense to me(I canāt figure it out).
Then make sure you create your topics in the right category. I moved it to Docker Engine.
Regarding the rules, Iām not so good at iptables, but I will check it when it is not so late as it is for me now. Maybe you will get an answer before that.
When I first saw your iptables rules I didnāt understand it either, than I relized some information was missing. There are a couple of ways to get the rules and it seems you ran iptables -t nat -L and iptables -t filter -L
That will show you the source IP addresses and destination IP addresses or āanywhereā instead of 0.0.0.0/0. But what is missing is the interfaces. The flag -n will show you the ip addresses as numbers even if it means "anywhere" and the flag -v` will enable verbose mode which will show more columns like in and out interfaces. For example for me in a virtual machine where only a portainer container is running.
iptables -t filter -vnL
Output:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 DOCKER-USER all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 DOCKER-ISOLATION-STAGE-1 all -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain DOCKER (1 references)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- !docker0 docker0 0.0.0.0/0 172.30.0.2 tcp dpt:9000
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
pkts bytes target prot opt in out source destination
0 0 DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
pkts bytes target prot opt in out source destination
0 0 DROP all -- * docker0 0.0.0.0/0 0.0.0.0/0
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
That shows in the isolation stage 1 there is only a return rule to go back to where the isolation stage 1 chain was called, and another rule to go to isolation stage 2 only when the in interface is docker0 but the out interface is not. It just means only when a process in a container on the default docker bridge requests something from outside that network.In the isoaltion stage 2 it drops packages only when the out interface is docker0, but in the previous stage it just filtered that case out. So packages will be dropped only when the isolation stage 2 was called from somewhere else or when isolation stage 1 is changed and it allows docker0 as out interface. So basically nothing happens here. These seems to be default rules until something changes them to restrict access.
Other ways to get the rules that might be more familiar to you if you wrote iptables rules:
use -S instead or -L
iptables -t filter -S
Using -v is not necessary as it would just add -c 0 0 which doesnāt help to undestand the rules better and -n is not supported as this returns lines that you could use as parameters of iptables.
If you installed iptables-persistent, you can run
iptables-save
or
iptables-save -t filter
or get only the filter table. This will return an output that could be saved in a file that you can use to restore
the rules using iptables-restore.
When I tried to refresh my memory about iptables, I found this blogpost which is a good summary of iptables
It includes a picture in svg format (if you open it in a new tab, you can zoom in) from wikipedia
That picture is something I donāt fully understand. It rquires deeper knowledge about the network layers