Kommunikation vom Docker-Container (Nginx Proxy Manager) zum Host (DS)

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Hallo zusammen,

folgende Situation: auf meiner DS laufen mehrere Docker Container, die ich über Portainer verwalte. Ich habe außerdem ein macvlan im Betrieb in diesem Zusammenhang. Pi-Hole, Unbound und Vaultwarden funktionieren auch ohne Probleme. Das Pi-Hole nutze ich als DNS-Server und habe hier eigene Domains, die ich zu den einzelnen Diensten/Websites lotse.

Auf meiner DS habe ich mehrere rein lokale Websites laufen, unter anderem ein MediaWiki. Das ist zu erreichen unter (IPs und Hostnamen geändert) 192.168.1.28/MediaWiki. Nun möchte ich gerne mit der Adresse wiki.example.com, die rein lokal bei mir im LAN läuft und von einem von eigener CA unterschriebenen Zertifikat dieses Wiki erreichen. Ich hab im DSM-internen Reverse Proxy Manager GUI keine Option finden können auf eine Unterseite, also /mediawiki, zu verweisen. Inzwischen weiß ich wie ich als root im Nginx einene .conf's anlegen kann. Allerdings möchte ich eher ungerne langfristig im Nginx der Syno DS rumfuhrwerken, da ich hier schon mal Probleme hatte nach DSM-Updates. Und eigentlich wäre mir ein GUI auch lieber. Also bin ich auf den Nginx Proxy Manager als Docker Container gekommen. Funktioniert auch, Vaultwarden beispielsweise kann ich prima unter vault.example.com verschlüsselt erreichen. Der Pi-Hole-DNS-Server löst entsprechend auf, wie gesagt.

Allerdings gibt es anscheinend das Problem, dass der Nginx-PM-Container keinen Reverse Proxy auf die DS leiten kann. Mir ist schon bekannt, dass Host und Container Prinzip-bedingt erstmal nicht miteinander kommunizieren können und mir ist auch die Möglichkeit bekannt eine Bridge für das macvlan zu erstellen. Das hab ich auch gemacht und sie funktioniert auch - allerdings offensichtlich nur einseitig. Also ich kann aus der DS-Kommandokonsole heraus, nachdem die Brücke erstellt wurde, den Nginx-PM und auch die anderen Container erfolgreich anpingen. Trotzdem gibt es immer einen "502 Bad Gateway" zurück wenn ich die im Nginx konfigurierte Domain aufrufe, also wiki.example.com. Die verweist auf 192.168.1.28/mediawiki.

Folgende Fehlermeldung im Log des Nginx-PM gibt es:
Code:
2024/02/24 17:21:12 [error] 338#338: *806 connect() failed (113: No route to host) while connecting to upstream, client: 192.168.1.201, server: wiki.example.com, request: "GET / HTTP/2.0", upstream: "http://192.168.1.28:80/mediawiki/", host: "wiki.example.com"

Reproduzierbar. Ich weiß ehrlich gesagt nicht wie ich mal versuchen könnte aus dem Container heraus die DS anzupingen, aber ich fürchte, dass das eben nicht funktionieren wird. Anders herum (DS --> Container) funktioniert es.

Hier noch die entsprechende .Conf aus dem Nginx-PM, falls das zum Verständnis hilft:

Code:
map $scheme $hsts_header {
    https   "max-age=63072000; preload";
}

server {
  set $forward_scheme http;
  set $server         "192.168.1.28";
  set $port           80;

  listen 80;
listen [::]:80;

listen 443 ssl http2;
listen [::]:443 ssl http2;

  server_name wiki.example.com;

  # Custom SSL
  ssl_certificate /data/custom_ssl/npm-1/fullchain.pem;
  ssl_certificate_key /data/custom_ssl/npm-1/privkey.pem;

    # Force SSL
    include conf.d/include/force-ssl.conf;

  access_log /data/logs/proxy-host-2_access.log proxy;
  error_log /data/logs/proxy-host-2_error.log warn;

  location / {
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Scheme $scheme;
    proxy_set_header X-Forwarded-Proto  $scheme;
    proxy_set_header X-Forwarded-For    $remote_addr;
    proxy_set_header X-Real-IP        $remote_addr;
    proxy_pass       http://192.168.1.28:80/mediawiki/;
    # Force SSL
    include conf.d/include/force-ssl.conf;
  }
  # Custom
  include /data/nginx/custom/server_proxy[.]conf;
}

Hat Jemand eine Idee, wie ich die Kommunikation Container --> DS hinbekomme? Oder noch andere Ideen/Gedanken dazu? Ich kann natürlich gerne auch noch mehr Infos geben wenn benötigt.

