Moby: Docker Network umgeht Firewall, keine Option zum Deaktivieren

Erstellt am 14. Apr. 2016  ·  114Kommentare  ·  Quelle: moby/moby

Ausgabe von docker version :

Client:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 15:54:52 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.10.3
 API version:  1.22
 Go version:   go1.5.3
 Git commit:   20f81dd
 Built:        Thu Mar 10 15:54:52 2016
 OS/Arch:      linux/amd64

Ausgabe von docker info :

Containers: 14
 Running: 5
 Paused: 0
 Stopped: 9
Images: 152
Server Version: 1.10.3
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 204
 Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Plugins: 
 Volume: local
 Network: bridge null host
Kernel Version: 3.13.0-58-generic
Operating System: Ubuntu 14.04.4 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 7.793 GiB
Name: brm-pheonix-dev
ID: Y6Z4:6D53:RFOL:Z3CM:P7ZK:H6HL:RLV5:JT73:LZMC:DTBD:7ILK:2RS5
Username: benjamenmeyer
Registry: https://index.docker.io/v1/

Zusätzliche Umgebungsdetails (AWS, VirtualBox, physisch usw.):
Rackspace Cloud Server, Ubuntu 14.04, aber das sollte eigentlich egal sein

Schritte zum Reproduzieren des Problems:

  1. Richten Sie das System mit einer gesperrten Firewall ein
  2. Erstellen Sie eine Reihe von Docker-Containern mit exponierten Ports
  3. Überprüfen Sie die Firewall; docker wird "anywhere" als Quelle verwenden, wodurch alle Container der Öffentlichkeit zugänglich sind.

Beschreiben Sie die Ergebnisse, die Sie erhalten haben:
root@brm-pheonix-dev :~/rse# iptables --list DOCKER
Kette DOCKER (1 Referenzen)
Ziel-Prot-Opt-Quell-Ziel
AKZEPTIEREN tcp -- überall 172.17.0.2 tcp dpt: 6379

Beschreiben Sie die erwarteten Ergebnisse:
root@brm-pheonix-dev :~/rse# iptables --list DOCKER
Kette DOCKER (1 Referenzen)
Ziel-Prot-Opt-Quell-Ziel
AKZEPTIEREN tcp -- 127.0.0.0/24 172.17.0.2 tcp dpt:6379
AKZEPTIEREN tcp -- 172.16.0.0/16 172.17.0.2 tcp dpt:6379

Zusätzliche Informationen, die Sie für wichtig erachten (z. B. ein Problem tritt nur gelegentlich auf):

Standardmäßig sperrt Docker die Firewall auf eine Weise, die die Sicherheit bricht – es erlaubt dem gesamten Datenverkehr von allen Netzwerkgeräten, auf die exponierten Ports von Containern zuzugreifen. Stellen Sie sich eine Site mit zwei Containern vor: Container A stellt 443 bereit, auf dem Nginx ausgeführt wird, und Container B führt eine API auf Port 8000 aus. Es ist wünschenswert, Container A für die Öffentlichkeit zu öffnen, Container B jedoch vollständig auszublenden, damit er nur mit localhost kommunizieren kann (zum Testen durch den Benutzer) und das Docker-Netzwerk (um mit Container A zu sprechen). Zu Testzwecken kann es auch wünschenswert sein, dass Container C eine Datenbank ist, die von Container B mit den gleichen Einschränkungen verwendet wird.

Ich fand dies, weil ich Protokolle eines Dienstes überwachte, von dem ich dachte, dass er nicht für die Öffentlichkeit zugänglich wäre. Nachdem ich Protokolleinträge von Quellen gefunden hatte, die versuchten einzubrechen, überprüfte ich die Firewall-Regeln und stellte fest, dass es keine Begrenzung der Quelladressen oder Schnittstellen gab. Ich verwende UFW und erlaube nur SSH auf dieser speziellen Box und würde es vorziehen, dies so zu belassen. Dies kann sich dramatisch auf die Verwendung von Docker-Containern zur Bereitstellung von Diensten auswirken und zu potenziellen Sicherheitsproblemen führen, wenn die Leute nicht aufpassen.

Die beste Sicherheitspraxis wäre, das Netzwerk standardmäßig so einzuschränken, dass es wie oben beschrieben funktioniert, und dem Benutzer dann zu erlauben, die entsprechende Firewall usw. Ich weiß, dass dies aus Legacy-Gründen unwahrscheinlich ist, da es bei der Aktualisierung viele Dinge kaputt machen würde; Es wäre also zumindest ein guter erster Schritt, die oben genannte Option zu aktivieren, die jetzt aktiviert werden kann, und möglicherweise später nach langer Warnung zum Standardverhalten zu machen. Angenommen, das Standardverhalten ist sicher, wäre es eine großartige Möglichkeit, dies zu verwalten (Firewall->Enable Public Port, IP) in der Docker-Compose-Yml-Datei, um sichtbar zu machen, was vor sich geht.

Ich habe die Option --iptables=false gefunden, möchte jedoch nicht alle Regeln selbst festlegen müssen. Das einzige, was ich beanstande, ist die Quelleneinstellung für die Regeln.

Obwohl ich es nicht überprüft habe, vermute ich, dass alle von Docker unterstützten Firewalls das gleiche Problem haben.

arenetworking versio1.10

Hilfreichster Kommentar

Das Problem, das Ben ans Licht bringt, ist real und überraschend (eine schlechte Kombination). Viele Admins, wie ich, verwenden die bewährte ufw-Firewall. Docker macht und beendet ufw und ändert die iptables-Regeln so, dass 1) ufw den aktuellen Status der Paketfilterregeln falsch meldet und 2) scheinbar private Dienste dem öffentlichen Netzwerk zugänglich gemacht werden. Damit Docker in der Gunst der Sysadmin-Gemeinde bleibt, muss ein anderer Ansatz gefunden werden. Im Moment gibt es viele Admins, die, wie Ben und ich, versehentlich Ports für das breitere Internet geöffnet haben. Im Gegensatz zu Ben und mir haben sie es jedoch noch nicht herausgefunden.

Alle 114 Kommentare

Hinweis: Mir ist in https://github.com/docker/docker/blob/master/vendor/src/github.com/docker/libnetwork/iptables/iptables.go aufgefallen, dass es nicht einmal eine Option zum Einstellen der Quelle gibt , es werden also nur die iptables-Standardeinstellungen für Quell-IP/Gerät verwendet.

Es ist nicht ganz #14041, da dieses Thema über exponierte Ports spricht. Das Offenlegen von Ports soll sie öffentlich zugänglich machen, da Sie auf diese Weise Dienste für die Außenwelt verfügbar machen. Wenn Sie in einer Entwicklungsumgebung arbeiten, können Sie entweder den Zugriff auf Ports von außerhalb Ihres Computers mit einer Host-Firewall deaktivieren oder die Ports einfach nicht verfügbar machen und direkt oder von anderen Containern im selben Netzwerk auf die Dienste zugreifen.

Ich würde Ihnen empfehlen, die neueren Docker-Netzwerkfunktionen zu verwenden, um private Netzwerke für Dienste einzurichten, die überhaupt nicht verfügbar gemacht werden sollen, siehe https://docs.docker.com/engine/userguide/networking/

Daran habe ich zuerst gedacht; war aber etwas verwirrt, weil _exposing_ a port ( EXPOSE ), eigentlich nichts tut, aber _publishing_ a port ( -p / -P ) macht ihn tatsächlich auf dem Gastgeber.

Wenn Sie tatsächlich von _publishing_ sprechen, dann ist dies wie geplant;

In Ihrem Beispiel sollten Container B und C ihre Ports nicht veröffentlichen, und Container A kann mit ihnen über das Docker-Netzwerk kommunizieren, z.

docker network create mynet

docker run -d --net=mynet --name=api api-image
docker run -d --net=mynet --name=db database-image
docker run -d --net=mynet --name=web -p 443:443 nginx

Dadurch wird nur der "Web"-Container auf dem Host veröffentlicht. Der Web-Container kann über ihren Namen auf die Container "API" und "Datenbank" zugreifen (dh http://api :80/ und db:3306 (unter der Annahme von MySQL))

@justincormack , ich glaube nicht, dass die Verwendung eines privaten Netzwerks das Problem löst. In meinem Fall verwende ich ein privates Netzwerk zwischen den Containern, und sie sind immer noch öffentlich zugänglich, da die Host-Firewall nicht so konfiguriert ist, dass sie die Exposition gegenüber dem privaten Netzwerk begrenzt.

@thaJeztah Das Problem liegt immer noch an der Firewall-Unterstützung - es gibt keine Firewall-Unterstützung in Docker, um sie auf ein bestimmtes Netzwerk zu beschränken. Sie können wahrscheinlich immer noch von einem anderen System auf diese Container zugreifen, da die Firewall andere Systeme nicht daran hindert, auf den Port auf dem Host zuzugreifen.

Jetzt führe ich dies über docker-compose aus; Es ist jedoch nicht ausschließlich ein Docker-Compose-Problem, da die libnetwork-Funktionalität _keine_ Möglichkeit hat, das Netzwerk in den Firewall-Regeln einzuschränken - iptables-Regeln haben keine Quellspezifikation, also unabhängig davon, wie man das Netzwerk konfiguriert, solange man sich auf Docker verlässt, um die zu erstellen Firewall-Regeln (was man tun sollte, weil es wahrscheinlicher ist, dass sie richtig sind), dann wird dies zu einem Problem. Berücksichtigen Sie Folgendes in einer docker-compose.yml-Datei:

nginx:
    build: ./docker/nginx/.
    ports:
        - "127.0.0.1:8080:80"
        - "127.0.0.1:443:443"
    environment:
        DESTINATION_HOST: repose
    links:
        - repose
repose:
    build: ./docker/repose/.
    ports:
        - "127.0.0.1:80:8080"
    environment:
        DESTINATION_HOST: phoenix
        DESTINATION_PORT: 8888
    links:
        - phoenix
curryproxy:
    build: ./docker/curryproxy/.
    ports:
        - "127.0.0.1:8081:8081"
    external_links:
        - rse_rse_1
        - rse_rse_2
        - rse_rse_3
phoenix:
    build: .
    ports:
        - '127.0.0.1:88:8888'
    links:
        - curryproxy:curry
    external_links:
        - rse_rse_1:rse
        - rse_rse_2
        - rse_rse_3
        - rse_cache_1:cache
    volumes:
        - .:/home/phoenix

Das obige ist ein Auszug aus einem meiner Projekte. Während ich in der Lage sein möchte, alle lokal von meinem Host aus zu testen, möchte ich, dass niemand anderes auf etwas anderes als die nginx-Instanz zugreifen kann.

Ich bin mir nicht sicher, wie sich dies auf Ihre Nomenklatur ausdrückt ... es kann sein, dass dies Teil des "Veröffentlichungs"-Aspekts ist und die Veröffentlichungsfähigkeiten erweitert werden müssen, um das zu tun, was ich sage.

Wenn dies beabsichtigt ist, dann ist es ein schlechtes Sicherheitsmodell, da Sie jetzt alle Entwickler extremen Risiken aussetzen, wenn sie sich in unbekannten Netzwerken befinden (z. B. auf Reisen).

Wie gesagt, ich erwarte nicht, dass sich die Standardeinstellung sofort ändert, aber die Option wäre ein guter erster Schritt.

Ich bin dann etwas verwirrt, können Sie einige externe Beispiele dafür geben, womit Sie eine Verbindung herstellen können? Die Backend-Dienste befinden sich (standardmäßig) im 172.17.0.0/16 Netzwerk, auf das Sie von außen nicht zugreifen können.

Es gibt ein potenzielles Problem, wenn Ihre externe IP auch eine private IP ist, dass der Verkehr, der für die internen Netzwerke geroutet wird, nicht verworfen wird (während er von öffentlich zu privat sein sollte) - ist das das Problem?

@justincormack also

firewall:
    external:
        ports:
            - 80
            - 443

Jetzt kann die Situation etwas gemildert werden, indem die Netzwerkzuordnung auf dem _host_ auf 127.0.0.1 statt auf die Standardzuordnung 0.0.0.0 beschränkt wird. Beachten Sie, dass dies dies wirklich abschwächt, da sonst das Bridging den Host-Port in das Docker-Netzwerk weiterleitet.

Und ja, ich habe überprüft, dass diese Begrenzung funktioniert; Es bleiben jedoch potenzielle Schwachstellen bestehen und die Firewall-Regeln stimmen nicht mit dem überein, was tatsächlich getan wird.

Als weiteres Beispiel gab es vor einiger Zeit eine Linux-Kernel-Schwachstelle (die derzeit Probleme hat, sie zu finden), die mit Ports zusammenhängt, die in IPtables als für die Verwendung durch Anwendungen geöffnet markiert waren, aber dann nicht wirklich mit einer Anwendung verbunden waren - zum Beispiel auf einem lokalen Host-Port, aber nicht auf einem öffentlichen IP-Port. Dadurch wird dies möglicherweise eingerichtet, und es wäre besser, die IPtables-Regeln auf die erwarteten Netzwerke zu beschränken, anstatt sie offen zu lassen, um von überall aus eine Verbindung herzustellen. Wie gesagt, zumindest die Möglichkeit zu spezifizieren. Sie haben wahrscheinlich dieses spezielle Problem behoben, aber warum die Möglichkeit offen lassen?

IOW, es dreht sich alles um Sicherheit.

@BenjamenMeyer Wenn Sie nicht möchten, dass die anderen Dienste zugänglich sind, warum veröffentlichen Sie dann ihre Ports überhaupt? dh "127.0.0.1:8081:8081" wird nicht benötigt, wenn nur über das Docker-Netzwerk darauf zugegriffen wird (andere Dienste verbinden sich direkt über das Docker-Netzwerk).

Ein Problem, das ich damit habe, ist, dass ich Ports veröffentlichen möchte, aber nur bestimmten IP-Adressen den Zugriff darauf zulassen möchte.

Zum Beispiel betreibe ich eine Jenkins-Umgebung in ein paar Containern. Der Master-Knoten ist "veröffentlicht", aber ich muss einige ziemlich komplizierte iptables-Regeln erstellen, um ihn zu sperren, damit nur die beiden Büros, die wir haben, darauf zugreifen können.

Gibt es eine Möglichkeit, dies derzeit in Docker zu umgehen? Oder zumindest eine empfehlenswerte Praxis? Ich habe in der Dokumentation gesehen, wie Sie den Zugriff auf eine IP-Adresse beschränken können. aber nicht mehrere. Das andere Problem dabei ist, dass Sie, wenn Sie einen Server haben, der bereits über eine iptables-Konfiguration verfügt, möglicherweise alle Regeln zurücksetzen, bevor Sie Ihre Regeln anwenden (daher die komplizierten Regeln, die ich einrichten musste).

Ich habe ein ähnliches Problem wie das von @SeerUK. Es liegt eine eklatante Verletzung der Erwartungen vor, wenn bereits vorhandene Firewallregeln nicht für die veröffentlichten Containerports gelten. Das gewünschte Verhalten ist wie folgt (zumindest für mich)

  1. Der Versuch einer Benutzerverbindung wird basierend auf INPUT-Konfigurationen usw. gefiltert
  2. Die Weiterleitung des Datenverkehrs erfolgt dann wie gewohnt basierend auf den im Docker hinzugefügten FORWARD-Regeln

Gibt es eine prägnante Möglichkeit, dies in iptables zu erreichen, oder lässt es ein solches Konstrukt nicht ohne weiteres zu. Ich bin in meinem Wissen über iptables besonders eingeschränkt, also haben Sie Geduld. Ich habe erst kürzlich Wissen darüber gesammelt, während ich versucht habe, die Interaktionen von Docker damit zu verstehen.

Worauf ich vorerst tatsächlich zurückgegriffen habe, da ich diese Container tatsächlich auf einem ziemlich leistungsstarken dedizierten Server betreibe, habe ich eine KVM-VM eingerichtet, auf der Docker ausgeführt wird, und dann einige weitere Standard-iptables-Regeln verwendet, um den Zugriff vom Host aus einzuschränken . Die VM verfügt über eine eigene Netzwerkschnittstelle, auf die nur vom Server aus zugegriffen werden kann, daher muss ich Regeln hinzufügen, um den Zugriff auf Ports in iptables auf dem Host explizit zuzulassen. Ich habe ein bisschen an Leistung verloren, aber nicht viel.

@thaJeztah Ich möchte vom lokalen System aus darauf zugreifen und es einfach testen können. Zum Beispiel das Einrichten einer RESTful-HTTP-API mit einem Health-Endpunkt und die zuverlässige Ausführung von curl mit localhost (ich muss dies für andere dokumentieren und IP-Adressen, die sich ändern, sind nicht zuverlässig ). In den meisten Fällen möchte ich für meine Entwicklungsumgebung nur, dass die Container miteinander kommunizieren, aber ich möchte auch vom Host darauf zugreifen können.

Für @SeerUK ‚s Fall einen IP - Block der Lage gesetzt wird (5.5.0.0/16 - ein gültiger Parameter für eine Quelladresse in iptables - Regeln) wäre eine sehr gute Sache sein. IPtables verfügt bereits über die Möglichkeit, die Einschränkung vorzunehmen, aber Docker nutzt dies nicht aus.

@thaJeztah Ich habe "127.0.0.1:8081:8081" explizit gesetzt, um es vom externen Netzwerk fernzuhalten; Ich hatte in meinen Docker-Containern Protokolle von Leuten gefunden, die versuchten, über die exponierten Häfen in die Container zu knacken.

Meine Arbeit besteht im Moment darin, Docker-Container auszuschalten, bevor ich für den Tag aufbreche, weil ich nicht sicherstellen kann, dass die Umgebung, die ich extern sein möchte, tatsächlich extern _ist_, oder dass die Umgebung aus Sicherheitsgründen ordnungsgemäß eingeschränkt ist.

@BenjamenMeyer Eine Möglichkeit, dies zu tun, besteht darin, diese Tests in einem Container

docker run --net -it --rm --net=mynetwork healthchecker 

Das Problem, das Ben ans Licht bringt, ist real und überraschend (eine schlechte Kombination). Viele Admins, wie ich, verwenden die bewährte ufw-Firewall. Docker macht und beendet ufw und ändert die iptables-Regeln so, dass 1) ufw den aktuellen Status der Paketfilterregeln falsch meldet und 2) scheinbar private Dienste dem öffentlichen Netzwerk zugänglich gemacht werden. Damit Docker in der Gunst der Sysadmin-Gemeinde bleibt, muss ein anderer Ansatz gefunden werden. Im Moment gibt es viele Admins, die, wie Ben und ich, versehentlich Ports für das breitere Internet geöffnet haben. Im Gegensatz zu Ben und mir haben sie es jedoch noch nicht herausgefunden.

