Lösung 1:
Nachdem ich ein paar Tage damit verbracht hatte, mir Protokolle und Konfigurationen für die beteiligten Komponenten anzusehen, wollte ich gerade das Handtuch werfen und zu Fedora 30 zurückkehren, wo dies sofort einsatzbereit zu sein scheint.
Als ich mich auf die Firewall konzentrierte, wurde mir klar, dass das Deaktivieren von firewalld
schien zu funktionieren, aber ich würde es vorziehen, das nicht zu tun. Beim Überprüfen der Netzwerkregeln mit iptables
, habe ich festgestellt, dass die Umstellung auf nftables
bedeutet, dass iptables
ist jetzt eine Abstraktionsschicht, die nur einen kleinen Teil der nftables
zeigt Regeln. Das bedeutet die meisten – wenn nicht alle – der firewalld
Konfiguration wird außerhalb des Geltungsbereichs von iptables
angewendet .
Ich war es gewohnt, in iptables
die ganze Wahrheit zu finden , also wird es etwas gewöhnungsbedürftig sein.
Um es kurz zu machen – damit das funktionierte, musste ich Masquerading aktivieren. Es sah aus wie dockerd
hat dies bereits durch iptables
getan , aber anscheinend muss dies speziell für die Firewall-Zone für iptables
aktiviert werden maskieren, um zu arbeiten:
# Masquerading allows for docker ingress and egress (this is the juicy bit)
firewall-cmd --zone=public --add-masquerade --permanent
# Specifically allow incoming traffic on port 80/443 (nothing new here)
firewall-cmd --zone=public --add-port=80/tcp
firewall-cmd --zone=public --add-port=443/tcp
# Reload firewall to apply permanent rules
firewall-cmd --reload
dockerd
neu starten oder neu starten , und sowohl eingehender als auch ausgehender Traffic sollten funktionieren.
Lösung 2:
Was in den vorherigen Antworten fehlt, ist die Tatsache, dass Sie zuerst Ihre Docker-Schnittstelle zu der von Ihnen konfigurierten Zone hinzufügen müssen, z. public (oder fügen Sie es der hier vorgeschlagenen "vertrauenswürdigen" Zone hinzu, aber ich bezweifle, dass dies aus Sicherheitsgründen sinnvoll ist). Weil es standardmäßig keiner Zone zugewiesen ist. Denken Sie auch daran, den Docker-Daemon neu zu laden, wenn Sie fertig sind.
# Check what interface docker is using, e.g. 'docker0'
ip link show
# Check available firewalld zones, e.g. 'public'
sudo firewall-cmd --get-active-zones
# Check what zone the docker interface it bound to, most likely 'no zone' yet
sudo firewall-cmd --get-zone-of-interface=docker0
# So add the 'docker0' interface to the 'public' zone. Changes will be visible only after firewalld reload
sudo nmcli connection modify docker0 connection.zone public
# Masquerading allows for docker ingress and egress (this is the juicy bit)
sudo firewall-cmd --zone=public --add-masquerade --permanent
# Optional open required incomming ports (wasn't required in my tests)
# sudo firewall-cmd --zone=public --add-port=443/tcp
# Reload firewalld
sudo firewall-cmd --reload
# Reload dockerd
sudo systemctl restart docker
# Test ping and DNS works:
docker run busybox ping -c 1 172.16.0.1
docker run busybox cat /etc/resolv.conf
docker run busybox ping -c 1 yourhost.local
Lösung 3:
Um feinkörnige Regeln für Docker festlegen zu können, musste ich docker0 nicht auf eine Zone festlegen.
# 1. Stop Docker
systemctl stop docker
# 2. Recreate DOCKER-USER chain in firewalld.
firewall-cmd --permanent \
--direct \
--remove-chain ipv4 filter DOCKER-USER
firewall-cmd --permanent \
--direct \
--remove-rules ipv4 filter DOCKER-USER
firewall-cmd --permanent \
--direct \
--add-chain ipv4 filter DOCKER-USER
# (Ignore any warnings)
# 3. Docker Container <-> Container communication
firewall-cmd --permanent \
--direct \
--add-rule ipv4 filter DOCKER-USER 1 \
-m conntrack --ctstate RELATED,ESTABLISHED \
-j ACCEPT \
-m comment \
--comment 'Allow docker containers to connect to the outside world'
firewall-cmd --permanent \
--direct \
--add-rule ipv4 filter DOCKER-USER 1 \
-j RETURN \
-s 172.17.0.0/16 \
-m comment \
--comment 'allow internal docker communication'
# Change the Docker Subnet to your actual one (e.g. 172.18.0.0/16)
# 4. Add rules for IPs allowed to access the Docker exposed ports.
firewall-cmd --permanent \
--direct \
--add-rule ipv4 filter DOCKER-USER 1 \
-o docker0 \
-p tcp \
-m multiport \
--dports 80,443 \
-i eth0 \
-o docker0 \
-s 1.2.3.4/32 \
-j ACCEPT \
-m comment \
--comment 'Allow IP 1.2.3.4 to docker ports 80 and 443'
# 5. log docker traffic (if you like)
firewall-cmd --direct \
--add-rule ipv4 filter DOCKER-USER 0 \
-j LOG \
--log-prefix ' DOCKER: '
# 6. Block all other IPs.
This rule has lowest precedence, so you can add allowed IP rules later.
firewall-cmd --permanent \
--direct \
--add-rule ipv4 filter DOCKER-USER 10 \
-j REJECT \
-m comment \
--comment 'reject all other traffic to DOCKER-USER'
# 7. Reload firewalld, Start Docker again
firewall-cmd --reload
systemctl start docker
Dies endet in Regeln, die in /etc/firewalld/direct.xml:
definiert sind<?xml version="1.0" encoding="utf-8"?>
<direct>
<chain ipv="ipv4" table="filter" chain="DOCKER-USER"/>
<rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'Allow docker containers to connect to the outside world'</rule>
<rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-j RETURN -s 172.17.0.0/16 -m comment --comment 'allow internal docker communication'</rule>
<rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-p tcp -m multiport --dports 80,443 -s 1.2.3.4/32 -j ACCEPT -m comment --comment 'Allow IP 1.2.3.4 to docker ports 80 and 443'</rule>
<rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="0">-j LOG --log-prefix ' DOCKER TCP: '</rule>
<rule ipv="ipv4" table="filter" chain="DOCKER-USER" priority="10">-j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'</rule>
</direct>
Der Nachteil ist immer noch, dass Sie containerd.io von CentOS7 installieren müssen, wie von Saustrup angegeben