Vielen Dank schon mal und viele Grüße
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.519
Punkte für Reaktionen
404
Punkte
103
Was Du erlebst ist der Effekt eines Kernel-Sicherheitsfeatures das verhindert, dass macvlan Eltern (=Host) und Kind (=bei Docker die Interfaces der Container) miteinander direkt kommunizieren dürfen und umgekehrt. Diese Einschränkung stammt vom Linux Kernel, nicht von Docker.

Lösung: Durch das Hinzufügen eines zusätzlichen macvlan Kind-Interfaces im Host, kann man das Problem umgehen, da dann Kind-Interface zu Kind-Interface Kommunikation verwendet wird.

Mit diesen Befehlen bekommt man es in einer root-shell hin:
Code:
# 1. Anlegen des Host macvlan Kind-Interfaces:
ip link add macvlan-shim link <maclan Eltern Interface> type macvlan mode bridge

# 2. dem Host macvlan Kind-Interface eine IP zuordnen und es online bringen:
ip addr add <ip des neuen macvlan Kind Interface>/32 dev macvlan-shim
ip link set macvlan-shim up

# 3. dem macvlan Kind-Interface die Route zum Container macvlan-Netzwerk setzen, damit der Host mit den Container kommunizieren kann
ip route add <ip Range es docker macvlan Netzwerks> dev macvlan-shim

zu 1: <maclan Eltern Interface> = sollte identisch sein wie das Eltern-Interface vom docker macvlan Netzwerk
zu 2: <ip des neuen macvlan Kind Interface>= Die IP sollte in der Range des Docker macvlan Netzwerks liegen und muss von /32 (=CIDR für eine IP) angegeben sein
zu 3: <ip Range es docker macvlan Netzwerks> = Hier sollte dieselbe CIDR-Range wie beim Anlegen des docker mavclan Netzwerks für `--ip-range` verwendet wurde.

Danach kann der Host direkt mit den Container IPs kommunizieren, aber die Container müssen dann mit er in 2. gesetzen macvlan Kind-Interface IP des Host kommunizieren. Die Einschränkung das die Container trotzdem nicht mit der Syno über die Host IP des Eltern-Interfaces kommunizierne können bleibt, aber man hat jetzt wenigstens einen Workaround.

Da das ganze nach einem NAS Neustart weg ist, sollte man es zusätzlich als Aufgabe beim Starten Planen.

Update: Schritt 1 legt technisch eine Bridge (=quasi einen logischen Switch) und diese bekommt in Schritt 2 eine IP zugewiesen. Als IP in Schritt 2 nehmt ihr idealerweise die letzte IP aus der --ip-range (mit Calculator ausrechnen welche das ist), oder klammert diese beim Anlegen des macvlan Netzwerks explizit vom Docker-DHCP Server für das Netzwerk mit --aux-addresses "<hostname vom nas>=<ip des neuen macvlan Kind Interface>" aus, oder achtet bei der händische ipv4 Adressvergabe beim Container diese IP keinem Container zu geben.
 
Zuletzt bearbeitet:

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Wow, vielen lieben Dank für die schnelle und ausführliche Antwort. Das müsste ich hinkriegen. Wenn nicht, frage ich nochmal konkret.

Eine Frage habe ich zum Verständnis:

Meine Bridge die ich erstellt hab und die mir die Kommunikation DS --> Container ermöglicht, Also Host --> Kind, aber eben nicht umgekehrt anscheinend, ist Folgende:

Code:
ip link add mvl-brg link eth0 type macvlan mode bridge
ip addr add 192.168.1.14/32 dev mvl-brg
ip link set mvl-brg up
ip route add 192.168.1.8/29 dev mvl-brg

Wobei der Nginx auf der .12 liegt und das macvlan halt .8/29 ist.

Brauche ich BEIDE Bridges für die Kommunikation in beide Richtungen?

Viele Grüße!

EDIT: ich merke gerade, dass das ja fast die gleiche Bridge ist....... oder stehe ich da gerade auf dem Schlauch? Dachte erst, dass das eine andere ist, aber eigentlich ist hier ja nur mvl-brg statt macvlan-shim, oder?
 

plang.pl

Benutzer
Contributor
Sehr erfahren
Mitglied seit
28. Okt 2020
Beiträge
15.028
Punkte für Reaktionen
5.401
Punkte
564
Das sollte so passen, denke ich.
Wenn du den VMM installiert hast, dann ist das parent interface ovs_eth0
 

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Danke für deine Antwort erneut, aber ich glaub wir haben aneinander vorbei geredet bzw. ich hab mich nicht klar genug ausgedrückt:

Die o.g. Bridge habe ich ja bereits vor dem ersten Post erstellt und der Fehler kommt trotzdem noch immer. Also das Problem besteht trotz dieser Bridge...

Den VMM hab ich nicht installiert.

Und Frage am Rande: was bedeutet macvlan-shim?
 

plang.pl

