Як я можу переслати gpg-ключ через ssh-агент?


29

Я можу використовувати файл конфігурації ssh для ввімкнення пересилання ключів ssh, доданих до ssh-агента. Як я можу зробити те саме за допомогою gpg-клавіш?


3
Обидва відповіді пропонують запустити socat, щоб виставити гнізда unix агента GPG на порт tcp. Однак, на відміну від unix-сокетів, порти TCP не мають однакового рівня контролю доступу. Зокрема, кожен користувач того самого хоста тепер може підключитися до вашого агента GPG. Це, мабуть, нормально, якщо у вас є однокористувацький ноутбук, але якщо будь-які інші користувачі також можуть увійти в ту саму систему (систему, де працює агент GPG), вони також можуть отримати доступ до вашого агента GPG, що створює значну проблему безпеки. Дозволити socat безпосередньо запускати SSH за допомогою типу адреси EXEC, мабуть, найкращий спосіб виправити це.
Matthijs Kooijman

Іншу презентацію рішення opensh 6.7+
phs

Це мені було корисно.
ph

Відповіді:


16

EDIT: Ця відповідь застаріла зараз, коли в OpenSSH була реалізована належна підтримка, дивіться відповідь Брайана Мінтона.

SSH здатний пересилати лише tcp-з'єднання всередині тунелю.

Однак ви можете використовувати таку програму, як socatретрансляція unix-сокета через TCP, з чимось подібним (вам знадобиться socat як на клієнті, так і на сервері-хості):

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

Перевірте, чи не виходить gpg-connect-agent. Переконайтеся, що на віддаленому хості не визначено GPG_AGENT_INFO, щоб він потрапляв назад у $HOME/.gnupg/S.gpg-agentрозетку.

Тепер, сподіваємось, все, що вам потрібно, це спосіб запустити все це автоматично!


Добре, що ключі агента ssh передаються автоматично, коли перенаправлення встановлено у файлі конфігурації. Я спробую це.
txwikinger

Ви маєте рацію, ssh-агент теж використовує unix-сокет, але має для нього спеціальну підтримку (тут трохи втомився :) Тим не менш, рішення все одно має працювати.
b0fh

1
Для цього рішення мій gpg-агент був би доступний у відкритому доступі через порт 12345, якби я не знаходився за брандмауером / NAT. Це слід зазначити у відповіді будь ласка.
Йонас Шефер

Я здогадуюсь, що твоя остання редакція виправила це питання, Джонасе? це лише localhostзараз обов'язкове .
jmtd

Це не може для мене наступного міркування від віддаленого хоста gpg-connect-agent: can't connect to server: ec=31.16383 gpg-connect-agent: error sending RESET command: Invalid value passed to IPC. Потім пульт socatвідмирає. Місцеві socatвмирають і вимовляють socat[24692] E connect(3, AF=1 "", 2): Invalid argument. Ця сторінка спонукає мене до думки, що це ніколи не вийде, оскільки агент не зберігає ключ (лише парольну фразу). Чи підтверджено це, що хтось працює?
jmtd

17

Нове переадресування доменних розеток Unix для OpenSSH може це зробити безпосередньо, починаючи з версії 6.7.

Ви повинні мати можливість щось подібне:

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

@DrewR. Радий це чути.
Брайан Мінтон

2
Я знайшов необхідну критичну деталь: на віддаленій машині (без приватних ключів) повинен бути присутнім відкритий ключ посвідчення особи. Локальна версія gpg 2.1.15 OS X, віддалений 2.1.11 Linux.
ph

4

У нових версіях дистрибутивів GnuPG або Linux шляхи розеток можуть змінюватися. Їх можна дізнатися через

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

і

$ gpgconf --list-dirs agent-socket

Потім додайте ці контури до своєї конфігурації SSH:

Host remote
  RemoteForward <remote socket> <local socket>

Швидке рішення для копіювання відкритих ключів:

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

На віддаленій машині активуйте GPG-агент:

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

На віддаленій машині також змініть конфігурацію сервера SSH та додайте цей параметр (/ etc / ssh / sshd_config):

StreamLocalBindUnlink yes

Перезавантажте SSH-сервер, підключіться до віддаленої машини - тоді він повинен працювати.


Більш детальний підручник з деякими проблемами ви знайдете тут: mlohr.com/gpg-agent-forwarding
MaLo