@thaJeztah das setzt voraus, dass ich es über die Befehlszeile mache und kein anderes Tool verwende, bei dem ich nur eine IP-Adresse festlegen muss.

Ich arbeite zum Beispiel an einer API. Ich habe ein Tool, das ich verwenden kann, um mit dieser API in der Produktion zu arbeiten, um sie zu unterstützen. für die Entwicklung des Tools und der API möchte ich das Tool nur auf die dockerisierte API verweisen. Das Tool weiß nichts über Docker und sollte es auch nicht. Und ich möchte das Tool nicht unbedingt in Docker legen, nur um es zu verwenden - es sollte ausreichen, es auf einen Port zu zeigen, der nur dem lokalen Host zugänglich ist.

@jcheroske Ich stimme zu, aber ich weiß nicht, ob es eine gute Lösung für _diesen_ Aspekt gibt. Dafür muss ufw wahrscheinlich intelligenter gemacht werden, um Regeln nachschlagen und melden zu können, an deren Erstellung es nicht beteiligt war. Es gibt eine Menge Software, die die iptables Regeln auf eine Weise anpassen kann, von der ufw (oder AFAIK-Firewalls usw.) nichts wissen. Es gibt auch keine wirklich einfache Lösung, um das zu beheben.

Trotzdem wäre es schön, wenn Docker sich in diese integrieren könnte, um die entsprechenden Konfigurationsdateien auszugeben, um sie aktivieren/deaktivieren zu können, oder in diese Tools zu integrieren, so dass es sich einklinkt und die Informationen jedoch entsprechend ausgibt es gibt bessere lösungen Ich glaube nicht, dass _dieser_ Aspekt wirklich gelöst wird. Hier geht es eher darum, den Geltungsbereich der iptables Regeln, die generiert werden, einzuschränken, um die potenziellen Auswirkungen zumindest zu minimieren, indem die Angabe der Quelle zugelassen wird (lo, eth0, 127.0.0.0/24 usw.).

Wenn Sie dazu bereit sind, macht die Verwendung von iptables dies vollständig möglich.

Dies ist ein reduziertes Beispiel dafür, wie Sie es verwenden können: https://gist.github.com/SeerUK/b583cc6f048270e0ddc0105e4b36e480

Ganz unten sehen Sie, dass 1.2.3.4 explizit Zugriff auf Port 8000 (der von Docker bereitgestellt wird) erhält, dann wird alles andere an diesem Port verworfen. Die PRE_DOCKER-Kette wird vor der DOCKER-Kette eingefügt, damit sie zuerst getroffen wird, was bedeutet, dass der DROP verhindert, dass die blockierten Anforderungen jemals die DOCKER-Kette erreichen.

Es ist ein bisschen ärgerlich, dass Docker diese Funktionalität nicht integriert hat, aber es ist jetzt möglich, sie zu umgehen.

Eine andere Alternative wäre die Verwendung einer externen Firewall. Einige Orte wie AWS und Scaleway bieten Dinge wie Sicherheitsgruppen an, in denen Sie den Zugriff auf Ihre Boxen von außen verwalten können, von dort aus verhält sich jeder Port gleich.

Ich habe es nie geschafft herauszufinden, wie das mit UFW funktioniert. Im Moment bin ich jedoch mit der Verwendung von iptables als Lösung zufrieden. Bei mir scheint es bisher sehr gut zu klappen.

Offensichtlich ist dies keine großartige Lösung, wenn Sie bereits einen einigermaßen komplizierten Satz von Firewall-Regeln um UFW herum erstellt haben. Es macht jedoch die Verwendung von Dingen wie iptables-persistent ziemlich einfach. Sie können auch alternative Methoden verwenden, um den Zugriff auf diese Weise zu ermöglichen, die in iptables "normaler" erscheinen.

@BenjamenMeyer haben Sie daran gedacht, ein benutzerdefiniertes docker network mit einer Subnetz- und IP-Bereichsoption zu verwenden und eine statische IP-Adresse für Container zuzuweisen und sie für die lokale Entwicklung zu verwenden, damit Sie sich nicht darauf verlassen müssen? eine virtuelle statische IP wie 127.0.0.1 ? Dadurch wird vermieden, dass für die Container, die für einen Host privat sind, eine Portzuordnung insgesamt erforderlich ist.

docker network create --subnet=30.1.0.0/16 --ip-range=30.1.0.0/24 mynetwork
docker run --net=mynetwork --ip=30.1.1.1 --name=myservice1 xxxx
docker run --net=mynetwork --ip=30.1.1.2 --name=myservice2 yyyy

Mit diesem Setup kann myservice2 myservice1 unter dem Namen myservice1 und es ist nicht einmal notwendig, sich auf die statische IP-Adresse zu verlassen. Auch kann der Host die statische IP frei erreichen, ohne dass ein Port-Mapping erforderlich ist.

Außerdem können Sie mit Compose 1.7 statische IP-Adressen für Container angeben und Netzwerk-Subnetze und -Bereiche angeben.

Ich habe einen einfachen Workaround gefunden.

1) Bearbeiten Sie /etc/default/docker: DOCKER_OPTS="--iptables=false"

2) ufw-Regel hinzufügen: ufw allow to <private_ip> port <port>

So einfach, dass ich mich wirklich frage, warum die Option --iptables=false nicht die Standardeinstellung ist. Warum eine solche Situation schaffen, wenn Docker nur sagen muss: "Hey, wenn Sie eine Firewall betreiben, müssen Sie ein Loch durchbohren!" Was vermisse ich?

https://fralef.me/docker-and-iptables.html
http://blog.viktorpetersson.com/post/101707677489/the-dangers-of-ufw-docker

Ich kann Docker nicht dazu bringen, iptables zu ändern, um mein Leben zu retten. Ich habe versucht, /etc/default/docker unter Ubuntu 16.04 ohne Erfolg zu aktualisieren

@enzeart Versuchen Sie /lib/systemd/system/docker.service .

@SeerUK Segne deine Seele

@enzeart Um einen Daemon zu konfigurieren, der auf einem Host läuft, der systemd verwendet, ist es am besten, die docker.unit-Datei selbst nicht zu bearbeiten, sondern eine "Drop-In" -Datei zu verwenden. Auf diese Weise treten beim Upgrade von Docker keine Probleme auf (falls es eine neuere docker.unit-Datei gibt). Weitere Informationen finden Sie unter https://docs.docker.com/engine/admin/systemd/#custom -docker-daemon-options.

Sie können auch eine daemon.json-Konfigurationsdatei verwenden, siehe https://docs.docker.com/engine/reference/commandline/daemon/#daemon -configuration-file

@mavenugo Es gibt bereits ein Docker-Netzwerk.

@jcheroske das funktioniert, aber wie ich bemerkt habe, würde es bedeuten, dass der _Endbenutzer_ (ich) dann sicherstellen müsste, dass alle iptables Regeln korrekt sind, was nicht optimal ist und nicht annähernd so wahrscheinlich ist wie Wenn docker es automatisch macht, daher dieses Problem.

Hallo, bitte hoch. Ich denke auch, dass es ein Problem ist. Containerketten in Iptables müssen den Hauptregeln entsprechen und dürfen nicht standardmäßig der Welt ausgesetzt sein.

Ich würde mir wirklich wünschen, dass Docker (und docker-compose) die Möglichkeit hat, IPs auf die Whitelist oder Blacklist zu setzen, die auf diesen Port zugreifen können.

Nehmen Sie zum Beispiel:

nginx:
    ports:
      - "8000:8000"
    whitelist:
      - 10.6.20.2

Würde bedeuten, dass nur eine Quell-IP von 10.6.20.2 auf Port 8000 auf diesem Host zugreifen kann.

@StefanPanait Ich mag diese Idee wirklich. Es könnte auch mit einer ähnlichen Syntax wie Volumes und Zugriffs-/Verweigerungslisten funktionieren, etwa:

nginx:
  access:
  - "10.0.1.6:allow"
  - "deny"

Es müsste natürlich noch Dinge wie die Kommunikation zwischen Containern zulassen.

@SeerUK Kommunikation zwischen Containern sollte eine Standardeinstellung sein, aber warum sollten Sie nicht in der Lage sein, einem Container die Kommunikation mit ihm zu verbieten? Das kann beim Debuggen sehr hilfreich sein...

Obwohl ich denke, dass dies der richtige Weg wäre, die Docker-Netzwerke zu trennen ...

nginx: access: - "10.0.1.6:allow" - "webapi:allow" - "database:deny" - "deny"
Könnte nützlich sein ... die Frage ist, ist es nützlich genug, um die Implementierung in diesem Maße zu rechtfertigen? Ich weiß nicht.

Derzeit würde ich gerne sehen, dass das ursprüngliche Problem behoben ist, dann können Funktionen wie diese hinzugefügt werden, wenn es keinen Sinn macht, in die Auflösung einzubinden (möglicherweise).

Warum sollte man einem Container nicht verbieten können, mit ihm zu sprechen? Das könnte beim Debuggen sehr nützlich sein

Dafür ist docker network disconnect ? Sie können einen Container zum Debuggen vom Netzwerk trennen und ihn mit docker network attach

Für diejenigen, die gerade entdeckt haben, dass eine Menge Ports auf ihren im Internet exponierten Servern offen waren, habe ich nach der Verwendung von UFW gegraben und gegraben und Folgendes entdeckt:

Ubuntu 16.04 mit UFW und Docker stellt neue Herausforderungen. Ich habe alle Schritte wie hier gezeigt durchgeführt: https://svenv.nl/unixandlinux/dockerrufw ABER ich konnte Docker plus UFW NICHT am 16.04. zum Laufen bringen. Mit anderen Worten, egal was ich tat, alle Docker-Ports wurden weltweit dem Internet ausgesetzt. Bis ich das gefunden habe: http://blog.samcater.com/how-to-set-docker-1-12-to-not-interfere-with-iptables-firewalld/
Ich musste die Datei /etc/docker/daemon.json erstellen und Folgendes eingeben:

{
"iptables": falsch
}

Ich habe dann sudo service docker stop ausgegeben dann sudo service docker start ENDLICH befolgt Docker einfach die entsprechenden Regeln in UFW.

Zusätzliche Daten: https://chjdev.com/2016/06/08/docker-ufw/

@thaJeztah

Warum sollte man einem Container nicht verbieten können, mit ihm zu sprechen? Das könnte beim Debuggen sehr nützlich sein
Dafür ist die Docker-Netzwerktrennung gedacht? Sie können einen Container zum Debuggen vom Netzwerk trennen und ihn mit Docker Network Attach erneut anhängen

Und was wäre, wenn die Netzwerkkonnektivität weiterhin gewünscht wäre? Beispiel: Fehler beim Testen der Integritätsprüfung von Server in Container B für Container A, während noch Dienste von Containern C, D und E bereitgestellt werden hängen vom Zugriff auf Container B ab, damit der Health Check erfolgreich ist.

Das hält dem "Lass uns das ursprüngliche Problem beheben" jedoch nicht stand.

@gts24 interessanter Fund.

IMHO, das ganze Problem ist, dass Docker, wie buchstäblich alle anderen Programme, die Firewall (iptables oder andere) überhaupt nicht berühren sollte. Wenn ich (zB) Apache installiere und ihm sage, dass es auf 0.0.0.0:80 lauschen soll, ist es meine Entscheidung, Port 80 auf der Firewall zu öffnen oder nicht, wo ich beliebige Regeln dafür festlegen kann, die ich möchte.

Anstatt Firewall-Regeln für Docker- (und/oder Compose-)Konfigurationsdateien neu zu erfinden, sollte die gesamte PUBLISH Funktion veraltet sein und eine neue LISTEN Funktion erstellt werden, die wie alle anderen Programme funktioniert. Im besten Fall könnte Docker auf Systemen, die ihn verwenden, standardmäßig deaktivierte Firewall-Dienste für jeden Port/Container erstellen.

@gcscaglia setze --iptables=false auf den Daemon und du solltest das bekommen

@thaJeztah Diese Funktion ist nutzlos, da Docker keine Alternative bietet, um die notwendigen Firewall-Regeln (oder spezifischere Trigger-Skript-Hooks mit den entsprechenden Parametern) vom Daemon zu bekommen. Es ist nur wenig nutzbar, wenn Sie statische Container haben und nie etwas daran ändern (zB veröffentlichte Ports), aber für alle anderen können Sie es vergessen.

