SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-28

วิธีแก้ปัญหา SSH Permission denied (publickey) ทุกกรณี

ข้อผิดพลาด Permission denied (publickey) เกิดจาก 5 สาเหตุหลัก ใช้คำสั่ง ssh -v เพื่อตรวจสอบ log และระบุปัญหาที่แท้จริง พร้อมขั้นตอนแก้ไขโดยไม่ทำให้คุณเข้าใช้งานไม่ได้

ความหมายที่แท้จริงของ Permission denied (publickey)

Permission denied (publickey) หมายความว่าไคลเอนต์ของคุณส่ง public key ไปหนึ่งชุดหรือมากกว่านั้น แต่เซิร์ฟเวอร์ไม่ยอมรับเลยสักชุด ระบบเครือข่ายทำงานปกติและ sshd ก็กำลังทำงานอยู่ การปฏิเสธเกิดขึ้นในขั้นตอนสุดท้ายของการยืนยันตัวตน หากเซสชันของคุณหลุดก่อนถึงจุดนั้น แสดงว่าคุณกำลังเจอกับ connection refused หรือ connection timed out ซึ่งเป็นการวินิจฉัยที่ต่างออกไปและต้องใช้วิธีทดสอบที่ต่างกัน การแก้ไขปัญหาไม่ควรใช้วิธีเดาสุ่ม เพราะ ssh -v จะบอกคุณว่าปัญหาเกิดจากสาเหตุใดใน 5 สาเหตุที่เป็นไปได้

ข้อความในวงเล็บคือวิธีการที่เซิร์ฟเวอร์ยินยอมให้ใช้ในการยืนยันตัวตน Permission denied (publickey) เพียงอย่างเดียวหมายความว่าการล็อกอินด้วยรหัสผ่านถูกปิดใช้งานบนเซิร์ฟเวอร์นั้น จึงไม่มีรหัสผ่านให้ใช้สำรอง Permission denied (publickey,password) หมายความว่ามีการเสนอให้ใช้รหัสผ่านแต่คุณไม่ผ่านการตรวจสอบในส่วนนั้นด้วยเช่นกัน

ข้อความเดียวครอบคลุมความผิดพลาด 5 ประการที่แยกจากกัน และถูกออกแบบมาให้คลุมเครือโดยเจตนา เซิร์ฟเวอร์ที่ตอบกลับว่า "no such user" หรือ "that key is not installed" จะเป็นการช่วยเหลือผู้ที่กำลังสแกนหาบัญชีผู้ใช้ที่ใช้งานได้ ดังนั้นอย่าเพิ่งเริ่มสลับคีย์หรือแก้ไขไฟล์ config ให้รันคำสั่งเดียว อ่านผลลัพธ์สามบรรทัด แล้วสาเหตุที่เป็นไปได้ 5 ประการจะเหลือเพียงสาเหตุเดียว

เรียกใช้ ssh -v ก่อน แล้วอ่านสามบรรทัดนี้

ทำซ้ำคำสั่งที่ล้มเหลวโดยเพิ่ม -v เข้าไป:

ssh -v deploy@203.0.113.10

ตัวอย่างผลลัพธ์ที่ตัดทอนมาแต่สมจริงมีลักษณะดังนี้:

OpenSSH_9.6p1 Ubuntu-3ubuntu13, OpenSSL 3.0.13 30 Jan 2024
debug1: Connecting to 203.0.113.10 [203.0.113.10] port 22.
debug1: Connection established.
debug1: Authenticating to 203.0.113.10:22 as 'deploy'
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:0eL/8sBw... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:0eL/8sBw... agent
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.
deploy@203.0.113.10: Permission denied (publickey).

ข้อมูลสามบรรทัดนี้มีทุกสิ่งที่คุณจำเป็นต้องทราบ

Authenticating to 203.0.113.10:22 as 'deploy' คือชื่อผู้ใช้ที่จะถูกนำไปใช้งานจริง ไม่ใช่ชื่อที่คุณตั้งใจจะใช้ แต่เป็นชื่อที่ ssh สรุปได้จากบรรทัดคำสั่ง จาก ~/.ssh/config หรือจากชื่อล็อกอินในเครื่องของคุณ

Authentications that can continue: publickey คือรายการวิธีการตรวจสอบสิทธิ์ที่เซิร์ฟเวอร์ยอมรับ ซึ่งจะส่งมาก่อนที่จะมีการลองใช้คีย์ใดๆ หาก publickey ไม่อยู่ในรายการแรกนี้ แสดงว่าเซิร์ฟเวอร์ปิดการล็อกอินด้วย public key ไว้ ดังนั้นจึงไม่มีคีย์ใดที่สามารถใช้งานได้

Offering public key: ... คือบรรทัดที่แสดงคีย์แต่ละรายการที่ไคลเอนต์ของคุณส่งไปจริง โดยระบุชื่อไฟล์ที่คีย์นั้นมาจากไหนและค่า SHA256 fingerprint ของคีย์ หากคีย์ใดไม่มีบรรทัด Offering แสดงว่าคีย์นั้นไม่เคยถูกส่งไปยังเซิร์ฟเวอร์

