Come creare un utente SSH limitato per il port forwarding?


106

ændrük ha suggerito una connessione inversa per ottenere una facile connessione SSH con qualcun altro (per assistenza remota). Perché funzioni, è necessario un utente aggiuntivo per accettare la connessione. Questo utente deve essere in grado di inoltrare la propria porta attraverso il server (il server funge da proxy).

Come faccio a creare un utente con restrizioni che non può fare altro che quanto sopra descritto?

Il nuovo utente non deve essere in grado di:

  • eseguire i comandi della shell
  • accedere ai file o caricare file sul server
  • usa il server come proxy (es. webproxy)
  • accedere a servizi locali che altrimenti non erano accessibili al pubblico a causa di un firewall
  • uccidere il server

Riassumendo, come faccio a creare un utente SSH con restrizioni che è in grado di connettersi al server SSH senza privilegi, in modo da poter connettersi attraverso tale connessione con il suo computer?


Risposte:


166

TL; DR: vai in fondo alla risposta, "Applicazione delle restrizioni"

L'aggiunta di un utente con accesso limitato consiste di due parti: 1. Creazione dell'utente 2. Configurazione del demone SSH (sshd)

Configurazione di sshd

Il posto migliore per conoscere le possibilità di SSH è leggere le relative pagine di manuale:

Dove può eseguire azioni il client SSH?

Prima di poter limitare qualcosa, è necessario conoscere le funzionalità di SSH. Sputare attraverso le pagine del manuale produce:

  • Shell comanda l'esecuzione
  • Caricamento file tramite sftp
  • Port forwarding
    • Il client inoltra al server una porta (non) utilizzata
    • Il server inoltra la sua porta al client
    • Il server inoltra al client una porta di un altro host (proxy-ish)
  • X11 forwarding (display forwarding)
  • Inoltro dell'agente di autenticazione
  • Inoltro di un dispositivo tunnel

Dalla sezione Autenticazione della pagina del manuale di sshd (8) :

Se il client si autentica correttamente, viene inserita una finestra di dialogo per preparare la sessione. In questo momento il client può richiedere cose come l' allocazione di una pseudo-tty, l'inoltro di connessioni X11, l'inoltro di connessioni TCP o l'inoltro della connessione dell'agente di autenticazione sul canale protetto.

Successivamente, il client richiede una shell o l'esecuzione di un comando . I lati quindi entrano in modalità sessione. In questa modalità, entrambe le parti possono inviare dati in qualsiasi momento e tali dati vengono inoltrati a / dalla shell o dal comando sul lato server e al terminale utente sul lato client.

Opzioni per limitare le funzionalità SSH

I file e le loro opzioni che alterano il comportamento sono:

  • ~/.ssh/authorized_keys - contiene chiavi a cui è consentito connettersi a cui è possibile assegnare opzioni:
    • command="command"- Il comando fornito dall'utente (se presente) viene ignorato. Si noti che il client può specificare l'inoltro TCP e / o X11 a meno che non siano esplicitamente vietati . Nota che questa opzione si applica all'esecuzione di shell, comandi o sottosistemi.
    • no-agent-forwarding - Vieta l'inoltro dell'agente di autenticazione quando questa chiave viene utilizzata per l'autenticazione.
    • no-port-forwarding - Vieta l'inoltro TCP quando questa chiave viene utilizzata per l'autenticazione
    • no-X11-forwarding - "Vieta l'inoltro X11 quando questa chiave viene utilizzata per l'autenticazione."
    • permitopen="host:port" - Limitare il port forwarding 'ssh -L' locale in modo tale che possa connettersi solo all'host e alla porta specificati.
  • ~/.ssh/environment- Questo file viene letto nell'ambiente all'accesso (se esiste). L'elaborazione dell'ambiente è disabilitata per impostazione predefinita ed è controllata tramite l'opzione PermitUserEnvironment
  • ~/.ssh/rc - Contiene routine di inizializzazione da eseguire prima che la directory home dell'utente diventi accessibile.
  • /etc/ssh/sshd_config - il file di configurazione dell'intero sistema
    • AllowAgentForwarding - Specifica se è consentito l'inoltro di ssh-agent (1).
    • AllowTcpForwarding
    • ForceCommand - "Forza l'esecuzione del comando specificato da ForceCommand, ignorando qualsiasi comando fornito dal client e ~ / .ssh / rc se presente. Il comando viene invocato utilizzando la shell di accesso dell'utente con l'opzione -c."
    • GatewayPorts - "Specifica se agli host remoti è consentito connettersi alle porte inoltrate per il client. Per impostazione predefinita, sshd (8) associa i port forwarding remoti all'indirizzo di loopback. Ciò impedisce ad altri host remoti di connettersi alle porte inoltrate. GatewayPorts può essere utilizzato per specificare che sshd dovrebbe consentire il port forwarding remoto da associare a indirizzi non loopback, permettendo così ad altri host di connettersi. "
    • PermitOpen:

      Specifica le destinazioni a cui è consentito il port forwarding TCP. La specifica di inoltro deve essere una delle seguenti forme:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      I forward multipli possono essere specificati separandoli con spazi bianchi. Un argomento di "qualsiasi" può essere utilizzato per rimuovere tutte le restrizioni e consentire eventuali richieste di inoltro. Per impostazione predefinita sono consentite tutte le richieste di port forwarding.

    • PermitTunnel- Specifica se è consentito l'inoltro del dispositivo tun (4). L'impostazione predefinita è "no"
    • X11Forwarding- Specifica se è consentito l'inoltro X11. L'impostazione predefinita è "no"

