6 คะแนน โดย GN⁺ 27 일 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ใบรับรอง SSH ช่วยแก้ความยุ่งยากของ การยืนยันตัวตน SSH แบบอิงกุญแจสาธารณะ แบบเดิม และมอบ ความเชื่อถืออัตโนมัติ ระหว่างไคลเอนต์กับเซิร์ฟเวอร์
  • รองรับตั้งแต่ OpenSSH 5.4 โดย CA (หน่วยงานออกใบรับรอง) จะลงนามคีย์ของผู้ใช้และโฮสต์ ทำให้ยืนยันตัวตนได้โดยไม่ต้องแก้ authorized_keys
  • ในใบรับรองสามารถระบุ ระยะเวลาที่มีผล, ผู้ใช้ที่อนุญาต (principal), IP ที่เข้าถึงได้, คำสั่งบังคับ (force-command) เป็นต้น เพื่อรองรับการควบคุมสิทธิ์การเข้าถึงอย่างละเอียด
  • ตัดขั้นตอน TOFU (Trust on First Use) ออกไป และเมื่อมีการเปลี่ยนโฮสต์คีย์ก็ยังเชื่อมต่อได้อย่างปลอดภัยโดยไม่มีคำเตือน
  • หากใช้เซิร์ฟเวอร์หรือตัวมือช่วยลงนามอัตโนมัติ ก็จะช่วย ทำให้การจัดการ SSH ในสภาพแวดล้อมเซิร์ฟเวอร์ขนาดใหญ่เป็นอัตโนมัติ และเพิ่มความปลอดภัยได้

ภาพรวมของใบรับรอง SSH และข้อจำกัดของการยืนยันตัวตนด้วยคีย์ SSH แบบเดิม

  • เมื่อเชื่อมต่อ SSH ไปยังเซิร์ฟเวอร์ที่ไม่เคยเข้ามาก่อน ต้องตรวจสอบ ลายนิ้วมือโฮสต์คีย์ (fingerprint) ของเซิร์ฟเวอร์ และผู้ใช้ส่วนใหญ่มักไม่ตรวจสอบจริงแต่พิมพ์ yes เลย ซึ่งเป็นแนวทางแบบ TOFU (Trust on First Use)
    • ผู้ดูแลระบบสามารถตรวจสอบลายนิ้วมือของเซิร์ฟเวอร์โดยตรง หรือใช้คำสั่ง ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key เพื่อตรวจสอบได้
  • การยืนยันตัวตนแบบอิงกุญแจสาธารณะช่วยให้เชื่อมต่อได้โดยไม่ต้องใช้รหัสผ่าน แต่ต้องกระจายกุญแจสาธารณะไปไว้ในไฟล์ authorized_keys ของแต่ละเซิร์ฟเวอร์
  • หากใช้ SSH agent (ssh-agent) ก็สามารถเก็บกุญแจส่วนตัวไว้ในหน่วยความจำและยืนยันตัวตนซ้ำได้โดยไม่ต้องป้อนทุกครั้ง
  • ข้อจำกัดของวิธีเดิม
    • ต้องคัดลอกกุญแจสาธารณะไปยังเซิร์ฟเวอร์สำหรับผู้ใช้แต่ละคน
    • เมื่อมีการเปลี่ยนโฮสต์คีย์ ฝั่งไคลเอนต์จะมี ข้อความเตือน ปรากฏขึ้น
    • การจัดการความเชื่อถือทำได้ไม่สะดวกเพราะอาศัย TOFU

ใบรับรอง SSH และ CA (หน่วยงานออกใบรับรอง)

  • ใบรับรอง SSH (Certificate) รองรับตั้งแต่ OpenSSH 5.4 (มีนาคม 2010) และเป็นโครงสร้างที่ขยายจากฟอร์แมตคีย์ SSH เดิม
  • SSH CA ประกอบด้วย คู่คีย์ SSH โดยกุญแจสาธารณะทำหน้าที่เป็นรากความเชื่อถือ
  • ข้อดีหลัก
    • ไม่จำเป็นต้องแก้ไฟล์ authorized_keys ของเซิร์ฟเวอร์
    • ไม่มีคำเตือนเมื่อเปลี่ยนโฮสต์คีย์
    • สร้าง ความเชื่อถืออัตโนมัติ ได้ด้วยการตัดขั้นตอน TOFU
    • ในใบรับรองสามารถใส่ ผู้ใช้ที่อนุญาต (principal), IP ที่อนุญาต, ระยะเวลาที่มีผล, คำสั่งบังคับ (force-command) เป็นต้นได้
    • เมื่อใบรับรองหมดอายุ การเข้าถึงจะถูกบล็อกโดยอัตโนมัติ