ตอนนี้ให้แยกปัญหาออกเป็นสองส่วน:

  • ไม่มีบรรทัด Offering public key สำหรับคีย์ที่คุณคาดหวัง: ปัญหาอยู่ที่เครื่องของคุณ เพราะเซิร์ฟเวอร์ยังไม่ได้รับคีย์ของคุณเลย
  • มีการเสนอคีย์ไปแล้วแต่ Authentications that can continue: publickey กลับมาอีกครั้ง: เซิร์ฟเวอร์ได้รับคีย์นั้นแล้วแต่ปฏิเสธการใช้งาน ดังนั้นปัญหาอยู่ที่ฝั่งเซิร์ฟเวอร์

สาเหตุต่างๆ ด้านล่างนี้เรียงลำดับตามความถี่ที่มักจะเป็นคำตอบของปัญหา

สาเหตุที่ 1: คุณกำลังเชื่อมต่อด้วยชื่อผู้ใช้ที่ไม่ถูกต้อง

สาเหตุที่พบบ่อยที่สุดกลับเป็นสาเหตุที่น่าสนใจน้อยที่สุด sshd ซึ่งเป็น SSH (secure shell) server daemon จะไม่แจ้งให้คุณทราบหากบัญชีผู้ใช้นั้นไม่มีอยู่จริง ระบบจะดำเนินการแลกเปลี่ยนข้อมูลทั้งหมดสำหรับชื่อผู้ใช้ที่สมมติขึ้นมาและปฏิเสธการเชื่อมต่อในตอนท้ายด้วยข้อความเดียวกัน เนื่องจากข้อมูลชื่อบัญชีที่ถูกต้องอาจช่วยให้ผู้โจมตีทำงานได้ง่ายขึ้น การพิมพ์ชื่อผู้ใช้ผิดจึงดูเหมือนกับกุญแจที่ใช้งานไม่ได้ทุกประการ

ตรวจสอบบรรทัด Authenticating to ... as ก่อนดำเนินการอื่นใด หากบรรทัดดังกล่าวระบุชื่อล็อกอินของแล็ปท็อปคุณแทนที่จะเป็นบัญชีบนเซิร์ฟเวอร์ แสดงว่าคุณไม่ได้ระบุชื่อผู้ใช้ในคำสั่ง

ssh -v deploy@203.0.113.10
ssh -v root@203.0.113.10

บัญชีผู้ใช้เริ่มต้นขึ้นอยู่กับอิมเมจที่ผู้ให้บริการของคุณสร้างขึ้น ณ เดือนสิงหาคม 2026 อิมเมจ Ubuntu cloud มักจะมาพร้อมกับบัญชี ubuntu อิมเมจ Debian มาพร้อมกับ debian หรือ admin อิมเมจ Rocky Linux และ AlmaLinux มาพร้อมกับ rocky และ almalinux และผู้ให้บริการ VPS หลายรายจะติดตั้งกุญแจของคุณลงใน root โดยตรง แผงควบคุมของผู้ให้บริการของคุณจะบันทึกว่าได้สร้างบัญชีใดไว้ ไม่มีคำสั่งใดที่รันจากภายนอกเซิร์ฟเวอร์จะสามารถตรวจสอบข้อมูลนี้ได้

บล็อก Host ใน ~/.ssh/config ยังสามารถกำหนดชื่อผู้ใช้ได้เช่นกัน และจะมีผลเหนือกว่าชื่อล็อกอินในเครื่องของคุณ:

Host vps-prod
  HostName 203.0.113.10
  User deploy

หากคุณสร้างบัญชีด้วยตนเองแล้วไม่สามารถล็อกอินด้วยบัญชีนั้นได้ เป็นไปได้ว่ากุญแจถูกติดตั้งไว้สำหรับผู้ใช้เริ่มต้นของอิมเมจและไม่ได้ถูกคัดลอกมา ขั้นตอนนี้เป็นส่วนหนึ่งของ สิบนาทีแรกบน VPS ใหม่ และเป็นขั้นตอนที่ข้ามได้ง่าย

สาเหตุที่ 2: กุญแจที่คุณคิดว่ากำลังส่งอยู่ ไม่ใช่กุญแจที่ถูกส่งจริง

โดยค่าเริ่มต้น ssh จะเสนอเฉพาะกุญแจที่เก็บไว้โดย ssh-agent และชื่อไฟล์ชุดหนึ่งที่กำหนดไว้ใน ~/.ssh ได้แก่ id_ed25519, id_ecdsa, id_rsa รวมถึงกุญแจประเภท hardware และ DSA ของชื่อเหล่านั้น กุญแจที่บันทึกเป็น ~/.ssh/vps-prod จะไม่ปรากฏให้ ssh เห็นจนกว่าคุณจะระบุชื่อไฟล์นั้น ซึ่งเป็นเหตุผลว่าทำไมผลลัพธ์แบบ verbose ถึงไม่แสดงบรรทัด Offering public key สำหรับกุญแจดังกล่าว

