SSL-Zertifikat für die Verbindung zum Heimserver über Socat

SSL-Zertifikat für die Verbindung zum Heimserver über Socat

Ich betreibe Nextcloud zu Hause auf einem Raspberry Pi. Es aktualisiert seine IPv6-Adresse auf einem Hostnamen beim DynDNS-Anbieter spDYN.de. Da mein Anbieter jedoch nur IPv6-Verbindungen anbietet (für IPv4 verwende ich DS-Lite), kann ich nur von anderen IPv6-Verbindungen aus direkt auf den Hostnamen zugreifen und muss einen IPv4-IPv6-Postmapper verwenden, um von IPv4-Netzwerken aus eine Verbindung dazu herzustellen.

Das ist kein großes Problem, da meine Website auf einem Server gehostet wird, der sowohl IPv6- als auch IPv4-Verbindungen hat, also habe ich socat gemäß verwendetdieses Tutorialum auf dem Server, auf dem meine Website gehostet wird, einen Portmapper einzurichten, der einen bestimmten Port von meiner Website-Domäne auf Port 443 des dynamischen DNS-Hostnamens umleitet. Das funktioniert einwandfrei, verursacht aber ein Problem mit SSL-Zertifikaten:

Auf dem RasPi habe ich mit certbot ein „Let’s encrypt“-Zertifikat für den dynamischen DNS-Hostnamen erstellt, das einwandfrei funktioniert und die Verbindung als gesichert anzeigt. Außerdem habe ich auf meinem Webserver ein ähnliches Zertifikat für die Domäne erstellt, die ich für den Portmapper verwende, was an sich funktioniert. Wenn ich jedoch mit dem spezifischen, weitergeleiteten Port auf die Domäne zugreife, um auf den RasPi zuzugreifen, zeigt der Browser weiterhin die URL an, die meine Domäne enthält, aber er empfängt das Zertifikat vom RasPi, das für den dynamischen DNS-Hostnamen ausgestellt wurde. Infolgedessen schlägt die Sicherheitsüberprüfung natürlich fehl, da das Zertifikat für die „falsche“ Domäne ausgestellt wurde. Ich habe bereits versucht, auf meinem RasPi ein Zertifikat für meine Domäne auszustellen, aber es schlägt fehl und ich erhalte die Meldung, dass ich „nicht autorisiert“ bin.

Wie kann ich dieses Problem lösen? Wo muss ich welches Zertifikat einrichten?

Antwort1

Um Zertifikatsfehler zu vermeiden, muss der Pi ein Zertifikat senden, das mit der verwendeten Domäne übereinstimmt.Hierzu gibt es zwei Ansätze:

  1. Verwenden Sie ein Zertifikat für beide Domänen, das sowohl auf dem Pi- als auch auf dem Hauptserver installiert ist. Es spielt keine Rolle, welche Domäne der Client in seiner Abfrage verwendet hat, das Zertifikat stimmt überein.
  2. Wählen Sie ein vom Client erwartetes Zertifikat aus und senden Sie dieses.

Option 1 ist einfacher und gängige Praxis. Sehen Sie sich das Zertifikat für google.com an! Sowohl der Pi als auch der Hauptserver haben dasselbe Zertifikat (für beide Domänen) installiert. Um ein solches Zertifikat von Let's Encrypt zu erhalten, müssen Sie auf dem Hauptserver auch eine Website für die dynamische Domäne des Pi betreiben und verwendeneinscertbot-Befehl, um die Kontrolle über beide Domänen gleichzeitig zu überprüfen. Die Site des Hauptservers für den Dyndns-Namen muss den Inhalt vom Pi nicht hosten – er ist nur da, damit Let’s Encrypt überprüfen kann, ob Sie die Kontrolle über diese Site haben (Sie können diese Site zwischen den Verlängerungen sogar ausschalten).

Beispiel eines Certbot-Befehls hierfür (auf dem Hauptwebserver ausführen):

letsencrypt certonly --webroot --csr request.csr -w /http/pisite/www -d mypi.spdyn.de -w /http/mainwebsite/www -d maindomain.de

Dabei request.csrwird eine der beiden Domänen als CN verwendet und beide Domänen im SAN-Feld enthalten sein. /http/pisite/wwwDies bezieht sich auf ein lokales Verzeichnis, das Sie für eine andere Website auf dem aktuellen Server erstellen würden, der an den dynamischen Namen des Pi gebunden ist, und /http/mainwebsite/wwwist das vorhandene Verzeichnis Ihrer Hauptwebsite.


Option 2 ist komplizierter, führt aber zu einem „saubereren“ Ergebnis: Der Client erhält ein Zertifikat, das mit der eingegebenen Domäne übereinstimmt. Führen Sie auf dem Raspberry Pi nginx mit dem Stream-Modul (oder einem gleichwertigen Modul) aus, das beim Öffnen einer TLS-Verbindung das SNI-Feld untersucht (ohne die TLS-Verbindung zu akzeptieren) und basierend auf der dort enthaltenen Domäne auswählt, an welchen Upstream die Verbindung weitergeleitet werden soll. Auf diese Weise können Sie auswählen, wie Sie mit Anfragen umgehen möchten, die an die Hauptdomäne über den externen Port gestellt und an den Raspberry Pi weitergeleitet werden. Sie können sie an den Hauptwebserver senden, als ob sie über den richtigen Port gestellt worden wären, Sie können sie an einen anderen Port auf dem Pi senden (z. B. Nextcloud oder einen anderen Port), Sie können sie mit derselben nginx-Instanz beenden und eine beliebige Seite anzeigen oder einfach die Verbindung schließen. Die Entscheidung liegt bei Ihnen.

Hier ist eine Beispielkonfiguration für diese Methode:

stream/sni-switch.conf

# Listen on 443, and on new connection:
#   if the SNI is mapped herein, handle it on this Nginx
#   else, forward the whole session to 192.168.1.80:443 (TCP passthrough, no decryption)

upstream mainwebserver {
    server 192.168.1.80:443;
}

upstream local_https {
    server 127.0.0.1:1443;
}

map $ssl_preread_server_name $name {
    default mainwebserver;

    pisite.spdyn.de     local_https;
}

server {
    listen 443;

    ssl_preread on;
    proxy_pass $name;
}

Und innginx.conf

load_module /usr/lib/nginx/modules/ngx_stream_module.so;

stream {
    include /etc/nginx/stream/sni-switch.conf;
}

...

Um dies mit Apache zu tun, sieheDasEine Beispielkonfiguration könnte wie folgt aussehen:

<VirtualHost *:*>
    ProxyPreserveHost On
    ProxyPass        "/" "http://192.168.1.80/"
    ProxyPassReverse "/" "http://192.168.1.80/"
    ServerName maindomain.de
</VirtualHost>

verwandte Informationen