Ho più raspberry pi che eseguono Arch Linux (nessuna GUI) a cui devo accedere. Questi pi sono dietro i firewall in ogni posizione univoca. Attualmente uso openvpn per connettermi a questi, ma i costi di quel sistema sono costosi per licenza. Uso il server di accesso da loro.
Di conseguenza, sto cercando di progettare e configurare un sistema che mi consenta di accedere al mio server VPN (vps) ed eseguire un comando per cercare un nome specifico (OfficeDevice1991) come:customcommandsearch "OfficeDevice1991"
e quindi restituisce l'indirizzo IP della macchina o qualcosa che posso usare per SSH. Sto anche cercando la possibilità di eseguire un comando per elencare tutti i dispositivi collegati attivi. Riporta l'IP, il nome e forse da quanto tempo è attivo.
Per questo obiettivo, ovviamente ho bisogno di creare qualcosa che includa il nome del dispositivo (in questo caso OfficeDevice1991) e quindi che pi sarà in grado di agganciarsi al mio server pubblico vps. Dal server pubblico, posso accedere ed eseguire una ricerca su ogni dispositivo ad esso connesso e restituire le informazioni necessarie per accedere a ssh.
Ho esaminato l'SSH inverso e finora ho collegato uno dei miei test pi e accessibile dal mio vps usando i seguenti comandi:
PI:
ssh -fN -R 12345:localhost:22 -i /publickeyfile [email protected] //Pi's command to connect to vpn
VPS:
ssh -p 12345 [email protected] //command for vpn to connect to pi
Funziona benissimo, ma usando questo metodo, se dovessi implementarlo, mi imbatterei in alcuni problemi:
- Avrei bisogno di impostare porte non utilizzate univoche
- Un modo per mantenere aperte queste porte/tunnel
- Devo trovare un sistema per identificare ogni dispositivo. Posso registrare ogni porta con un nome in locale come un file di testo? Sarebbe utile poterlo includere nella configurazione ssh per ciascun dispositivo, se possibile. Dovrei comunque assicurarmi che le porte che utilizzo non vengano utilizzate da altri programmi o dispositivi già presenti.
Cosa non voglio dover fare
-
Controlla quali porte possono essere utilizzate gratuitamente per ogni RPI
-
Devi modificare manualmente
.ssh/config
per aggiungere un nome per rappresentare ciascuna porta assegnata a RPI dalla parte 1 sopra.
Sto scrivendo questo per informazioni/assistenza su cosa fare per il mio obiettivo.
Qualcuno potrebbe fornirmi una soluzione adatta?
Risposta accettata:
Ecco una soluzione che utilizza OpenSSH>=6.7 + socat:
-
OpenSSH>=6.7 può utilizzare l'inoltro socket di dominio Unix
Ciò significa che l'endpoint del tunnel inverso sarà un socket di ascolto UNIX anziché un socket di ascolto TCP tradizionale. Puoi quindi gestire più facilmente la flottiglia di RPI con un semplice schema di denominazione:il nome del socket sarà il nome scelto (e fisso) dell'RPI, come
OfficeDevice1991
. Potrebbe anche essere una proprietà univoca dell'RPI purché sia un nome file valido (poiché i nomi dei socket unix aderiscono alle convenzioni sui nomi dei file). Ad esempio il suo nome host, l'indirizzo MAC della sua scheda ethernet o wifi...SSH può gestire socket unix per i tunnel, non per la connessione stessa. Avrà bisogno dell'aiuto di un
ProxyCommand
per poter lavorare come client unix-socket. socat può gestire molti tipi di connessioni, inclusi i socket Unix.AGGIORNAMENTO:
C'è anche un problema specifico da gestire:il file socket unix non viene eliminato all'uscita pulita, né sarebbe stato comunque eliminato, ad esempio dopo un arresto anomalo. Ciò richiede l'opzioneStreamLocalBindUnlink=yes
. Inizialmente non ho trovato che, come forse suggerisce il nome, questa opzione deve essere impostata sul nodo che crea il socket unix. Quindi alla fine viene impostato sul client con un inoltro locale (-L
) o altro sul server (insshd_config
) con un inoltro remoto (-R
). OP l'ha trovato lì. Questa soluzione utilizza un forward remoto.Configurazione su VPS:
mkdir /rpi-access
(come root) modifica
sshd_config
file (/etc/ssh/sshd_config
). Richiede questa opzione aggiuntiva:StreamLocalBindUnlink yes
A seconda delle opzioni predefinite potrebbe anche richiedere
AllowStreamLocalForwarding yes
UPDATE2:
Impostato anche insshd_config
i parametriClientAliveInterval
eClientAliveCountMax
, consentendo così di rilevare una disconnessione in un tempo ragionevole, ad esempio:ClientAliveInterval 300 ClientAliveCountMax 2
Le connessioni ssh non aggiornate dovrebbero quindi essere rilevate in precedenza sul VPS (~10 minuti con l'esempio) e il processo sshd corrispondente verrà quindi chiuso.
Utilizzo su RPI:
ssh -fN -R /rpi-access/OfficeDevice1991:localhost:22 -i /privatekeyfile [email protected]
In un file di configurazione sarebbe simile a questo:
Host ip User useraccount RemoteForward /rpi-access/OfficeDevice1991:localhost:22 IdentityFile /privatekeyfile
Ripetendo di nuovo:il
StreamLocalBindUnlink yes
impostato susshd
lato VPS l'opzione è importante:il socket appena creato non viene rimosso, anche all'uscita normale. Questa opzione garantisce che la presa venga rimossa se esiste prima dell'uso, consentendo così di essere riutilizzata per ulteriori ricollegamenti. Ciò significa anche che non si può considerare la semplice presenza della presa nel senso che l'RPI è connesso (ma vedi più avanti).Ora questo permette di fare su VPS:
ssh -o 'ProxyCommand=socat UNIX:/rpi-access/%h -' [email protected]
Come file di configurazione, considerando ad esempio gli RPI hanno tutti un nome che inizia con OfficeDevice :
Host OfficeDevice* User rpiuseraccount ProxyCommand socat UNIX:/rpi-access/%h -
-
Per mantenere il link, usa un loop
L'RPI può eseguire un loop riconnettendo ssh al VPS ogni volta che le connessioni terminano. Per questo non deve utilizzare la modalità in background (no
-f
). Dovrebbe essere utilizzato anche un meccanismo keep-alive. Sono disponibili TCPKeepAlive (livello di sistema) o ServerAliveInterval (livello di applicazione). Penso che TCPKeepAlive sia utile solo sul server (il lato che riceve la connessione), quindi utilizziamo piuttosto ServerAliveInterval.Il suo valore (così come ServerAliveCountMax) dovrebbe probabilmente essere adattato in base a vari criteri:un firewall che interrompe le connessioni inattive dopo un certo tempo, il ritardo di ripristino desiderato, non genera traffico inutile, … diciamo qui 300s.
OfficeDevice1991 RPI:
#!/bin/sh while : ; do ssh -N -o ConnectTimeout=30 -o ServerAliveInterval=300 -R /rpi-access/OfficeDevice1991:localhost:22 -i /privatekeyfile [email protected] sleep 5 # avoid flood/DDoS in case of really unexpected issues done
Anche se il lato remoto non ha ancora rilevato il precedente errore di connettività e per un po' di tempo la vecchia connessione ssh è ancora in esecuzione,
StreamLocalBindUnlink yes
aggiornerà comunque forzatamente il socket unix alla nuova connessione. -
è già gestito da 1.
Non c'è
customcommandsearch
necessario. Con le giuste impostazioni impostate in 1. semplicemente usandossh OfficeDevice1991
si collegherà a OfficeDevice1991.Se necessario sul VPS, come
root
solo utente, questo comando:fuser /rpi-access/*
può mostrare quali RPI sono attualmente connessi (ovviamente ad eccezione di quelli che hanno perso la connessione di recente prima del rilevamento). Non mostrerà i file socket Unix non aggiornati perché non c'è alcun processo ad essi collegato.