Benutzer
Contributor
Sehr erfahren
Mitglied seit
28. Okt 2020
Beiträge
15.028
Punkte für Reaktionen
5.401
Punkte
564
Das ist nur der Name, der kann beliebig gesetzt werden.
Ist die Firewall der DS an?
 

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Das ist nur der Name, der kann beliebig gesetzt werden.
Ist die Firewall der DS an?
Da hatte ich auch schon dran gedacht und sie deaktiviert. Deshalb bin ich gerade etwas überfragt.

Wie gesagt der Ping DS --> Container funktioniert. Anders herum weiß ich nicht wie ich es testen soll, also vom Container aus auf den Host zu pingen.
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.519
Punkte für Reaktionen
404
Punkte
103
Den Namen kannst Du frei wählen. In der IT ist ein Shim ein transparenter Vermittler in der Kommunikation.

Probier doch aus, ob Du die IP auch an die vom docker macvlan Netzwerk erstelle Bridge hängen kannst. Mit `brctl show` kannst Du die Bridges auflisten.

UPDATE: ach Du hast das alles schon gemacht. Dann musst Du nicht noch eine weitere Bridge anlegen. Ich dachte Du wolltest Dich an die Bridge vom Docker macvlan Netzwerk ranhängen :END-OF-UPDATE


Wie gesagt der Ping DS --> Container funktioniert. Anders herum weiß ich nicht wie ich es testen soll, also vom Container aus auf den Host zu pingen.
In einem Container ein Terminal aufmachen und `ping 192.168.1.14` ausführen.


Ich selber verwende macvlan nicht. Das stammt aus meinen damaligen Notizen, als ich damit mal kurz rumgespielt habe vor 5 Jahren. Meine Container laufen aber auch nicht auf der DS, die laufen in VMs: einige auf einem Swarm Cluster, einige auf einem Kubernetes Cluster. Den Swarm Cluster könnte ich mir eigentlich auch sparen.
 
  • Like
Reaktionen: Impidimpi

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
In einem Container ein Terminal aufmachen und `ping 192.168.1.14` ausführen.
Hallo und Danke auch dir für die schnelle Antwort und Hilfe!

Das habe ich schon versucht über den Container Manager und über Portainer (dürfte aus gleiche rauskommen) in zwei unterschiedlichen Containern - und jedes Mal kommt, dass der das Ping- Command nicht finden kann. Also:

Code:
ping 192.168.1.28                                        
bash: ping: command not found

Auch egal welche IP ich anpingen will. Gibts noch andere Möglichkeiten?

UPDATE: ich muss mich korrigieren: tatsächlich ging es im Pi-Hole-Container! Und da zeigt sich wie vermutet, dass der Host, also die 28, nicht erreicht wird - andere IPs aber wohl.
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.519
Punkte für Reaktionen
404
Punkte
103
Dir ist schon klar, dass keiner von uns die Kontextinformationen hat, mit denen Du in Deinem Kopf arbeitest, und uns dann antworten gibst, die ohne das Kontextwissen nicht nachvollziehbar sind?

Deine Antwort sollte die Frage "Was muss jemand, der meine Umgebung nicht kennt, wissen, damit er meinen Post verstehen kann?" berücksichtigen.

Welche IP hat das NAS?
Welche Range hat das macvlan Netzwerk?
Welche IP hat die Bridge mit dem Kind-Interface?
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.519
Punkte für Reaktionen
404
Punkte
103
UPDATE: ich muss mich korrigieren: tatsächlich ging es im Pi-Hole-Container! Und da zeigt sich wie vermutet, dass der Host, also die 28, nicht erreicht wird - andere IPs aber wohl.
Das heißt es läuft jetzt alles? Und mit deinem Post bestätigst Du eigentlich nur das hier:

Danach kann der Host direkt mit den Container IPs kommunizieren, aber die Container müssen dann mit er in 2. gesetzen macvlan Kind-Interface IP des Host kommunizieren. Die Einschränkung das die Container trotzdem nicht mit der Syno über die Host IP des Eltern-Interfaces kommunizierne können bleibt, aber man hat jetzt wenigstens einen Workaround.
 

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Dir ist schon klar, dass keiner von uns die Kontextinformationen hat, mit denen Du in Deinem Kopf arbeitest, und uns dann antworten gibst, die ohne das Kontextwissen nicht nachvollziehbar sind?

Deine Antwort sollte die Frage "Was muss jemand, der meine Umgebung nicht kennt, wissen, damit er meinen Post verstehen kann?" berücksichtigen.

Welche IP hat das NAS?
Welche Range hat das macvlan Netzwerk?
Welche IP hat die Bridge mit dem Kind-Interface?
Sorry, ich dachte eigentlich, dass ich diese Informationen gegeben hätte (siehe oben). War vielleicht ein bisschen durcheinander.

