Como encaminhar uma chave gpg via ssh-agent?


29

Posso usar o arquivo de configuração ssh para habilitar o encaminhamento de chaves ssh adicionadas ao ssh-agent. Como posso fazer o mesmo com as teclas gpg?


3
Ambas as respostas sugerem a execução do socat para expor o soquete unix do agente GPG em uma porta tcp. No entanto, diferentemente dos soquetes unix, as portas TCP não têm o mesmo nível no controle de acesso. Em particular, todos os usuários no mesmo host agora podem se conectar ao seu agente GPG. Provavelmente, tudo bem se você tiver um laptop para usuário único, mas se outros usuários também puderem acessar o mesmo sistema (o sistema em que o agente GPG está em execução), eles também poderão acessar o seu agente GPG, o que representa um problema de segurança significativo. Permitir que o socat inicie diretamente o SSH usando o tipo de endereço EXEC é provavelmente a melhor maneira de corrigir isso.
Matthijs Kooijman

Para outra apresentação da solução openssh 6.7+, consulte 2015.rmll.info/IMG/pdf/an-advanced-introduction-to-gnupg.pdf
phs

Isso foi útil para mim.
Phs

Respostas:


16

EDIT: Esta resposta está obsoleta agora que o suporte adequado foi implementado no OpenSSH, consulte a resposta de Brian Minton.

O SSH é capaz apenas de encaminhar conexões TCP dentro do túnel.

Você pode, no entanto, usar um programa como o socatde retransmitir o soquete unix pelo TCP, com algo assim (você precisará socat nos hosts do cliente e do servidor):

# 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) &

Teste se funciona com gpg-connect-agent. Verifique se GPG_AGENT_INFO está indefinido no host remoto, para que ele volte ao $HOME/.gnupg/S.gpg-agentsoquete.

Agora espero que tudo que você precisa seja uma maneira de executar tudo isso automaticamente!


Bem, as chaves do agente ssh são encaminhadas automaticamente quando o encaminhamento é definido no arquivo de configuração. Eu vou tentar isso.
21410 TJMG:

Você está certo, o ssh-agent também usa um soquete unix, mas tem suporte especial para ele (um pouco cansado aqui :) No entanto, a solução ainda deve funcionar.
b0fh

1
Para esta solução, meu gpg-agent seria publicamente acessível via porta 12345 se eu não estivesse atrás de um firewall / NAT. Isso deve ser mencionado na resposta, por favor.
Jonas Schäfer

Acho que sua última edição corrigiu esse problema, Jonas? é apenas vinculativo para localhostagora.
jmtd

Esta falha para mim com o seguinte argumento a partir do host remoto de gpg-connect-agent: can't connect to server: ec=31.16383 gpg-connect-agent: error sending RESET command: Invalid value passed to IPC. O controle remoto socatmorre. O local socatmorre e pronuncia socat[24692] E connect(3, AF=1 "", 2): Invalid argument. Essa página me leva a acreditar que isso nunca funcionará, porque o agente não armazena a chave (apenas a senha). Isso foi confirmado para funcionar por alguém?
jmtd

17

O novo Unix Domain Socket Forwarding do OpenSSH pode fazer isso diretamente a partir da versão 6.7.

Você deve ser capaz de algo como:

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

@DrewR. Fico feliz em ouvir isso.
Brian Minton

2
Encontrei um detalhe crítico necessário: na máquina remota (sem chave privada), a chave pública da identidade de assinatura deve estar presente. Versão local do gpg 2.1.15 OS X, Linux 2.1.11 remoto.
Phs #

4

Nas novas versões das distribuições GnuPG ou Linux, os caminhos dos soquetes podem mudar. Estes podem ser encontrados através de

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

e

$ gpgconf --list-dirs agent-socket

Em seguida, adicione esses caminhos à sua configuração SSH:

Host remote
  RemoteForward <remote socket> <local socket>

Solução rápida para copiar as chaves públicas:

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

Na máquina remota, ative o agente GPG:

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

Na máquina remota, modifique também a configuração do servidor SSH e adicione este parâmetro (/ etc / ssh / sshd_config):

StreamLocalBindUnlink yes

Reinicie o servidor SSH, reconecte-se à máquina remota - então deve funcionar.


Um tutorial mais detalhado, incluindo algumas soluções de
MaLo