Applicando le restrizioni

La modifica del file di configurazione a livello di sistema /etc/ssh/sshd_configconsente di applicare la configurazione anche se viene applicata l'autenticazione basata su password o se le restrizioni ~/.ssh/authorized_keysvengono rimosse accidentalmente. Se hai modificato le impostazioni predefinite globali, dovresti decommentare le opzioni di conseguenza.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Ora aggiungi un utente:

sudo useradd -m limited-user

L'opzione ForceCommandpuò essere omessa se la shell è impostata su un tipo non shell /bin/false(o /bin/true) in quanto /bin/false -c [command]non farà nulla.

Ora il client può connettersi solo alla porta 62222 sull'indirizzo di loopback del server su SSH (non ascolterà sull'indirizzo IP pubblico)

La disabilitazione AllowTcpForwardingimpedirebbe anche l'uso di -R, sconfiggendo così l'uso di un account così limitato per l'inoltro di una singola porta. PermitOpen localhost:62222presuppone che la porta 62222 sul server non sia mai in uso perché il client può connettersi felicemente ad esso e ascoltare anche su di esso.

Se l'inoltro TCP è consentito nella configurazione a livello di sistema e l'autenticazione basata su password disabilitata, è possibile utilizzare anche le impostazioni per chiave. Modifica ~/.ssh/authorized_keyse aggiungi le opzioni seguenti prima di ssh-(con uno spazio tra le opzioni e ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

Verificare

Per essere sicuri che funzioni come previsto, è necessario eseguire alcuni casi di test. Nei comandi seguenti, hostdeve essere sostituito dall'account di accesso effettivo se non è impostato ~/.ssh/config. Dietro al comando, viene mostrato un comando che dovrebbe essere eseguito sul client o sul server (come specificato).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Conclusione

Elenco di controllo: l'utente SSH non dovrebbe:

  • esegui comandi shell - fatto
  • accedere ai file o caricare i file sul server - fatto
  • usa il server come proxy (es. webproxy) - fatto
  • accedere a servizi locali che altrimenti non erano accessibili al pubblico a causa di un firewall - in parte , il client non può accedere ad altre porte oltre a 62222, ma può ascoltare e connettersi alla porta 62222 sul server
  • kill the server - done (nota che questi controlli sono limitati al server SSH. Se hai un altro servizio vulnerabile sulla macchina, potrebbe consentire a un eventuale aggressore di eseguire comandi, uccidere il server, ecc.)

3
Perché ciò funzioni, l'account aggiunto da useradddeve essere sbloccato. Ciò può essere fatto sostituendo la password /etc/shadowcon un asterico ( *) o impostando una password usando sudo passwd limited-user.
Lekensteyn,

2
SFTP funziona perché il server SSH esegue il sftp-servercomando. Con ForceCommand, questo comando non verrà più eseguito.
Lekensteyn,

2
Utile anche l' from=opzione in authorized_keys. Ti consente di limitare l'uso della chiave alle origini con un determinato indirizzo IP o nome host. Esempio from="1.1.1.1"o from="10.0.0.?,*.example.com". Vedi la sezione "FORMATO FILE AUTHORIZED_KEYS" nella pagina man ( linux.die.net/man/8/sshd ) per tutte le opzioni di authorized_keys.
Donn Lee,

2
"AllowTcpForwarding local" proibisce l'inoltro remoto. (Non so se esistesse quando è stata scritta questa risposta.)
Simon Sapin,

1
Nota che questo viene interrotto da connessioni ssh persistenti, quindi non dovresti avere qualcosa di simile Host * ControlMaster autonel tuo ~/.ssh/configfile quando ti connetti ssh -N. Se ne hai bisogno, usassh -N -o ControlMaster=no
nh2

3

Sono sicuro che ci sono molte soluzioni a questo, e molte più robuste di quella che sto proponendo. Tuttavia, questo può essere sufficiente per le tue esigenze. Per farlo, suppongo che l'utente sia in grado di eseguire l'autenticazione basata su chiave ssh (putty o qualsiasi unix ssh dovrebbe supportare questo).

  • Aggiungi un utente come faresti normalmente ("adduser" o qualsiasi altro strumento)

  • Creare gli utenti .ssh dir e .ssh / authorized_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • Disabilita l'accesso con password a questo account.
your_user $ sudo usermod --lock ssh_forwarder

Ora, l'unico modo in cui l'utente può entrare nel tuo sistema è tramite l'accesso alla chiave ssh corretta e ssh eseguirà "/ bin / bash -c 'read a'" per loro, indipendentemente da ciò che tentano di eseguire. 'read a' leggerà semplicemente fino a quando una nuova riga, e quindi la shell uscirà, quindi l'utente deve solo premere 'enter' per terminare la connessione.

Ci sono molte altre cose che potresti fare in 'command ='. Vedere man authorized_keyse cercare "comando" per ulteriori informazioni.

Se non ti piace il fatto che premere invio uccida la connessione, potresti usare qualcosa come il seguente per la voce 'command =':

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

Questo crea solo un FIFO temporaneo nella home directory degli utenti e quindi prova a leggere da esso. Nulla scriverà su quel file, quindi questo si bloccherà indefinitamente. Inoltre, se si desidera terminare forzatamente tale connessione, è possibile fare qualcosa del tipo:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

Questo dovrebbe usare pochissime risorse e nulla dovrebbe essere in grado di andare storto in quello script che non finirebbe con la chiusura della shell.

sleep 1h; echo You have been here too long. Good bye.

Non ho visto da vicino come si potesse consentire all'utente di inoltrare in remoto ( ssh -R) ma limit ( ssh -L). Forse 'permesso' potrebbe essere usato. Googling non è stato molto utile. Sembrerebbe che qualcosa come "no-port-forwarding, allowremoteopen = 10001" sarebbe utile per consentire ssh -R 6901:localhost:6901.

Questa è una soluzione Può sicuramente essere migliorato e qualsiasi apertura delle porte remote dovrebbe essere esaminata. Se il mio obiettivo fosse quello di consentire a mia nonna di connettersi alla mia LAN in modo da poter usare VNC per visualizzare il suo schermo e l'accesso a quelle chiavi era limitato a lei, personalmente mi sentirei ragionevolmente al sicuro. Se questo fosse per un'impresa, sarebbero necessarie indagini più approfondite. Una cosa da tenere presente è ssh -Nche non richiede affatto una shell, quindi il codice 'command =' non viene eseguito.

Altri meccanismi, forse più sicuri, possono includere la creazione di una shell personalizzata per l'utente e persino il blocco con apparmour.


3
Sembra molto hack, non è nemmeno necessario avere una shell perché non è necessario eseguire alcun comando. Vedere la pagina di manuale dissh per l' -Nopzione. Ci deve essere un modo più pulito per raggiungere questo obiettivo.
Lekensteyn,

È vero. Spero di vedere anche una soluzione più pulita. Ritengo che le autorità autorizzate in combinazione con il no-port-forwarding sarebbe una soluzione piuttosto valida se esistesse un'opzione "consentitoteopen".
Smoser,

Ho fatto un po 'di ricerca (vedi sopra). Poiché ssh -Nnon esegue affatto un comando, non è un problema che command="something"chiude la sessione.
Lekensteyn,

Mi sto perdendo qualcosa? Sembrava chsh ssh_forwarder -s /bin/false tutto ciò che serve.
dattiloscritto il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.