Gerne nochmal geordnet:

NAS-IP: 192.168.1.28
Range macvlan Netzwerk: 192.168.1.8/29
Bridge-IP: 192.168.1.14

Nginx Proxy Manager: 192.168.1.12
Aufzurufende Website: 192.168.1.28/mediawiki
Mit dieser Domain: wiki.example.de

Im Moment leitet Pi-Hole als DNS-Server wiki.example.de an 192.168.1.12 (Nginx)

In Nginx ist die Konfiguration wie im ersten Post, also Forward Hostname / IP: http:// 192.168.1.28 Port 80
Und bei Custom Location: Location=/ und http:// 192.168.1.28/mediawiki/ Port 80

Die Frage ist nun, ob diese Konfiguration richtig ist. Ich habe auch mal versucht statt der 28 die 14 einzusetzen, aber das hat auch nicht funktioniert.
Das heißt es läuft jetzt alles? Und mit deinem Post bestätigst Du eigentlich nur das hier:
Leider noch nicht. Aber vielleicht kommen wir der Sache mit den obigen Informationen näher?
Tut mir leid, wenn es verwirrend war bisher.

Und ja, ich verstehe jetzt, dass der Container auch mit der Bridge nicht direkt mit dem Host kommunizieren kann. Die Frage ist wie ich dann die Bridge richtig nutze. Das hab ich vermutlich noch nicht verstanden.
 

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Sorry für den Doppelpost: ich hatte hier etwas falsch gelesen, tut mir leid. Das erklärt einen Teil der Verwirrung.

In einem Container ein Terminal aufmachen und `ping 192.168.1.14` ausführen.
Ich hatte den Ping auf das NAS direkt, also die .28 ausgeführt. Mit der .14 (also der Bridge) funktionierte es auch erst nicht. Das lag aber wohl daran, dass die Bridge aus irgendeinem Grund nicht mehr aktiv war. Eigentlich hatte ich nichts neu gestartet.

Jetzt funktioniert jedenfalls alles, also auch der Reverse Proxy. Ich hatte da nur noch nicht die .14 eingetragen, sondern nach wie vor die .28, was natürlich ein Denkfehler war.

Vielen, vielen Dank nochmal, ihr habt mir sehr geholfen!
 

haydibe

Benutzer
Sehr erfahren
Mitglied seit
12. Apr 2016
Beiträge
1.519
Punkte für Reaktionen
404
Punkte
103
Sorry, ich dachte eigentlich, dass ich diese Informationen gegeben hätte (siehe oben). War vielleicht ein bisschen durcheinander.
Die Information hat auf jeden Fall zur Klarheit und besseren Nachvollziehbarkeit geführt. Damit kann man natürlich bessere, bzw. auf Deine Situation exakt passende Antworten geben.

Jetzt funktioniert jedenfalls alles, also auch der Reverse Proxy. Ich hatte da nur noch nicht die .14 eingetragen, sondern nach wie vor die .28, was natürlich ein Denkfehler war.
Ich hatte schon vermutet, dass Du aus einem macvlan Kind-Interface weiterhin versuchst das NAS über die Host-IP und nicht über die IP der Bridge-IP anzusprechen.

Gratulation!
 

Impidimpi

Benutzer
Mitglied seit
21. Aug 2014
Beiträge
69
Punkte für Reaktionen
5
Punkte
8
Danke! :)

Mit der .14 (also der Bridge) funktionierte es auch erst nicht. Das lag aber wohl daran, dass die Bridge aus irgendeinem Grund nicht mehr aktiv war. Eigentlich hatte ich nichts neu gestartet.
Das hier konnte ich inzwischen auch aufklären: Ich hab parallel am Syno-internen Nginx gearbeitet und den mehrmals neu gestartet. Dadurch gerät offensichtlich auch die Bridge durcheinander oder baut sich ab, wäre meine Vermutung. Jedenfalls funktionierte danach reproduzierbar die Bridge entweder in beide Richtungen oder eben nur in Container >> Bridge IP (Host) Richtung nicht. Das hat dann zur zusätzlichen Verwirrung bei mir beigetragen.

Lehre unter anderem: nicht alles gleichzeitig machen wollen. :D

Und Reload statt Restart zu nutzen beim Nginx wenn ich eine Conf ändere. Aber dadurch, dass jetzt der Container-Nginx funktioniert, muss ich am Syno-internen-Nginx auch nicht mehr so viel modifizieren, was ja ein Ziel des Ganzen war.
 
  • Love
Reaktionen: haydibe


 

Kaffeautomat

Wenn du das Forum hilfreich findest oder uns unterstützen möchtest, dann gib uns doch einfach einen Kaffee aus.

Als Dankeschön schalten wir deinen Account werbefrei.

:coffee:

Hier gehts zum Kaffeeautomat