@thaJeztah genau das, was Taladar gesagt hat.

--iptables=false sollte in --networking=false da nicht einmal das interne Container-zu-Container-Netzwerk mit deaktivierter Funktion funktioniert. Eine Option, einen Container auf eine Port/Schnittstellen-Kombination abhören zu lassen, ohne Löcher in die eingehenden Firewall-Regeln zu schlagen (zB LISTEN ), würde all dies lösen, abwärtskompatibel sein und die Verwendung von --iptables=true ermöglichen .

Mit einem solchen Hörmodus können diejenigen, die es "einfach funktionieren" wollen, weiterhin PUBLISH , und diejenigen, die die Kontrolle haben möchten, können LISTEN .

@gcscaglia ok, also wenn Sie möchten, dass Docker die Grundregeln --iptables aktiviert lassen, aber _nicht_ verwenden Sie -p / --publish . Sie sollten in der Lage sein, die IPTables-Regeln manuell festzulegen, um Ports an Container weiterzuleiten. Der Container lauscht bereits an seiner eigenen privaten IP-Adresse und an den Ports, auf denen der Dienst in Ihrem Container lauscht.

@thaJeztah Nein, das kannst du nicht. Denn Sie haben keine Ahnung, dass es überhaupt einen Container gibt, der gerade erst gestartet wurde und Firewall-Regeln benötigt. Sie haben auch keine Möglichkeit zu sagen, wer die API verwendet hat, um sie zu starten, auf welchem ​​Host-Port sie lauscht.

Einfaches Beispiel. Wir verwenden Docker-Container, um Jenkins-Jobs auszuführen. Sie legen ihren SSH-Port offen, damit Docker sie kontaktieren kann. Sie werden vernichtet, sobald die Arbeit erledigt ist. Docker bietet keine Möglichkeit, dies mit --iptables=false zum Laufen zu bringen, da Sie Jenkins (mit der Docker-API zum Starten des Containers) nicht den Host-Port mitteilen und nicht einmal ein Skript zum Setup auslösen können die notwendigen Firewall-Regeln.

Ihre Idee funktioniert nur für den lächerlich einfachen Anwendungsfall, permanente, nie wechselnde Container manuell starten zu lassen. Sogar ein einfaches --restart=always im Container wird in diesem Setup unterbrechen, es sei denn, der Container hat eine statische IP.

@taladar Ich antworte auf den Anwendungsfall von --iptables=false , sondern um es aktiviert zu lassen, aber nicht die Funktion -p / --publish (die Docker anweist, die über IPTables zugänglichen Ports).

@thaJeztah Während Sie meinen Anwendungsfall richtig verstanden haben, funktioniert AFAIK die vorgeschlagene Lösung aus den gleichen Gründen nicht für mich, aus den gleichen Gründen funktioniert sie nicht für den Fall Taladar: Ein einzelner Neustart von allem und plötzlich müssen meine manuellen Regeln aktualisiert werden. Es gibt keine Hooks oder Trigger, mit denen ich über einen Neustart benachrichtigt werden kann, damit ich ein solches Update automatisieren kann (ganz zu schweigen davon, dass ich das Rad neu erfunden habe).

Derzeit besteht die einzige Lösung für meinen Fall darin, eine weitere Firewall (die Docker nicht berühren kann) zwischen dem Docker-Host und allen externen Netzwerken zu haben. Aber wenn Docker einfach alles tun würde, was es bereits tut, außer Ports für die Welt zu öffnen, könnte ich die zweite Firewall komplett abschaffen.

Ich denke, man kann nicht alles haben, aber es ist sicherlich frustrierend. Ist es Ihrer Meinung nach wert, eine Feature-Anfrage zu meiner LISTEN Idee zu stellen, oder das Docker-Team hätte kein Interesse an einer solchen Funktion?

Was würden die LISTEN tun? Es gibt EXPOSE , mit dem Sie mit Anmerkungen versehen können, auf welchen Ports der Container lauscht. Für Trigger können Sie sich den Docker events anhören.

Ich sage nicht, dass es hier keinen Raum für Verbesserungen gibt (ich weiß, dass es geprüft wird), nur fragen Sie sich, was Sie erwarten würden

Wie Sie bereits sagten, binden derzeit alle Dienste, die in einem Container ausgeführt werden, an die private IP des Containers (wenn Sie nicht --net=host oder ähnliches verwenden). Dies ist gut und wünschenswert, da eine solche Isolierung zwischen dem Host und den Containern genau das Verkaufsargument von Docker ist.

Wenn ich jedoch derzeit möchte, dass eine Anwendung, die außerhalb eines Containers (sei es auf dem Host oder anderswo im Netzwerk) ausgeführt wird, Zugriff auf einen Dienst hat, der in einem Container ausgeführt wird, brauche ich Mittel, damit dieser Dienst auf einer der Netzwerkschnittstellen des Hosts lauscht. Um dieses Problem zu lösen, ohne die Schnittstellen eines Hosts für den Container verfügbar zu machen, hat Docker die Funktion -p / --publish , die:

  1. Erstellt iptables-Regeln, um einen ausgewählten Port auf der Schnittstelle eines ausgewählten Hosts an einen ausgewählten Port auf der privaten IP des Containers weiterzuleiten (was wir alle erwarten, da wir danach gefragt haben)
  2. Weist iptables an, jedem von überall auf der Welt den Zugriff auf diesen Port auf der Schnittstelle des ausgewählten Hosts zu ermöglichen (was für die Weiterleitung unnötig ist und daher viele von uns überrascht)

Was ich vorschlage, ist eine Funktion (mit dem Namen LISTEN oder anders), die nur "1" macht und "2" nach Ermessen des Benutzers zulässt, wie es alle anderen Dienste / Programme normalerweise tun.

Wie bei EXPOSE , AFAIK sind das nur Metadaten in Docker-Images, damit der Daemon weiß, was zu tun ist, wenn der Benutzer -P angibt (alles veröffentlichen). Vielleicht liege ich da falsch, und können "exponierte" Ports neustartsicher (ohne weltweiten Zugriff) weitergeleitet werden?

--off-topic--

IMHO fragt das OP dieses Problems genau, warum -p "2" macht und wie man Docker davon abhält, dies zu tun. Während eine Einstellung auf Daemon-Ebene (außer der Deaktivierung des Netzwerks) das Problem lösen könnte, um die Dinge abwärtskompatibel zu halten, wäre das Beste ein neues Feature (zB LISTEN oder ein anderer Name).

Während viele Benutzer diesen "out of the box"-Effekt mögen, erwartet kein Systemadministrator, dass andere Programme als ihre iptables / Firewalld Ports auf der Firewall öffnen, noch weniger auf eine Weise, die ihre Firewall-Verwaltungssoftware nicht meldet.

Ich sehe drei große Probleme:

  1. Dockers Methode zum Veröffentlichen/Freigeben von Ports umgeht gängige Firewall-Regeln wie UFW.
  2. Die obige Tatsache scheint nicht gut dokumentiert zu sein (es ist völlig unerwartet, da mir keine anderen Linux-Dienste bekannt sind, die Firewall-Regeln selbst umgehen).
  3. Es gibt keine einfache Möglichkeit, iptables an Dockers Methode zum Veröffentlichen/Freigeben von Ports anzupassen, oder die Methoden, von denen die Leute wissen, dass sie nicht einfach zu automatisieren sind und keine dokumentiert sind.

Möglicherweise ist es technisch nicht machbar, Port-Exposing an der FILTER-Tabelle zu implementieren, und daher ist Fix 1 nicht möglich. Zumindest sollte dies irgendwo eine große Warnung erhalten (Fix 2), aber idealerweise könnte 3 mit neuen Optionen gelöst werden, wie die Leute hier vorgeschlagen haben, wie allow oder deny die zusätzliche Firewall-Regeln hinzufügen würden automatisch, um bestimmte IPs für die exponierten/veröffentlichten Ports zuzulassen oder zu verweigern.

Beispiel: allow: "tcp:{your_trusted_ip}" für einen Container mit dem Namen "elasticsearch", der Port 9200 veröffentlicht, könnte Folgendes tun:

iptables -t mangle -N DOCKER-elasticsearch
iptables -t mangle -A DOCKER-elasticsearch -s {your_trusted_ip} -j RETURN
iptables -t mangle -A DOCKER-elasticsearch -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 9200 -j DOCKER-elasticsearch

Ich fand dies in den Docker-Dokumenten ziemlich nützlich: https://docs.docker.com/engine/userguide/networking/default_network/container-communication/#communicating -to-the-outside-world

Die Forward-Regeln von Docker lassen standardmäßig alle externen Quell-IPs zu. Um nur einer bestimmten IP oder einem bestimmten Netzwerk den Zugriff auf die Container zu ermöglichen, fügen Sie eine negierte Regel am Anfang der DOCKER-Filterkette ein. Um beispielsweise den externen Zugriff so einzuschränken, dass nur die Quell-IP 8.8.8.8 auf die Container zugreifen kann, könnte die folgende Regel hinzugefügt werden:

$iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

@jmimico ja, das ist mir schon

Was ist so schwierig daran, dass Docket einfach eine Option zum Ausführen eines Shell-Skripts an einer Stelle hinzufügt, an der jetzt iptables-Regeln mit allen Docker-internen Informationen erstellt werden, die als Parameter an das Skript übergeben werden? Das würde es jedem ermöglichen, genau die Regeln zu erstellen, die er braucht. Fügen Sie eine Möglichkeit hinzu, um eine erneute Ausführung der Skripte für aktive Container auszulösen, die Benutzer aufrufen können, nachdem sie eine iptables-Wiederherstellung durchgeführt oder die Ketten aus anderen Gründen geleert haben, und Sie sind fertig.

Docker muss nicht alle Arten von vorgefertigten Firewall-Szenarien neu erstellen, wie einige Leute hier vorschlagen, die auf einem System wie diesem durch Verteilungssätze von Hook-Skripten aufgebaut werden könnten. Höchstens so etwas wie nur auf localhost verfügbar machen und global verfügbar machen (wie Docker es jetzt tut) könnte Sinn machen. IPTables hat zu viel Flexibilität, als dass Docker jemals hoffen könnte, alle Szenarien direkt in den Einstellungen zu modellieren.

Dieses Ticket gibt es anscheinend schon ewig, das aktuelle Verhalten macht Docker grenzwertig unbrauchbar (scheint die Standardmethode zu sein, um in diesem Projekt Funktionen zu implementieren, z Backend,...) und es gibt eine einfache Lösung, mit der Benutzer ihre eigenen Lösungen implementieren können, die zu ihrer Umgebung passen.

@StefanPanait Gute Frage. Meine Wette ist, dass Sie die Verwendung von Objektgruppen nutzen müssen. Füllen Sie die Objektgruppen mit IPs auf der Whitelist und verwenden Sie diese Objektgruppe dann in der ersten Zeile der DOCKER-Kette.

Beispiel:
iptables -N docker-allow
iptables -A docker-allow -s 1.1.1.1 -j ACCEPT
iptables -A docker-allow -s 2.2.2.2 -j ACCEPT
iptables -A docker-allow -s 3.3.3.3 -j ACCEPT
iptables -A docker-allow -j DROP

iptables -I DOCKER -i ext_if -j docker-allow

Werden Regeln, die der DOCKER-Kette hinzugefügt werden, nicht jemals durch Dinge wie den Neustart des Daemons überlagert? Ich denke, das Problem mit manuellen Lösungen ist, dass sie schwer richtig zu machen sind, und daher gibt es starke Argumente dafür, die üblichen Fälle (Blockieren / Zulassen einzelner IPs) direkter besser zu unterstützen.

Vielleicht wäre ein Plugin der geeignete Ort, um dies zu unterstützen? Beispielsweise könnte ein "ufw"-Plugin Regeln auf ufw-kompatible Weise hinzufügen, damit der Benutzer die Firewall mit seiner regulären Firewall-Toolchain effektiv verwalten kann und sich Docker-Dienste eher wie normale Host-Dienste verhalten.

Werden Regeln, die der DOCKER-Kette hinzugefügt werden, nicht jemals durch Dinge wie den Neustart des Daemons überlagert? Ich denke, das Problem mit manuellen Lösungen ist, dass sie schwer richtig zu machen sind, und daher gibt es starke Argumente dafür, die üblichen Fälle (Blockieren / Zulassen einzelner IPs) direkter besser zu unterstützen.

Das Hinzufügen der Löschregel zur DOCKER-USER-Kette scheint besser zu funktionieren, um sie über Docker-Neustarts hinweg persistent zu machen.

Mit Docker v.17.06 gibt es eine neue iptables-Kette namens DOCKER-USER. Dies ist für Ihre benutzerdefinierten Regeln, siehe meine Antwort auf serverfault: https://serverfault.com/questions/704643/steps-for-limiting-outside-connections-to-docker-container-with-iptables/886257#886257

Wie ich zu SF kommentiert habe, vermisse ich, warum sich diese DOCKER-USER-Kette von jeder anderen von Benutzern hinzugefügten Kette unterscheidet Sie müssen die Schnittstellennamen immer noch selbst angeben und es ist immer noch anfällig, dass Nicht-iptables-Experten schwerwiegende Fehler machen.

Auf der anderen Seite geht es immer noch mit der "Docker is the only iptables user"-Mentalität, die für Leute scheiße ist, die iptables für mehr als nur Docker verwenden wollen. Es ist also schlecht für die gesamte Bandbreite potenzieller Benutzer, außer vielleicht für die Leute, die ganze Hosts nur Docker widmen.

OK, die Verwendung von DOCKER-USER löst also das Problem der Reihenfolge von Einfügungen, indem sichergestellt wird, dass es immer vor den anderen Docker-bezogenen Regeln in der Kette steht. Dies macht es jedoch nicht viel einfacher, Verkehr zu einem Container nach Portnummer auf die Whitelist zu setzen, da --dport zu diesem Zeitpunkt der Port des Dienstes im Docker-Container ist, nicht der exponierte Port. Beispiel:

Veröffentlichen Sie Port 9900, um einen Docker-Dienst verfügbar zu machen, der intern auf 9000 lauscht.

$ sudo iptables -A DOCKER-USER -m limit --limit 20/min -j LOG --log-prefix "IPTables: "
$ docker run --rm -it -p '192.168.56.101:9900:9000' alpine nc -l 9000

Von einem anderen Computer im Netzwerk:

$ telnet 192.168.56.101 9900

Was wird protokolliert:

IPTables: IN=enp0s8 OUT=docker0 MAC=08:00:27:b6:8d:d6:0a:00:27:00:00:04:08:00 SRC=192.168.56.1 DST=172.17.0.2 LEN=52 TOS=0x00 PREC=0x00 TTL=127 ID=14127 DF PROTO=TCP SPT=51208 DPT=9000 WINDOW=64240 RES=0x00 SYN URGP=0
IPTables: IN=docker0 OUT=enp0s8 PHYSIN=veth05ba007 MAC=02:42:0f:f9:76:4c:02:42:ac:11:00:02:08:00 SRC=172.17.0.2 DST=192.168.56.1 LEN=40 TOS=0x00 PREC=0x00 TTL=63 ID=23041 DF PROTO=TCP SPT=9000 DPT=51208 WINDOW=0 RES=0x00 ACK RST URGP=0

