SSH μέσω ρελέ ροής NGINX χωρίς να το χαλάσετε
Η κεφαλίδα PROXY είναι μήνυμα για έναν δέκτη που την περιμένει, και μια καταχώριση DNS με διαμεσολάβηση δεν είναι ρελέ TCP. Διορθώστε την άκρη και το ανάντη ξεχωριστά.
Το δημόσιο SSH μέσω ρελέ αποτυγχάνει σε δύο άσχετα σύνορα, και η διόρθωση του ενός συνήθως αποκαλύπτει το άλλο. Είτε η άκρη επιστρέφει απόκριση HTTP αντί να μεταφέρει ροή, είτε το ρελέ προσθέτει μπροστά μια κεφαλίδα που το backend δεν δέχτηκε ποτέ να διαβάσει. Τρεις συνθήκες καθορίζουν ποια από τις δύο βλέπετε: σε τι δείχνει πραγματικά η δημόσια καταχώριση, τι στέλνει το μπλοκ ροής προς τα ανάντη και ποιο όνομα επαληθεύει ο πελάτης SSH. Δουλέψτε τις με αυτή τη σειρά.
Δύο σύνορα, δύο συμπτώματα
Μια αποτυχία στην άκρη μοιάζει με σελίδα κατάστασης HTTP που φτάνει εκεί όπου θα έπρεπε να βρίσκεται ένα banner SSH. Η σύνδεση ολοκληρώνεται σε επίπεδο TCP και τα πρώτα byte είναι κείμενο που ανήκει σε διακομιστή ιστού. Αυτή είναι ασυμφωνία πρωτοκόλλου, όχι χαμένο πακέτο. Σας λέει επίσης ότι η άκρη εξυπηρετεί σκόπιμα κάτι άλλο για αυτό το όνομα.
Μια αποτυχία στα ανάντη φαίνεται διαφορετική. Η σύνδεση φτάνει στο sshd, το sshd διαβάζει byte που δεν είναι η ανταλλαγή ταυτοποίησης που περιμένει, και η συνεδρία πεθαίνει ή κολλάει χωρίς να προσφέρει ποτέ κλειδί.
Τα δύο μπερδεύονται εύκολα γιατί και τα δύο παράγουν πελάτη που συνδέεται και μετά αποτυγχάνει. Η πρώτη απόκριση πρωτοκόλλου που λαμβάνετε είναι αυτό που τα ξεχωρίζει, γι' αυτό ανήκει στο δελτίο.
Η κεφαλίδα PROXY είναι μήνυμα, όχι διακόπτης
Στο άρθρωμα ροής, το proxy_protocol on δίνει εντολή στο NGINX να γράψει κεφαλίδα πρωτοκόλλου PROXY προς τα ανάντη πριν από το ωφέλιμο φορτίο. Δεν ενεργοποιεί διαμεσολάβηση TCP και δεν έχει καμία σχέση με την κρυπτογράφηση SSH. Είναι σημείωμα που απευθύνεται στον δέκτη. Αν ο δέκτης δεν μπορεί να το διαβάσει, γίνεται σκουπίδι στην αρχή της ροής.
Η υπηρεσία υποδοχής πρέπει να καταναλώσει αυτή την κεφαλίδα σκόπιμα. Ένα κανονικό sshd περιμένει την ανταλλαγή ταυτοποίησης SSH ως τα πρώτα byte της σύνδεσης, οπότε ένα απρόσμενο προοίμιο σπάει τη χειραψία με τρόπο που μοιάζει με κατεστραμμένο διακομιστή.
stream {
server {
listen 2222;
proxy_pass 10.77.0.20:22;
}
}
Αυτό το απόσπασμα είναι ολόκληρο ένα λειτουργικό ρελέ για backend προσβάσιμο μέσω του VPN. Δεν εμφανίζεται οδηγία PROXY επειδή ο δέκτης δεν μιλάει το πρωτόκολλο, και αυτή η απουσία είναι απόφαση, όχι παράλειψη.
Διαχωρίστε επίσης τις δύο κατευθύνσεις. Η ρύθμιση proxy_protocol στη γραμμή listen σημαίνει ότι το NGINX περιμένει ο δικός του πελάτης να στείλει πρώτος την κεφαλίδα· η ενεργοποίησή του για έναν συνηθισμένο πελάτη SSH παράγει ακριβώς το αντίθετο από το πρόβλημα που συνήθως προσπαθούν να λύσουν.
Τι φτάνει πραγματικά το δημόσιο όνομα κεντρικού υπολογιστή
Μια σελίδα HTTP 400 σε συνεδρία SSH είναι απόδειξη για την άκρη. Κάτι στη διαδρομή μιλάει HTTP, και καμία εργασία σε κλειδί ή λογαριασμό στο backend δεν θα το αλλάξει. Σταματήστε να αλλάζετε το backend μέχρι να τακτοποιηθεί η άκρη.
Η συνηθισμένη καταχώριση με διαμεσολάβηση του Cloudflare μεταφέρει την υποστηριζόμενη κίνηση HTTP και HTTPS σε καθορισμένες θύρες. Η ενεργοποίηση της διαμεσολάβησης για ένα όνομα κεντρικού υπολογιστή δεν δημιουργεί γενικό ρελέ TCP, και η μετακίνηση του SSH στη θύρα 443 δεν το κάνει HTTPS.
Υπάρχουν δύο εφαρμόσιμες κατευθύνσεις. Μια καταχώριση μόνο DNS μπορεί να δείχνει στο δικό σας ρελέ TCP, κάτι που βάζει την απόφαση έκθεσης στα χέρια σας. Εναλλακτικά, χρησιμοποιήστε ένα προϊόν που τεκμηριώνει ρητά τη μεταφορά SSH, με δική του ρύθμιση προέλευσης, πελάτη και πρόσβασης.
Όποια κι αν επιλέξετε, το ρελέ χρειάζεται ακόμη διαδρομή VPN προς το backend, επιτρεπόμενη σύνδεση και διαδρομή επιστροφής. Η διαδρομή δεν είναι προαιρετική επειδή λειτουργεί η δημόσια πλευρά.
Κρατήστε την ταυτότητα SSH σταθερή μέσω ψευδωνύμου
Οι χρήστες συνήθως θέλουν να συνεχίσουν να πληκτρολογούν το υπάρχον όνομα κεντρικού υπολογιστή τους. Ένα ψευδώνυμο στη ρύθμιση SSH μπορεί να το κάνει χωρίς να αλλάξει τίποτα στο ρελέ, και κρατά την αλλαγή στην πλευρά του πελάτη όπου ανήκει.
Host git.example.com
HostName ssh-entry.example.net
Port 2222
User git
HostKeyAlias git.example.com
Χωρίς το HostKeyAlias, το OpenSSH αναζητά το κλειδί κεντρικού υπολογιστή με το όνομα στο οποίο συνδέεται, οπότε η καταχώριση μετακινείται και κάθε χρήστης βλέπει προειδοποίηση αλλαγμένου κλειδιού στην πρώτη χρήση. Η ρύθμιση του ψευδωνύμου κρατά σταθερές τις καταχωρίσεις known-hosts ενώ η σύνδεση εξακολουθεί να πηγαίνει στο ρελέ.
Αυτό το ψευδώνυμο ισχύει μόνο για απομακρυσμένα αποθετήρια βασισμένα σε SSH. Ένα URL Git μέσω HTTPS δεν το συμβουλεύεται, και το τυπικό URL απομακρυσμένου πρέπει να ταιριάζει με τη μεταφορά που όντως παρέχετε.
Αυτό που δεν πρέπει να κάνετε είναι να απενεργοποιήσετε την επαλήθευση κλειδιού κεντρικού υπολογιστή για να εξαφανιστεί η προειδοποίηση. Αυτό αφαιρεί μια προστασία που η επισκευή προώθησης δεν ζήτησε ποτέ να αγγίξετε, και μετατρέπει μια καλλωπιστική ενόχληση σε πραγματική έκθεση.
Επαληθεύστε κάθε άλμα ξεχωριστά
Δοκιμάστε τον δημόσιο ακροατή μόνο του, μετά τη σύνδεση ρελέ-προς-backend από τον κεντρικό υπολογιστή του ρελέ, και μόνο τότε τον πελάτη από άκρη σε άκρη. Κάθε μία από αυτές τις τρεις δοκιμές αποκλείει διαφορετικό επίπεδο. Η παράλειψη μιας σημαίνει ότι τα δύο εναπομείναντα αποτελέσματα δεν μπορούν να ερμηνευτούν. Τρεις παρατηρήσεις, τρία σημεία όπου μπορεί να ζει μια αποτυχία.
Κρατήστε τη διεύθυνση προορισμού, τη θύρα και τα πρώτα byte πρωτοκόλλου μαζί με κάθε αποτέλεσμα. Αυτή η τριάδα ξεχωρίζει σφάλμα άκρης από πρόβλημα δρομολόγησης VPN και από αποτυχία ταυτοποίησης SSH, και είναι η διαφορά μεταξύ διόρθωσης και εικασίας.
Τέλος, τεκμηριώστε την προβλεπόμενη έκθεση. Ένα ρελέ TCP που μεταφέρει SSH σε ιδιωτικό backend είναι σκόπιμο άνοιγμα στη δημόσια περίμετρο, και αξίζει την ίδια εξέταση με κάθε άλλη εισερχόμενη υπηρεσία.