Öffentliches SSH über einen Relay scheitert an zwei unabhängigen Grenzen, und die Behebung der einen legt meist die andere offen. Entweder liefert die Edge eine HTTP-Antwort statt eines Streams, oder der Relay stellt einen Header voran, dessen Lektüre das Backend nie zugestimmt hat. Drei Bedingungen entscheiden, welchen Fall Sie sehen: worauf der öffentliche Eintrag tatsächlich zeigt, was der Stream-Block upstream sendet und welchen Namen der SSH-Client prüft. Arbeiten Sie sie in dieser Reihenfolge ab.

Zwei Grenzen, zwei Symptome

Ein Fehler an der Edge sieht aus wie eine HTTP-Statusseite, die ankommt, wo ein SSH-Banner stehen sollte. Die Verbindung kommt auf TCP-Ebene zustande, und die ersten Bytes sind Text, der zu einem Webserver gehört. Das ist eine Protokollabweichung, kein verlorenes Paket. Es sagt Ihnen außerdem, dass die Edge für diesen Namen bewusst etwas anderes ausliefert.

Ein Fehler am Upstream sieht anders aus. Die Verbindung erreicht sshd, sshd liest Bytes, die nicht der erwartete Identifikationsaustausch sind, und die Sitzung stirbt oder hängt, ohne je einen Schlüssel anzubieten.

Beide sind leicht zu verwechseln, weil beide einen Client erzeugen, der sich verbindet und dann scheitert. Die erste Protokollantwort, die Sie erhalten, unterscheidet sie, deshalb gehört sie ins Ticket.

Der PROXY-Header ist eine Nachricht, kein Schalter

Im Stream-Modul weist proxy_protocol on NGINX an, vor der Nutzlast einen PROXY-Protokoll-Header in Richtung Upstream zu schreiben. Es aktiviert kein TCP-Proxying und hat nichts mit SSH-Verschlüsselung zu tun. Es ist eine an den Empfänger adressierte Notiz. Kann der Empfänger sie nicht lesen, wird sie zu Müll am Anfang des Streams.

Der empfangende Dienst muss diesen Header bewusst konsumieren. Ein normales sshd erwartet den SSH-Identifikationsaustausch als erste Bytes der Verbindung, daher bricht eine unerwartete Präambel den Handshake so, dass es wie ein beschädigter Server aussieht.

stream {
    server {
        listen 2222;
        proxy_pass 10.77.0.20:22;
    }
}

Dieses Fragment ist die Gesamtheit eines funktionierenden Relays für ein über das VPN erreichbares Backend. Es erscheint keine PROXY-Direktive, weil der Empfänger das Protokoll nicht spricht, und dieses Fehlen ist eine Entscheidung, keine Auslassung.

Trennen Sie auch die beiden Richtungen. proxy_protocol in der listen-Zeile zu setzen bedeutet, dass NGINX erwartet, dass sein eigener Client den Header zuerst sendet; es für einen gewöhnlichen SSH-Client zu aktivieren, erzeugt genau das Gegenteil des Problems, das man üblicherweise lösen will.

Was der öffentliche Hostname tatsächlich erreicht

Eine HTTP-400-Seite in einer SSH-Sitzung ist ein Beweis über die Edge. Etwas auf dem Pfad spricht HTTP, und keine Schlüssel- oder Kontenarbeit am Backend wird das ändern. Hören Sie auf, das Backend zu ändern, bis die Edge geklärt ist.

Der gewöhnliche proxyte Eintrag von Cloudflare trägt seinen unterstützten HTTP- und HTTPS-Verkehr auf festgelegten Ports. Den Proxy für einen Hostnamen einzuschalten erzeugt kein allgemeines TCP-Relay, und SSH auf Port 443 zu verschieben macht es nicht zu HTTPS.

Es gibt zwei gangbare Richtungen. Ein reiner DNS-Eintrag kann auf Ihr eigenes TCP-Relay zeigen, was die Entscheidung über die Exposition in Ihre Hände legt. Alternativ nutzen Sie ein Produkt, das SSH-Transport ausdrücklich dokumentiert, mit eigener Origin-, Client- und Zugriffskonfiguration.

Was auch immer Sie wählen, der Relay braucht weiterhin eine VPN-Route zum Backend, eine erlaubte Verbindung und einen Rückweg. Die Route ist nicht optional, weil die öffentliche Seite funktioniert.

Halten Sie die SSH-Identität über einen Alias stabil

Nutzer möchten meist ihren bestehenden Hostnamen weitertippen. Ein Alias in der SSH-Konfiguration kann das tun, ohne am Relay etwas zu ändern, und er hält die Änderung auf der Clientseite, wo sie hingehört.

Host git.example.com
    HostName ssh-entry.example.net
    Port 2222
    User git
    HostKeyAlias git.example.com

Ohne HostKeyAlias sucht OpenSSH den Hostschlüssel unter dem Namen, mit dem es sich verbindet, sodass der Eintrag wandert und jeder Nutzer beim ersten Gebrauch eine Warnung über einen geänderten Schlüssel sieht. Das Setzen des Alias hält known-hosts-Einträge stabil, während die Verbindung weiterhin zum Relay geht.

Dieser Alias gilt nur für SSH-basierte Remotes. Eine HTTPS-Git-URL konsultiert ihn nicht, und die typische Remote-URL muss zum tatsächlich bereitgestellten Transport passen.

Was Sie nicht tun dürfen, ist die Hostschlüsselprüfung abzuschalten, damit die Warnung verschwindet. Das entfernt einen Schutz, den die Weiterleitungsreparatur nie anzutasten verlangt hat, und verwandelt ein kosmetisches Ärgernis in eine echte Exposition.

Prüfen Sie jeden Sprung einzeln

Testen Sie den öffentlichen Listener für sich, dann die Relay-zu-Backend-Verbindung vom Relay-Host aus und erst dann den Client von Ende zu Ende. Jeder dieser drei Tests schließt eine andere Schicht aus. Wird einer übersprungen, lassen sich die beiden übrigen Ergebnisse nicht deuten. Drei Beobachtungen, drei Orte, an denen ein Fehler leben kann.

Halten Sie Zieladresse, Port und die ersten Protokollbytes zu jedem Ergebnis fest. Dieses Trio unterscheidet einen Edge-Fehler von einem VPN-Routingproblem und von einem SSH-Authentifizierungsfehler, und das ist der Unterschied zwischen einer Reparatur und einer Vermutung.

Dokumentieren Sie schließlich die beabsichtigte Exposition. Ein TCP-Relay, das SSH zu einem privaten Backend führt, ist eine bewusste Öffnung im öffentlichen Perimeter und verdient dieselbe Prüfung wie jeder andere eingehende Dienst.

Ähnliche Artikel