Wie Sie sehen, gibt es an dieser Stelle keine Möglichkeit, den Verkehr auf Port 9900 zu filtern. Sicher, ich könnte den Verkehr auf 9000 filtern, aber dies ist ein Problem, da sich der interne Port unbeabsichtigt zwischen mehreren Containern oder sogar Diensten auf dem Host überlappen könnte. Dies ist eines der großen Verkaufsargumente von Docker, dass Sie mehrere Dienste auf einem Host ausführen können und sich keine Sorgen um Portkonflikte machen müssen. Viele Container sind also so konzipiert, dass sie nur auf einem Port lauschen, und der Benutzer kann die Option --publish zu ändern, welcher Port auf welcher Schnittstelle verfügbar gemacht wird:

$ docker run -d -p 7777:6379 --name data1 redis
$ docker run -d -p 8888:6379 --name data2 redis

Ich kann jedoch DOCKER-USER (bitte korrigieren Sie mich, wenn ich falsch liege) nicht verwenden, um den Datenverkehr zu data1 zu beeinflussen, ohne auch den Datenverkehr zu data2 zu beeinflussen, es sei denn, ich verwende eine Art Introspektion, um die Zielcontainer-IP zu entdecken, die vorübergehend ist und Sie zurück zu Platz eins darin, einen einfachen, zuverlässigen Weg zu finden, um veröffentlichte Dienste ohne Skripting und Introspektion durch Firewalls zu schützen.

Um es klar zu sagen, das funktioniert NICHT:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 7777 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 8888 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 7777 -j DROP
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 8888 -j DROP

Dies funktioniert zwar, aber das Ergebnis ist, dass beide Dienste beiden CIDRs auf der Whitelist ausgesetzt sind:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 6379 -j DROP

Es sieht also so aus, als ob DOCKER-USER nur nützlich ist, um alle Ports bestimmten IPs zugänglich zu machen, aber nicht um bestimmte Ports bestimmten IPs auszusetzen, es sei denn, es macht Ihnen nichts aus, Ihre iptables-Regeln so zu schreiben, dass sie auf interne Portnummern verweisen und nicht mehrere Container verwenden, die dieselben verwenden interne Portnummern. Jeder scheint diese Punkte zu vermissen und mit DOCKER-USER als Lösung zu laufen und ich denke, das verdient eine neue, bessere Lösung.

@SeerUK
Die in https://gist.github.com/SeerUK/b583cc6f048270e0ddc0105e4b36e480 gepostete Lösung hat bei mir nicht funktioniert. Kannst du bitte helfen?

Der Docker-Fehler besteht darin, iptables (Systemfirewall) zum Ausführen eines Anwendungsroutings zu verwenden. Es wird für immer Probleme und Chaos schaffen. Ändern Sie iptables, es ist sehr gefährlich. Diese im Docker eingebettete Funktion hinzuzufügen ist nicht so teuer. Darüber hinaus kann es auch einen inkonsistenten Status haben, wenn Sie docker gleichzeitig ausführen.

Es scheint, dass iptables ein seltsames Verhalten hat, wenn Sie iptables ändern, während Docker ausgeführt wird. Wenn Sie docker set iptables stoppen und Docker neu starten, funktionieren alle wie vorgesehen. Meine Sorge ist ... wenn ich iptables in der Produktion ändern muss?

Es scheint, dass iptables ein seltsames Verhalten hat, wenn Sie iptables ändern, während Docker ausgeführt wird.

iptables ist iptables, es ist egal, ob Docker läuft oder nicht.

Es ist besser, wenn Sie vorher viele Tests machen ... iptables zu sagen, dass iptables nur eine Tautologie ist. Es ist mein Vorschlag :)

Ich denke, sein Punkt war, dass sich iptables nicht anders verhält, wenn Docker wie in Ihrem Kommentar vorgeschlagen ausgeführt wird. Dies ist eindeutig ein Docker-Problem mit der Art und Weise, wie sie iptables verwenden, als ob es niemand sonst auf demselben System benötigt.

Ich verstehe nicht, warum DOCKER-USER dies nicht behebt.
Sie verwenden iptables, um nach Belieben zu filtern: Quellport, Zielport, Quelladresse, nicht-lokaler Datenverkehr usw.

Der springende Punkt von DOCKER-USER ist, dass es alle Regeln ausführt, die der Benutzer ausführen möchte, bevor Docker-Regeln ausgeführt werden.

@cpuguy83 Das Kernproblem besteht darin, dass Docker ohne Vorankündigung Ports für das öffentliche Netzwerk - außerhalb des Systems - öffnet, da es die exponierten Ports nicht an eine Netzwerkschnittstelle (wie eth0 oder lo) oder eine bestimmte IP (z. 0.1, 172.16.1.1); Die von Docker eingeführten Regeln werden auch nicht in iptables-Verwaltungstools wie UFW angezeigt - dadurch wissen Benutzer möglicherweise nicht, dass die verschiedenen Docker-Container von jedem System im Netzwerk aus zugänglich sind, nicht nur von ihrem lokalen Host.

DOCKER-USER kann das nicht lösen, da es die Docker-Netzwerke auch nicht an eine bestimmte Netzwerkschnittstelle oder eine bestimmte IP (zB 127.0.0.1) bindet.

Auf meine ursprüngliche Anfrage:
1. Docker sollte sich – basierend auf der Docker-Netzwerkkonfiguration – an eine bestimmte IP binden und dem Benutzer dann ermöglichen, Regeln hinzuzufügen, um den Container außerhalb des Systems verfügbar zu machen (mit den Tools seiner Wahl); Standardmäßig sollte der Container nicht außerhalb des Systems verfügbar gemacht werden.

  1. Das ist ohne Übergangsfrist nicht möglich, da sich zumindest einige Leute auf das historische Verhalten verlassen.

IMHO, das ganze Problem ist, dass Docker, wie buchstäblich alle anderen Programme, die Firewall (iptables oder andere) überhaupt nicht berühren sollte. Wenn ich (zB) Apache installiere und ihm sage, dass es auf 0.0.0.0:80 lauschen soll, ist es meine Entscheidung, Port 80 auf der Firewall zu öffnen oder nicht, wo ich beliebige Regeln dafür festlegen kann, die ich möchte.
Anstatt Firewall-Regeln für Docker- (und/oder Compose-)Konfigurationsdateien neu zu erfinden, sollte die gesamte PUBLISH-Funktion veraltet sein und eine neue LISTEN-Funktion erstellt werden, die wie alle anderen Programme funktioniert. Im besten Fall könnte Docker auf Systemen, die ihn verwenden, standardmäßig deaktivierte Firewall-Dienste für jeden Port/Container erstellen.

Gut gesagt @gcscaglia ! Noch verblüffender ist, dass all dies in https://docs.docker.com/engine/reference/run/#expose -incoming-ports kaum oder gar nicht erwähnt wird, was meiner Meinung nach der Ort ist, nach dem die meisten suchen ein wenig Dokumentation zur Ergänzung des Learning-by-Example-Endes. Es sollte irgendwo ein leuchtend rotes Kästchen geben, das die Risiken erklärt, dass Docker bereits vorhandene iptables-Regeln überschreibt.

Wenn Sie nicht möchten, dass Docker iptables verwaltet, legen Sie --iptables-=false
Wenn Docker nur Ports auf einer bestimmten Schnittstelle öffnen soll, können Sie dies auch in der Daemon-Konfiguration einstellen.

@BenjamenMeyer
Sie könnten den gesamten Verkehr in DOCKER-USER blockieren und nur das durchlassen, was Sie wollen.

Sie könnten den gesamten Verkehr in DOCKER-USER blockieren und nur das durchlassen, was Sie wollen.

@cpuguy83 Bitte sagen Sie mir, ob etwas, was ich hier sage, falsch ist:

$ docker run -d -p 7777:6379 --name data1 redis
$ docker run -d -p 8888:6379 --name data2 redis

Ich kann jedoch DOCKER-USER (bitte korrigieren Sie mich, wenn ich falsch liege) nicht verwenden, um den Datenverkehr zu data1 zu beeinflussen, ohne auch den Datenverkehr zu data2 zu beeinflussen, es sei denn, ich verwende eine Art Introspektion, um die Zielcontainer-IP zu entdecken, die vorübergehend ist und Sie zurück zu Platz eins darin, einen einfachen, zuverlässigen Weg zu finden, um veröffentlichte Dienste ohne Skripting und Introspektion durch Firewalls zu schützen.

Um es klar zu sagen, das funktioniert NICHT:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 7777 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 8888 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 7777 -j DROP
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 8888 -j DROP

Dies funktioniert zwar, aber das Ergebnis ist, dass beide Dienste beiden CIDRs auf der Whitelist ausgesetzt sind:

$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 192.168.56.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp -s 10.0.24.0/24 --dport 6379 -j RETURN
$ sudo iptables -A DOCKER-USER -p tcp -m tcp --dport 6379 -j DROP

Es gibt also keine Möglichkeit, den Datenverkehr zum/vom data1-Container unabhängig vom data2-Container mit DOCKER-USER zu steuern. Für mich macht das DOCKER-USER keine große Lösung.

@colinmollenhour

Wenn Sie eine generische Drop-Regel in DOCKER-USER , wie unterscheidet sich dies davon, wenn Docker angehängt oder seine Hauptsprungregel vorangestellt wurde?

@ cpuguy83 mein Punkt ist nicht gegen die Überschreibung an sich. Was ich sagen möchte, ist, dass Docker bereits vorhandene iptables-Regeln überschreiben sollte, definitiv eine Opt-in-Funktion und keine Opt-out-Funktion.

Und selbst als Opt-out – was es nicht sein sollte – sollte es extrem gut dokumentiert sein, da es völlig unerwartet und ziemlich unintuitiv zu debuggen ist. Vor allem, wenn man bedenkt, wie viele ufw . Ich kenne keine andere Software, die so etwas ohne sehr explizite Warnungen macht und ich persönlich würde mich von solcher Software fernhalten.

Darüber hinaus wird dies durch die Tatsache verschärft, dass die meisten Docker-Benutzer - zumindest nach meiner Erfahrung - damit beginnen, es in Umgebungen zu verwenden, in denen eine zusätzliche Netzwerkinfrastruktur das Problem verdeckt, was die Annahme verstärkt, dass die Maschine so konfiguriert ist, wie sie es glauben.

Ich hoffe, Docker wird zu einem LISTEN-only-Ansatz übergehen , wie am Beispiel von

Wenn Sie eine generische Drop-Regel in DOCKER-USER haben, inwiefern unterscheidet sich dies davon, wenn Docker angehängt oder seine Hauptsprungregel vorangestellt wurde?

Ich glaube nicht, dass ich Ihre Frage verstehe ... Bitte ignorieren Sie meinen Kommentar vom 22. April 2017, da dies nur in Bezug auf die Persistenz ist, die DOCKER-USER tatsächlich löst. Das Problem, auf das ich hinweist, ist nicht die Beständigkeit.

@taladar Was genau

@jacoscaz

Erstens denke ich, dass alle Betreuer darin übereinstimmen, dass das bestehende Verhalten nicht ideal ist. Leider existiert das Verhalten schon seit Ewigkeiten. Eine Standardeinstellung für etwas zu ändern, das von Millionen von Menschen verwendet wird, ist hier nicht wirklich etwas, was wir tun können. Dies ist einer der Gründe, warum wir DOCKER-USER hinzugefügt haben, damit die Leute zumindest alle Regeln einfügen können, die sie benötigen.

Wir kommen jedoch nicht darum herum, iptables (oder ebpf oder eine andere Nating-Lösung) zu verwenden UND die Funktionalität bereitzustellen, die -p bietet... verbieten Sie ihnen, -p .

Zusammenfassend können Sie:

  1. Sagen Sie Docker auf (Standard) binden an eine bestimmte Adresse (die Standardadresse ist natürlich 0.0.0.0 , oder alle Schnittstellen) ... aber das wird nicht jemand verhindern , dass manuell eine Adresse in der Angabe von -p Spezifikation (zB -p 1.2.3.4:80:80 )
  2. Fügen Sie benutzerdefinierte Regeln in DOCKER-USER , einschließlich einer Deny All
  3. Deaktivieren Sie die iptables-Verwaltung mit --iptables=false

Gibt es noch etwas, das Sie vorschlagen können, das nicht das Brechen bestehender Benutzer einschließt?

@ cpuguy83 Das verstehe ich. Ich plädiere nicht dafür, dass eine solche Änderung drastisch von einer Version zur anderen erfolgt. Ich denke, es wäre eine gute Änderung, im Laufe einer Reihe von Versionen zu planen. Ich glaube auch nicht, dass Docker aufhören sollte, iptables vollständig zu verwenden. Forwarding unterscheidet sich von ermöglicht und soweit ich verstehen kann Docker sollte standardmäßig weiterleiten können , ohne standardmäßig Zugriff auf jedermann überall möglich ist .

Was jetzt getan werden kann, sollte die zusätzliche Dokumentation dazu an erster Stelle stehen. Welches wäre der geeignetste Kanal, um dies mit den Betreuern von docker.com zu besprechen?

Wenn ihrerseits kein Interesse besteht, ist es wahrscheinlich der beste Weg, dieses Gespräch am Leben zu erhalten, um die Chancen zu maximieren, dass dieses Verhalten bekannter wird.

Ich stimme der Aufforderung zu, zusätzliche Dokumentation für diese Funktionalität hinzuzufügen. Soweit ich das beurteilen kann, wird es nur auf https://docs.docker.com/network/iptables/ erwähnt. Ich habe von diesem Problem erst erfahren, nachdem ich versucht hatte herauszufinden, warum ein Dienst, den ich durch die Firewall auf eine bestimmte IP-Adresse beschränkt hatte, der Öffentlichkeit zugänglich war. Dieses Verhalten war für mich völlig unerwartet, da es im Gegensatz zu allen anderen vernetzten Diensten steht, mit denen ich je zu tun hatte.

Mir ist bewusst, dass es Problemumgehungen gibt, aber ich denke, dies sollte für eine langfristige Änderung der Funktionsweise von Docker in Betracht gezogen werden. Ich mag die Idee, es auf einem Port auf LISTEN einzustellen und benutzerdefinierten Regeln zu erlauben, darauf aufzubauen.

Wie vorgeschlagen, habe ich DOCKER-USER eine DROP-Regel hinzugefügt, um zu verhindern, dass Container versehentlich nach außen gelangen (was alarmierenderweise geschah).

Allerdings habe ich jetzt einen Dienst, den ich vorstellen möchte. Aber wie @colinmollenhour erklärt hat, kann ich nur nach der Docker-IP (die nicht festgelegt ist) und der internen Portnummer (die für mehrere Container gleich sein könnte) filtern, da NAT vor der Filterung stattfindet.

Wie kann ich diesen einen Dienst verfügbar machen?

@SystemParadox das ist einer der vielen Gründe, warum DOCKER-USER keine wirkliche Lösung für das Problem ist.

@cpuguy83
Ich mag die vorgeschlagene LISTEN-Lösung und habe nie einen Breaking Change von einem Release zum anderen befürwortet; sondern plädierte eher dafür, die Änderung über eine Reihe von Versionen mit entsprechenden Hinweisen vorzunehmen, die b/c herausgehen.

Ich stimme auch zu, dass die Aktualisierung der Docker-Dokumentation bezüglich -p und EXPOSE usw. eine Priorität sein sollte, die sofort durchgeführt werden sollte, um zumindest auf das Problem aufmerksam zu machen. Meiner Erfahrung nach sind die meisten Leute, die Docker verwenden, keine Firewall-Experten, daher vertrauen sie darauf, dass Docker tut, was sie erwarten, was im aktuellen Design nicht der Fall ist.