ให้ระบุชื่อไฟล์และป้องกันไม่ให้กุญแจจาก agent เข้ามาแทนที่:

ssh -i ~/.ssh/vps-prod -o IdentitiesOnly=yes deploy@203.0.113.10

การใช้เพียง -i อย่างเดียวไม่เพียงพอเมื่อ agent มีกุญแจเก็บไว้ เพราะ ssh จะยังคงเสนอกุญแจของ agent ก่อนและใช้ไฟล์ที่ระบุเป็นลำดับสุดท้าย ซึ่งเป็นเรื่องสำคัญเพราะเซิร์ฟเวอร์จะนับกุญแจที่ถูกปฏิเสธทุกดอกรวมเข้ากับ MaxAuthTries ซึ่งมีค่าเริ่มต้นอยู่ที่ 6 หาก agent เก็บกุญแจไว้ 7 ดอก ก็อาจใช้โควตาจนหมดก่อนที่จะถึงกุญแจที่ถูกต้องของคุณ และข้อความจะเปลี่ยนเป็น:

Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures

หากข้อความที่คุณเห็นเป็นข้อความนี้แทน แสดงว่าเซิร์ฟเวอร์ยุติเซสชันก่อนที่จะลองใช้ key ที่ถูกต้องของคุณ ซึ่งเป็นประเด็นของ การยืนยันตัวตนล้มเหลวมากเกินไป IdentitiesOnly=yes จำกัดการลองใช้ไว้ที่ไฟล์ที่คุณระบุ ดูรายการที่ agent กำลังถืออยู่ด้วย ssh-add -l และล้างรายการด้วย ssh-add -D หากมี key เก่าเก็บสะสมมาหลายปี จากนั้นบันทึกการตั้งค่าไว้ เพื่อให้การเข้าสู่ระบบครั้งถัดไปไม่ต้องอาศัยการจำ flags:

Host vps-prod
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/vps-prod
  IdentitiesOnly yes

อีกหนึ่งกับดักฝั่งไคลเอนต์คือ ssh จะปฏิเสธการใช้ private key ที่บัญชีผู้ใช้อื่นบนเครื่องของคุณสามารถอ่านได้ โดยระบบจะแสดงคำเตือนแล้วเพิกเฉยกุญแจนั้น ทำให้กุญแจไม่ถูกส่งออกไปและเซิร์ฟเวอร์จะไม่ได้รับกุญแจดังกล่าว:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/you/.ssh/vps-prod' are too open.

chmod 600 ~/.ssh/vps-prod จะช่วยแก้ไขปัญหานี้ การย้ายกุญแจผ่าน USB หรือ Windows share มักเป็นสาเหตุที่ทำให้สิทธิ์การเข้าถึง (mode) สูญหายไป ข้อมูลเกี่ยวกับตำแหน่งที่เก็บกุญแจและวิธีการตั้งชื่อกุญแจครอบคลุมอยู่ใน พื้นฐานการจัดการ SSH key

สาเหตุที่ 3: public key ไม่ถูกเพิ่มลงใน authorized_keys

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

sudo ls -l /home/deploy/.ssh/
sudo ssh-keygen -lf /home/deploy/.ssh/authorized_keys

ssh-keygen -lf บนไฟล์ authorized_keys จะแสดง fingerprint รายการละหนึ่งบรรทัด:

256 SHA256:0eL/8sBw... you@laptop (ED25519)
3072 SHA256:9Tq2yZk... old-laptop (RSA)

เปรียบเทียบค่าเหล่านั้นกับ fingerprint ในบรรทัด Offering public key ของคุณ หากไม่พบในรายการ แสดงว่าไม่ได้ติดตั้ง key ไว้ในบัญชีนั้น ไม่ว่าคุณจะจำว่าได้ทำอะไรไปก็ตาม

มี 4 สาเหตุที่ทำให้เกิดข้อผิดพลาด ซึ่งพบได้บ่อย:

  • คุณคัดลอก private key ไปวางแทนที่จะเป็นไฟล์ .pub โดยบรรทัดของ public key จะขึ้นต้นด้วย ssh-ed25519 หรือ ssh-rsa ส่วน private key จะขึ้นต้นด้วย -----BEGIN OPENSSH PRIVATE KEY-----
  • การวางข้อความถูกตัดขึ้นบรรทัดใหม่โดยอัตโนมัติ แต่ละรายการต้องอยู่บนบรรทัดเดียวเท่านั้น ดังนั้น key ที่ถูกตัดบรรทัดจะถูกอ่านเป็นหลายรายการที่เสียหายและไม่ตรงกับค่าใดเลย
  • key ถูกเพิ่มเข้าไปใน /root/.ssh/authorized_keys ในขณะที่คุณล็อกอินด้วยชื่อ deploy หรือในทางกลับกัน ไฟล์นี้แยกตามบัญชีผู้ใช้และไม่มีการใช้ร่วมกัน
  • ช่อง "add my key" ของผู้ให้บริการเขียน key ลงในผู้ใช้เริ่มต้นของ image เท่านั้น ทำให้บัญชีที่คุณสร้างขึ้นภายหลังมีไดเรกทอรี .ssh ว่างเปล่า

วิธีที่ปลอดภัยในการเพิ่ม key จากคอนโซลในฐานะ root:

sudo install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
sudo tee -a /home/deploy/.ssh/authorized_keys >/dev/null <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyDataHere you@laptop
EOF
sudo chown deploy:deploy /home/deploy/.ssh/authorized_keys
sudo chmod 600 /home/deploy/.ssh/authorized_keys

รัน sudo ssh-keygen -lf /home/deploy/.ssh/authorized_keys อีกครั้งหลังจากนั้น fingerprint ใหม่ควรจะปรากฏอยู่ในรายการแล้ว สำหรับเครื่องที่ยังสามารถล็อกอินด้วยรหัสผ่านได้ คำสั่ง ssh-copy-id -i ~/.ssh/vps-prod.pub deploy@203.0.113.10 จะทำงานแบบเดียวกันและตั้งค่าสิทธิ์การเข้าถึงไฟล์ให้ถูกต้องโดยอัตโนมัติ

สาเหตุที่ 4: ทำไม sshd ถึงเพิกเฉยต่อ authorized_keys เมื่อสิทธิ์การเข้าถึงเปิดกว้างเกินไป

StrictModes yes คือค่าเริ่มต้นของ sshd ภายใต้เงื่อนไขนี้ sshd จะปฏิเสธการอ่าน authorized_keys หากไฟล์ดังกล่าว ไดเรกทอรี .ssh หรือไดเรกทอรี home ของบัญชีผู้ใช้ สามารถถูกเขียนโดยบุคคลอื่นที่ไม่ใช่เจ้าของได้ เหตุผลนั้นชัดเจน: หากกลุ่มผู้ใช้หรือบุคคลทั่วไปสามารถเขียนไฟล์ในไดเรกทอรี home ของคุณได้ บัญชีใดก็ตามที่มีสิทธิ์นั้นจะสามารถแทนที่ authorized_keys และเข้ายึดการล็อกอินได้ sshd จึงถือว่าพาธที่ไม่น่าเชื่อถือเสมือนไม่มีคีย์อยู่จริง

ฝั่งไคลเอนต์จะเห็นเพียงข้อความ Permission denied ทั่วไป แต่ log ของเซิร์ฟเวอร์จะบันทึกสาเหตุที่แท้จริงไว้:

Authentication refused: bad ownership or modes for directory /home/deploy/.ssh

หรือในกรณีที่ตัวไฟล์เองเป็นปัญหา:

Authentication refused: bad ownership or modes for file /home/deploy/.ssh/authorized_keys

สิ่งที่ sshd จะยอมรับ:

  • ไดเรกทอรี home: ต้องไม่สามารถเขียนได้โดยกลุ่มผู้ใช้และบุคคลทั่วไป 755, 750 และ 700 ถือว่าผ่านทั้งหมด ส่วน 775 และ 777 จะไม่ผ่าน
  • ~/.ssh: ต้องมีโหมด 700
  • ~/.ssh/authorized_keys: ต้องมีโหมด 600
  • ความเป็นเจ้าของ: ทั้งสามรายการต้องเป็นเจ้าของโดยบัญชีผู้ใช้ที่คุณใช้ล็อกอิน ไม่ใช่ root

ความเป็นเจ้าของมีความสำคัญพอๆ กับโหมดของไฟล์ ไฟล์ที่อยู่ภายใน /home/deploy/.ssh ซึ่งเป็นเจ้าของโดย root จะไม่ผ่านการตรวจสอบเช่นกัน ซึ่งมักเกิดขึ้นเมื่อคุณสร้างไฟล์ด้วยคำสั่ง sudo nano แล้วลืมเปลี่ยนความเป็นเจ้าของกลับมา ให้แก้ไขทั้งสองอย่างพร้อมกันด้วยคำสั่งนี้:

sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
sudo chmod go-w /home/deploy
ls -ld /home/deploy /home/deploy/.ssh

คำสั่งสุดท้ายจะแสดงผลลัพธ์ที่คุณต้องการ คุณควรตั้งค่าไดเรกทอรี home ให้เป็น drwxr-xr-x หรือเข้มงวดกว่านั้น และตั้งค่า .ssh ให้เป็น drwx------ หากคุณยังไม่เข้าใจสตริงเหล่านี้ ให้ศึกษา วิธีการอ่านสตริงสิทธิ์การเข้าถึง เช่น drwxr-xr-x ก่อนที่คุณจะเปลี่ยนโหมดบนเซิร์ฟเวอร์ที่ใช้งานจริง

บน Rocky Linux และ AlmaLinux ให้เพิ่ม SELinux (Security-Enhanced Linux) เข้าไปในรายการสิ่งที่ต้องสงสัยด้วย ไดเรกทอรี .ssh ที่ถูกสร้างขึ้นด้วยวิธีที่ไม่ปกติอาจมี label ของไฟล์ที่ไม่ถูกต้อง ทำให้ sshd ถูกปฏิเสธสิทธิ์การอ่านแม้ว่าโหมดของไฟล์จะดูถูกต้องแล้วก็ตาม sudo restorecon -Rv /home/deploy/.ssh จะช่วยคืนค่า label ให้ถูกต้อง และ sudo ausearch -m avc -ts recent จะแสดงให้เห็นว่า SELinux เป็นส่วนประกอบที่ปฏิเสธการเข้าถึงหรือไม่

สาเหตุที่ 5: sshd ถูกตั้งค่าให้ปฏิเสธการเชื่อมต่อของคุณ

การอ่าน /etc/ssh/sshd_config เพียงอย่างเดียวไม่เพียงพอสำหรับระบบ Ubuntu หรือ Debian ในปัจจุบัน ไฟล์ดังกล่าวเริ่มต้นด้วย Include /etc/ssh/sshd_config.d/*.conf และ OpenSSH จะยึดค่าแรกที่พบสำหรับทุกการตั้งค่า ดังนั้นไฟล์เสริมอย่าง 50-cloud-init.conf จึงถูกอ่านก่อนและมีผลเหนือกว่าสิ่งที่คุณแก้ไขในส่วนล่างของไฟล์หลัก นี่คือสาเหตุที่การแก้ไขอาจดูถูกต้องแต่ไม่มีผลใดๆ เลย

ให้สอบถาม sshd ว่ากำลังใช้การตั้งค่าใดอยู่จริง:

sudo sshd -T | grep -Ei 'pubkeyauth|authorizedkeysfile|permitrootlogin|allowusers|allowgroups|denyusers'

คำตอบที่ปกติจะมีลักษณะดังนี้:

permitrootlogin prohibit-password
pubkeyauthentication yes
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2

สิ่งที่ควรตรวจสอบในผลลัพธ์ของคุณ:

  • pubkeyauthentication no: จะไม่มีกุญแจใดได้รับการยอมรับเลย ค่านี้จะปรากฏใน ssh -v เป็นรายการ Authentications that can continue: แรกที่ไม่มี publickey อยู่ข้างใน
  • authorizedkeysfile: ชี้ไปยังตำแหน่งอื่น เช่น /etc/ssh/authorized_keys/%u ไฟล์ในโฮมไดเรกทอรีของคุณจะถูกเพิกเฉยโดยสิ้นเชิง และกฎเรื่องโหมดจากสาเหตุที่ 4 จะไปมีผลกับพาธใหม่แทน
  • มี allowusers หรือ allowgroups อยู่: บัญชีใดที่ไม่อยู่ในรายการจะถูกปฏิเสธด้วยข้อผิดพลาดนี้โดยไม่มีคำอธิบายเพิ่มเติม ส่วน denyusers และ denygroups จะทำงานในทางกลับกัน
  • permitrootlogin no: ในขณะที่คุณพยายามล็อกอินเป็น root โดยที่ prohibit-password เป็นการตั้งค่าระดับกลางที่มีประโยชน์ คืออนุญาตให้ root ใช้กุญแจได้แต่ห้ามใช้รหัสผ่าน

บล็อก Match จะไม่ปรากฏใน sshd -T แบบปกติ เนื่องจากผลลัพธ์ขึ้นอยู่กับว่าใครเป็นผู้เชื่อมต่อ ให้สอบถามเกี่ยวกับการเชื่อมต่อเฉพาะเจาะจงแทน:

sudo sshd -T -C user=deploy,host=vps.example.com,addr=198.51.100.7

มีการตั้งค่าอีกหนึ่งอย่างที่ส่งผลต่อกุญแจรุ่นเก่า OpenSSH 8.8 เลิกยอมรับลายเซ็น SHA-1 (ssh-rsa) เป็นค่าเริ่มต้น ดังนั้นกุญแจ RSA ที่เคยใช้งานได้มาหลายปีอาจหยุดทำงานทันทีหลังจากการอัปเกรดเซิร์ฟเวอร์ ซึ่งฝั่งไคลเอนต์จะแจ้งเตือนไว้อย่างชัดเจน:

debug1: send_pubkey_test: no mutual signature algorithm

วิธีแก้ไขที่ถูกต้องคือการสร้างกุญแจใหม่ด้วย ssh-keygen -t ed25519 -C "deploy@vps-prod" แล้วติดตั้งไฟล์ .pub ตามที่แสดงไว้ข้างต้น การตั้งค่า PubkeyAcceptedAlgorithms +ssh-rsa บนเซิร์ฟเวอร์จะเปิดใช้งานลายเซ็นเก่าอีกครั้งเพื่อให้คุณเข้าใช้งานได้ในวันนี้ ดังนั้นให้ถือว่าเป็นเพียงวิธีเข้าถึงเซิร์ฟเวอร์ชั่วคราว ไม่ใช่วิธีแก้ปัญหาที่ถาวร การตั้งค่าฝั่งเซิร์ฟเวอร์ส่วนที่เหลือที่ควรตรวจสอบสามารถดูได้ที่ การเพิ่มความปลอดภัยให้กับ SSH server บน VPS

วิธีตรวจสอบว่า private key ตรงกับ public key ที่ติดตั้งไว้หรือไม่

ความไม่แน่นอนส่วนใหญ่ในข้อผิดพลาดนี้เกิดจากการไม่ทราบว่าไฟล์ทั้งสองเป็นคู่กันหรือไม่ คำสั่งเดียวที่ใช้ตรวจสอบได้คือ:

ssh-keygen -y -f ~/.ssh/vps-prod

คำสั่งนี้จะแสดง public key ที่ได้มาจาก private key โดยไม่ได้อ่านไฟล์ .pub ที่อยู่ข้างกัน จึงเป็นการระบุตัวตนที่แท้จริงของ private key แทนที่จะอ้างอิงจากไฟล์ .pub ที่อาจล้าสมัย หากกุญแจมีการตั้งรหัสผ่านไว้ คำสั่งจะถามรหัสผ่าน ซึ่งเป็นการยืนยันว่าคุณยังจำรหัสผ่านนั้นได้

ssh-keygen -lf ~/.ssh/vps-prod.pub
ssh-add -l

คำสั่งแรกจะแสดง fingerprint ของไฟล์ public key หนึ่งไฟล์ ส่วนคำสั่งที่สองจะแสดง fingerprint ที่อยู่ใน agent ของคุณ ตอนนี้ให้เปรียบเทียบค่าทั้ง 4 ชุด: fingerprint ในบรรทัด Offering public key จาก ssh -v, fingerprint ของไฟล์ .pub ของคุณ, fingerprint ใน ssh-keygen -lf บนไฟล์ authorized_keys ของเซิร์ฟเวอร์ และ fingerprint ใน log ของเซิร์ฟเวอร์ จุดที่ค่าเหล่านี้ไม่ตรงกันคือจุดที่เกิดปัญหาจากฝั่งคุณ

อ่าน log ของเซิร์ฟเวอร์ขณะที่การเข้าสู่ระบบล้มเหลว

ฝั่งไคลเอนต์จะไม่ได้รับข้อมูลที่เป็นประโยชน์โดยเจตนา แต่เซิร์ฟเวอร์จะบันทึกสาเหตุที่แท้จริงไว้ ให้เริ่มการติดตาม log บนเซสชันคอนโซล จากนั้นรันคำสั่ง ssh ที่ล้มเหลวจากแล็ปท็อปของคุณ

sudo journalctl -u ssh -f

Ubuntu 24.04 ไม่ได้ติดตั้ง rsyslog มาให้โดยค่าเริ่มต้น ดังนั้น /var/log/auth.log อาจไม่มีอยู่บนระบบนั้น สำหรับ Rocky Linux และ AlmaLinux ยูนิตจะมีชื่อว่า sshd และบันทึกข้อมูลเดียวกันจะถูกเก็บไว้ใน /var/log/secure เช่นกัน

ตั้งค่า LogLevel VERBOSE ในการกำหนดค่า sshd แล้ว reload บริการ ทุกความพยายามในการเชื่อมต่อจะบันทึก fingerprint ที่เซิร์ฟเวอร์ได้รับจริง:

Failed publickey for deploy from 198.51.100.7 port 49812 ssh2: ED25519 SHA256:0eL/8sBw...

บรรทัดดังกล่าวจะบอกคุณว่าความผิดพลาดอยู่ที่ฝั่งใด หากเป็น fingerprint ที่คุณรู้จัก แสดงว่ากุญแจของคุณส่งไปถึงแล้วแต่ถูกเซิร์ฟเวอร์ปฏิเสธ ให้ตรวจสอบสาเหตุที่ 3, 4 และ 5 หากเป็น fingerprint ที่คุณไม่รู้จัก แสดงว่าไคลเอนต์ของคุณส่งกุญแจที่คุณไม่ได้ตั้งใจจะใช้ ให้ย้อนกลับไปดูสาเหตุที่ 2

เมื่อ log ยังคงไม่ชัดเจน ให้รัน sshd ตัวที่สองบนพอร์ตอื่นในโหมด debug มันจะทำงานใน foreground, รองรับการเชื่อมต่อหนึ่งรายการ, แสดงเหตุผลการทำงาน แล้วจึงปิดตัวลง:

sudo /usr/sbin/sshd -ddd -p 2222

จากเซสชันคอนโซลบนเซิร์ฟเวอร์เดียวกัน ให้เชื่อมต่อไปยังพอร์ตนั้นผ่าน loopback address:

ssh -p 2222 -i ~/.ssh/vps-prod -o IdentitiesOnly=yes deploy@127.0.0.1

การเชื่อมต่อผ่าน 127.0.0.1 จะช่วยตัดปัญหาเรื่อง firewall ออกจากการทดสอบ ผลลัพธ์จากโหมด debug จะระบุชื่อไฟล์ที่เปิด, fingerprint ที่นำมาเปรียบเทียบ และสาเหตุการปฏิเสธที่ชัดเจน รวมถึงบรรทัดข้อความเช่น Authentication refused: bad ownership or modes for directory /home/deploy ให้กด Ctrl+C เมื่อคุณได้คำตอบแล้ว sshd ตัวหลักที่พอร์ต 22 จะไม่ได้รับผลกระทบใดๆ ตลอดกระบวนการนี้

วิธีป้องกันการเข้าใช้งานไม่ได้

ทุกขั้นตอนที่แก้ไขการตั้งค่าเซิร์ฟเวอร์จำเป็นต้องมีช่องทางสำรองในการเข้าถึงที่ไม่ขึ้นอยู่กับ SSH ให้ตั้งค่าช่องทางนี้ไว้ในขณะที่ SSH ยังใช้งานได้ ไม่ใช่หลังจากที่เข้าใช้งานไม่ได้แล้ว

  1. เปิดคอนโซลของผู้ให้บริการของคุณผ่านทาง serial หรือ VNC (virtual network computing) และตรวจสอบให้แน่ใจว่าคุณสามารถเข้าสู่ระบบผ่านช่องทางนั้นได้
  2. ตรวจสอบให้แน่ใจว่าคุณมีรหัสผ่านท้องถิ่นที่ใช้งานได้สำหรับบัญชีที่มีสิทธิ์ sudo หากคุณไม่มี ให้ รีเซ็ตรหัสผ่าน root จากคอนโซลของผู้ให้บริการ ก่อน
  3. เปิดเซสชัน SSH ปัจจุบันของคุณทิ้งไว้ เซสชันที่เปิดอยู่จะยังคงอยู่แม้เกิด systemctl restart ssh ดังนั้นมันจึงเป็นช่องทางสำรองหากการตั้งค่าใหม่ไม่ถูกต้อง
  4. ตรวจสอบไวยากรณ์ก่อนเริ่มการทำงานใหม่: sudo sshd -t จะไม่แสดงผลลัพธ์ใดๆ หากไฟล์ถูกต้อง และจะแสดงชื่อไฟล์พร้อมหมายเลขบรรทัดหากมีข้อผิดพลาด
  5. เปิดเทอร์มินัลที่สองและเข้าสู่ระบบใหม่ก่อนที่จะปิดเทอร์มินัลแรก การตั้งค่าที่ผิดพลาดจะขัดขวางการเข้าสู่ระบบใหม่แต่จะยังคงรักษาเซสชันเดิมไว้ ดังนั้นเซสชันที่คุณใช้งานอยู่จะไม่สามารถบอกคุณได้ว่าการเปลี่ยนแปลงนั้นสำเร็จหรือไม่

เริ่มการทำงานใหม่ด้วย sudo systemctl restart ssh บน Debian และ Ubuntu หรือ sudo systemctl restart sshd บน Rocky Linux และ AlmaLinux สำหรับ Ubuntu 24.04 นั้น sshd จะเริ่มทำงานจาก socket unit ดังนั้นการเปลี่ยนแปลงใน Port หรือ ListenAddress จึงจำเป็นต้องใช้ sudo systemctl restart ssh.socket ก่อนที่การตั้งค่าจะมีผล

FAQ

ทำไมฉันถึงได้รับข้อผิดพลาด Permission denied (publickey) ทั้งที่คีย์เดียวกันใช้งานได้บนเซิร์ฟเวอร์อื่น?

เพราะคีย์ของคุณไม่ได้มีปัญหา แต่มีบางอย่างในสภาพแวดล้อมที่เกี่ยวข้องไม่ถูกต้อง ให้รันคำสั่ง ssh -v แล้วหาบรรทัด Offering public key หากคีย์ของคุณไม่อยู่ในรายการ แสดงว่า ssh ไม่ได้ส่งคีย์นั้นไป เนื่องจากไฟล์ไม่ได้อยู่ใน ~/.ssh ด้วยชื่อมาตรฐานและไม่ได้โหลดไว้ใน agent ให้เพิ่มด้วย -i /path/to/key -o IdentitiesOnly=yes หากคีย์อยู่ในรายการแล้วแต่เซิร์ฟเวอร์ยังปฏิเสธ แสดงว่าคีย์นั้นไม่มีอยู่ในไฟล์ authorized_keys ของบัญชีผู้ใช้นั้น, path ของไฟล์ถูกตั้งค่าให้กลุ่มอื่นเขียนได้ (group-writable) หรือการตั้งค่า sshd บล็อกผู้ใช้รายนี้ไว้ โดย log ของเซิร์ฟเวอร์จะระบุสาเหตุที่แตกต่างกันเหล่านี้

ฉันจะดูได้อย่างไรว่า SSH กำลังส่งคีย์ไหนไปจริง ๆ?

ssh -v host จะแสดงบรรทัด debug1: Offering public key: หนึ่งบรรทัดต่อคีย์ โดยระบุไฟล์ต้นทางและ SHA256 fingerprint ของแต่ละคีย์ ส่วน ssh-add -l จะแสดงรายการ fingerprint ที่ agent ถืออยู่ ssh-keygen -lf ~/.ssh/id_ed25519.pub จะแสดง fingerprint ของไฟล์คีย์เดี่ยว และ ssh-keygen -y -f ~/.ssh/id_ed25519 จะแสดง public key ที่ได้จาก private key นั้น เพื่อให้การล็อกอินสำเร็จ fingerprint จากบรรทัด Offering จะต้องปรากฏอยู่ในผลลัพธ์ของ ssh-keygen -lf ที่รันกับไฟล์ authorized_keys ของเซิร์ฟเวอร์ด้วย

ทำไม sshd ถึงเพิกเฉยต่อไฟล์ authorized_keys ของฉัน?

เพราะ StrictModes ถูกเปิดใช้งานเป็นค่าเริ่มต้น และไฟล์ดังกล่าว, ไดเรกทอรี .ssh หรือโฮมไดเรกทอรีมีการตั้งค่าให้กลุ่มอื่นหรือทุกคนเขียนได้ (writable) หรือเป็นเจ้าของโดยบัญชีที่ไม่ถูกต้อง sshd จะไม่เชื่อถือ path ที่บุคคลอื่นสามารถแก้ไขได้ จึงทำงานเสมือนว่าไม่มีคีย์อยู่ ให้ตั้งค่าโฮมไดเรกทอรีเป็น 755 หรือเข้มงวดกว่านั้น, ตั้ง .ssh เป็น 700, ตั้ง authorized_keys เป็น 600 และตรวจสอบให้แน่ใจว่าทั้งสามรายการมีบัญชีผู้ใช้ที่ล็อกอินเป็นเจ้าของ โดยเมื่อใช้ LogLevel VERBOSE เซิร์ฟเวอร์จะบันทึก Authentication refused: bad ownership or modes for directory /home/deploy/.ssh ไว้

คีย์ของฉันใช้งานไม่ได้ทันทีหลังจากอัปเกรดเซิร์ฟเวอร์ เกิดอะไรขึ้น?

หากเป็นคีย์ RSA สาเหตุที่พบบ่อยที่สุดคือการเปลี่ยนแปลงเกี่ยวกับ SHA-1 โดย OpenSSH 8.8 ได้ปิดการใช้งานลายเซ็น ssh-rsa SHA-1 เป็นค่าเริ่มต้น ดังนั้นคีย์ที่สามารถลงชื่อได้ด้วยวิธีนั้นเพียงอย่างเดียวจึงถูกปฏิเสธ ผลลัพธ์แบบละเอียดของไคลเอนต์จะแสดง debug1: send_pubkey_test: no mutual signature algorithm ให้สร้างคีย์สมัยใหม่ด้วย ssh-keygen -t ed25519 และติดตั้งไฟล์ .pub ของคีย์นั้น หากคุณต้องการเข้าถึงระบบทันที การใช้ PubkeyAcceptedAlgorithms +ssh-rsa บนเซิร์ฟเวอร์จะเปิดใช้งานลายเซ็นเก่าอีกครั้ง และคุณควรลบบรรทัดนั้นออกเมื่อคีย์ใหม่ใช้งานได้แล้ว

ฉันแก้ไข sshd_config แล้วตอนนี้ล็อกอินไม่ได้เลย จะกลับเข้าไปได้อย่างไร?

ให้ใช้คอนโซลของผู้ให้บริการของคุณซึ่งไม่ได้ผ่านการเชื่อมต่อ SSH ให้ล็อกอินด้วยรหัสผ่านท้องถิ่นที่นั่น รันคำสั่ง sudo sshd -t เพื่อดูข้อผิดพลาดทางไวยากรณ์และหมายเลขบรรทัด จากนั้นยกเลิกการแก้ไขและรีสตาร์ทบริการ จากนั้นตรวจสอบ sudo sshd -T เพื่อยืนยันค่าที่กำลังทำงานอยู่ เนื่องจากไฟล์ใน /etc/ssh/sshd_config.d/ อาจกำลังทับการตั้งค่าหลักอยู่ หากคุณไม่มีรหัสผ่านท้องถิ่น ให้รีเซ็ตรหัสผ่าน root จากคอนโซลก่อน แล้วจึงซ่อมแซมไฟล์ดังกล่าว