1
Caso o host remoto execute uma versão atual do Debian, parece systemctl --global mask --now gpg-agent.service gpg-agent.socket gpg-agent-ssh.socket gpg-agent-extra.socket gpg-agent-browser.socketser necessário rodar para impedir que o systemd lance um soquete que rouba o gpg-agent remoto. De acordo com bugs.debian.org/850982, este é o comportamento pretendido.
Sampi

3

Eu tive que fazer o mesmo e baseei meu script na solução por b0fh, com algumas pequenas modificações: ele captura e fecha processos em segundo plano e usa as opções "fork" e "reuseaddr" para socat, o que poupa a você loop (e torna o plano de fundo socat perfeitamente capaz de matar).

A coisa toda configura todos os encaminhamentos de uma só vez, por isso provavelmente se aproxima de uma configuração automatizada.

Observe que no host remoto, você precisará de:

  1. Os chaveiros que você pretende usar para assinar / en / descriptografar as coisas.
  2. Dependendo da versão do gpg no controle remoto, uma GPG_AGENT_INFOvariável falsa . Eu prefiro o meu ~/.gnupg/S.gpg-agent:1:1- o primeiro 1 é um PID para o agente gpg (eu o invoco como "init", que está sempre em execução), o segundo é o número da versão do protocolo do agente. Isso deve corresponder ao que está sendo executado na sua máquina local.

#!/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'

Acredito que também exista uma solução que envolva apenas uma chamada de comando SSH (conectando-se novamente do host remoto ao local) -o LocalCommand, mas não consegui descobrir como matá-lo convenientemente na saída.


Você não está sentindo falta de algum argumento 'user @ host' antes do socat, no último comando? De qualquer forma, mesmo depois de corrigir isso, isso falha para mim com "socat [6788] E connect (3, AF = 2 127.0.0.1.0, 16): Conexão recusada" aparecendo localmente, ao tentar o gpg-connect-agent remotamente.
David Faure

1

De acordo com o GnuPG Wiki , você deve encaminhar o soquete remoto S.gpg-agent.extrapara o soquete local S.gpg-agent. Além disso, você precisa habilitar StreamLocalBindUnlinkno servidor.
Lembre-se de que você também precisa da parte pública da sua chave disponível no GnuPG remoto .

Use gpgconf --list-dir agent-socketrespectivamente gpgconf --list-dir agent-extra-socketno controle remoto para obter os caminhos reais.


Sumário

  1. Configuração adicionada no controle remoto /etc/sshd_config:

    StreamLocalBindUnlink yes
    
  2. Importe sua chave pública no controle remoto:

    gpg --export <your-key> >/tmp/public
    scp /tmp/public <remote-host>:/tmp/public
    ssh <remote-host> gpg --import /tmp/public
    
  3. Comando para conectar-se através do SSH com o encaminhamento do gpg-agent ativado: (caminhos para o meu Debian)

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

@ Brian Minton: Ele não funciona para mim, se não encaminhar para o soquete extra.
Dok #

0

Como uma alternativa para modificar /etc/ssh/sshd_configcom StreamLocalBindUnlink yes, você, em vez pode impedir a criação dos arquivos de soquete que precisam de substituição:

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

Observe que isso afeta todos os usuários no host.

Bônus: Como testar o encaminhamento do agente GPG está funcionando:

  • Local: ssh -v -o RemoteForward=${remote_sock}:${local_sock} ${REMOTE}
  • Verifique se ${remote_sock}é mostrado na saída detalhada do ssh
  • Controlo remoto: ls -l ${remote_sock}
  • Controlo remoto: gpg --list-secret-keys
    • Você deve ver muitas debug1mensagens do ssh mostrando o tráfego encaminhado

Se isso não funcionar (como não aconteceu comigo), você pode rastrear qual soquete o GPG está acessando:

strace -econnect gpg --list-secret-keys

Saída de amostra:

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

No meu caso, o caminho que está sendo acessado corresponde perfeitamente ${remote_sock}, mas esse soquete não foi criado sshdquando eu entrei, apesar de adicionar StreamLocalBindUnlink yesao meu /etc/ssh/sshd_config. Eu fui criado pelo systemd no login.

(Observe que eu era covarde demais para reiniciar o sshd, pois não tenho acesso físico ao host no momento. service reload sshdClaramente não era suficiente ...)

Testado no Ubuntu 16.04

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.