Außerdem funktionieren die Zusammenfassungslösungen in https://github.com/moby/moby/issues/22054#issuecomment -425580301 auch nicht wirklich. Wieso den? Ich führe Docker nicht direkt aus, ich führe Docker Compose aus - basierend auf YAML; IP-Adressen sind dynamisch (von Docker gesteuert) und oft stelle ich mehrere Dienste innerhalb desselben Docker-Netzwerks bereit, die miteinander interagieren müssen. Somit sind sowohl die Verwendung von -p Verwendung der Adressbindung (Option 1 in der Zusammenfassung) keine Lösungen. DOCKER-USER löst nicht wirklich alles, wie andere darauf hingewiesen haben (Option 2 in der Zusammenfassung) und das vollständige Deaktivieren von IP-Tabellen (Option 3 in der Zusammenfassung) hilft auch nichts, da jetzt alles kaputt ist (IPs sind dynamisch, also schwer, eine Lösung zu skripten; Inter-Container-Netzwerk ist kaputt b/c Docker verlässt sich auf IPTables, um sich zwischen den Containern zu bewegen; etc).

Auch hier gibt es in diesem Thread keinen Aufruf zu einem Breaking Change zwischen zwei Versionen; aber ein Ruf nach einem geplanten schrittweisen Ansatz, der es den Menschen ermöglicht, angemessen zu migrieren.

Als Workaround können Sie mit -m conntrack --ctorigdstport auf den ursprünglichen Zielport zugreifen.

Also in meinem Fall habe ich folgendes:

-A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow docker out
-A DOCKER-USER -s 172.17.0.0/16 -j ACCEPT
# Allow access to docker service mapped to host 8702 (the service is actually listening on port 8088 in the container)
-A DOCKER-USER -p tcp -m conntrack --ctorigdstport 8702 -j ACCEPT
# Prevent access to docker from outside
-A DOCKER-USER -j DROP

@SystemParadox

Hurra für die richtige iptables-Lösung! 🍻

Ich hatte noch nie von --ctorigdstport aber ich denke, das liegt daran, dass ich nicht alle möglichen iptables-Erweiterungen gelesen und ausprobiert habe und Sie meines Wissens der Erste in diesem Zusammenhang sind.

Ich habe es getestet und das funktioniert tatsächlich:

$ docker run -d -p 7777:6379 --name data1 redis
$ docker run -d -p 8888:6379 --name data2 redis
$ sudo iptables -N DOCKER-USER-redis1
$ sudo iptables -A DOCKER-USER-redis1 -s 192.168.56.0/24 -p tcp -m tcp -j RETURN
$ sudo iptables -A DOCKER-USER-redis1 -j REJECT --reject-with icmp-port-unreachable
$ sudo iptables -N DOCKER-USER-redis2
$ sudo iptables -A DOCKER-USER-redis2 -s 10.0.24.0/24 -p tcp -m tcp -j RETURN
$ sudo iptables -A DOCKER-USER-redis2 -j REJECT --reject-with icmp-port-unreachable
$ sudo iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 7777 -j DOCKER-USER-redis1
$ sudo iptables -A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 8888 -j DOCKER-USER-redis2

Ich denke, ein Beispiel wie dieses gehört in die Dokumentation, da es wahrscheinlich das abdeckt, wonach 99% der Benutzer suchen: die Möglichkeit, Ports mit -p aber trotzdem den Datenverkehr mit gängigen Filtern wie -s zu steuern.

Ich habe eine Anfrage zur Aktualisierung der Docker-Dokumentation bezüglich iptables erstellt.

https://github.com/docker/docker.github.io/issues/8087

Die dort aufgeführte Lösung in https://unrouted.io/2017/08/15/docker-firewall/
scheint etwas ähnliches zu sein und erstellt eine zusätzliche iptables-Kette namens FILTERS
wohin die Ketten INPUT und DOCKER-USER springen.

@SystemParadox @colinmollenhour Nachdem ich --ctorigdstport getestet habe, kann ich bestätigen, dass es funktioniert, aber mit einem kleinen Vorbehalt.

In meinem Fall habe ich eine dockerisierte PHP-Anwendung auf Apache, die auf Port 80 lauscht. Meine Regeln, die nur 1.2.3.4 zulassen, sind wie folgt:

-A DOCKER-USER -s 1.2.3.4/32 -i eth0 -p tcp -m conntrack --ctorigdstport 80 -j ACCEPT
-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 80 -j DROP

Meine Dropping-Regel ist also etwas spezifischer als Ihre und lässt nur Pakete fallen, die meinen Webserver treffen – dachte ich zumindest. Tatsächlich verlor es Pakete, die an meinen Webserver gerichtet waren, sowie Pakete, die mit Antworten auf Anfragen von PHP-Anwendungen an Server von Drittanbietern zurückkehrten.

Dies liegt daran, dass --ctorigdstport nicht mit dem Zielport des zu filternden Pakets übereinstimmt, sondern dem Paket, das die Verbindung SPT=80 und stimmen auch mit --ctorigdstport 80 überein.

Wenn jemand mehr Kontrolle über die DROP-Regeln haben möchte, muss auch --ctdir hinzugefügt werden:

-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j DROP

Tatsächlich sollten alle Regeln, die die Verbindung zulassen, auch --ctdir hinzugefügt haben, um ihre Bedeutung genau auszudrücken:

-A DOCKER-USER -s 1.2.3.4/32 -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j ACCEPT

@jest wow das ist wirklich wichtig zu wissen! Ich hatte nicht bemerkt, dass es Pakete in die andere Richtung abgleichen konnte. Es macht Sinn, wenn Sie darüber nachdenken, da es mit dem Status der gesamten Verbindung übereinstimmt, aber es ist beim Lesen der Dokumente leicht zu übersehen.

@SystemParadox ja, ich hatte keine Chance, mich durch die Dokumente zu informieren und wurde von Anfragen von Docker überrascht, die auf Antworten warteten. :)

Ich drehe mich immer wieder im Kreis mit den Gründen, warum ich --ctdir ORIGINAL . Einerseits macht die Erklärung von @jest durchaus Sinn, andererseits muss ich mich normalerweise nie mit Antwortpaketen befassen, warum sollte es hier also anders sein?

Ich denke, der Unterschied besteht darin, dass ich -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT als erste Regel habe, sodass der Rest meiner Regeln keine Antwortpakete sieht. In diesem Fall denke ich, dass --ctdir ORIGINAL nicht unbedingt erforderlich ist, obwohl es wahrscheinlich sowieso sicherer wäre, es aufzunehmen.

@jest , würdest du dem zustimmen? Vermutlich hast du keine frühe ESTABLISHED,RELATED -j ACCEPT Regel, weshalb das für dich einen Unterschied macht?

@jest Dein Beitrag war eine große Hilfe, danke.

Ist Ihr Ansatz nur für Dinge erforderlich, die von Docker verwaltet werden, oder für alles? Mein SSH-Port (22) hat zum Beispiel nichts mit Docker zu tun. Muss ich -m tcp --dport 22 wie gewohnt verwenden oder muss ich -m conntrack --ctorigdstport 22 --ctdir ORIGINAL ?

Ich gehe davon aus, dass Ihr Ansatz nur für den vom Docker verwalteten Datenverkehr benötigt wird, da diese Pakete einem Verstümmeln / Natting unterzogen werden, bevor sie in der Filtertabelle zu mir gelangen. ABER, ich bin neu bei iptables, also möchte ich von jemandem wissen, der mehr weiß als ich!

@lonix1 Die Regeln werden von Docker nur dann zur DOCKER-Kette hinzugefügt, wenn Sie einen Port verfügbar machen, und wahrscheinlich nur, wenn der Container ausgeführt wird. Wenn Sie in keinem Ihrer Container Port 22 freigeben, sollten Ihre Firewall-Regeln unverändert funktionieren.

@SystemParadox Es ist einige Zeit her und ich habe keinen Zugriff auf diesen Server, um ihn zu überprüfen, aber wenn ich mich richtig erinnere, gab es ESTABLISHED,RELATED Regeln (verwaltet von UFW, in ufw-before-input Kette). In meinem Fall würden sie jedoch beim ersten Paket (SYN) von Verbindungen, die von Docker zu Internet-Hosts auf Port 80 hergestellt wurden, nicht übereinstimmen. Und würden von der entsprechenden Regel in DOCKER-USER fallen gelassen, wenn kein --ctdir .

@Ionix1 , Pakete für Dienste auf dem Host gehen nur über INPUT, während Pakete für Docker-Dienste nur über FORWARD und DOCKER-USER gehen.

Bei einer externen IP von 10.0.0.1 und zwei Containern mit -p 4000:80 und -p 4001:80 würden Sie beispielsweise Pakete mit den folgenden Eigenschaften sehen:

INPUT:
dst 10.0.0.1 dport 80 ctorigdst 10.0.0.1 ctorigdstport 80
FORWARD/DOCKER-USER:
dst 172.17.0.5 dport 80 ctorigdst 10.0.0.1 ctorigdstport 4000
dst 172.17.0.6 dport 80 ctorigdst 10.0.0.1 ctorigdstport 4001

Sie können also sicher --dport 80 für die INPUT-Regeln verwenden, da sie sich in völlig separaten Ketten befinden. Wie Sie sehen, würde --ctorigdstport 80 immer noch übereinstimmen, aber wenn Sie nicht aus irgendeinem Grund auch Eingaben verstümmeln, würde ich das wahrscheinlich nicht tun.

Sie werden vielleicht auch bemerken, dass Sie --dport 80 mit --dst 172.17.0.5 tatsächlich verwenden könnten, um Pakete für einen bestimmten Docker-Container zu filtern, aber diese IP ist nicht vorhersehbar, weshalb wir --ctorigdstport .

Letztendlich müssen Sie sich darüber im Klaren sein, welchen Paketen eine bestimmte Regel entsprechen könnte, je nachdem, in welcher Kette Sie sich befinden, was das Ziel ist und ob es zu Misshandlungen kommt.

@jest danke, das scheint meine Meinung zu bestätigen.

Also brauche ich eine kleine Anleitung... um von UFW zu iptables zu wechseln...
- schalte ich UFW einfach über "ufw disable" aus?
-Erstelle ich meine eigene .sh-Datei oder gibt es eine vorhandene (ich bin Ubuntu auf DigitalOcean)?
-Ich muss Docker nur sagen "--iptables=false"? (das ist es für Docker?)
-DOCKER-USER wird bereits von Docker erstellt und verkettet?

@fredjohnston Sie können UFW weiterhin verwenden, wenn Sie möchten. Profile werden in /etc/ufw gespeichert. Das Problem hier ist, dass Docker nicht angezeigt wird, weil in /etc/ufw/applications.d kein App-Profil aufgeführt ist (dasselbe gilt für jedes andere Firewall-Tool und seine Konfiguration).

Das Deaktivieren von IPTables in Docker bedeutet, dass Sie in Docker nicht viel von Netzwerken haben, nur IP-Adressen und Container können nicht miteinander kommunizieren. DOCKER_USER ist ein Hack, um Ihnen etwas Kontrolle zu geben, löst das Problem jedoch nicht wirklich – es geht wirklich darum, die Docker-Container nicht standardmäßig im Netzwerk öffentlich zu machen, sondern an die IP-Adresse des Containers zu sperren.

Im Moment empfehle ich Ihnen, weiterhin das Firewall-Tool zu verwenden, mit dem Sie sich am wohlsten fühlen (ufw usw.), aber beachten Sie, dass Docker-Container in Ihrem Netzwerk öffentlich sind.

Da ich irgendwie hier drin bin, stoße ich jetzt tatsächlich auf ein verwandtes Problem, bei dem dies auch auf anderen Plattformen als Linux auftritt. Folgendes berücksichtigen:

  • Projekt A hat zwei Container, einen für eine Datenbank und einen für eine Anwendung.
  • Projekt B hat zwei Container, einen für eine Datenbank und einen für eine Anwendung.
  • Beide Projekte sind voneinander isoliert (getrennte Quell-Repositorys, Konfigurationen usw.)
  • Beide Projekte werden unter Docker Compose verwaltet
  • Beide Projekte machen ihre Datenbankports für lokale Entwicklungszwecke verfügbar
  • Beide Projekte verwenden denselben Datenbankserver (postgres, mysql usw.)

Angenommen, Sie möchten beide Projekte lokal ausführen – zum Beispiel, um an einer gemeinsam genutzten Bibliothek zu arbeiten, die beide Projekte verwenden, damit Sie sie zum Testen einfach in ihren Code ziehen können.

Unter dem aktuellen Firewall-Interaktionsdesign - und was teilweise zu den oben genannten Problemen führt, den Container ohne das Wissen des Benutzers dem öffentlichen Netzwerk zugänglich zu machen - können die Datenbank-Docker beider Projekte nicht gleichzeitig ausgeführt werden, da sie um die exponierter Port für die Datenbank. Dasselbe gilt, wenn Sie sowohl ihren Anwendungs-Port freigeben wollten als auch beide denselben Port für den Anwendungsserver verwenden - häufig, da HTTP-basierte APIs und Anwendungen jetzt besonders in Cloud-orientierten Anwendungen sehr verbreitet sind.

Sicher können Sie sich hacken, um beides unter einem DB-Container einzurichten. Sie isolieren sie jedoch nicht gemäß Ihrem Projektdesign und müssen bei Konfigurationen usw. noch vorsichtiger sein.

In einer richtigen Lösung ist hier zweierlei:

  1. Die Container wären nur an ihre IPs gebunden und ihre exponierten Ports wären nur an ihre IPs innerhalb ihrer jeweiligen Docker-Netzwerke gebunden, nicht auf dem System stimmen alle IPs überein ( 0.0.0.0 , :: ).
  2. Docker würde die Route zu den Docker-Netzwerken auch nicht standardmäßig außerhalb des Systems veröffentlichen. Docker Networking kann verwendet werden, um Verbindungen zwischen Netzwerken (Docker-Netzwerk zu Docker-Netzwerk) wie derzeit geplant herzustellen und dann standardmäßig auch lokale Hostverbindungen zuzulassen.
  3. Die Benutzer wären dann am Haken, um die entsprechenden Firewall-Regeln hinzuzufügen, um den Container bei Bedarf der Außenwelt zugänglich zu machen - zum Beispiel durch Portweiterleitung von Port 443 an Port 443 ihres Containers ihrer Wahl.

Auch dies könnte schrittweise erfolgen:

  • Version 1: Implementieren Sie die Schritte 1 und 2; aber fügen Sie auch nicht-lokales Host-Routing (vorübergehend) mit einer Warnung hinzu. Das aktuelle Verhalten von first-come-first-serve zum Erhalten eines Ports wird beibehalten; und eine Warnung, dass dieses Verhalten verschwindet, wird ausgegeben.
  • Lassen Sie 1+N los: Löschen Sie die Warnung und löschen Sie das nicht-localhost-Routing. Erfordern Sie Schritt 3 für Benutzer, die möchten, dass Docker die Ports außerhalb des Systems freigibt, und stellen Sie sicher, dass dies gut dokumentiert ist.

DOCKER_USER ist ein Hack, um Ihnen etwas Kontrolle zu geben, löst das Problem jedoch nicht wirklich – es geht wirklich darum, die Docker-Container nicht standardmäßig im Netzwerk öffentlich zu machen, sondern an die IP-Adresse des Containers zu sperren.