1
Якщо віддалений хост працює з поточною версією Debian, здається, що systemctl --global mask --now gpg-agent.service gpg-agent.socket gpg-agent-ssh.socket gpg-agent-extra.socket gpg-agent-browser.socketдля запуску сокету крадіжка віддаленого gpg-агента вимагає запуску системи. За словами bugs.debian.org/850982, це призначена поведінка.
сампі

3

Я повинен був зробити те ж саме, і мій сценарій базувався на рішенні від b0fh, з кількома крихітними модифікаціями: він захоплює виходи та вбиває фонові процеси, і він використовує параметри "fork" та "reuseaddr" для socat, що дозволяє економити цикл (і робить фоновий socat чисто вбитим).

Вся справа налаштовує все вперед за один раз, тому, ймовірно, це наближається до автоматизованого налаштування.

Зауважте, що на віддаленому хості вам знадобляться:

  1. Брелоки, які ви збираєтесь використовувати для підписання / ен / розшифрування матеріалів.
  2. Залежно від версії gpg на пульті, підроблена GPG_AGENT_INFOзмінна. Я попередньо заповнюю шахту ~/.gnupg/S.gpg-agent:1:1- перший 1 - це ПІД для агента gpg (я підробляю це як "init", який завжди працює), другий - номер версії протоколу агента. Це має відповідати тому, яке працює на вашій локальній машині.

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

Я вважаю, що також існує рішення, яке передбачає лише одне виклик команд SSH (підключення назад від віддаленого хоста до локального) -o LocalCommand, але я не міг зрозуміти, як зручно вбити це при виході.


Ви не пропускаєте аргументу "user @ host" перед socat в останній команді? У будь-якому випадку, навіть після виправлення цього, мені не вдасться "socat [6788] E connect (3, AF = 2 127.0.0.1tons, 16): З'єднання відмовилося" вискакує локально, коли віддалено намагається gpg-connect-агент.
Девід Форе

1

Згідно з GnuPG Wiki , ви повинні переслати віддалений сокет S.gpg-agent.extraна локальний сокет S.gpg-agent. Крім того, вам потрібно включити StreamLocalBindUnlinkна сервері.
Майте на увазі, що вам також потрібна відкрита частина вашого ключа, доступна на віддаленому GnuPG .

Використовуйте gpgconf --list-dir agent-socketвідповідно gpgconf --list-dir agent-extra-socketна пульті дистанційного керування, щоб отримати фактичні шляхи.


Підсумок

  1. Додана конфігурація на дистанційному /etc/sshd_config:

    StreamLocalBindUnlink yes
    
  2. Імпортуйте свій відкритий ключ на віддалений:

    gpg --export <your-key> >/tmp/public
    scp /tmp/public <remote-host>:/tmp/public
    ssh <remote-host> gpg --import /tmp/public
    
  3. Команда для підключення через SSH з включеною переадресацією gpg-агента: (шляхи для мого Debian)

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

@brian minton: Це не працює для мене, якщо його не пересилають у додатковий сокет.
doak

0

Як альтернатива модифікації за /etc/ssh/sshd_configдопомогою StreamLocalBindUnlink yes, ви можете замість цього запобігти створенню файлів сокет, які потребують заміни:

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

Зауважте, що це впливає на всіх користувачів хоста.

Бонус: Як перевірити переадресацію агента GPG:

  • Місцеві: ssh -v -o RemoteForward=${remote_sock}:${local_sock} ${REMOTE}
  • Перевірте, що ${remote_sock}показано на багатослівному висновку з ssh
  • Віддалене: ls -l ${remote_sock}
  • Віддалене: gpg --list-secret-keys
    • Ви повинні побачити безліч debug1повідомлень з ssh, що показують переадресований трафік

Якщо це не працює (як це не було у мене), ви можете відстежити, до якого сокета GPG звертається:

strace -econnect gpg --list-secret-keys

Вибірка зразка:

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

У моєму випадку шлях до нього ідеально відповідає ${remote_sock}, але цей сокет був створений не під sshdчас входу в систему, не дивлячись на додавання StreamLocalBindUnlink yesдо мого /etc/ssh/sshd_config. Мене створили systemd при вході в систему.

(Зауважте, я був занадто боязко, щоб перезапустити sshd, оскільки я не маю фізичного доступу до хоста прямо зараз. service reload sshdОчевидно, недостатньо ...)

Тестовано на Ubuntu 16.04

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.