การสร้าง SSH CA และขั้นตอนการลงนาม

  • บนระบบ CA ให้สร้าง คู่คีย์ CA ด้วยอัลกอริทึม ECDSA
    • ssh-keygen -t ecdsa -C "SSH CA" -f CA/ssh-ca
  • ผู้ใช้ส่งกุญแจสาธารณะของตน (*.pub) ไปยัง CA แล้ว CA จะ ลงนาม (sign) เพื่อออกใบรับรอง (*-cert.pub)
    • ตัวอย่าง: ssh-keygen -s CA/ssh-ca -I "Jane Jolie" -n jane -z 001 -V +1w jane.pub
  • การตั้งค่าเซิร์ฟเวอร์
    • บันทึกกุญแจสาธารณะของ CA ไว้ที่ /etc/ssh/ssh-ca.pub และเพิ่มการตั้งค่า TrustedUserCAKeys
    • ลงนามโฮสต์คีย์ของเซิร์ฟเวอร์ด้วย CA (ssh-keygen -h -s CA/ssh-ca ...) แล้วลงทะเบียนในรายการ HostCertificate
  • การตั้งค่าไคลเอนต์
    • เพิ่มหนึ่งบรรทัด @cert-authority ลงในไฟล์ known_hosts
    • ตัวอย่าง: @cert-authority *.example.com $(cat CA/ssh-ca.pub)

การเชื่อมต่อและการตรวจสอบด้วยใบรับรอง SSH

  • ผู้ใช้เชื่อมต่อโดยใช้ใบรับรองที่ลงนามแล้วร่วมกับกุญแจส่วนตัว (ssh -i jane -l jane alice.example.com)
  • ในล็อกของเซิร์ฟเวอร์จะมีการบันทึก ID, serial และลายนิ้วมือของ CA ของใบรับรอง
  • สามารถเพิ่มชื่อโฮสต์หรือ IP ได้หลายรายการเป็น principal ในใบรับรอง
  • หากพยายามล็อกอินด้วยผู้ใช้อื่นที่ไม่อยู่ใน principal ของใบรับรอง จะเกิดข้อผิดพลาด “Certificate invalid: name is not a listed principal”
  • สามารถกำหนด คำสั่งบังคับ (force-command) หรือ IP ที่อนุญาต (source-address) ในใบรับรองเพื่อควบคุมสิทธิ์การเข้าถึงอย่างละเอียดได้

เช็กลิสต์สำหรับตรวจสอบและแก้ปัญหา

  • รายการตรวจสอบฝั่งเซิร์ฟเวอร์

    • มีการตั้งค่า TrustedUserCAKeys และมีกุญแจสาธารณะของ CA อยู่จริง
    • มีการลงนามโฮสต์คีย์และระบุ HostCertificate แล้ว
    • ต้องรีสตาร์ต sshd
  • รายการตรวจสอบฝั่งไคลเอนต์

    • คีย์ของผู้ใช้ต้องได้รับการลงนามโดย CA
    • รายการ @cert-authority ใน known_hosts และ principal ต้องตรงกัน
    • เมื่อใบรับรองหมดอายุ จะมีข้อความ “Certificate invalid: expired” แสดงขึ้น
    • หากเงื่อนไขจำกัดของใบรับรองไม่ตรงกัน จะมีการร้องขอรหัสผ่าน
    • เมื่อนำใบรับรองเข้า SSH agent จะมีการลงทะเบียนทั้งคีย์และใบรับรอง (ssh-add jane)
    • สามารถควบคุมฟังก์ชันด้วยตัวเลือก (-O) ตอนลงนาม
    • ตัวอย่าง: ใช้ -O clear เพื่อล้างสิทธิ์ทั้งหมดก่อน แล้วอนุญาตเฉพาะ permit-agent-forwarding, permit-port-forwarding

การทำใบรับรองโฮสต์คีย์ให้เป็นอัตโนมัติ

  • ใช้โมดูล Python sshkey-tools และ BottlePy เพื่อสร้าง เซิร์ฟเวอร์ลงนามอัตโนมัติ (hkbot)
    • รัน hkbot.py บนเซิร์ฟเวอร์ CA แล้วเมื่อต้องมีคำขอ HTTP เพื่ออัปโหลดกุญแจสาธารณะของโฮสต์ ก็จะมีการลงนามให้อัตโนมัติ
    • ที่ฝั่งไคลเอนต์สามารถติดตั้งอัตโนมัติได้ด้วยคำสั่ง curl -F hostkey=@/etc/ssh/ssh_host_ed25519_key.pub http://CA:8870 | sh
    • แก้ไข /etc/ssh/sshd_config และตรวจสอบแล้วจึงใช้ systemctl restart sshd เพื่อให้มีผล
  • หลังจากนั้น เมื่อเชื่อมต่อ SSH ก็จะสามารถเชื่อถือและล็อกอินแบบอัตโนมัติด้วยใบรับรองได้

