ฉันจะส่งต่อคีย์ gpg ผ่าน ssh-agent ได้อย่างไร


29

ฉันสามารถใช้ไฟล์การกำหนดค่า ssh เพื่อเปิดใช้งานการส่งต่อของคีย์ ssh ที่เพิ่มไปยัง ssh-agent ฉันจะทำเช่นเดียวกันกับปุ่ม gpg ได้อย่างไร


3
คำตอบทั้งสองแนะนำให้ใช้ socat เพื่อเปิดเผยซ็อกเก็ตยูนิกซ์ของเอเจนต์ GPG บนพอร์ต tcp อย่างไรก็ตามแตกต่างจากซ็อกเก็ตยูนิกซ์พอร์ต TCP ไม่มีระดับเดียวกันกับการควบคุมการเข้าถึง โดยเฉพาะผู้ใช้ทุกคนในโฮสต์เดียวกันสามารถเชื่อมต่อกับตัวแทน GPG ของคุณได้ นี่อาจจะโอเคถ้าคุณมีแล็ปท็อปที่มีผู้ใช้คนเดียว แต่ถ้าผู้ใช้อื่นสามารถเข้าสู่ระบบเดียวกันได้ (ระบบที่เอเจนต์ GPG กำลังทำงานอยู่) พวกเขายังสามารถเข้าถึงเอเจนต์ GPG ของคุณได้ การให้ socat เริ่ม SSH โดยตรงโดยใช้ประเภทที่อยู่ EXEC น่าจะเป็นวิธีที่ดีที่สุดในการแก้ไขปัญหานี้
Matthijs Kooijman

สำหรับการนำเสนออีกครั้งของโซลูชัน openssh 6.7+ ให้ดูที่2015.rmll.info/IMG/pdf/an-advanced-introduction-to-gnupg.pdf
phs

สิ่งนี้มีประโยชน์สำหรับฉัน
phs

คำตอบ:


16

แก้ไข: คำตอบนี้ล้าสมัยแล้วในขณะนี้ว่ามีการสนับสนุนที่เหมาะสมใน OpenSSH ดูคำตอบของ Brian Minton

SSH สามารถส่งต่อการเชื่อมต่อ tcp ภายในอุโมงค์เท่านั้น

อย่างไรก็ตามคุณสามารถใช้โปรแกรมที่ต้องการsocatถ่ายทอดซ็อกเก็ตยูนิกซ์ผ่าน 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-agent ใช้ซ็อกเก็ตยูนิกซ์ด้วย แต่ได้รับการสนับสนุนเป็นพิเศษ (เหนื่อยเล็กน้อยที่นี่ :) อย่างไรก็ตามวิธีแก้ปัญหายังคงใช้ได้
b0fh

1
สำหรับวิธีนี้ตัวแทน gpg ของฉันจะสามารถเข้าถึงสาธารณะผ่านพอร์ต 12345 หากฉันไม่ได้อยู่หลังไฟร์วอลล์ / NAT โปรดพูดถึงคำตอบนี้ด้วย
Jonas Schäfer

ฉันเดาว่าการแก้ไขครั้งล่าสุดของคุณจะแก้ไขปัญหานั้นได้ไหม Jonas? 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 Domain Socket Forwarding ของ 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 ดีใจที่ได้ยินเช่นนั้น.
Brian Minton

2
ฉันพบรายละเอียดที่สำคัญที่ต้องการ: บนเครื่องระยะไกล (ส่วนตัวไม่ต้องใช้กุญแจ) ต้องใช้กุญแจสาธารณะของตัวตนการเซ็นชื่อ Local gpg เวอร์ชั่น 2.1.15 OS X, ระยะไกล 2.1.11 linux
phs

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จำเป็นต้องมีการเรียกใช้เพื่อป้องกันไม่ให้ systemd เปิดใช้ซ็อกเก็ตขโมย gpg-agent ทางไกล อ้างอิงจากbugs.debian.org/850982นี่เป็นพฤติกรรมที่ตั้งใจไว้
sampi

3

ฉันต้องทำแบบเดียวกันและใช้สคริปต์ของฉันในการแก้ปัญหาโดย b0fh ด้วยการปรับเปลี่ยนเล็ก ๆ น้อย ๆ : กับดักมันออกจากและฆ่ากระบวนการพื้นหลังและใช้ตัวเลือก "fork" และ "reuseaddr" เป็น socat ซึ่งช่วยคุณประหยัด วนรอบ (และทำให้พื้นหลังโซคอทหมดจดสามารถฆ่าล้างได้)

การตั้งค่าทั้งหมดส่งต่อทั้งหมดในครั้งเดียวดังนั้นจึงอาจเข้าใกล้การตั้งค่าอัตโนมัติ

โปรดทราบว่าในรีโมตโฮสต์คุณจะต้อง:

  1. keyrings ที่คุณตั้งใจจะใช้ในการเซ็นชื่อ / en / ถอดรหัสสิ่งต่าง ๆ
  2. GPG_AGENT_INFOตัวแปรปลอมขึ้นอยู่กับเวอร์ชันของ gpg บนรีโมท ฉันเติมของฉันด้วย~/.gnupg/S.gpg-agent:1:1- อันแรกคือ PID สำหรับเอเจนต์ 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 เชื่อมต่อ (3, AF = 2 127.0.0.1, 16): การเชื่อมต่อถูกปฏิเสธ" โผล่ขึ้นมาในเครื่องเมื่อพยายาม gpg-connect-agent จากระยะไกล
David Faure

1

ตามGnuPG วิกิพีเดียที่คุณต้องส่งต่อซ็อกเก็ตระยะไกลกับซ็อกเก็ท้องถิ่น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-agent: (เส้นทางสำหรับ 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}แสดงในเอาต์พุต verbose จาก 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.