run a centos8 container on a centos7 host iptables duplicate - docker

when run a centos8 container on a centos7 host. in the container, add a iptables rule to one CHAIN(eg, filter table INPUT CHAIN), the rule will not only be added to INPUT CHAIN ,but also other CHAINs(eg OUTPUT,FORWARD, even PREROUTING,POSTROUTING)
run a centos8 container on a centos7 host
docker run -it --privileged centos:8 sh
when it running, install iptables in container
yum install -y iptables
show iptables version: iptables -V
iptables version: v1.8.4 (nf_tables)
list current rules: iptables -t nat -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
# Warning: iptables-legacy tables present, use iptables-legacy to see them
add a new rule: iptables -I INPUT -i eth0 -j REJECT
list rules again: iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- eth0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- eth0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- eth0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
# Warning: iptables-legacy tables present, use iptables-legacy to see them
and I have test if run centos8 container on a centos8 host,this would not happen.

In one word: host and container mix iptables and nftables.
https://github.com/kubernetes/kubernetes/issues/71305
https://bugzilla.redhat.com/show_bug.cgi?id=1668007

Related

How do I prevent Docker from source NAT'ing traffic on Synology NAS

On a Synology NAS, it appears the default setup for docker/iptables is to source NAT traffic going to the container to the gateway IP. This fundamentally causes problems when the container needs to see the correct/real client IP. I do not see this issue when running on an ubuntu system, for example.
Let me walk you though what I'm seeing. On the Synology NAS, I'll run a simple nginx container:
docker run --rm -ti -p 80:80 nginx
(I have disabled the Synology NAS from using port 80)
I'll do a curl from my laptop and I see the following log line:
172.17.0.1 - - [05/May/2020:17:02:44 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"
Hm... the client IP (172.17.0.1) is the docker0 interface on the NAS.
user#synology:~$ ifconfig docker0
docker0 Link encap:Ethernet HWaddr 02:42:B5:BE:C5:51
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
<snip>
When I first saw this, I was quite confused because I did not recall docker networking working this way. So I fired up my ubuntu VM and tried the same test (same docker run command from earlier).
The log line from my curl test off box:
172.16.207.1 - - [05/May/2020:17:12:04 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.64.1" "-"
In this case the docker0 IP was not the source of the traffic as seen by the container.
user#ubuntu-vm:~# ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
<snip>
So it appears that the docker network setup for a Synolgy NAS is different vs a more standard ubuntu deployment. Okay, neat. So how does one fix this?
This is where I'm struggling. Clearly something is happening with iptables. Running the same iptables -t nat -L -n command on both systems shows vastly different results.
user#synology:~$ iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
DEFAULT_OUTPUT all -- 0.0.0.0/0 0.0.0.0/0
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
DEFAULT_POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0
Chain DEFAULT_OUTPUT (1 references)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain DEFAULT_POSTROUTING (1 references)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (1 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
user#ubuntu-vm:~# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 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 -- 0.0.0.0/0 !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 0.0.0.0/0
MASQUERADE all -- 172.18.0.0/16 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
I do not really understand how these chains work or why they're different for different systems. I haven't changed any docker level settings on either system, these are default configs.
Has anyone ran into this before? Is there a quick way to toggle this?
I've experienced this issue myself while using Pi-hole (described here) and this iptables rule seems to fix it:
sudo iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
Be aware that this is not permanent, so if you reboot the NAS you will have to apply it again.
Update: Here's a more "permanent" fix: https://gist.github.com/PedroLamas/db809a2b9112166da4a2dbf8e3a72ae9

Why Docker NAT iptables has RETURN in first row?

Hello StackOverflow users.
Now I'm studying docker nat network especially in iptables.
I executed docker command like below.
Make it to accessible from remote server computer.
docker run -d -p 32170:80 --name nginx_server nginx
When I investigate iptables nat table. I found something weird.
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 !localhost/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 anywhere
RETURN all -- 192.168.123.0/24 base-address.mcast.net/24
RETURN all -- 192.168.123.0/24 255.255.255.255
MASQUERADE tcp -- 192.168.123.0/24 !192.168.123.0/24 masq ports: 1024-65535
MASQUERADE udp -- 192.168.123.0/24 !192.168.123.0/24 masq ports: 1024-65535
MASQUERADE all -- 192.168.123.0/24 !192.168.123.0/24
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:5000
MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:http
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
DNAT tcp -- anywhere anywhere tcp dpt:5000 to:172.17.0.2:5000
DNAT tcp -- anywhere anywhere tcp dpt:32170 to:172.17.0.3:80
As I searched, packet first checked in PREROUTING.
So its rule is like below and packet should go to DOCKER chain.
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL
After it came to DOCKER chain.
My queistion is here... As like below all packets are matched to RETURN and back to previous chain.
If it is right, then when does its source address is changed to docker container and when does its port is changed to docker port?
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- anywhere anywhere
To summarize I have two questions
What is ADDRTYPE match dst-type LOCAL meaning?
When and where does outside packet's source and port will be changed in iptables?
Is there any reference about iptables NAT in docker?
You can try use iptables -t nat -L -v.
The result contins in.
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
3088 185K RETURN all -- docker0 any anywhere anywhere
0 0 RETURN all -- br-5db28a02ac5c any anywhere anywhere
0 0 DNAT tcp -- !docker0 any anywhere anywhere tcp dpt:postgres to:172.17.0.2:5432
28 1792 DNAT tcp -- !docker0 any anywhere anywhere tcp dpt:8084 to:172.17.0.3:8082
14 860 DNAT tcp -- !docker0 any anywhere anywhere tcp dpt:us-srv to:172.17.0.3:8081
Only package from docker0 will return

how DOCKER chain in iptables works?

I'm new to docker.
Recently I experienced somewhat strange scenario.
I created ubuntu instance in OCI(Oracle Cloud Infrastructure).
When I started nginx process in this ubuntu instance, access from external network fails.
When I started nginx with docker container, access from external network successes.
After some search, I found that INPUT chain in iptables does not allow tcp 80.
Additionally, docker will update my iptables to ADD rule in PREROUTING chain.
Here is result of command sudo iptables -nL -t nat.
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DOCKER all -- 0.0.0.0/0 0.0.0.0/0 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 -- 0.0.0.0/0 !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 0.0.0.0/0
MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
But as you can see in DOCKER chain, I think, RETURN rule is always applied former than DNAT rule.
This means, DOCKER chain does not do anything!
Can anybody give any explanations on this?
One possible assumption is that RETURN rule is applied last regardless of order of rule. (But I'm not sure this is true or not).
Thanks!
RETURN rule actually will be applied at first, but it is not mean to ignore other rules. There also have another two variables IN and OUT which describe the rule's input and output.
You can add -v to your command to show it.
$ iptables -nL -v -t nat
......
Chain DOCKER (2 references)
pkts bytes target prot opt in out source destination
12 720 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
1691 107K DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8601 to:172.17.0.2:8601
......

Block port from the outside except for Docker

I installed a jenkins via Docker on my server and assigned to a specific domain (jenkins.mydomain.com), which works perfectly fine. But I can also reach jenkins (and every other service in docker) if I browse my domain with the service's port, for example: mydomain.com:8181
I'v already tried a few thing to block the port from the outside and make it only accessible via domain, but no luck.
First I tried to block the port for the eth0 interface:
iptables -A INPUT -i eth0 -p tcp --destination-port 8181 -j DROP
But it didn't work because when I tried to reach jenkins from the domain, I'v got an error 503.
Also tried to block the port for every incoming requests except docker's ip. It didn't work either.
So how can I make the ports unaccessible from the outside but accessible for Docker?
iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 DOCKER-ISOLATION all -- 0.0.0.0/0 0.0.0.0/0
2 DOCKER all -- 0.0.0.0/0 0.0.0.0/0
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Chain DOCKER (1 references)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:3000
2 ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
3 ACCEPT tcp -- 0.0.0.0/0 172.17.0.3 tcp dpt:8081
4 ACCEPT tcp -- 0.0.0.0/0 172.17.0.4 tcp dpt:50000
5 ACCEPT tcp -- 0.0.0.0/0 172.17.0.4 tcp dpt:8080
Chain DOCKER-ISOLATION (1 references)
num target prot opt source destination
1 RETURN all -- 0.0.0.0/0 0.0.0.0/0

Can't run Docker daemon on Intel Edison

i'm trying to install Docker on my Intel Edison that is running Ubilinux, but need some help.
i compiled the source code using this guide -> https://github.com/docker/docker/blob/master/project/PACKAGERS.md
... but when i try to run the daemon with "./docker daemon" i get this error:
xotl#ubilinux:~/docker/bundles/1.9.0-dev/binary$ sudo ./docker daemon
INFO[0000] Listening for HTTP on unix (/var/run/docker.sock)
INFO[0000] [graphdriver] using prior storage driver "aufs"
INFO[0000] Option DefaultDriver: bridge
INFO[0000] Option DefaultNetwork: bridge
INFO[0000] Firewalld running: false
FATA[0001] Error starting daemon: Error initializing network controller: Error creating default "bridge" network: Failed to program NAT chain: Failed to inject docker in PREROUTING chain: iptables failed: iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER: iptables: No chain/target/match by that name.
(exit status 1)
xotl#ubilinux:~/docker/bundles/1.9.0-dev/binary$
Need help. =(
EDIT:
This is the output of the sudo iptables -L -v command:
xotl#ubilinux:~/docker/bundles/1.9.0-dev/binary$ sudo iptables -L -v
[sudo] password for xotl:
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- any docker0 anywhere anywhere ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- docker0 !docker0 anywhere anywhere
0 0 ACCEPT all -- docker0 docker0 anywhere anywhere
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain DOCKER (0 references)
pkts bytes target prot opt in out source destination
xotl#ubilinux:~/docker/bundles/1.9.0-dev/binary$
This is the output of the sudo iptables -L -v -t natcommand:
xotl#El-Edison:~/docker/bundles/1.9.0-dev/binary$ sudo iptables -L -v -t nat
[sudo] password for xotl:
Chain PREROUTING (policy ACCEPT 4 packets, 1312 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 4 packets, 1312 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 65 packets, 4940 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 65 packets, 4940 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- any !wlan0 10.10.0.0/21 anywhere
Chain DOCKER (0 references)
pkts bytes target prot opt in out source destination
Docker requires a 64-bit version of your Operating system (https://docs.docker.com/engine/installation/ubuntulinux/). The Intel Edison runs a 32-bit processor and will not be able to run Docker (at least, that's what I found after spending some time researching this.

Resources