สรุปข้อดีของใบรับรอง SSH

  • ไม่ต้องใช้ TOFU และสร้างความเชื่อถืออัตโนมัติระหว่างไคลเอนต์กับเซิร์ฟเวอร์
  • ออก ใบรับรองอายุสั้น เพื่อควบคุมการเข้าถึงชั่วคราวได้
  • เมื่อใบรับรองหมดอายุ การเข้าถึงจะถูกบล็อกอัตโนมัติ และไม่ต้องคอยจัดการ authorized_keys
  • ตั้งค่านโยบายละเอียดได้ เช่น คำสั่งบังคับ, การจำกัด PTY, การควบคุม IP ที่เข้าถึงได้
  • ใช้เครื่องมืออัตโนมัติเพื่อ ทำให้การดูแลสภาพแวดล้อมเซิร์ฟเวอร์ขนาดใหญ่ง่ายขึ้น
  • แนะนำโปรเจกต์ที่เกี่ยวข้องคือ Smallstep SSH

เอกสารอ้างอิงเพิ่มเติม

อัปเดต

  • SSH CA มีประโยชน์อย่างยิ่งในสภาพแวดล้อมที่ มีเซิร์ฟเวอร์ของตนเองและมีสิทธิ์ระดับ root
  • ในระบบหลายผู้ใช้ วิธี known_hosts และ authorized_keys แบบเดิมยังคงจำเป็นอยู่
  • ร่างมาตรฐานฟอร์แมตใบรับรอง SSH: draft-miller-ssh-cert-06