Im Moment empfehle ich Ihnen, weiterhin das Firewall-Tool zu verwenden, mit dem Sie sich am wohlsten fühlen (ufw usw.), aber beachten Sie, dass Docker-Container in Ihrem Netzwerk öffentlich sind.

Hier gibt es eine Dokumentaktualisierungsanforderung https://github.com/docker/docker.github.io/pull/8357 , um eine statische Konfiguration für angeschraubte iptables zu erstellen, aber ich bin mir des Status nicht sicher.

Edit: Mir ist aufgefallen, dass du die Bedeutung von DOCKER-USER falsch verstanden hast. Es wird nicht verwendet, um "Container an die IP-Adresse des Containers zu sperren", sondern um den Zugriff auf den Container mit iptables-Regeln zu filtern.

@aki-k per DOCKER_USER Mir ist bekannt, dass DOCKER_USER den Container nicht gegen die IP-Adresse sperrt und nie behauptet, dass dies der Fall ist. DOCKER_USER übergibt das Sicherheitsproblem einfach an den Benutzer, der verwaltet werden muss - was bedeutet, dass der Benutzer wissen muss, wie er seine Firewall manipulieren kann, um sicherzustellen, dass er tatsächlich über eine sichere Umgebung verfügt. Es ist ebenso inakzeptabel, daraus ein Benutzerproblem zu machen, da die meisten Benutzer nicht wissen, wie sie ihre Firewall verwalten sollen - Firewall-Regeln sind hart, und selbst diejenigen von uns, die sich mit dem Schreiben von Firewall-Regeln auskennen, können immer noch Fehler machen.

