รับคีย์รหัสเซิร์ฟเวอร์ SSH


82

มีวิธีการรับลายนิ้วมือคีย์เซิร์ฟเวอร์ SSH โดยทางโปรแกรมโดยไม่ต้องพิสูจน์ตัวตนหรือไม่?

ฉันกำลังพยายามอยู่ssh -v user@host false 2>&1 | grep "Server host key"แต่สิ่งนี้กำลังรอรหัสผ่านหากการตรวจสอบสิทธิ์ด้วยรหัสไม่ได้ตั้งค่า

คำตอบ:


71

คุณสามารถทำได้โดยการรวมssh-keyscanและssh-keygen:

$ file=$(mktemp)
$ ssh-keyscan host > $file 2> /dev/null
$ ssh-keygen -l -f $file
521 de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:de:ad:be:ef host (ECDSA)
4096 8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d:8b:ad:f0:0d host (RSA)
$ rm $file

(น่าเสียดายที่ง่ายกว่าssh-keyscan host | ssh-keygen -l -f /dev/stdinไม่ทำงาน)


1
อาจssh-keygen -l -f - <(ssh-keyscan host)จะใช่มั้ย
CVN

21
OpenSSH> = 7.2 ssh-keyscan สามารถอ่านได้จาก stdin:ssh-keyscan host | ssh-keygen -lf -
mykhal

1
เพิ่งทำ:ssh-keygen -l -f <(ssh-keyscan host)
Christopher

1
นั่นเป็นนิพจน์ที่ค่อนข้างแย่สำหรับเชลล์สคริปต์เนื่องจากมันขึ้นอยู่กับเชลล์ที่สนับสนุนเชลล์ POSIX เชลล์ไม่ได้
Andreas Wiese

2
ssh-keygen -l -f -ทำงานได้มากตามที่คาดไว้ใน ssh-keygen 7.2 ขึ้นไป มันสร้างบรรทัดความคิดเห็นบางส่วนให้กับ STDERR ที่สามารถกรองออกได้ดังที่ได้กล่าวไว้ในคำตอบโดย Anthony Geoghegan หรือssh-keyscan host 2>/dev/null | ssh-keygen -l -f -
Cedric Knight

56

ฉันเพิ่งต้องทำสิ่งนี้ด้วยตัวเองดังนั้นฉันคิดว่าฉันจะเพิ่มคำตอบซึ่งแสดงให้เห็นว่าสิ่งนี้สามารถทำได้ (ด้วยOpenSSH เวอร์ชั่น 7.2 หรือใหม่กว่า ) ในหนึ่งบรรทัดโดยใช้การทดแทนกระบวนการ:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

ข้อความต่อไปนี้อธิบายการทำงานของคำสั่งเหล่านี้และเน้นถึงความแตกต่างของพฤติกรรมระหว่างยูทิลิตี้ OpenSSH เวอร์ชันเก่าและใหม่กว่า

ดึงกุญแจโฮสต์สาธารณะ

ssh-keyscanคำสั่งได้รับการพัฒนาเพื่อให้ผู้ใช้สามารถรับกุญแจโฮสต์ที่สาธารณะโดยไม่จำเป็นต้องตรวจสอบสิทธิ์กับเซิร์ฟเวอร์ SSH จากหน้าคนของมัน:

ssh-keyscanเป็นเครื่องมือสำหรับการรวบรวมกุญแจโฮสต์ ssh สาธารณะของจำนวนโฮสต์ มันถูกออกแบบมาเพื่อช่วยในการสร้างและตรวจสอบ ssh_known_hostsไฟล์

ประเภทของกุญแจ

ประเภทของคีย์ที่จะดึงข้อมูลถูกระบุโดยใช้-tตัวเลือก

  • rsa1 (ล้าสมัยโปรโตคอล SSH รุ่น 1)
  • rsa
  • dsa
  • ecdsa (OpenSSH เวอร์ชันล่าสุด)
  • ed25519 (OpenSSH เวอร์ชันล่าสุด)

ในรุ่น OpenSSH ที่ทันสมัยประเภทคีย์เริ่มต้นที่จะดึงข้อมูลคือrsa (ตั้งแต่รุ่น 5.1) ecdsa(ตั้งแต่รุ่น 6.0) และed25519(ตั้งแต่รุ่น 6.7)

ด้วยเวอร์ชันที่เก่ากว่าของssh-keyscan(ก่อน OpenSSH เวอร์ชัน 5.1) ประเภทคีย์เริ่มต้นคือล้าสมัยrsa1(SSH Protocol 1) ดังนั้นประเภทคีย์จะต้องมีการระบุอย่างชัดเจน:

ssh-keyscan -t rsa,dsa hostname

รับแฮชลายนิ้วมือของคีย์ Base64

ssh-keyscanพิมพ์รหัสโฮสต์ของเซิร์ฟเวอร์ SSH ใน รูปแบบที่เข้ารหัส Base64 ในการแปลงเป็นแฮชลายนิ้วมือssh-keygenยูทิลิตี้นี้สามารถใช้กับ-lตัวเลือกเพื่อพิมพ์ลายนิ้วมือของคีย์สาธารณะที่ระบุ

หากใช้ Bash, Zsh (หรือ Korn เชลล์) การทดแทนกระบวนการสามารถใช้เป็นสายการบินเดียวที่มีประโยชน์:

ssh-keygen -lf <(ssh-keyscan hostname 2>/dev/null)

หมายเหตุ : สำหรับเวอร์ชั่นของ OpenSSH ก่อนหน้า 7.2 ฟังก์ชั่นที่ใช้ ssh-keygenในการอ่านไฟล์ไม่สามารถจัดการกับ pipes ที่มีชื่อ (FIFO) ได้เป็นอย่างดีดังนั้นวิธีการนี้จะไม่ทำงานดังนั้นจึงต้องใช้ไฟล์ชั่วคราว

อัลกอริทึม Hashing

hash ssh-keygenพิมพ์ลายนิ้วมือของคีย์รุ่นล่าสุดของSHA256 ในการรับMD5 hash ของลายนิ้วมือคีย์เซิร์ฟเวอร์ (พฤติกรรมเก่า) -E สามารถใช้ตัวเลือกเพื่อระบุอัลกอริทึมแฮช:

ssh-keygen -E md5 -lf <(ssh-keyscan hostname 2>/dev/null)

ใช้ไปป์ไลน์

หากใช้เชลล์ POSIX (เช่นdash) ซึ่งไม่มีคุณสมบัติการทดแทนกระบวนการโซลูชันอื่นที่ใช้ไฟล์ชั่วคราวจะใช้งานได้ อย่างไรก็ตามด้วยเวอร์ชันที่ใหม่กว่าของ OpenSSH (ตั้งแต่ 7.2) สามารถใช้ไพพ์ไลน์แบบง่ายได้เนื่องจากssh-keygenจะยอมรับ-เป็นชื่อไฟล์สำหรับสตรีมอินพุตมาตรฐานอนุญาตให้ใช้คำสั่งไพพ์ไลน์แบบบรรทัดเดียว

ssh-keyscan hostname 2>/dev/null | ssh-keygen -E md5 -lf -

คำตอบที่ดีและทั่วถึงนี้ดีกว่าการมีไฟล์ชั่วคราว! ฉันขอแนะนำให้คุณเตรียม TL; DR ไว้ในตอนต้นด้วยเวอร์ชันการทดแทนกระบวนการเพื่อให้คนที่มีความอดทนพบได้เร็วขึ้นหรือไม่ :)
goncalopp

3
ดูเหมือนจะไม่ทำงานบน Ubuntu 14.04 LTS; ฉันได้รับข้อผิดพลาด "/ dev / fd / 63 ไม่ใช่ไฟล์กุญแจสาธารณะ" กระบวนการย่อยไม่ทำงาน
Melle

@melb ฉันพบสิ่งเดียวกันในระบบ 12.04 ที่ฉันสามารถเข้าถึงได้ ฉันสงสัยว่าssh-keygenจาก OpenSSH เวอร์ชันเก่ามีปัญหาในการอ่านจากไปป์ FIFO / named ฉันจะตรวจสอบเรื่องนี้ (และอัปเดตคำตอบของฉัน) เมื่อฉันมีเวลาว่าง
Anthony Geoghegan

3
@mellb หลังจากใช้เวลา luch-time ในการดาวน์โหลดซอร์สโค้ดที่หลากหลายและการแทรกprintfคำสั่งการดีบักในdo_fingerprint()ฟังก์ชั่นฉันพบว่าด้วย OpenSSH เวอร์ชันก่อน 7.2 หน้าที่ที่ใช้ssh-keygenในการอ่านไฟล์ไม่ได้จัดการกับไพพ์ชื่อ วิธีการแทนที่กระบวนการจะไม่ทำงาน
Anthony Geoghegan