1 ความคิดเห็น

 
GN⁺ 27 일 전
ความคิดเห็นบน Hacker News
  • น่าแปลกใจที่คนยังใช้ รหัสผ่าน SSH กันอยู่
    โดยเฉพาะในสภาพแวดล้อมองค์กรใหญ่ที่มีนโยบายรหัสผ่านหลายชุดพันกันอยู่ ทำให้แค่จะเข้าเซิร์ฟเวอร์ก็เสียเวลาแล้ว
    เพราะงั้นต่อให้บอกให้ใช้คีย์ด้วย ssh-keygen คนส่วนใหญ่ก็มักจะคิดว่า “ไว้วันหลังค่อยทำ” แล้วสุดท้ายก็ไม่ทำ

    • คีย์มีประโยชน์เมื่อมี ระบบบริหารจัดการแบบศูนย์กลาง ทั้งในระดับบุคคลหรือบริษัท
      แต่ในความเป็นจริงก็มักจัดการกันเละ เช่น ใช้คีย์สาธารณะอันเดียวกับหลายเซิร์ฟเวอร์ หรือแชร์คีย์กันไปมา
      อย่างน้อยรหัสผ่านก็มีข้อดีตรงที่เรียบง่าย
    • ฉันจัดการคีย์ SSH ด้วย Yubikey-based HSM มาหลายปีแล้ว
      ไม่มีรหัสผ่าน แต่ตอนล็อกอินต้องแตะ Yubikey จริง ๆ
    • การใช้คีย์แบบกระจายอย่าง ssh-copy-id ทำให้แฮ็กเกอร์เคลื่อนที่ภายในเครือข่ายได้ง่ายขึ้น หลายองค์กรเลยบล็อกวิธีนี้
  • ทุก ๆ ไม่กี่เดือนก็จะมีคนค้นพบ ใบรับรอง SSH ใหม่อีกครั้งแล้วเขียนบล็อกถึงมัน
    ฉันเองก็เคยเขียนบทความเกี่ยวกับเรื่องนี้เมื่อ 15 ปีก่อน แต่ตอนนี้กลับไปดูแล้วก็ยังไม่ดีพอ

    • หลายคนสับสนระหว่าง คีย์กับใบรับรอง
      แม้แต่วิศวกรความปลอดภัยเองก็ยังลืมว่าตัวเองใช้การยืนยันตัวตนด้วยคีย์ ไม่ใช่ใบรับรอง SSH
    • ใบรับรอง SSH มีประโยชน์เพราะสามารถให้สิทธิ์เข้าถึงแก่ผู้ใช้เฉพาะรายด้วย ช่วงเวลาและสิทธิ์ที่จำกัด ได้
    • ฉันเองก็รู้จักใบรับรอง SSH มานาน แต่ยังย้ายออกจากระบบแบบใช้คีย์ไม่ได้
      การต้องจัดการคีย์ของหลายเซิร์ฟเวอร์ด้วยมือนั้นยุ่งยากเกินไป
      ตอนนี้ก็กำลังคิดอยู่ว่าย้ายตอนนี้ยังจะคุ้มไหม
    • ตอนที่ที่ทำงานฉันสร้าง SSH CA เมื่อ 10 ปีก่อน ก็อ้างอิงจากบทความบล็อกข้างบนนั่นแหละ
  • วิธีแบบ TOFU (Trust On First Use) นั้นเรียบง่าย แต่ก็ไปได้ไกลพอสมควร
    บนเซิร์ฟเวอร์ของฉัน พอตรวจสอบ host key ด้วยตัวเองครั้งหนึ่งแล้วก็ถือว่าเพียงพอ
    ในสภาพแวดล้อมองค์กรใหญ่ แค่เอารายการ public key ของเซิร์ฟเวอร์ภายในไปลงไว้บนเว็บภายในที่เซ็นด้วย SSL ก็พอ
    แต่ถ้ามีเซิร์ฟเวอร์จำนวนมากหรือมีการเปลี่ยนบ่อย ใบรับรองจะดีกว่ามาก และ TOFU ก็มีข้อจำกัดในหลายด้าน
    อยากให้เบราว์เซอร์มีฟีเจอร์แจ้งเตือนเวลาคีย์ TLS ของเซิร์ฟเวอร์เปลี่ยนด้วย

    • ฉันใช้ SSH มาตั้งแต่ปี 1996 แต่ไม่เคยเห็นใคร ตรวจสอบ public key ด้วยตนเอง จริง ๆ เลย
      ส่วนใหญ่ก็แค่พิมพ์ “yes” แล้วผ่านไป
  • ที่บริษัทเสียทั้งเวลาและเงินไปมหาศาลเพราะ การตรวจสอบ SSL ของ Zscaler
    พอขึ้น error ว่า “self-signed certificate in certificate chain” ทีไรก็ปวดหัวทุกที

    • ฉันวิเคราะห์ Zscaler ที่ติดตั้งอยู่บน Windows 11 ของบริษัทเพื่อนมาแล้ว มันแทบจะ ระดับมัลแวร์ เลย
      มันฝัง root certificate ของตัวเอง และล็อกการตั้งค่าเบราว์เซอร์เพื่อไม่ให้ใช้พร็อกซีได้
      ต่อให้แก้ไฟล์ตั้งค่าของ Firefox หรือ Chrome มันก็เขียนทับกลับทันที
      ขนาดจะปิดจาก GUI ยังต้องมีรหัสผ่านของฝ่าย IT
      พูดได้แค่ว่าดีกว่าแอนติไวรัส Cybereason นิดหน่อย
    • Cisco Umbrella ของบริษัทเราก็เหมือนกัน
      มันทำให้โปรโตคอลที่อิง HTTP พังไปหมด
      ทั้ง Git, RubyGems, go mod, Nix และเครื่องมืออีกมากมายใช้ไม่ได้
      ผู้ขายบอกว่า “โปร่งใส” แต่ในความเป็นจริงไม่โปร่งใสเลย
      ต้องเสียเวลาหลายชั่วโมงกว่าจะวินิจฉัยปัญหาได้ และผู้ดูแลส่วนใหญ่ก็ไม่รู้ว่ามันทำลายได้มากแค่ไหน
    • ขอย้ำว่าใบรับรอง SSH ไม่เหมือนกับใบรับรอง X.509
  • ในบทความพูดถึงแต่ข้อดีของใบรับรอง CA แต่ ข้อเสีย ก็มีอยู่ชัดเจนเหมือนกัน
    ฉันไม่เคยเจอปัญหาด้านความปลอดภัยจาก TOFU เลย

    • การบอกว่า “ไม่เคยมีเหตุ ก็แปลว่าปลอดภัย” นั้นเหมือนตรรกะว่า ไม่คาดเข็มขัดนิรภัยก็ได้
      ถ้าใบรับรอง SSH มีข้อเสีย อยากรู้ว่าเป็นเรื่องไหนโดยเฉพาะ
    • TOFU สะดวก แต่ไม่ใช่สิ่งจำเป็น
      ถ้าอยากเพิ่มความปลอดภัย ก็แลก public key กันผ่าน ช่องทางที่ปลอดภัย อย่าง USB ได้
      ต่อให้ใช้ใบรับรอง สุดท้ายก็ต้องผ่านขั้นตอนคล้ายกันอยู่ดี ต่างกันแค่ว่าย้ายภาระการจัดการจากผู้ใช้ไปอยู่ฝั่งผู้ดูแล
      ในองค์กรขนาดใหญ่ใบรับรองอาจมีประโยชน์ แต่ในแง่ความปลอดภัยทั่วไปก็เท่าเดิม
    • ถ้าตั้งค่า CA ไว้ล่วงหน้าได้ ก็เลี่ยง TOFU ได้
      แค่ใส่ไว้ในสคริปต์ติดตั้งหรืออิมเมจสำหรับ deploy
      TOFU จะมีความหมายก็ต่อเมื่อเข้าถึงเครื่องที่ตั้งค่าไปแล้วเท่านั้น
    • การพูดว่า “ยังไม่เคยมีเหตุการณ์ด้านความปลอดภัยจาก TOFU” ก็หมายความแค่ว่า แค่ยังไม่เกิดเท่านั้น
  • ในสภาพแวดล้อม dev/stg ของเรา มีการลงเครื่องใหม่ครึ่งหนึ่งทุกวัน
    ด้วย ใบรับรองโฮสต์ SSH เลยสะดวกขึ้นมาก เพราะไม่ต้องลบ known_hosts หรือพยายามคงคีย์เดิมไว้

  • ฉันกำลังทำเครื่องมือชื่อ Sshifu เป็นโปรเจกต์ส่วนตัว
    มันเป็นเครื่องมือที่ทำให้การล็อกอินด้วยใบรับรอง SSH และ SSO เป็นเรื่องง่าย
    ติดตั้ง sshifu-server บนเซิร์ฟเวอร์เพื่อใช้เป็น CA แล้วตั้งให้แต่ละเซิร์ฟเวอร์ SSH เชื่อถือ CA นี้
    ฝั่งผู้ใช้แค่รันคำสั่ง npx sshifu เพื่อล็อกอินก็จบ
    ดูได้ที่ GitHub repository

  • ในสภาพแวดล้อมใช้งานจริง การเข้าถึงแบบอิงใบรับรองมักนำไปสู่ ปัญหาการจัดการที่ซับซ้อน
    มีทั้งเรื่องใบรับรองหมดอายุ การลบผู้ใช้ การล็อกอินระหว่างเซิร์ฟเวอร์ล่ม และประเด็นอื่น ๆ อีกมาก
    ที่ Userify เราจัดการปัญหาเหล่านี้มา 15 ปีแล้ว และการสร้างโครงสร้างพื้นฐานสำหรับการยืนยันตัวตนผ่าน SSH ที่เสถียรนั้นไม่ง่ายเลย

    • แต่ฉันคิดว่าวิธีแบบ SaaS เป็นตัวเลือกที่แย่ที่สุด
  • เราเพิ่มการรองรับใบรับรอง SSH ให้กับ pico.sh แล้ว และมันมีประโยชน์มากเพราะทำให้ทำ การควบคุมการเข้าถึงสไตล์ RBAC ได้
    ดู เอกสาร

  • ในโปรดักชัน ใบรับรอง SSH กลับยิ่ง รวมศูนย์ความซับซ้อน จนทำให้ปัญหาใหญ่ขึ้น
    ต้องมี CA เดี่ยวที่พร้อมใช้งานตลอดเวลา และถ้ามันล่ม การเข้าถึงทั้งหมดก็หยุดทันที
    ยังมีปัญหาใช้งานจริงอีกมาก เช่น การปรับ TTL การจัดการ trust root และความยากในการดีบัก
    สุดท้ายผู้คนก็มักต้องเอาแคชหรือเอเจนต์กลับมาใช้อีก
    ฝั่งเราทำตรงกันข้าม โดยให้แต่ละโหนดซิงก์ข้อมูลผู้ใช้ผ่าน HTTPS ลงสู่ authorized_keys แบบโลคัล
    แบบนี้ยังคงการควบคุมจากศูนย์กลางได้ แต่จำกัดผลกระทบของความล่มให้อยู่เฉพาะจุด
    ที่ Userify เราใช้วิธีนี้อยู่ และมันจัดการได้ทั้งการยืนยันตัวตนและการจัดการสิทธิ์
    ใบรับรองอย่างเดียวไม่สามารถแก้ปัญหาอย่างการสร้างผู้ใช้ บทบาท sudo หรือการเก็บกวาด home directory ได้

    • มีคนถามว่าแล้วจะแก้ TOFU อย่างไร