Meine Bitte – und der springende Punkt – in diesem Thema ist, dass Docker standardmäßig sicher sein muss und Container nicht ohne Wissen des Benutzers oder explizites Eingreifen der Außenwelt zugänglich macht. Und gemäß meinem letzten Kommentar (https://github.com/moby/moby/issues/22054#issuecomment-552951146) hat dies auch einige andere technische Vorteile.

Meine Bitte – und der springende Punkt – in diesem Thema ist, dass Docker standardmäßig sicher sein muss und Container nicht ohne Wissen des Benutzers oder explizites Eingreifen der Außenwelt zugänglich macht.

Der früheste Ausgabebericht, den ich dazu gefunden habe, stammt vom 18. März 2014:

https://github.com/moby/moby/issues/4737

Es ist wahrscheinlich eine Designentscheidung, die sie nicht ändern und versuchen möchten, mit der DOCKER-USER-iptables-Kette zu beheben. Sie können die Option -p für docker run verwenden, um den Port nur für den Docker-Host (-p 127.0.0.1:port:port) zu veröffentlichen, aber auch das löst das Problem nicht.

Lassen Sie uns klarstellen, Docker ist standardmäßig sicher. Sie müssen Docker anweisen, eine Portweiterleitung durchzuführen.

Bei Diensten, die miteinander kommunizieren müssen, sollten Sie Netzwerke ( docker network ) verwenden, um den Zugriff einzuschränken, und nicht die Portweiterleitung.

Um es klar zu sagen, Docker _ist_ standardmäßig sicher. Sie müssen Docker anweisen, eine Portweiterleitung durchzuführen.

Bitte lehnen Sie ein sachliches Problem nicht ab, bei dem Docker über Ihren etablierten iptables-Schutz läuft. Ich bin sicher, Sie haben die unzähligen Problemberichte gesehen, in denen dies diskutiert wird.

Um es klar zu sagen, Docker _ist_ standardmäßig sicher. Sie müssen Docker anweisen, eine Portweiterleitung durchzuführen.

Bei Diensten, die miteinander kommunizieren müssen, sollten Sie Netzwerke ( docker network ) verwenden, um den Zugriff einzuschränken, und nicht die Portweiterleitung.

Um es klar zu sagen - Docker ist sicher, bis Sie außerhalb des Docker-Netzwerks darauf zugreifen möchten. Wenn Sie sogar vom lokalen Host (127.0.0.1) darauf zugreifen möchten, ist Docker standardmäßig nicht sicher, da es an 0.0.0.0 bindet und die Container vom System freigibt - alles umgeht, was der Benutzer tut, um sein System zu sichern, ohne aufzutauchen in anderen Werkzeugen als der direkten Verwendung von iptables . DOCKER_USER ist und wird niemals eine geeignete Lösung sein, da der Benutzer zu viel über das zugrunde liegende Firewall-System wissen muss (iptables unter Linux, was auch immer Mac verwendet, und die Windows-Firewall unter Windows). Das muss immer noch standardmäßig sicher sein. Es gibt eine sehr einfache Möglichkeit, dies zu tun, wie ich zuvor in https://github.com/moby/moby/issues/22054#issuecomment -552951146 beschrieben und in dieser Ausgabe mehrmals aufgerufen habe (wenn auch vielleicht nicht so klar wie darin) Kommentar).

Beachten Sie auch, dass die Dokumentation zum Freigeben eines Ports dieses Sicherheitsproblem ebenfalls nicht erwähnt und keinen Hinweis darauf gibt, wie Docker beim Freilegen eines Ports mit der Systemfirewall interagiert – wodurch die Sicherheit auf Systemen verringert wird, die bis zur Verwendung von Docker sicher ausgelegt waren .

Um es klar zu sagen, Docker _ist_ standardmäßig sicher. Sie müssen Docker anweisen, eine Portweiterleitung durchzuführen.
Bei Diensten, die miteinander kommunizieren müssen, sollten Sie Netzwerke ( docker network ) verwenden, um den Zugriff einzuschränken, und nicht die Portweiterleitung.

Um es klar zu sagen - Docker ist sicher, bis Sie außerhalb des Docker-Netzwerks darauf zugreifen möchten. Wenn Sie auch vom lokalen Host (127.0.0.1) darauf zugreifen möchten, ist Docker standardmäßig _nicht_ sicher, da es gegen 0.0.0.0 bindet [...]

Um genau zu sein, bindet Docker nicht an 0.0.0.0. Das ist die (angemessene) Erwartung des Benutzers: dass die Angabe von --publish auf der CLI, also das Arbeiten im Benutzerbereich, eine Art Proxy-Daemon startet, der auf dem angegebenen Port lauscht, eingehende Verbindungen akzeptiert und hin und her pusht alle Pakete zwischen Docker und der Außenwelt.

Aber stattdessen injiziert Docker magische DNAT/Masquarading-Regeln in die Firewall, um die Adressen auf dem Paket neu zu schreiben, und bricht damit willkürlich jedes vorinstallierte Regelsystem.

Meiner Meinung nach ist das Durcheinanderbringen von Abstraktionsebenen hier der größte Nachteil und verwirrt den Benutzer. Ich weiß nicht, welche Szenarien das Docker-Team bei der Entwicklung der hier gezeigten --publish Maschinen in Betracht gezogen hat, ich sehe keine, die die Entscheidung rechtfertigen (vielleicht neben Performance-Gründen).

Lassen Sie uns klarstellen, Docker ist standardmäßig sicher. Sie müssen Docker anweisen, eine Portweiterleitung durchzuführen.

... was zufällig eine der am häufigsten verwendeten Funktionen von Docker ist. Tatsächlich haben Sie gerade festgestellt, dass eine nicht dokumentierte Überschreibung bereits vorhandener Firewall-Regeln innerhalb einer der am häufigsten verwendeten Funktionen von Docker _standardmäßig sicher_ macht.

Nun, was auch immer für Sie funktioniert, denke ich. Da es bei mir nicht funktioniert, werde ich nach alternativen Containerplattformen suchen. Sicherheitsprobleme können behoben werden, aber die eklatante Missachtung vernünftiger Sicherheitserwartungen ist ein anderes Tier.

Beurteilen wir die Situation wie sie heute ist:

Standardmäßig werden keine Ports verfügbar gemacht. Sie müssen Docker anweisen, einen Port freizugeben.
In der Vergangenheit hat Docker iptables so eingerichtet, dass alles, was wusste, wie man zum Bridge-Netzwerk routet, auf die Container-IPs zugreifen konnte (indem die Weiterleitungsrichtlinie auf "akzeptieren") gesetzt wurde, aber dies ist nicht mehr der Fall.

Ich habe einige Leute gesehen, die sagten, dass sie -p , um sich gegenseitig Dienste zur Verfügung zu stellen, was nicht erforderlich sein sollte.
Im Standardnetzwerk können Sie --link , um Dienste miteinander zu verbinden, der Container ist über DNS verfügbar.
In nicht standardmäßigen Netzwerken (benutzerdefinierten Netzwerken) können Container auch über DNS aufeinander zugreifen, einschließlich der Einrichtung von Aliasen über --link oder sogar auf ein Netzwerk mit einem angegebenen Alias.

Es scheint, als ob Sie in vielen Fällen wirklich nur eine Verbindung zum Dienst vom Client herstellen möchten. In diesem Fall wird empfohlen, einen anderen Container mit Zugriff auf den Dienst zu verwenden, mit dem Sie eine Verbindung herstellen möchten, anstatt einen Port freizugeben.

-p speziell für Ingress entwickelt, da externe Dinge auf diesen Dienst zugreifen können.
Die Standardeinstellung für -p ist in der Tat, Verkehr von überall her zuzulassen. Sie können dies ändern, indem Sie die zuzulassende Adresse manuell angeben, entweder pro -p oder als daemonweite Einstellung.
Da -p iptables verwendet, wurde die Kette DOCKER-USER erstellt, damit Benutzer ihre eigenen Filterregeln hinzufügen können, bevor sie auf den Container trifft.

Da -p für Ingress konzipiert ist, halte ich es für sinnvoll, den Datenverkehr so ​​offenzulegen, wie er es tut. Ich finde es bedauerlich, dass die Docker-Regeln oben in der Filtertabelle eingefügt werden, aber dies zu ändern, wäre für eine große Gruppe von Benutzern, die dieses Verhalten wünschen, eine bahnbrechende Änderung.

Es gibt noch ein paar andere Alternativen zu -p :

  1. Verwenden Sie nicht -p , sondern verbinden Sie sich direkt mit der Container-IP. Dies erfordert ein wenig zusätzliche Arbeit, da Sie die IP nachschlagen müssen, diese Daten sind jedoch über die API verfügbar. Sie müssen auch sicherstellen, dass die Weiterleitungsrichtlinie der Firewall dies zulässt (vorausgesetzt, Sie verbinden sich von einem anderen Host aus, derselbe Host sollte in Ordnung sein).
  2. Verwenden Sie macvlan- oder ipvlan-Netzwerke für Dienste, auf die Sie über das Netzwerk des Hosts (dh Ingress) zugreifen möchten. Diese Netzwerkoptionen geben dem Container eine IP direkt von der Netzwerkschnittstelle des Hosts (Sie wählen, an welche Schnittstelle er gebunden ist).
  3. Verwenden Sie --net=host , dies führt den Dienst im Host-Netzwerk-Namespace aus, wodurch der Dienst Zugriff auf die Netzwerkinfrastruktur erhält, die bereits auf dem Host vorhanden ist.

Sie sagen "dies standardmäßig sicher machen", aber das Freigeben eines Ports ist per Definition eine potenziell unsichere Aktion. Es scheint auch eine Idee zu geben, dass die Bereitstellung nur für localhost sicher ist, aber nicht, da alles, was auf dem Host ausgeführt wird, auf localhost zugreifen kann (einschließlich Javascript in einem Browser, wenn es sich um einen Desktop handelt).

Welchen Anwendungsfall versuchen Sie mit -p zu lösen?
Haben Sie einige Gedanken zu den tatsächlichen Veränderungen, die Sie gerne sehen würden?

Ich kann etwas ändern, um dies für Ihren Workflow zu verbessern, aber es gibt hier viele verschiedene Anwendungsfälle und eine Größe passt nie für alle (siehe Beschwerden über -p ).

@ cpuguy83 das ist alles in Ordnung und

Benutzer verwenden Docker und möchten von ihrem lokalen System aus eine Verbindung zu Anwendungen herstellen, die unter Docker ausgeführt werden - dies ist ein äußerst häufiger Anwendungsfall für Entwickler, insbesondere wenn sie versuchen, etwas zu diagnostizieren oder einen Dienst zu schreiben, der nicht unter Docker steht, aber eine Verbindung zu Diensten herstellen muss, die in Docker gehostet werden (um eine Entwicklungsumgebung auszufüllen). Die Entwicklung unter Docker ist nicht immer eine gute, lustige oder nützliche Erfahrung.

Es wird empfohlen, einen anderen Container mit Zugriff auf den Dienst zu verwenden, zu dem Sie eine Verbindung herstellen möchten, anstatt einen Port freizugeben.

Ist einfach ein No-Go. Nicht alle Tools sind Docker-freundlich und sollten es auch nicht sein. Der Benutzer sollte nicht vollständig unter Docker sein müssen, um Dienste nutzen zu können, die unter Docker ausgeführt werden. Selbst dann, wenn Docker zum Betrieb von Servern verwendet wird, kann der Administrator diese nicht einfach über die Firewall-Konfiguration steuern und die Expose-Port-Funktionalität ist jedoch orchestriert (Kommandozeile, Dockerfile, Docker Compose Config) völlig kaputt.

Außerdem verwenden die Leute Docker Compose, um einen Großteil der Umgebung zu verwalten, und geben über docker-compose.yml oder Dockerfile dass ein Port verfügbar gemacht werden muss, damit sie lokal darauf zugreifen können. Daher ist die Angabe des Parameters use the -p falsch, da er nie direkt mit dem Docker-Befehl so verbunden ist, dass dies funktioniert.

Die Offenlegung eines Ports bedeutet nicht, dass die Sicherheit gebrochen werden muss. Ich habe beschrieben, wie Sie einen Port für das lokale System freigeben können, ohne die Sicherheit zu beeinträchtigen (https://github.com/moby/moby/issues/22054#issuecomment-552951146) und die Verwaltung der externen Exposition (aus) System) in den Händen des Benutzers so, dass er es mit seinen vorhandenen Werkzeugen einfach steuern kann.

Lösung:

  • Docker-Netzwerk verwenden
  • Machen Sie die Ports im Docker-Netzwerk allein und auf dem lokalen Host verfügbar
  • Stoppen Sie die Bindung des Ports an 0.0.0.0 - oder tun Sie dies effektiv
  • Fordern Sie die Benutzer auf, ihre eigenen Firewall-Tools zu verwenden, um den Port vom System freizugeben (ufw, Firewalld usw.).
  • Stellen Sie Integrationen für gängige Firewalls bereit, um dies zu vereinfachen

Mit anderen Worten, anstatt über 127.0.0.1:<port> auf einen Dienst in einem Docker-Container zuzugreifen, benötigen Sie <docker container ip>:<service port> sogar vom lokalen Host. Wenn Benutzer den Dienst außerhalb des Systems freigeben möchten, können sie über ihre Tools (ufw usw.) eine Firewallregel hinzufügen, um die Portweiterleitung von einem bestimmten Port zu <docker container ip>:<service port> .

Alternativ können Sie dem Kubernetes-Ansatz mit ihrem Proxy-Design folgen und effektiv so vorgehen , wie https://github.com/moby/moby/issues/22054#issuecomment -554665865 vorgeschlagen hat. Auch hier müsste es sich nur um ein lokales System handeln, bis der Benutzer dies absichtlich dem externen Netzwerk zugänglich macht.

Das größte Problem dabei ist, dass Docker die Integrität der Firewall kompromittiert, um seine Dienste bereitzustellen, ohne es dem Benutzer überhaupt mitzuteilen und ohne in die Tools des Benutzers zu integrieren, sodass der Benutzer weder davon weiß noch es kontrollieren kann.

Mir ist klar, dass es eine Menge Firewall-Schnittstellen auf dem Markt gibt - selbst bei iptables gibt es Firewalld, ufw und ein Dutzend andere. Ich erwarte nicht wirklich, dass Docker sich in sie integriert (obwohl das schön wäre), aber ich erwarte, dass Docker so funktioniert, dass sie nicht umgangen oder die vom Benutzer eingerichtete Sicherheit verletzt wird.

Als grundlegender Testfall:

  • Einen Debian-basierten Server einrichten (Debian, Ubuntu)
  • Installieren Sie ufw, OpenSSH-Server
  • laufe ufw allow OpenSSH
  • laufe ufw enable

An diesem Punkt haben Sie einen ziemlich sicheren Server; der einzige erlaubte Datenverkehr ist entweder (a) bezogen auf ausgehenden Datenverkehr oder (b) SSH-Server-Datenverkehr.

Starten Sie nun einen Docker-Container mit einem exponierten Port.

Eine akzeptable Lösung würde Folgendes erfüllen:

  • Der Port sollte nicht von einem anderen Computer aus zugänglich sein; die Firewall sollte es weiterhin von externen Systemen blockieren.
  • Der Port sollte vom lokalen Computer (localhost) aus zugänglich sein.
  • Mehrere Docker-Container sollten in der Lage sein, denselben Port bereitzustellen und alles funktioniert. Alle Container mit einem exponierten Port sollten nur vom lokalen System aus zugänglich sein.
  • Der Benutzer sollte nicht über seine Firewall-Konfigurationsdetails Bescheid wissen müssen, um dies zu ermöglichen.

Versuchen Sie dasselbe für ein CentOS/Fedora/RHEL-basiertes System mit firewalld .

@cpuguy83 IMO-Leute erwarten, dass -p auf Anwendungsebene funktioniert. Das heißt, wenn ich -p 80:80 schreibe, erwarte ich das Verhalten, als ob die an Port 80 im Container gebundene Anwendung auf dem Host ausgeführt würde.

VirtualBox- oder SSH-Modell-Ports werden auf diese Weise weitergeleitet, sodass die Leute davon ausgehen, dass dies auch im Docker-Fall der Fall ist.

Um eine breitere Erwartungsparallele zu verwenden: Aus Benutzersicht sollte es als hostgebundene Volumes funktionieren. Sie zeigen einfach auf das Host-Verzeichnis, und "wie von Zauberhand" ist es im Container sichtbar; Alle Änderungen, die von der anderen Seite am Dateisystem vorgenommen werden, funktionieren genauso, einschließlich Berechtigungen, Kontingente usw.

Eingrenzen von -p Problemen auf die Firewall-Fälle: In der normalen Welt erwartet der Benutzer, dass eine Anwendung, die an 0.0.0.0:80 gebunden ist, für die Außenwelt sichtbar ist. Wenn der Benutzer den Zugriff einschränken möchte, wird er in zahlreichen Anleitungen angewiesen, eine Firewall zu verwenden und eine Regel in der INPUT Kette einzurichten:

-P INPUT DROP
-A INPUT -s 1.2.3.4/32 -p tcp --dst-port 80 -j ACCEPT

oder verwenden Sie Tools wie UFW:

ufw enable
ufw allow http

Aber mit Docker muss der Benutzer in der Lage sein, solche Regeln aus heiterem Himmel zu konstruieren:

-A DOCKER-USER -s 1.2.3.4/32 -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j ACCEPT
-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 80 --ctdir ORIGINAL -j DROP

Bitte zeigen Sie mir eine umfassende Anleitung für einen durchschnittlichen Benutzer, wie Sie solche häufigen Szenarien mit Docker lösen können.

Und für zB einen durchschnittlichen Entwickler – dem Sie das ganze Konzept der „Anwendungscontainerisierung“ verkauft haben – sind die Folgen der Offenlegung eines Ports einfach unvorhersehbar.

Heutzutage lege ich aus Mangel an Wissen einfach keine Ports frei und nutze stattdessen Dienste wie Traefik. Vielleicht sollte --expose auch nicht als Allzweck in CLI-Dokumenten vorgeschlagen werden, weil es IMO für einen durchschnittlichen Benutzer einfach nicht nützt.

Oder stellen Sie jedem ohne fundierte Kenntnisse dieser Tools einen Linux-Laptop zur Verfügung, z einen Kaffee bei Starbucks trinken.

Genau dieses Problem hat bei uns eine Systemschwachstelle verursacht, die ich am Wochenende entdeckt habe. Per @jacoscaz konnte ich gerade auf die lokale Datenbank eines anderen Entwicklers zugreifen, weil sie einen veröffentlichten Port hat. Es wäre großartig, wenn Sie dies in die Einführungsdokumentation aufnehmen könnten, damit andere nicht dasselbe tun. Wir brauchen einen nicht-containerisierten Dienst, um eine Verbindung zu einem Container herzustellen, ohne dass alle anderen im Netzwerk Zugriff erhalten, sodass Docker-Netzwerke nicht in Frage kommen. Klingt wie die beste Option im Moment ist, sich mit der lokalen Container-IP zu verbinden, es sei denn, jemand hat eine bessere Idee.

@dentonmwood Das klingt genau so, wie Sie es tun sollten. Wie oben erwähnt, können Sie den Dienst sogar so einrichten, dass er mit macvlan oder ipvlan ausgeführt wird, wodurch ihm eine IP direkt in Ihrem normalen Netzwerk zugewiesen wird.

@BenjamenMeyer @jest @jacoscaz

Danke für das zusätzliche Feedback.

Ich stimme zu, dass das Wissen, das wir in dieser Hinsicht von den Benutzern verlangen, nicht großartig ist. Wir legen derzeit die Verantwortung auf den Benutzer (sei es ein Systemadministrator oder ein Entwickler), um zu verstehen, was -p tut, und geeignete Vorkehrungen zu treffen, um sicherzustellen, dass der Dienst nur denjenigen zugänglich ist, denen er seiner Meinung nach ausgesetzt ist. Wir gehen noch einen Schritt weiter, indem wir sogar erwarten, dass Entwickler, die oft keinen Grund haben, iptables zu kennen, eingreifen und es für ihre eigene Umgebung reparieren (über DOCKER-USER ).
Wir befinden uns im Grunde in dieser Situation, weil wir befürchten, die Kompatibilität zu brechen.

Ich habe einige Ideen, die ich noch nicht vollständig durchdacht habe, aber im Grunde würde ich das Verhalten von -p basierend auf der API-Version des Clients ändern und eingehenden Traffic separat behandeln. Immer noch eine bahnbrechende Änderung, die mich beunruhigt, aber zumindest ist das alte Verhalten in älteren API-Versionen erhalten geblieben.

Ich hatte den Gedanken, dass wir einen lokalen Proxy (ala kubectl proxy ) für den Anwendungsfall des lokalen Zugriffs erstellen könnten, aber auch dies legt die Verantwortung auf die Entwickler, mehr zu wissen und zu verstehen, als sie wirklich brauchen sollten .

Die Gedanken?

Ich denke, dass die Einführung von Proxy ein Schritt in die richtige Richtung ist.

Ich erkenne an, dass die "Portweiterleitung" eine gemeinsame Verantwortung zwischen einem Container und einem Orchestrator ist, ähnlich dem Swarm-Modus. Aber die minimale Host-Integration ist immer erforderlich, und wenn dem (nicht erfahrenen) Benutzer eine Option wie -p , sollte die vorgeschlagene Lösung für eine solche Person verständlich sein.

Da die Auswirkungen von -p auf die Umgebung nicht spezifiziert sind (zumindest auf CLI-Ebene, denke ich), besteht die Möglichkeit, eine benutzerfreundliche Konfiguration der Funktionsweise einzuführen.

Im Moment gibt es beispielsweise iptables in /etc/docker/daemon.json das bestimmt, ob DOCKER manipuliert werden soll oder nicht. Die Config könnte um einen weiteren Eintrag erweitert werden, so dass eine Kombination wie iptables==true && expose_with_network_proxy==true das Proxy-ähnliche Verhalten einschalten würde.

Dies sollte für Neuinstallationen im Allgemeinen sicher sein, da ich vor einiger Zeit overlay2 gegenüber aufs vorgezogen habe (wenn ich mich richtig erinnere). Und als solches einfach zu implementieren, da Upgrades vorhandene Konfigurationsdateien nicht berühren, aber neue Installationen kostenlos sind.

Wir befinden uns im Grunde in dieser Situation, weil wir befürchten, die Kompatibilität zu brechen.

Ich möchte wirklich betonen, dass die Schwere dieses Problems, zumindest in meinen Augen, mehr mit der fehlenden Dokumentation zu tun hat als mit den aktuellen technischen Grundlagen von -p . Ja, ich glaube nicht, dass der derzeitige Mechanismus als _sicher_ bezeichnet werden kann, aber Sicherheitsmängel können behoben werden, und ich bin nicht in der Lage, die Gründe zu kritisieren, die zu dem aktuellen Szenario geführt haben. Im Nachhinein ist schließlich immer 20/20, und ich bewundere das Engagement für Rückwärtskompatibilität und die Bereitschaft, sich den technischen Herausforderungen zu stellen, die ein solches Engagement mit sich bringt.

Was ich nicht verstehe, ist, warum es in der Docker-Dokumentation immer noch keine hellen, großen, roten Kästchen gibt, die ausdrücklich vor den Nebenwirkungen der Verwendung von -p warnen. Wäre ich auf eine solche Warnung gestoßen, glaube ich, wäre ich gar nicht erst hier.

Die Gedanken?

Die Proxy-Option klingt vernünftig. Außerdem gefällt mir die Idee, Ports bei Bedarf freigeben und freigeben zu können, anstatt dies beim Starten von docker run tun zu müssen.

@BenjamenMeyer @jest @jacoscaz

Danke für das zusätzliche Feedback.

Danke, dass du dir das endlich mal genauer angeschaut hast.

Ich stimme zu, dass das Wissen, das wir in dieser Hinsicht von den Benutzern verlangen, nicht großartig ist. Wir legen derzeit die Verantwortung auf den Benutzer (sei es ein Systemadministrator oder ein Entwickler), um zu verstehen, was -p tut, und geeignete Vorkehrungen zu treffen, um sicherzustellen, dass der Dienst nur denjenigen zugänglich ist, denen er seiner Meinung nach ausgesetzt ist. Wir gehen noch einen Schritt weiter, indem wir sogar erwarten, dass Entwickler, die oft keinen Grund haben, iptables zu kennen, eingreifen und es für ihre eigene Umgebung reparieren (über DOCKER-USER ).
Wir befinden uns im Grunde in dieser Situation, weil wir befürchten, die Kompatibilität zu brechen.

Ich habe einige Ideen, die ich noch nicht vollständig durchdacht habe, aber im Grunde würde ich das Verhalten von -p basierend auf der API-Version des Clients ändern und eingehenden Traffic separat behandeln. Immer noch eine bahnbrechende Änderung, die mich beunruhigt, aber zumindest ist das alte Verhalten in älteren API-Versionen erhalten geblieben.

Die Gedanken?

  1. Beginnen Sie mit der Aktualisierung der Dokumentation, damit die Benutzer die Auswirkungen von EXPOSE von allen Methoden kennen (-p, Dockerfile, docker-compose.yml). So viel ist schnell erledigt. Es kann auch helfen, etwas Aufmerksamkeit auf das Problem zu lenken, um mehr Leute zu gewinnen, die Rat / Fachwissen bei der Suche nach einer guten Lösung anbieten und bei der Beantwortung helfen, wenn auch der Wunsch der Community nach Abwärtskompatibilität besteht.
  2. Planen Sie eine Methode, um von dem Punkt, an dem Docker jetzt ist, dorthin zu gelangen, wo Docker sein muss. Dies kann irgendwann einen Breaking Change beinhalten.

Ich denke, der Ernst der Situation erlaubt sicherlich eine bahnbrechende Änderung, um sie zu beheben; Tu es einfach nicht, ohne die Leute zu informieren. Legen Sie einen Zeitplan (6 Monate? 12 Monate?) fest, in dem die Änderung intensiv diskutiert wird usw. und bereiten Sie die Community vor; dann in einer "Major"-Version die Änderung vornehmen. Basierend auf Ihrem Versionsschema sieht es so aus, als ob der erste Satz das Jahr (19) ist; da wir Ende 2019 sind, verwenden Sie den Rest von 2019 und dann 2020, um die Lösung zu erarbeiten und sie zu bewerben; es irgendwann im Jahr 2020 als optionale Funktion einführen und es dann 2021 auf den ersten Platz / die Standardnutzung hochstufen.

Die Dockerfile-Version und die Docker Compose-Schema-Version können auch gute Werkzeuge sein, um ein Standardverhalten festzulegen, aber ich würde ältere Versionen nicht daran hindern, sie zu nutzen, und würde eine starke Warnung vor der Notwendigkeit einer Aktualisierung aussprechen auch in so einem fall.

Wie auch immer es eingeführt wird, ich denke, Sie werden feststellen, dass die gesamte Community eine solche Änderung viel mehr unterstützt, wenn sie verstehen, warum und was vor sich geht, und sich nicht davon blenden lassen.

Ich hatte den Gedanken, dass wir einen lokalen Proxy (ala kubectl proxy ) für den Anwendungsfall des lokalen Zugriffs erstellen könnten, aber auch dies legt die Verantwortung auf die Entwickler, mehr zu wissen und zu verstehen, als sie wirklich brauchen sollten .

Ich mag die Proxy-Idee, und der Vorschlag von @jest , wie man sie aktivieren kann, kann auch eine großartige Methode für die Migration sein.

Ehrlich gesagt, die meisten Leute, die versuchen werden, es außerhalb des Systems aufzudecken, werden oder sollten bis zu einem gewissen Grad mit Firewalls vertraut sein, selbst wenn es nur darum geht, UFW oder Firewalld dafür zu konfigurieren. Wenn die Lösung sie also nur dem lokalen Host zur Verfügung stellt, ist es meiner Meinung nach akzeptabel, dass die Leute lernen, wie sie ihre Firewall-Tools verwenden, um eine Portweiterleitung durch die Firewall durchzuführen.

Ich denke, es ist wichtig, dass solche Funktionen über die Firewall-Tools ausgeführt werden, für die sich der Benutzer entschieden hat, da sie alles für ihn sichtbar machen. Eine solche Funktionalität sollte ihre Werkzeuge nicht umgehen. Mir ist auch klar, dass es so viele Firewall-Tools gibt, dass es für Docker unvernünftig ist, sie alle zu integrieren. Daher würde ich vorschlagen, eine Dokumentationsroute zu beschreiten und hervorzuheben, wie dies mit einigen der beliebtesten zu beginnen ist, und die Community weitere hinzufügen und aktualisieren zu lassen.

Ich mag die Proxy-Idee, und der Vorschlag von @jest , wie man sie aktivieren kann, kann auch eine großartige Methode für die Migration sein.

Ehrlich gesagt, die meisten Leute, die versuchen werden, es außerhalb des Systems aufzudecken, werden oder sollten bis zu einem gewissen Grad mit Firewalls vertraut sein, selbst wenn es nur darum geht, UFW oder Firewalld dafür zu konfigurieren. Wenn die Lösung sie also nur dem lokalen Host zur Verfügung stellt, ist es meiner Meinung nach akzeptabel, dass die Leute lernen, wie sie ihre Firewall-Tools verwenden, um eine Portweiterleitung durch die Firewall durchzuführen.

Ich wiederhole das. Mit der Proxy-Lösung denke ich, dass es möglich wäre, etwas zu entwickeln, das es Benutzern ermöglicht, den Proxy an jede gewünschte Kombination von Schnittstelle(n) und Port(s) zu binden. Wenn Sie jedoch im Namen der Abwärtskompatibilität (die ich unterstütze!)

Zusätzlich zu meinem Kommentar könnte der Proxy je nach verfügbarem Firewall-Tool auf unterschiedliche Weise funktionieren. Wenn ein unterstütztes Firewall-Konfigurationstool erkannt wurde, könnte der Proxy dieses verwenden, um die entsprechenden Weiterleitungsregeln festzulegen. Das Vorhandensein eines solchen Tools könnte als Voraussetzung für Produktionsumgebungen hinzugefügt werden. Sollte ein solches Tool nicht verfügbar sein, würde der Proxy standardmäßig einen Proxy-Server auf Anwendungsebene starten.

Docker umgeht die macOS-Firewall genauso wie unter Linux.

Auf meinem Entwicklungscomputer (Docker Desktop für Mac) habe ich "ip": "127.0.0.1" zur Docker-Daemon-Konfiguration hinzugefügt. Auf diese Weise sind alle Entwicklungsdatenbanken usw. standardmäßig nur von localhost aus zugänglich. In den seltenen Fällen, in denen ich eine App für andere sichtbar machen muss, kann ich sie explizit mit -p 0.0.0.0:8080:8080 .

Bearbeiten: Anscheinend bindet Docker Compose immer noch standardmäßig an 0.0.0.0, unabhängig von der Docker-Daemon-Konfiguration. Dieser Trick funktioniert also nur, wenn Docker über die Befehlszeile ausgeführt wird. Und da Compose-Dateien oft mit Teamkollegen geteilt werden, die möglicherweise eine andere Systemkonfiguration haben, ist es besser, 127.0.0.1 explizit zur Compose-Datei hinzuzufügen.

@luontola Was für eine elegante Lösung.

Bearbeiten: Was ich auch dachte, war vielleicht eine Möglichkeit, eine Zulassungs-/Sperrliste von Adressen zu erstellen, die beispielsweise in Docker Compose definiert werden könnte, die dann automatisch der DOCKER-USER-iptables-Kette hinzugefügt würde.

Ein kleines Gänseblümchen, das die Bedeutung dieses Problems hervorhebt: https://github.com/docker/for-linux/issues/810 (Zusammenfassung: DOCKER-USER wurde entfernt, selbst wenn Sie iptables so konfiguriert haben, dass der externe Zugriff von Dockern blockiert wird, es würde diese zusätzliche Konfiguration ignorieren und alle Container verfügbar machen)

@danhallin Kommentare wie Ihre können in manchen Situationen wirklich den Tag retten. Ich danke Ihnen für das Teilen.

Hm, interessante Lektüre!

Ich verwende Mac OS X und habe auch eine lokale Firewall namens LittleSnitch. Es öffnete sich gerade ein Dialogfeld, in dem gefragt wurde, ob es in Ordnung ist, dass 185.156.177.252 eine Verbindung zum com.docker.backend-Prozess herstellt. Ich habe auf verweigern geklickt.

Ich habe mich gefragt, wie es in meinem Router eine Portweiterleitung öffnen könnte, aber ich habe gerade festgestellt, dass dies natürlich über UPnP geschieht! Alle Router unterstützen dies.

Was ich mich jetzt frage, ist das Warum. Warum versucht etwas von 185.156.177.252 von außen eine Verbindung herzustellen? Wenn mein lokaler Docker-Prozess etwas benötigt, sollte er von innen nach Hause rufen und keinen Port außen öffnen.

@ cpuguy83 das ist alles in Ordnung und

Benutzer verwenden Docker und möchten von ihrem lokalen System aus eine Verbindung zu Anwendungen herstellen, die unter Docker ausgeführt werden - dies ist ein äußerst häufiger Anwendungsfall für Entwickler, insbesondere wenn sie versuchen, etwas zu diagnostizieren oder einen Dienst zu schreiben, der nicht unter Docker steht, aber eine Verbindung zu Diensten herstellen muss, die in Docker gehostet werden (um eine Entwicklungsumgebung auszufüllen). Die Entwicklung unter Docker ist nicht immer eine gute, lustige oder nützliche Erfahrung.

Es wird empfohlen, einen anderen Container mit Zugriff auf den Dienst zu verwenden, zu dem Sie eine Verbindung herstellen möchten, anstatt einen Port freizugeben.

Ist einfach ein No-Go. Nicht alle Tools sind Docker-freundlich und sollten es auch nicht sein. Der Benutzer sollte nicht vollständig unter Docker sein müssen, um Dienste nutzen zu können, die unter Docker ausgeführt werden. Selbst dann, wenn Docker zum Betrieb von Servern verwendet wird, kann der Administrator diese nicht einfach über die Firewall-Konfiguration steuern und die Expose-Port-Funktionalität ist jedoch orchestriert (Kommandozeile, Dockerfile, Docker Compose Config) völlig kaputt.

Außerdem verwenden die Leute Docker Compose, um einen Großteil der Umgebung zu verwalten, und geben über docker-compose.yml oder Dockerfile dass ein Port verfügbar gemacht werden muss, damit sie lokal darauf zugreifen können. Daher ist die Angabe des Parameters use the -p falsch, da er nie direkt mit dem Docker-Befehl so verbunden ist, dass dies funktioniert.

Die Offenlegung eines Ports bedeutet nicht, dass die Sicherheit gebrochen werden muss. Ich habe beschrieben, wie Sie einen Port für das lokale System freigeben können, ohne die Sicherheit zu #22054 (Kommentar) ) und die Verwaltung der externen

Lösung:

* Use Docker Network

* Expose the Ports on the Docker Network alone and local host

* Stop binding the port on 0.0.0.0 - or effectively doing so

* Require users to use their own firewall tooling to expose the port off system (ufw, firewalld, etc)

* Provide integrations for common firewalls to make this easy

Mit anderen Worten, anstatt auf einen Dienst in einem Docker-Container über 127.0.0.1:<port> zuzugreifen, benötigen Sie <docker container ip>:<service port> sogar vom lokalen Host. Wenn Benutzer den Dienst außerhalb des Systems verfügbar machen möchten, können sie über ihre Tools (ufw usw.) eine Firewallregel hinzufügen, um die Portweiterleitung von einem bestimmten Port zu <docker container ip>:<service port> .

Alternativ können Sie dem Kubernetes-Ansatz mit ihrem Proxy-Design folgen und effektiv so vorgehen , wie #22054 (Kommentar) vorgeschlagen hat . Auch hier müsste es sich nur um ein lokales System handeln, bis der Benutzer dies absichtlich dem externen Netzwerk zugänglich macht.

Das größte Problem dabei ist, dass Docker die Integrität der Firewall kompromittiert, um seine Dienste bereitzustellen, ohne es dem Benutzer überhaupt mitzuteilen und ohne in die Tools des Benutzers zu integrieren, sodass der Benutzer weder davon weiß noch es kontrollieren kann.

Mir ist klar, dass es eine Menge Firewall-Schnittstellen auf dem Markt gibt - selbst bei iptables gibt es Firewalld, ufw und ein Dutzend andere. Ich erwarte nicht wirklich, dass Docker sich in sie integriert (obwohl das schön wäre), aber ich erwarte, dass Docker so funktioniert, dass sie nicht umgangen oder die vom Benutzer eingerichtete Sicherheit verletzt wird.

Als grundlegender Testfall:

* Setup a Debian-based server (Debian, Ubuntu)

* Install ufw, OpenSSH Server

* run `ufw allow OpenSSH`

* run `ufw enable`

An diesem Punkt haben Sie einen ziemlich sicheren Server; der einzige erlaubte Datenverkehr ist entweder (a) bezogen auf ausgehenden Datenverkehr oder (b) SSH-Server-Datenverkehr.

Starten Sie nun einen Docker-Container mit einem exponierten Port.

Eine akzeptable Lösung würde Folgendes erfüllen:

* The port should not be accessible from another computer; the firewall should continue to block it from outside systems.

* The port should be accessible from the local computer (localhost).

* Multiple docker containers should be able to expose the same port and have everything work; all containers with an exposed port should be accessible from the local system only.

* The user should not have to know about their firewall configuration details to make this happen.

Versuchen Sie dasselbe für ein CentOS/Fedora/RHEL-basiertes System mit firewalld .

Ich bin auf dieses Problem gestoßen, als ich versuchte herauszufinden, ob es eine Möglichkeit gibt, Docker so zu konfigurieren, dass meine Firewall-Eingaberegeln nicht jedes Mal umgangen werden, wenn ein Port veröffentlicht wird. Der obige Kommentar leistet gute Arbeit, um das Ganze zu erklären und ist auch ein vorzuziehender, IMO-Ansatz.

Gestern bin ich zufällig über dieses Thema gestolpert. Ich habe Wochen damit verbracht, meine iptables-Firewall-Regeln für meinen VPS akribisch anzupassen. Ich habe versucht, vorsichtig und restriktiv zu sein. Filter Input & Output sind standardmäßig auf Drop eingestellt. Ich erlaube ausdrücklich bestimmten Verkehr und blockiere alles andere. Der Verkehr wird protokolliert, und ich habe getestet und überwacht.

Ich wusste, dass Docker seine eigenen Änderungen an der Forward-Kette und der NAT-Tabelle vorgenommen hat. Daher habe ich diese Änderungen während meines gesamten Prozesses _extrem_ sorgfältig respektiert. Außerdem sind alle meine Container an benutzerdefinierte Netzwerke angehängt. Das Standardhostnetzwerk wird nie verwendet. Die offizielle Dokumentation sagt uns, es nicht zu tun.

Meine erste Überraschung war, dass mein containerisierter Nginx-Proxy für das gesamte Internet zugänglich war. Ich habe eine Option in meinen Firewall-Regeln, um eingehenden Webverkehr aus der ganzen Welt zuzulassen. Aber diese Funktion hatte ich noch nicht aktiviert. Nirgendwo in meinen iptables ist ersichtlich, dass HTTP 80/443 erlaubt ist.

Einige meiner Webanwendungen basieren auf Datenbanken wie MySQL. Anfangs habe ich die Option -p in Docker Compose _nicht_ verwendet. Ich wusste, dass dies nicht notwendig war, da meine Webanwendung und der DB-Server dasselbe benutzerdefinierte Docker-Netzwerk teilten. Aber als ehemaliger DBA denke ich immer an Backups. Also habe ich die Option -p aktiviert, damit die Cron-Jobs und Backup-Tools meines

Nach meiner Überraschung bei Nginx entschied ich mich klugerweise, noch einmal zu überprüfen, ob MySQL nicht auch exponiert war. Ich habe versucht, eine Verbindung (von meinem Laptop) mit der MySQL-Datenbank auf meinem Remote-VPS herzustellen. Und war wieder geschockt, als ich sofort erfolgreich verbunden wurde.

Nichts, was ich sage, wurde in früheren Beiträgen nicht ausführlich diskutiert. Vielen Dank an @BenjamenMeyer @jest @jacoscaz für ihre hilfreichen Untersuchungen und Vorschläge. Aber für diejenigen, die nach modernen Anwendungsfällen und Erfahrungen fragen? Hier hast du es. Über 4 Jahre nach Beginn dieses Threads stoßen Leute wie ich immer noch auf dieses Verhalten. Und immer noch schockiert.

Ja, es gibt viele Workarounds. Ein paar werde ich sofort verfolgen. Aber um diese zu implementieren, müssen Sie tatsächlich wissen, dass dieses Problem überhaupt existiert. Das enttäuscht mich am meisten. Nicht, dass Docker-Entwickler bestimmte Designentscheidungen getroffen hätten, seien sie gut oder schlecht.

Aber dass dieses "Firewall-Bypass-Verhalten" nicht klar herausgestellt, laut gewarnt und umfassender dokumentiert wird. Wenn es um Netzwerksicherheit geht, sind Überraschungen nie gut.

Wollte meine Problemumgehung für dieses Problem teilen, falls andere es nützlich finden. Verwenden von iptables & ipset. Getestet auf Ubuntu, CentOS 7 & RHEL 7. ipset wird verwendet, da "vertrauenswürdige" IPs nicht immer im gleichen IP-Bereich liegen (Begrenzung von iptables behoben).
Es funktioniert mit normalem Docker und Docker Swarm (auch bekannt als SwarmKit).
Es stellt sicher, dass Sie standardmäßig sicher sind, und lässt nur IPs zu, die Sie angeben, um eine Verbindung zu OS-Ports und Docker-Ports (mit iptables und ipset) herzustellen, die Sie angeben, sollten geöffnet sein. Hat auch die Möglichkeit, einen OS-Port oder Docker-Port "öffentlich" zu machen (für alle IPs offen)

Ansible ist nicht erforderlich, macht es aber einfacher.. Ansible-Rolle: https://github.com/ryandaniels/ansible-role-iptables-docker
Manuelle Schritte für CentOS/RHEL:
https://github.com/ryandaniels/ansible-role-iptables-docker#manual -commands-centosrhel
Und Ubuntu 18.04/20.04:
https://github.com/ryandaniels/ansible-role-iptables-docker#manual -commands-ubuntu-2004

Sie müssen ipset zusätzlich zu iptables installieren/konfigurieren (siehe oben stehende Links, wenn Sie Probleme haben).
Beispiel für eine iptables-Konfiguration (mit SSH-Port 22 für alle offen):

*filter
:DOCKER-USER - [0:0]
:FILTERS - [0:0]
#Can't flush INPUT. wipes out docker swarm encrypted overlay rules
#-F INPUT
#Use ansible or run manually once instead to add -I INPUT -j FILTERS
#-I INPUT -j FILTERS
-A DOCKER-USER -m state --state RELATED,ESTABLISHED -j RETURN
-A DOCKER-USER -i docker_gwbridge -j RETURN
-A DOCKER-USER -s 172.18.0.0/16 -j RETURN
-A DOCKER-USER -i docker0 -j RETURN
-A DOCKER-USER -s 172.17.0.0/16 -j RETURN
#Below Docker ports open to everyone if uncommented
#-A DOCKER-USER -p tcp -m tcp -m multiport --dports 8000,8001 -j RETURN
#-A DOCKER-USER -p udp -m udp -m multiport --dports 9000,9001 -j RETURN
-A DOCKER-USER -m set ! --match-set ip_allow src -j DROP
-A DOCKER-USER -j RETURN
-F FILTERS
#Because Docker Swarm encrypted overlay network just appends rules to INPUT
-A FILTERS -p udp -m policy --dir in --pol ipsec -m udp --dport 4789 -m set --match-set ip_allow src -j RETURN
-A FILTERS -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FILTERS -p icmp -j ACCEPT
-A FILTERS -i lo -j ACCEPT
#Below OS ports open to everyone if uncommented
-A FILTERS -p tcp -m state --state NEW -m tcp -m multiport --dports 22 -j ACCEPT
#-A FILTERS -p udp -m udp -m multiport --dports 53,123 -j ACCEPT
-A FILTERS -m set ! --match-set ip_allow src -j DROP
-A FILTERS -j RETURN
COMMIT
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen