Ich versuche, eine ziemlich einfache Firewall in Fedora zu implementieren, bei der das öffentliche Internet auf SSH, HTTP, HTTPS und Cockpit zugreifen kann, aber sonst auf nichts. In der Zwischenzeit führen die Server über Docker Microservices aus, die über die Ports 8000-8999 miteinander kommunizieren können.
Ich habe dies auf einer Neuinstallation von Fedora Server mit den folgenden Befehlen eingerichtet:
firewall-cmd --zone=public --add-service=cockpit
firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --add-service=https
firewall-cmd --zone=internal --add-source=192.168.1.65
firewall-cmd --zone=internal --add-source=192.168.1.66
firewall-cmd --zone=internal --add-port=8000-8999/tcp
firewall-cmd --runtime-to-permanent
Wenn ich meine Konfiguration mit überprüfe --list-all
, sieht alles korrekt aus:
> firewall-cmd --list-all --zone=internal
internal (active)
target: default
icmp-block-inversion: no
interfaces:
sources: 192.168.1.65 192.168.1.66
services: dhcpv6-client ssh
ports: 8000-8999/tcp
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
> firewall-cmd --list-all --zone=public
public (active)
target: default
icmp-block-inversion: no
interfaces: enp2s0
sources:
services: cockpit dhcpv6-client http https ssh
ports:
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
Wenn ich dies jedoch teste, kann ich treffenhttp://192.168.1.65:8080. Ich kann es von einem Rechner im selben internen Netzwerk (192.168.128.128) aus aufrufen, ebenso wie eine öffentliche Anfrage von einem externen Rechner. Da keines von internal
beiden in aufgeführt war sources
, nahm ich an, dass Firewalld die Anfragen nicht durchlassen würde.
Ich habe eine automatisch konfigurierte docker
Zone mit der docker0
Schnittstelle, aber wenn ich diese entferne, ändert das anscheinend nichts an meiner Fähigkeit, den internen Port zu erreichen.
Warum kann ich :8080 erfolgreich von Quellen anfordern, die nicht auf aufgeführt sind internal
?
Antwort1
Nun, es stellt sich heraus, dass das Problem daher rührt, dass ich Docker für meine internen Ports verwende. Um den Prozess zu vereinfachen, Container mit der Welt und untereinander kommunizieren zu lassen, hat Docker beschlossen, einen Großteil der Kontrolle über Ihre Firewalls/Netzwerke zu übernehmen. Das bedeutet, dass, wenn Sienichtmöchten, dass Ihre Container öffentlich zugänglich sindUNDSie müssen den öffentlichen Zugriff über die Firewall auf demselben Computer wie Ihren Docker-Daemon steuern. Sie müssen Ihre Firewalls etwas anders konfigurieren.Docker verfügt über eine offizielle Dokumentation dazu, wie dies zu tun ist.Grundsätzlich stehen Ihnen folgende Möglichkeiten zur Verfügung:
- Richten Sie eine separate Maschine nur für Ihre Firewall ein. Dies ist wahrscheinlich am einfachsten, da Docker und Ihre Firewall keine Ressourcen gemeinsam nutzen müssen.
- Fügen Sie der Kette Ihre
iptables
Regeln hinzuDOCKER-USER
(das ist eher eine Antwort füriptables
Benutzer; ich bin nicht sicher, wie ichfirewalld
diesen Ansatz replizieren kann) - Deaktivieren Sie das Ganze durch entsprechende Einstellungen
iptables=false
in Ihrer Docker-Dienstkonfiguration. (dieser Blog-Beitragdiskutiert diese Option)
ich auchhabe einen Beitrag gefundendas fand ich eine nette Variante der DOCKER-USER
Kettenoption. Im Grunde erstellt man mit eine iptables.conf
Datei, die man ohne Flush laden kann iptables-restore -n
. Leider ist das keine iptables
Lösung, sondern eine firewalld
Lösung.
Einer der schwierigen Aspekte bei der Diagnose dieses Problems bestand darin, dass ich ein Skript ausführte, um die Firewall meinen Wünschen entsprechend zu ändern. Dies funktionierte, bis ich den Computer neu startete oder den Docker-Daemon startete. Docker überschreibt die iptables
Konfiguration beim Start.
Antwort2
Ich konnte das Problem durch die Neuerstellung der DOCKER-USER
Kette beheben und möchte sie weitergeben, falls sie jemand anderes nützlich findet.
Dies basiert auf einer Lösung, die ich auf Github gefunden habe (https://github.com/firewalld/firewalld/issues/869) und auf dem Blog eines Genies (https://roosbertl.blogspot.com/2019/06/docker-ports-mit-firewalld-sichern.html), aber ich musste es ein wenig anpassen/verfeinern.
# 1. Stop Docker
systemctl stop docker.socket
systemctl stop docker.service
# 2. Recreate DOCKER-USER iptables chain with firewalld. Ignore warnings, do not ignore errors
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
# 3. Add iptables rules to DOCKER-USER chain - unrestricted outbound, restricted inbound to private IPs
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment 'Allow containers to connect to the outside world'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 127.0.0.0/8 -m comment --comment 'allow internal docker communication, loopback addresses'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 172.16.0.0/12 -m comment --comment 'allow internal docker communication, private range'
# 3.1 optional: for wider internal networks
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 10.0.0.0/8 -m comment --comment 'allow internal docker communication, private range'
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 1 -j RETURN -s 192.168.0.0/16 -m comment --comment 'allow internal docker communication, private range'
# 4. Block all other IPs. This rule has lowest precedence, so you can add rules before this one later.
firewall-cmd --permanent --direct --add-rule ipv4 filter DOCKER-USER 10 -j REJECT -m comment --comment 'reject all other traffic to DOCKER-USER'
# 5. Activate rules
firewall-cmd --reload
# 6. Start Docker
systemctl start docker.socket
systemctl start docker.service