SSH inverso per un singolo dispositivo: listener loopback o VPN instradata?
Un solo porto di gestione per un dispositivo che può solo chiamare verso l'esterno. Tre condizioni decidono se un tunnel inverso basta o se serve un vero percorso instradato.
Il tuo dispositivo sta dietro il NAT di un operatore, può aprire connessioni in uscita e gestisce un server SSH che nessuno può raggiungere. La richiesta che arriva è di solito formulata come "dagli una VPN", che è una risposta tra diverse. Prima di accettarla, decidi se ti serve un solo porto TCP amministrativo o un percorso instradato verso un'intera sottorete, perché sono progetti diversi con esposizione diversa.
Un tunnel inverso risponde bene alla versione ristretta. Il dispositivo chiama il tuo hub, chiede all'hub di ascoltare su una porta loopback e inoltra quella porta al proprio servizio SSH. Poi gli amministratori raggiungono il listener attraverso l'hub, non attraverso l'internet pubblico.
Tre condizioni che decidono la scelta
Scrivile prima di qualsiasi configurazione. Sono il confine tra un ingresso di gestione circoscritto e un'estensione di rete, e confonderle è il modo in cui un tunnel di cinque righe diventa una rete piatta senza proprietario.
| Condition | Reverse tunnel fits | Something else is needed |
|---|---|---|
| How many services must be reachable? | One, or a small fixed set on loopback | Anything that needs many ports or dynamic discovery |
| Who connects, and how are they authenticated? | Named administrators with their own hub accounts | Third parties, or anything needing per-flow audit you do not control |
| Does the device's own LAN need to be reachable? | No | Yes, so a routed VPN or a managed platform is the honest answer |
La terza riga è quella su cui la gente discute. Un tunnel verso la porta SSH di un dispositivo non mette i suoi vicini sulla tua rete, e non lo si deve far sembrare tale tramite una catena di ulteriori inoltri. Se il requisito è davvero la LAN, dillo e progetta quella invece.
Lato hub: un account di relay circoscritto
Assegna a ogni dispositivo il proprio account di relay con autenticazione a chiave pubblica e senza sessione interattiva. Match blocco circoscritto a quell'account mantiene il permesso piccolo, e la chiave privata resta sul dispositivo dove le compete.
Match User relay-dev-7
AuthenticationMethods publickey
PubkeyAuthentication yes
AllowTcpForwarding remote
PermitListen 127.0.0.1:21022
GatewayPorts no
MaxSessions 0
PermitTTY no
X11Forwarding no
AllowAgentForwarding no
MaxSessions 0 è la riga interessante. Nega le sessioni di shell e dei sottosistemi pur consentendo l'inoltro di cui il dispositivo ha bisogno, quindi una chiave rubata non può essere trasformata in un accesso interattivo. PermitListen fissa l'indirizzo e la porta del listener sul lato hub, e GatewayPorts no lo mantiene su loopback invece di aprirlo alla rete in cui si trova l'hub.
Prova la configurazione effettiva prima di ricaricare, e tieni aperta una seconda sessione mentre lo fai. Match blocco che si applica accidentalmente a tutti, o un refuso nel nome di un'opzione, è il modo classico di chiudersi fuori dalla macchina che stai indurendo. Scarica la configurazione in esecuzione e rileggi le opzioni invece di fidarti del file che hai appena scritto. Nota che il supporto delle opzioni varia tra le build, quindi una riga accettata da un server più nuovo può semplicemente essere ignorata da uno più vecchio.
Lato dispositivo: inoltro che fallisce rumorosamente
Il dispositivo apre la connessione e richiede il listener. I due indirizzi nell'argomento -R significano cose diverse, e leggerli da sinistra a destra è il modo più rapido per ricordare quale sia quale.
ssh -NT \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-R 127.0.0.1:21022:127.0.0.1:22 \
[email protected]
La coppia sinistra è dove l'hub dovrebbe ascoltare. La coppia destra è ciò a cui il dispositivo si connette quando arriva una richiesta, risolta dal lato del dispositivo stesso. Scambiarle produce un tunnel che sale pulito e inoltra nel posto sbagliato, il che è peggio di un fallimento.
ExitOnForwardFailure=yes fa uscire il comando quando il listener richiesto non può essere stabilito, così un ciclo di riavvio ti dice la verità invece di lasciare una sessione a metà funzionante. Non dice nulla sulla salute del servizio SSH locale in seguito, quindi abbinalo a un gestore di processi e a un test di connessione reale ogni tanto.
Non sostituire mai l'indirizzo di ascolto loopback con un carattere jolly per evitare un salto in più. Quell'unica modifica è la differenza tra un percorso di gestione e una porta raggiungibile pubblicamente, e di solito accade durante il debug e poi resta. Se un collega non raggiunge la porta attraverso l'hub, correggi la configurazione del salto invece di ampliare il bind. Il loopback è tutto l'argomento di sicurezza di questo progetto.
Accesso amministratore attraverso l'hub
Un amministratore con un account ordinario sull'hub può saltare attraverso di esso fino alla porta inoltrata. L'account di relay non viene usato per questo, ed è proprio il punto di tenerli separati.
ssh -J [email protected] -o HostKeyAlias=device-7 \
-p 21022 [email protected]
Verifica la chiave host del dispositivo sotto l'alias che hai scelto, perché quella chiave identifica il dispositivo in fondo alla catena e il tunnel è solo trasporto. L'accesso end-to-end autentica ancora entrambe le estremità; un tunnel che termina su un hub condiviso non lo rende di per sé un percorso fidato.
Fatti carico del ciclo di vita
Esegui il comando del dispositivo sotto un gestore di processi con esattamente un'istanza attiva e una politica di riavvio che hai scelto deliberatamente. Le opzioni keepalive rilevano un peer morto; non resuscitano un processo che è uscito.
Poi scrivi la procedura di dismissione. Ogni dispositivo ha il proprio listener e la propria chiave, quindi dismettere significa revocare quell'account e rimuovere quella chiave, non ruotare un segreto condiviso da tutta la flotta.
Infine, ricorda cosa ti dà il loopback. Limita l'esposizione di rete e non fa nulla per gli altri utenti locali su un hub condiviso, quindi la politica di accesso dell'hub stesso deve comunque essere corretta. Riferimento sshd_config documenta ciascuna delle opzioni usate sopra, e vale la pena leggere per intero le sezioni sull'inoltro prima di ampliarne una.