Bagaimana saya bisa meneruskan kunci gpg melalui ssh-agent?

29

Saya dapat menggunakan file konfigurasi ssh untuk mengaktifkan penerusan kunci ssh yang ditambahkan ke ssh-agent. Bagaimana saya bisa melakukan hal yang sama dengan kunci gpg?

txwikinger
sumber
3
Kedua jawaban menyarankan menjalankan socat untuk mengekspos agen unix socket GPG pada port tcp. Namun, tidak seperti soket unix, port TCP tidak memiliki level yang sama pada kontrol akses. Khususnya, setiap pengguna di host yang sama sekarang dapat terhubung ke agen GPG Anda. Ini mungkin ok jika Anda memiliki laptop pengguna tunggal, tetapi jika ada pengguna lain juga dapat masuk ke sistem yang sama (sistem di mana agen GPG berjalan), mereka juga dapat mengakses agen GPG Anda, yang menimbulkan masalah keamanan yang signifikan. Membiarkan socat langsung memulai SSH menggunakan tipe alamat EXEC mungkin merupakan cara terbaik untuk memperbaikinya.
Matthijs Kooijman
Untuk presentasi lain dari solusi openssh 6.7+, lihat 2015.rmll.info/IMG/pdf/an-advanced-introduction-to-gnupg.pdf
phs
Ini berguna bagi saya.
phs

Jawaban:

16

EDIT: Jawaban ini sudah usang sekarang karena dukungan yang tepat telah diterapkan di OpenSSH, lihat jawaban Brian Minton.

SSH hanya mampu meneruskan koneksi tcp di dalam terowongan.

Anda dapat, bagaimanapun, menggunakan program seperti socatuntuk menyampaikan soket unix melalui TCP, dengan sesuatu seperti itu (Anda perlu socat baik pada klien dan server host):

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

Tes jika berhasil gpg-connect-agent. Pastikan GPG_AGENT_INFO tidak ditentukan pada host jarak jauh, sehingga jatuh kembali ke $HOME/.gnupg/S.gpg-agentsoket.

Sekarang semoga yang Anda butuhkan adalah cara untuk menjalankan semua ini secara otomatis!

b0fh
sumber
Yah kunci ssh agent diteruskan secara otomatis ketika penerusan diatur dalam file konfigurasi. Saya akan mencoba ini.
txwikinger
Anda benar, ssh-agent menggunakan soket unix juga, tetapi memiliki dukungan khusus untuk itu (sedikit lelah di sini :) Namun demikian, solusinya tetap bekerja.
b0fh
1
Untuk solusi ini, agen gpg saya akan dapat diakses publik melalui port 12345 jika saya tidak berada di belakang firewall / NAT. Tolong, ini harus disebutkan dalam jawaban.
Jonas Schäfer
Saya kira suntingan terakhir Anda memperbaiki masalah itu, Jonas? itu hanya mengikat localhostsekarang.
jmtd
Ini gagal untuk saya dengan argumen berikut dari host remote gpg-connect-agent: can't connect to server: ec=31.16383 gpg-connect-agent: error sending RESET command: Invalid value passed to IPC. Remote socatkemudian mati. Warga setempat socatmati dan mengucapkannya socat[24692] E connect(3, AF=1 "", 2): Invalid argument. Halaman ini membuat saya percaya bahwa ini tidak akan berhasil, karena agen tidak menyimpan kunci (hanya frasa sandi). Apakah ini sudah dikonfirmasi untuk bekerja oleh siapa pun?
jmtd
17

Unix Domain Socket Forwarding baru dari OpenSSH dapat melakukan ini secara langsung dimulai dengan versi 6.7.

Anda harus dapat sesuatu seperti:

ssh -R /home/bminton/.gnupg/S.gpg-agent:/home/bminton/.gnupg/S-gpg-agent -o "StreamLocalBindUnlink=yes" -l bminton 192.168.1.9
Brian Minton
sumber
@DrewR. Senang mendengarnya.
Brian Minton
2
Saya menemukan detail penting yang diperlukan: pada mesin jarak jauh (tanpa kunci privat), kunci publik dari identitas penandatanganan harus ada. Versi gpg lokal 2.1.15 OS X, remote 2.1.11 linux.
phs
4

Dalam versi baru distribusi GnuPG atau Linux, jalur soket dapat berubah. Ini dapat ditemukan melalui

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

dan

$ gpgconf --list-dirs agent-socket

Kemudian tambahkan jalur ini ke konfigurasi SSH Anda:

Host remote
  RemoteForward <remote socket> <local socket>

Solusi cepat untuk menyalin kunci publik:

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

Pada mesin jarak jauh, aktifkan agen GPG:

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

Pada mesin jarak jauh, ubah juga konfigurasi server SSH dan tambahkan parameter ini (/ etc / ssh / sshd_config):

StreamLocalBindUnlink yes

Mulai ulang server SSH, sambungkan kembali ke mesin jarak jauh - maka itu akan berfungsi.

