Come posso inoltrare una chiave gpg tramite ssh-agent?


29

Posso usare il file di configurazione di ssh per abilitare l'inoltro di chiavi ssh aggiunte a ssh-agent. Come posso fare lo stesso con le chiavi gpg?


3
Entrambe le risposte suggeriscono di eseguire socat per esporre l'agente GPG unix socket su una porta tcp. Tuttavia, a differenza dei socket unix, le porte TCP non hanno lo stesso livello sul controllo degli accessi. In particolare, ogni utente sullo stesso host può ora connettersi al tuo agente GPG. Questo probabilmente va bene se hai un laptop a utente singolo, ma se anche altri utenti possono accedere allo stesso sistema (il sistema su cui è in esecuzione l'agente GPG), possono anche accedere al tuo agente GPG, presentando un problema di sicurezza significativo. Consentire a socat di avviare direttamente SSH utilizzando il tipo di indirizzo EXEC è probabilmente il modo migliore per risolvere il problema.
Matthijs Kooijman,

Per un'altra presentazione della soluzione openssh 6.7+, vedere 2015.rmll.info/IMG/pdf/an-advanced-introduction-to-gnupg.pdf
phs

Questo mi è stato utile.
phs,

Risposte:


16

EDIT: questa risposta è obsoleta ora che il supporto adeguato è stato implementato in OpenSSH, vedi la risposta di Brian Minton.

SSH è in grado di inoltrare solo connessioni tcp all'interno del tunnel.

Tuttavia, è possibile utilizzare un programma simile socatper inoltrare il socket unix su TCP, con qualcosa del genere (sarà necessario socat sia sul client che sugli host del server):

# Get the path of gpg-agent socket:
GPG_SOCK=$(echo "$GPG_AGENT_INFO" | cut -d: -f1)

# Forward some local tcp socket to the agent
(while true; do
    socat TCP-LISTEN:12345,bind=127.0.0.1 UNIX-CONNECT:$GPG_SOCK;
done) &

# Connect to the remote host via ssh, forwarding the TCP port
ssh -R12345:localhost:12345 host.example.com

# (On the remote host)
(while true; do
    socat UNIX-LISTEN:$HOME/.gnupg/S.gpg-agent,unlink-close,unlink-early TCP4:localhost:12345;
done) &

Verifica se funziona gpg-connect-agent. Assicurarsi che GPG_AGENT_INFO non sia definito sull'host remoto, in modo che ricada sul $HOME/.gnupg/S.gpg-agentsocket.

Spero che tutto ciò di cui hai bisogno sia un modo per eseguire tutto questo automaticamente!


Bene, le chiavi dell'agente ssh vengono inoltrate automaticamente quando l'inoltro è impostato nel file di configurazione. Lo proverò.
txwikinger,

