SSH gennem en NGINX-streamrelæ uden at ødelægge det
Et PROXY-header er en besked til en modtager, der forventer det, og en proxyet DNS-post er ikke et TCP-relæ. Ret kanten og upstreamen hver for sig.
Offentlig SSH gennem et relæ fejler ved to uafhængige grænser, og når man retter den ene, afsløres som regel den anden. Kanten returnerer enten et HTTP-svar i stedet for at føre en stream, eller relæet sætter et header foran, som backend aldrig har accepteret at læse. Tre forhold afgør, hvilken af dem du ser: hvad den offentlige post faktisk peger på, hvad stream-blokken sender upstream, og hvilket navn SSH-klienten verificerer. Behandl dem i den rækkefølge.
To grænser, to symptomer
En fejl ved kanten ser ud som en HTTP-statusside, der ankommer, hvor et SSH-banner burde være. Forbindelsen fuldføres på TCP-niveau, og de første bytes er tekst, der tilhører en webserver. Det er en uoverensstemmelse i protokollen, ikke en tabt pakke. Det fortæller dig også, at kanten bevidst betjener noget andet for det navn.
En fejl ved upstream ser anderledes ud. Forbindelsen når sshd, sshd læser bytes, der ikke er den identifikationsudveksling, den forventer, og sessionen dør eller hænger uden nogensinde at tilbyde en nøgle.
De to er lette at forveksle, fordi begge giver en klient, der forbinder og derefter fejler. Det første protokolsvar, du modtager, er det, der skelner dem, og derfor hører det i billetten.
PROXY-headeren er en besked, ikke en kontakt
I stream-modulet instruerer proxy_protocol on NGINX i at skrive et PROXY-protokolheader mod upstream før nyttelasten. Det aktiverer ikke TCP-proxy, og det har intet at gøre med SSH-kryptering. Det er en note rettet til modtageren. Hvis modtageren ikke kan læse den, bliver den til affald i begyndelsen af streamen.
Den modtagende tjeneste skal bevidst forbruge det header. En normal sshd forventer SSH-identifikationsudvekslingen som de første bytes på forbindelsen, så en uventet præambel ødelægger håndtrykket på en måde, der ligner en beskadiget server.
stream {
server {
listen 2222;
proxy_pass 10.77.0.20:22;
}
}
Det fragment er hele et fungerende relæ for en backend, der kan nås over VPN'en. Der optræder ingen PROXY-direktiv, fordi modtageren ikke taler protokollen, og den udeladelse er en beslutning, ikke en forglemmelse.
Adskil også de to retninger. At sætte proxy_protocol på listen-linjen betyder, at NGINX forventer, at dens egen klient sender headeren først; at aktivere det for en almindelig SSH-klient giver præcis det modsatte af det problem, folk normalt prøver at løse.
Hvad det offentlige værtsnavn faktisk når
En HTTP 400-side i en SSH-session er et bevis om kanten. Noget på vejen taler HTTP, og ingen mængde arbejde med nøgle eller konto på backend vil ændre det. Hold op med at ændre backend, indtil kanten er afklaret.
Cloudflares almindelige proxyede post bærer sin understøttede HTTP- og HTTPS-trafik på definerede porte. At slå proxyen til for et værtsnavn skaber ikke et generelt TCP-relæ, og at flytte SSH til port 443 gør det ikke til HTTPS.
Der findes to brugbare retninger. En DNS-only-post kan pege på dit eget TCP-relæ, hvilket lægger beslutningen om eksponering i dine hænder. Alternativt kan du bruge et produkt, der udtrykkeligt dokumenterer SSH-transport, med sin egen oprindelses-, klient- og adgangskonfiguration.
Uanset hvad du vælger, har relæet stadig brug for en VPN-rute til backend, en tilladt forbindelse og en returvej. Ruten er ikke valgfri, fordi den offentlige side virker.
Hold SSH-identiteten stabil gennem et alias
Brugere vil normalt fortsætte med at skrive deres eksisterende værtsnavn. Et alias i SSH-konfigurationen kan gøre det uden at ændre noget ved relæet, og det holder ændringen på klientsiden, hvor den hører hjemme.
Host git.example.com
HostName ssh-entry.example.net
Port 2222
User git
HostKeyAlias git.example.com
Uden HostKeyAlias slår OpenSSH værtsnøglen op under det navn, den forbinder til, så posten flytter sig, og hver bruger ser en advarsel om ændret nøgle ved første brug. At sætte aliaset holder known-hosts-poster stabile, mens forbindelsen stadig går til relæet.
Dette alias gælder kun for SSH-baserede fjernlagre. En HTTPS-Git-URL konsulterer det ikke, og den typiske fjern-URL skal matche den transport, du faktisk har etableret.
Det, du ikke må gøre, er at deaktivere værtsnøgleverifikation for at få advarslen til at forsvinde. Det fjerner en beskyttelse, som videresendelsesreparationen aldrig bad om at røre, og det gør en kosmetisk gene til en reel eksponering.
Verificer hvert hop separat
Test den offentlige lytter alene, derefter relæ-til-backend-forbindelsen fra relæværten og først derefter klienten ende til ende. Hver af de tre tests udelukker et forskelligt lag. Springes en over, betyder det, at de to resterende resultater ikke kan fortolkes. Tre observationer, tre steder, hvor en fejl kan bo.
Behold destinationsadressen, porten og de første protokolbytes sammen med hvert resultat. Den trio skelner en kantfejl fra et VPN-routingproblem fra en SSH-godkendelsesfejl, og det er forskellen mellem en rettelse og et gæt.
Dokumenter til sidst den tilsigtede eksponering. Et TCP-relæ, der fører SSH til en privat backend, er en bevidst åbning i den offentlige perimeter, og det fortjener samme gennemgang som enhver anden indgående tjeneste.