วิธีนี้ใช้งานได้ แต่หากใช้เพื่อยืนยันลายนิ้วมือผู้ใช้ควรทราบว่ามีสภาพการแข่งขัน: ลายนิ้วมือที่คุณกำลังตรวจสอบด้วยคำสั่งนี้ไม่จำเป็นต้องเป็นของกุญแจที่คุณดึงข้อมูลเว้นแต่คุณจะทิ้งกุญแจก่อนโทร ssh- keygen กับมัน
CodeGnome

20

nmapจัดเตรียมความสามารถนี้โดยใช้ssh-hostkeyสคริปต์

วิธีคืนลายนิ้วมือเลขฐานสิบหกของคีย์:

$ nmap [SERVER] --script ssh-hostkey

ในการส่งคืนเนื้อหาของคีย์:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=full

ในการส่งคืนฟองภาพของกุญแจ

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey='visual bubble'

หากต้องการส่งคืนทั้งหมดข้างต้น:

$ nmap [SERVER] --script ssh-hostkey --script-args ssh_hostkey=all

ที่มา: เอกสาร nmap


3
ตัวอย่างเหล่านี้สมมติว่า SSH ทำงานอยู่บนพอร์ต 22 เสมอหรือไม่ เกิดอะไรขึ้นถ้า ssh ฟังพอร์ตที่ไม่ได้มาตรฐาน
Martin Vegter

3
@MartinVegter (ถอดความ Guarin42 ที่ไม่สามารถแสดงความคิดเห็นได้ :) nmap มีตัวเลือกที่สามารถระบุพอร์ตเช่น-p -p 22000นอกจากนี้ยังเป็นไปได้ที่จะใช้-vvตัวเลือกเพื่อเพิ่มความฟุ่มเฟื่อย (จำนวนข้อมูลที่กำหนด)
goncalopp

2

filezilla แสดงคีย์ที่แฮชด้วย md5 ในรูปแบบเลขฐานสิบหก

ค้นหาสิ่งนี้บนเครื่องubuntu linuxของคุณใช้คำสั่งนี้:

ssh-keygen -l -E md5 -f <(ssh-keyscan localhost 2>/dev/null)

หมายเหตุ: แทนที่ "localhost" ด้วย ip ของเครื่องที่คุณต้องการตรวจสอบ


1

นี่คือเชลล์สคริป (ส่วนใหญ่เป็นบอร์นเชลล์ แต่ใช้localคีย์เวิร์ดซึ่งมีอยู่ในปัจจุบันมากที่สุด/bin/sh) ฉันได้เขียนขึ้นเพื่อทำสิ่งนี้ ssh-hostkey hostnameใช้มันเหมือน มันจะแสดงทั้งลายนิ้วมือรูปแบบ sha256 และ md5 สำหรับโฮสต์ทั้งหมดสำหรับชื่อโฮสต์หรือที่อยู่ IP ที่กำหนด คุณสามารถระบุ " md5" หรือ " sha256" ด้วยตนเองเป็นอาร์กิวเมนต์ที่สองเพื่อแสดงเฉพาะรูปแบบนั้น

มันใช้ไฟล์ชั่วคราวแทนการวางท่อเพื่อให้เข้ากันได้กับแพ็คเกจ OpenSSH รุ่นเก่า (ดังที่อธิบายไว้ในคำตอบอื่น ๆ ) ไฟล์ชั่วคราวใช้/dev/shm(หน่วยความจำที่ใช้ร่วมกัน) หากมี

#!/bin/sh
usage () {
  printf '%s\n' "Usage: ssh-hostkey HOSTNAME [FPRINTHASH]"
}

ssh_hostkey () {
  local host="$1"
  local fprinthash="$2"
  local tmp=

  case "$host" in
    -h|--help|'')
      usage >&2
      return 1
      ;;
  esac

  case "$fprinthash" in
    md5|sha256|'') true;;
    *)
      usage >&2
      printf '%s\n' "Fingerprint hash may be 'md5' or 'sha256'" >&2
      return 2
      ;;
  esac

  if test -d /dev/shm
  then tmp="$(mktemp -d -p /dev/shm)"
  else tmp="$(mktemp -d)"
  fi

  trap 'trap - INT TERM EXIT; rm -rf "$tmp"' INT TERM EXIT
  ssh-keyscan "$host" > "$tmp/f" 2> /dev/null
  case "$fprinthash" in
    sha256|'') ssh-keygen -l -f "$tmp/f" 2> /dev/null;;
  esac
  case "$fprinthash" in
    md5|'') ssh-keygen -l -E md5 -f "$tmp/f" 2> /dev/null;;
  esac

  trap - INT TERM EXIT
  rm -rf "$tmp" > /dev/null 2>&1
}

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