Hai ragione, ssh-agent usa anche un socket unix, ma ha un supporto speciale per questo (un po 'stanco qui :) Tuttavia, la soluzione dovrebbe ancora funzionare.
b0fh

1
Per questa soluzione, il mio agente gpg sarebbe pubblicamente accessibile tramite la porta 12345 se non fossi dietro un firewall / NAT. Questo dovrebbe essere menzionato nella risposta per favore.
Jonas Schäfer,

Immagino che la tua ultima modifica abbia risolto il problema, Jonas? è vincolante solo per localhostora.
jmtd,

Questo non per me con il seguente argomento dal telecomando host del gpg-connect-agent: can't connect to server: ec=31.16383 gpg-connect-agent: error sending RESET command: Invalid value passed to IPC. Il telecomando socatquindi muore. Il locale socatmuore e pronuncia socat[24692] E connect(3, AF=1 "", 2): Invalid argument. Questa pagina mi porta a credere che questo non funzionerà mai, perché l'agente non memorizza la chiave (solo la passphrase). È stato confermato che funziona da qualcuno?
jmtd,

17

Il nuovo Inoltro socket di dominio Unix di OpenSSH può farlo direttamente a partire dalla versione 6.7.

Dovresti essere in grado di qualcosa come:

ssh -R /home/bminton/.gnupg/S.gpg-agent:/home/bminton/.gnupg/S-gpg-agent -o "StreamLocalBindUnlink=yes" -l bminton 192.168.1.9

@DrewR. Felice di sentirlo.
Brian Minton,

2
Ho trovato un dettaglio critico richiesto: sulla macchina remota (senza chiave privata), deve essere presente la chiave pubblica dell'identità della firma. Versione gpg locale 2.1.15 OS X, Linux 2.1.11 remoto.
phs,

4

Nelle nuove versioni di GnuPG o distribuzioni Linux i percorsi dei socket possono cambiare. Questi possono essere trovati tramite

$ gpgconf --list-dirs agent-extra-socket

e

$ gpgconf --list-dirs agent-socket

Quindi aggiungi questi percorsi alla tua configurazione SSH:

Host remote
  RemoteForward <remote socket> <local socket>

Soluzione rapida per la copia delle chiavi pubbliche:

scp .gnupg/pubring.kbx remote:~/.gnupg/

Sul computer remoto, attiva l'agente GPG:

echo use-agent >> ~/.gnupg/gpg.conf

Sul computer remoto, modificare anche la configurazione del server SSH e aggiungere questo parametro (/ etc / ssh / sshd_config):

StreamLocalBindUnlink yes

Riavvia il server SSH, riconnettiti al computer remoto, quindi dovrebbe funzionare.


Un tutorial più dettagliato che include una risoluzione dei problemi può essere trovato qui: mlohr.com/gpg-agent-forwarding
MaLo

1
Nel caso in cui l'host remoto esegua una versione corrente di Debian, sembra che l'esecuzione systemctl --global mask --now gpg-agent.service gpg-agent.socket gpg-agent-ssh.socket gpg-agent-extra.socket gpg-agent-browser.socketsia necessaria per impedire a systemd di lanciare un socket rubando gpg-agent remoto. Secondo bugs.debian.org/850982 questo è il comportamento previsto.
sampi

3

Ho dovuto fare lo stesso, e ho basato il mio script sulla soluzione di b0fh, con alcune minuscole modifiche: intercetta le uscite e uccide i processi in background e utilizza le opzioni "fork" e "reuseaddr" per socat, il che consente di risparmiare loop (e rende lo sfondo socat perfettamente in grado di uccidere).

Il tutto imposta tutto in una volta, quindi probabilmente si avvicina a una configurazione automatizzata.

Nota che sull'host remoto avrai bisogno di:

  1. I portachiavi che intendi utilizzare per firmare / en / decrypt roba.
  2. A seconda della versione di gpg sul telecomando, un falso GPG_AGENT_INFO variabile . Compilare il mio con ~/.gnupg/S.gpg-agent:1:1- il primo 1 è un PID per l'agente gpg (lo falso come "init", che è sempre in esecuzione), il secondo è il numero di versione del protocollo dell'agente. Questo dovrebbe corrispondere a quello in esecuzione sul tuo computer locale.

#!/bin/bash -e

FORWARD_PORT=${1:-12345}

trap '[ -z "$LOCAL_SOCAT" ] || kill -TERM $LOCAL_SOCAT' EXIT

GPG_SOCK=$(echo "$GPG_AGENT_INFO" | cut -d: -f1)
if [ -z "$GPG_SOCK" ] ; then
    echo "No GPG agent configured - this won't work out." >&2
    exit 1
fi

socat TCP-LISTEN:$FORWARD_PORT,bind=127.0.0.1,reuseaddr,fork UNIX-CONNECT:$GPG_SOCK &
LOCAL_SOCAT=$!

ssh -R $FORWARD_PORT:127.0.0.1:$FORWARD_PORT socat 'UNIX-LISTEN:$HOME/.gnupg/S.gpg-agent,unlink-close,unlink-early,fork,reuseaddr TCP4:localhost:$FORWARD_PORT'

Credo che ci sia anche una soluzione che prevede solo una chiamata al comando SSH (ricollegamento dall'host remoto a quello locale) utilizzando -o LocalCommand , ma non sono riuscito a capire come ucciderlo comodamente all'uscita.


Non ti manca qualche argomento "user @ host" prima di socat, nell'ultimo comando? Ad ogni modo, anche dopo averlo risolto, ciò non funziona con "socat [6788] E connect (3, AF = 2 127.0.0.1:0, 16): Connessione rifiutata" che compare localmente, quando provo gpg-connect-agent da remoto.
David Faure,

1

Secondo GnuPG Wiki , devi inoltrare la presa remota S.gpg-agent.extraalla presa locale S.gpg-agent. Inoltre è necessario abilitare StreamLocalBindUnlinksul server.
Tieni presente che hai anche bisogno della parte pubblica della tua chiave disponibile su GnuPG remoto .

Utilizzare gpgconf --list-dir agent-socketrispettivamente gpgconf --list-dir agent-extra-socketsul telecomando per ottenere i percorsi effettivi.


Sommario

  1. Configurazione aggiunta sul telecomando /etc/sshd_config:

    StreamLocalBindUnlink yes
    
  2. Importa la tua chiave pubblica sul telecomando:

    gpg --export <your-key> >/tmp/public
    scp /tmp/public <remote-host>:/tmp/public
    ssh <remote-host> gpg --import /tmp/public
    
  3. Comando per connettersi tramite SSH con l'inoltro dell'agente gpg abilitato: (percorsi per il mio Debian)

    ssh -R /run/user/1000/gnupg/S.gpg-agent:/run/user/1000/gnupg/S.gpg-agent.extra <remote-host>
    

@brian minton: non funziona per me se non inoltro al socket aggiuntivo.
Doak

0

In alternativa alla modifica /etc/ssh/sshd_configconStreamLocalBindUnlink yes , puoi invece impedire la creazione dei file socket che devono essere sostituiti:

systemctl --global mask --now \
  gpg-agent.service \
  gpg-agent.socket \
  gpg-agent-ssh.socket \
  gpg-agent-extra.socket \
  gpg-agent-browser.socket

Si noti che questo influisce tutti gli utenti sull'host.

Bonus: come testare l'inoltro dell'agente GPG funziona:

  • Locale: ssh -v -o RemoteForward=${remote_sock}:${local_sock} ${REMOTE}
  • Controllalo ${remote_sock} sia mostrato nell'output dettagliato di ssh
  • A distanza: ls -l ${remote_sock}
  • A distanza: gpg --list-secret-keys
    • Dovresti vedere molti debug1messaggi di ssh che mostrano il traffico inoltrato

Se ciò non funziona (come non ha funzionato per me) puoi tracciare quale socket GPG sta accedendo:

strace -econnect gpg --list-secret-keys

Uscita campione:

connect(5, {sa_family=AF_UNIX, sun_path="/run/user/14781/gnupg/S.gpg-agent"}, 35) = 0

Nel mio caso il percorso a cui si accede corrispondeva perfettamente ${remote_sock}, ma quel socket non è stato creato da sshdquando ho effettuato l'accesso, nonostante sia stato aggiunto StreamLocalBindUnlink yesal mio/etc/ssh/sshd_config . Sono stato creato da systemd al momento del login.

(Nota che ero troppo codardo per riavviare sshd, dato che al momento non ho accesso fisico all'host. service reload sshdChiaramente non era sufficiente ...)

Testato su Ubuntu 16.04

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.