MaLo
sumber
Tutorial yang lebih terperinci termasuk beberapa pemecahan masalah dapat ditemukan di sini: mlohr.com/gpg-agent-forwarding
MaLo
1
Jika host jarak jauh menjalankan versi Debian saat ini, sepertinya menjalankan systemctl --global mask --now gpg-agent.service gpg-agent.socket gpg-agent-ssh.socket gpg-agent-extra.socket gpg-agent-browser.socketdiperlukan untuk mencegah systemd meluncurkan soket mencuri agen gpg jarak jauh. Menurut bugs.debian.org/850982 ini adalah perilaku yang dimaksud.
sampi
3

Saya harus melakukan hal yang sama, dan mendasarkan skrip saya pada solusi oleh b0fh, dengan beberapa modifikasi kecil: Ini menjebak keluar dan membunuh proses latar belakang, dan menggunakan opsi "fork" dan "reuseaddr" untuk socat, yang menyelamatkan Anda dari lingkaran (dan membuat latar belakang socat bersih bisa-membunuh).

Semuanya mengatur semuanya ke depan dalam sekali jalan, jadi mungkin datang lebih dekat ke pengaturan otomatis.

Perhatikan bahwa pada host jarak jauh, Anda perlu:

  1. Kunci yang ingin Anda gunakan untuk menandatangani / mendekripsi barang.
  2. Tergantung pada versi gpg pada remote, GPG_AGENT_INFOvariabel palsu . Saya lebih suka milik saya dengan ~/.gnupg/S.gpg-agent:1:1- yang pertama adalah PID untuk agen gpg (saya memalsukannya sebagai "init", yang selalu berjalan), yang kedua adalah nomor versi protokol agen. Ini harus cocok dengan yang berjalan di mesin lokal Anda.

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

Saya percaya ada juga solusi yang melibatkan hanya satu permintaan perintah SSH (menghubungkan kembali dari host jarak jauh ke yang lokal) menggunakan -o LocalCommand, tetapi saya tidak bisa mencari cara untuk dengan mudah membunuh itu saat keluar.

antifuchs
sumber
Apakah Anda tidak melewatkan argumen 'user @ host' sebelum socat, pada perintah terakhir? Bagaimanapun juga setelah memperbaikinya, ini gagal bagi saya dengan "socat [6788] E connect (3, AF = 2 127.0.0.1.1, 16): Sambungan ditolak" muncul secara lokal, ketika mencoba gpg-connect-agent dari jarak jauh.
David Faure
1

Menurut GnuPG Wiki , Anda harus meneruskan soket jarak jauh S.gpg-agent.extrake soket lokal S.gpg-agent. Selanjutnya Anda perlu mengaktifkan StreamLocalBindUnlinkdi server.
Ingatlah bahwa Anda juga memerlukan bagian publik dari kunci Anda yang tersedia di GnuPG jarak jauh .

Gunakan gpgconf --list-dir agent-socketmasing-masing gpgconf --list-dir agent-extra-socketpada remote untuk mendapatkan jalur yang sebenarnya.


Ringkasan

  1. Konfigurasi tambahan pada remote /etc/sshd_config:

    StreamLocalBindUnlink yes
    
  2. Impor kunci publik Anda di remote:

    gpg --export <your-key> >/tmp/public
    scp /tmp/public <remote-host>:/tmp/public
    ssh <remote-host> gpg --import /tmp/public
    
  3. Perintah untuk terhubung melalui SSH dengan penerusan gpg-agent diaktifkan: (jalur untuk Debian saya)

    ssh -R /run/user/1000/gnupg/S.gpg-agent:/run/user/1000/gnupg/S.gpg-agent.extra <remote-host>
    
doak
sumber
@ Brian Minton: Ini tidak berfungsi untuk saya jika tidak meneruskan ke soket tambahan.
doak
0

Sebagai alternatif untuk memodifikasi /etc/ssh/sshd_configdengan StreamLocalBindUnlink yes, Anda malah dapat mencegah penciptaan file socket yang harus diganti:

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

Perhatikan bahwa ini memengaruhi semua pengguna di host.

Bonus: Cara menguji penerusan agen GPG berfungsi:

  • Lokal: ssh -v -o RemoteForward=${remote_sock}:${local_sock} ${REMOTE}
  • Periksa yang ${remote_sock}ditunjukkan pada output verbose dari ssh
  • Terpencil: ls -l ${remote_sock}
  • Terpencil: gpg --list-secret-keys
    • Anda akan melihat banyak debug1pesan dari ssh yang menunjukkan lalu lintas yang diteruskan

Jika itu tidak berhasil (karena tidak bagi saya), Anda dapat melacak soket GPG mana yang mengakses:

strace -econnect gpg --list-secret-keys

Output sampel:

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

Dalam kasus saya, jalur yang diakses sangat cocok ${remote_sock}, tetapi soket itu tidak dibuat oleh sshdketika saya masuk, meskipun menambah StreamLocalBindUnlink yessaya /etc/ssh/sshd_config. Saya dibuat oleh systemd saat login.

(Catatan saya terlalu pengecut untuk memulai kembali sshd, karena saya tidak punya akses fisik ke host sekarang. service reload sshdJelas tidak cukup ...)

Diuji pada Ubuntu 16.04

RobM
sumber