SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor

แก้ SSH ขึ้น Too many authentication failures

ข้อผิดพลาด Too many authentication failures เกิดจาก client ส่งกุญแจเกินค่า MaxAuthTries ซึ่งค่าเริ่มต้นมักเป็น 6 ตรวจสอบด้วย ssh -v และแก้โดยเลือกกุญแจให้ถูกต้อง

ความหมายของ "Too many authentication failures"

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

ลำดับเหตุการณ์เป็นดังนี้ ssh-agent จะเก็บกุญแจส่วนตัว (private key) ทุกตัวที่คุณโหลดไว้ Client ของคุณจะทยอยส่งกุญแจเหล่านั้นให้เซิร์ฟเวอร์ทีละตัว เนื่องจาก client ไม่ทราบว่าบัญชีผู้ใช้นั้นยอมรับกุญแจตัวใด เซิร์ฟเวอร์จะปฏิเสธกุญแจที่ไม่ปรากฏใน authorized_keys และนับการปฏิเสธแต่ละครั้งเป็นความพยายามยืนยันตัวตนที่ล้มเหลว ค่า MaxAuthTries ใน sshd_config จะเป็นตัวกำหนดขีดจำกัดจำนวนครั้งที่อนุญาตให้ล้มเหลวได้ในการเชื่อมต่อหนึ่งครั้ง โดยค่าเริ่มต้นคือ 6 หาก agent ของคุณเก็บกุญแจไว้ 10 ตัวและกุญแจที่ถูกต้องอยู่ในลำดับที่ 8 เซิร์ฟเวอร์จะตัดการเชื่อมต่อก่อนที่จะตรวจสอบถึงกุญแจตัวนั้น

ดังนั้น วิธีแก้ไขคือการตั้งค่าให้ client ส่งกุญแจเพียงตัวเดียว นั่นคือตัวที่ถูกต้องเท่านั้น

สิ่งที่เซิร์ฟเวอร์นับ และบทบาทของ MaxAuthTries

การยืนยันตัวตนด้วย public key เริ่มจากการลองตรวจสอบแบบหนึ่ง ไคลเอนต์ส่ง public key และถามว่าเซิร์ฟเวอร์จะยอมรับลายเซ็นที่สร้างด้วย key นี้หรือไม่ เซิร์ฟเวอร์ตอบว่าใช่หรือไม่ใช่ การตอบว่าไม่ใช่ถือเป็นความพยายามที่ล้มเหลว เช่นเดียวกับการป้อนรหัสผ่านผิด

หน้าคู่มือ sshd_config(5) อธิบายค่าจำกัดนี้ไว้ว่า: "ระบุจำนวนสูงสุดของความพยายามยืนยันตัวตนที่อนุญาตต่อการเชื่อมต่อ เมื่อจำนวนครั้งที่ล้มเหลวถึงครึ่งหนึ่งของค่านี้ ระบบจะบันทึกความล้มเหลวเพิ่มเติมลง log ค่าเริ่มต้นคือ 6"

ความพยายาม 6 ครั้งเพียงพอสำหรับคนที่กำลังพิมพ์รหัสผ่าน แต่ไม่มากนักสำหรับ agent ที่ถือ 10 keys เมื่อจำนวนครั้งที่ล้มเหลวถึงค่าจำกัด sshd จะตัดการเชื่อมต่อ และเขียนบรรทัดลักษณะนี้ลงใน system log:

error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2

ไคลเอนต์ของคุณจะแสดงอีกครึ่งหนึ่งของเหตุการณ์เดียวกัน:

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

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

เหตุใดกุญแจเดียวกันจึงใช้งานได้จากแล็ปท็อปของเพื่อนร่วมงาน

ไม่มีสิ่งใดแตกต่างกันทั้งในส่วนของกุญแจหรือตัวเซิร์ฟเวอร์ ตัวแทน (agent) ของเพื่อนร่วมงานเก็บกุญแจไว้ 2 ดอก ในขณะที่ของคุณเก็บไว้ 12 ดอก ข้อเสนอที่ส่งไปถึงก่อนสำหรับพวกเขาจะกลายเป็นลำดับที่ 9 สำหรับคุณ ซึ่งในตอนนั้นการเชื่อมต่อได้สิ้นสุดลงแล้ว

จำนวนกุญแจเพิ่มขึ้นอย่างเงียบเชียบ AddKeysToAgent yes ใน ~/.ssh/config จะเพิ่มกุญแจแต่ละดอกที่คุณใช้เข้าไปในตัวแทนและทิ้งไว้ที่นั่น ตัวแทนจัดการกุญแจบนเดสก์ท็อป เช่น GNOME Keyring บน Linux หรือ login keychain บน macOS จะโหลดกุญแจโดยอัตโนมัติเมื่อเข้าสู่ระบบโดยไม่ถาม เมื่อคุณเพิ่มกุญแจสำหรับไคลเอนต์, กุญแจสำหรับโฮสต์ git และกุญแจสำหรับเครื่องในห้องแล็บสะสมไปเรื่อยๆ ตลอดทั้งปี วันหนึ่งเซิร์ฟเวอร์ที่เคยใช้งานได้ตามปกติจะเริ่มปฏิเสธการเชื่อมต่อของคุณ ทั้งที่ไม่มีสิ่งใดเปลี่ยนแปลงบนเซิร์ฟเวอร์ แต่เป็นเพราะตัวแทนของคุณมีกุญแจมากเกินไป

วิธีตรวจสอบข้อเสนอ (offers) ด้วย ssh -v

ให้รันคำสั่งเชื่อมต่อที่ล้มเหลวด้วย -v แล้วอ่านข้อมูลการติดตาม (trace) ที่แสดงออกมา

ssh -v deploy@203.0.113.10

บรรทัดสองประเภทที่มีความสำคัญคือ Will attempt key: ซึ่งจะแสดงรายการ identity ที่ไคลเอนต์รวบรวมไว้ตามลำดับที่จะนำไปใช้งานจริง และ Offering public key: ซึ่งจะปรากฏขึ้นหนึ่งครั้งสำหรับกุญแจแต่ละดอกที่ถูกส่งไปยังเซิร์ฟเวอร์

debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Will attempt key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent

พาธ ประเภทของกุญแจ และลายนิ้วมือ (fingerprints) ของคุณจะแตกต่างจากตัวอย่าง สิ่งที่คุณต้องนับคือจำนวนบรรทัด Offering public key: ที่ปรากฏก่อนการตัดการเชื่อมต่อ หากข้อเสนอต่างๆ แสดงผ่านไปจนจบเซสชันโดยไม่มีกุญแจที่คุณต้องการปรากฏขึ้น แสดงว่าปัญหาได้รับการวินิจฉัยแล้ว คำว่า agent ที่ท้ายบรรทัดหมายความว่า identity นั้นมาจาก ssh-agent ส่วนคำว่า explicit หมายความว่า identity นั้นมาจากบรรทัด IdentityFile หรือมาจาก -i ในบรรทัดคำสั่ง

จากนั้นให้ตรวจสอบว่า agent ของคุณเก็บกุญแจอะไรไว้บ้าง:

ssh-add -l

ผลลัพธ์แต่ละบรรทัดคือหนึ่งกุญแจที่ถูกโหลดไว้ หากคำสั่งแสดงผลเป็น The agent has no identities. แสดงว่าปัญหาไม่ได้อยู่ที่ agent และคุณควรตรวจสอบบรรทัด IdentityFile ใน ~/.ssh/config แทน หากคำสั่งแสดงผลเป็น Could not open a connection to your authentication agent. แสดงว่าไม่มี agent ทำงานอยู่ และข้อเสนอที่ส่งไปนั้นมาจากไฟล์กุญแจเริ่มต้นของคุณ

แก้ไข 1: ใช้ IdentitiesOnly โดยกำหนด 1 key ต่อ host

IdentitiesOnly yes สั่งให้ ssh ส่งเฉพาะ identity ที่คุณกำหนดไว้ และไม่ใช้ identity อื่นที่ agent เสนอมาเอง เมื่อใช้ร่วมกับบรรทัด IdentityFile client จะส่งเพียง 1 offer

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

บันทึกการตั้งค่านี้ไว้ใน ~/.ssh/config แล้วเรียกใช้ chmod 600 ~/.ssh/config หากไฟล์เปิดให้ group หรือทุกคนเขียนได้ ssh จะปฏิเสธการทำงานและแสดง Bad owner or permissions on /home/you/.ssh/config ขณะนี้ ssh vps จะเสนอเพียง 1 key และ ssh -v vps ควรแสดงบรรทัด Offering public key: เพียง 1 บรรทัดเท่านั้น

มีรายละเอียด 2 ประการที่มักทำให้ผู้ใช้ประหลาดใจ

  • IdentitiesOnly yes เพียงอย่างเดียวไม่ได้หมายความว่า "1 key" หากไม่มีบรรทัด IdentityFile ไฟล์ identity เริ่มต้นจะถูกนับเป็น identity ที่กำหนดไว้ด้วย ดังนั้น ssh ยังคงลองใช้ ~/.ssh/id_ed25519, ~/.ssh/id_rsa และไฟล์เริ่มต้นอื่นที่พบ คุณต้องมีบรรทัด IdentityFile ด้วย เมื่อกำหนดบรรทัดนี้แล้ว ssh จะหยุดเพิ่มไฟล์เริ่มต้น
  • agent ยังคงเป็นผู้ทำ signing IdentitiesOnly ควบคุมว่าจะเสนอ key ใด ไม่ได้ควบคุมว่าใครจะเป็นผู้ทำ signing หาก private key ที่ระบุโดย IdentityFile ถูกโหลดไว้ใน agent agent จะสร้าง signature ให้ และระบบจะไม่ถาม passphrase คุณยังสามารถชี้ IdentityFile ไปยังไฟล์ .pub ที่ตรงกันได้ ซึ่งเป็นวิธีที่ใช้เมื่อ private key มีอยู่เฉพาะใน agent หรือ hardware token

ข้อผิดพลาดอย่างหนึ่งใน ~/.ssh/config อาจทำให้การแก้ไขนี้ไม่ทำงานโดยไม่แสดงสาเหตุ keyword ส่วนใหญ่ใช้ค่าที่พบเป็นค่าแรก จึงควรวาง block Host ที่เจาะจงไว้ก่อน Host * แต่ IdentityFile ไม่ทำงานตามกฎนี้ คู่มือระบุว่า: "สามารถระบุไฟล์ identity หลายไฟล์ในไฟล์ config ได้ โดยระบบจะลองใช้ identity ทั้งหมดตามลำดับ" ดังนั้น IdentityFile ใต้ Host * จะถูกเพิ่มเข้าไปจากค่าที่กำหนดเฉพาะต่อ host ไม่ได้ถูกแทนที่ บรรทัดระดับ global ที่ลืมไว้จึงทำให้ทุก connection มี offer เพิ่มกลับมาอีกครั้ง

หากต้องการตั้งค่า safety net ระดับ global ให้ตั้งเฉพาะ flag ไว้ที่ส่วนท้ายของไฟล์:

Host *
  IdentitiesOnly yes

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

วิธีแก้ไขที่ 2: ล้างข้อมูลหรือรีสตาร์ท agent

หากคุณยังไม่สามารถแก้ไขไฟล์ config ได้ ให้ล้างข้อมูลใน agent และโหลดเฉพาะสิ่งที่จำเป็นเท่านั้น

ssh-add -l                    # list what is loaded
ssh-add -d ~/.ssh/id_rsa      # remove one key
ssh-add -D                    # remove every key
ssh-add ~/.ssh/id_ed25519_vps # load the one you need

หากการเชื่อมต่อทำงานได้ทันทีหลังจากใช้ ssh-add -D แสดงว่าสาเหตุมาจากตัว agent ให้ถือว่านี่เป็นการทดสอบไม่ใช่การซ่อมแซมถาวร ตัว desktop keyring agent จะโหลดกุญแจใหม่เมื่อคุณล็อกอินครั้งถัดไป ดังนั้นปัญหาจะกลับมาอีกในวันพรุ่งนี้ การเพิ่มบรรทัด IdentitiesOnly ลงใน ~/.ssh/config จะคงอยู่ถาวรแม้หลังจากรีบูตเครื่อง แต่การล้าง agent จะไม่คงอยู่ถาวร

คุณยังสามารถกำหนดอายุการใช้งานให้กับกุญแจเพื่อให้ agent ลบออกให้คุณโดยอัตโนมัติ:

ssh-add -t 1800 ~/.ssh/id_ed25519_vps

กุญแจจะถูกลบออกหลังจากเพิ่มเข้าไปแล้ว 1800 วินาที การรีสตาร์ท agent ก็เป็นอีกวิธีหนึ่ง ซึ่งวิธีการทำจะขึ้นอยู่กับว่าคุณเริ่มการทำงานของมันอย่างไร ssh-agent ที่คุณรันด้วยตัวเองจะหยุดทำงานด้วยคำสั่ง ssh-agent -k หากคุณรันผ่าน systemd user unit ที่คุณเขียนขึ้นเอง ให้รีสตาร์ท unit นั้นด้วย systemctl --user restart <unit> ส่วน keyring agent จะรีสตาร์ทพร้อมกับ session บนเดสก์ท็อปของคุณ

วิธีแก้ไขที่ 3: คำสั่งแบบครั้งเดียวสำหรับเซิร์ฟเวอร์ที่เข้าถึงเพียงครั้งเดียว

สำหรับโฮสต์ที่คุณจะไม่เพิ่มลงในไฟล์คอนฟิกูเรชัน ให้ระบุการตั้งค่าเดียวกันนี้ผ่านบรรทัดคำสั่ง:

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

การใช้ -i เพียงอย่างเดียวเป็นวิธีแก้ไขที่ผิดซึ่งพบบ่อยที่สุด -i จะเพิ่มคีย์เข้าไปในรายการ identity แต่มันไม่ได้ลบกุญแจที่มีอยู่ใน agent ออกจากรายการนั้น ดังนั้นคีย์อื่นๆ ทั้งหมดจะยังคงถูกส่งไปก่อนคีย์ของคุณ และการเชื่อมต่อจะยังคงถูกตัดเมื่อถึงขีดจำกัด ให้ลองรัน ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 โดยไม่มี IdentitiesOnly แล้วคุณจะเห็นว่าคีย์จาก agent ถูกส่งไปก่อนเสมอ -i จำเป็นต้องมี -o IdentitiesOnly=yes กำกับอยู่ด้วย

หากต้องการตัดการทำงานของ agent ออกไปโดยสิ้นเชิงสำหรับการเชื่อมต่อหนึ่งครั้ง:

ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

จากนั้น ssh จะอ่าน private key จากดิสก์โดยตรงและถามหา passphrase หากมีการตั้งค่าไว้

เครื่องมือที่สร้างขึ้นบนพื้นฐานของ ssh ก็ยอมรับตัวเลือกเดียวกันนี้เช่นกัน:

scp -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps report.tar.gz deploy@203.0.113.10:/tmp/
rsync -av -e "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" ./site/ deploy@203.0.113.10:/srv/site/
GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" git clone git@example.com:team/repo.git

เหตุใดข้อผิดพลาดจึงปรากฏที่ hop ที่สอง

เมื่อใช้ ForwardAgent yes agent socket จะพร้อมใช้งานบนเซิร์ฟเวอร์ที่คุณเชื่อมต่ออยู่ คำสั่ง ssh ที่เรียกใช้บนเซิร์ฟเวอร์นั้นจะใช้ agent ภายในเครื่องของคุณ พร้อม key ทั้งหมดของคุณ ผ่าน socket ที่ forward ไว้ ด้วยเหตุนี้ ข้อผิดพลาดจึงอาจเกิดขึ้นใน hop จาก jump host ไปยังเซิร์ฟเวอร์ปลายทาง ทั้งที่ hop แรกทำงานได้ตามปกติ เรียกใช้ echo $SSH_AUTH_SOCK บนเครื่องกลาง หากไม่มีผลลัพธ์ แสดงว่าไม่มี agent ที่เข้าถึงได้ หากแสดง path ของ socket แสดงว่ามี agent อยู่ แต่ไม่จำเป็นต้องเป็น agent ของคุณ เพราะ agent ที่เริ่มทำงานบนเครื่องนั้นสามารถกำหนดตัวแปรเดียวกันได้ เรียกใช้ ssh-add -l บนเครื่องนั้นด้วย หากแสดง key จากเครื่องของคุณ แสดงว่าการ forward ทำงานอยู่

การ forward agent มีความเสี่ยงเพิ่มเติม ผู้ใดก็ตามที่มีสิทธิ์ root บนเครื่องกลางสามารถใช้ agent ของคุณเพื่อยืนยันตัวตนในนามของคุณได้ ตราบเท่าที่ session ของคุณยังเปิดอยู่ ProxyJump หลีกเลี่ยงปัญหาทั้งสองประการนี้:

ssh -J deploy@jump.example.com deploy@10.0.0.5

ProxyJump เปิดการเชื่อมต่อผ่าน jump host และยืนยันตัวตนกับเซิร์ฟเวอร์ปลายทางจากเครื่องของคุณเอง ดังนั้น ~/.ssh/config ภายในเครื่องของคุณจึงมีผลในทุก hop รวมถึง IdentitiesOnly การปิด ForwardAgent เป็นขั้นตอนมาตรฐานเมื่อ เสริมความปลอดภัยให้ SSH บน VPS

ควรเพิ่มค่า MaxAuthTries บนเซิร์ฟเวอร์หรือไม่?

โดยทั่วไปไม่ควรเพิ่ม ให้ตรวจสอบค่าปัจจุบันก่อน:

sudo sshd -T | grep -i maxauthtries

sshd -T จะแสดง configuration ที่มีผลจริง รวมค่าเริ่มต้นด้วย จึงรายงานค่าที่ใช้งานจริง แม้ว่า sshd_config จะไม่ได้ระบุค่านี้ไว้ก็ตาม ให้เพิ่ม -C user=deploy,host=example.com,addr=203.0.113.10 หากใช้บล็อก Match เนื่องจากบล็อกเหล่านี้จะถูกประเมินแยกตามแต่ละ connection และจะถูกข้ามไปหากไม่ใช้ตัวเลือกดังกล่าว

การเพิ่ม limit ช่วยได้ในความหมายจำกัด คือทำให้ client ที่ทำงานผิดปกติมีจำนวนครั้งให้ลองมากขึ้น:

MaxAuthTries 20

ตรวจสอบไฟล์และ reload service จากนั้นเปิด session สำรองไว้อีกหนึ่ง session ระหว่างดำเนินการ:

sudo sshd -t
sudo systemctl reload ssh      # Debian and Ubuntu
sudo systemctl reload sshd     # RHEL family

หาก systemctl is-enabled ssh.socket รายงาน enabled บน Ubuntu 24.04 แสดงว่า sshd ถูกเปิดใช้งานผ่าน socket Ubuntu's ssh.socket จะไม่เริ่ม daemon ใหม่สำหรับแต่ละ connection แต่จะเริ่ม ssh.service เมื่อมี connection แรกเข้ามา จากนั้น service นี้จะทำงานต่อและจัดการ connection ถัดไป การ reload ตามคำสั่งข้างต้นยังเป็นวิธีที่ทำให้การเปลี่ยนแปลงมีผล หาก ssh.service ยังไม่ active ก็ไม่มีอะไรให้ reload และ connection ถัดไปจะเป็นผู้เริ่ม service ด้วยไฟล์ใหม่

ต่อไปให้ดูว่าการเปลี่ยนแปลงนี้ส่งผลอย่างไร client กำลังส่ง key ที่เซิร์ฟเวอร์นี้จะไม่ยอมรับ การเพิ่มเพดานทำให้เซิร์ฟเวอร์ตรวจสอบ key ที่ถูกปฏิเสธได้ 20 รายการต่อ connection แทนที่จะเป็น 6 รายการ สำหรับทุก client ที่เชื่อมต่อและทุกผู้พยายามเดารหัสผ่านบนอินเทอร์เน็ต การตรวจสอบแต่ละรายการทำให้เซิร์ฟเวอร์ต้องค้นหาใน authorized_keys การ login ของคุณเองยังคงช้า เพราะ key ที่ถูกต้องยังอยู่ลำดับสุดท้าย หากเพิ่ม key รายการที่ 13 ลงใน agent คุณก็จะกลับไปมีปัญหาเดิม และต้องเพิ่มตัวเลขให้มากขึ้นอีกครั้ง

ให้เพิ่มค่านี้เฉพาะเมื่อ client ที่ถูกต้องจำเป็นต้องส่งหลาย identity จริง ๆ ในกรณีอื่นให้แก้ไขที่ client แทน การลดค่านี้เป็นแนวทาง hardening ที่เหมาะสม หลังจากผู้ใช้ทุกคน login ด้วย key ที่กำหนดค่าไว้แล้ว เนื่องจากค่าที่น้อยลงทำให้ผู้พยายามเดารหัสผ่านมีจำนวนครั้งต่อ connection ลดลง

เหตุใด fail2ban จึงแบนคุณได้จากกรณีนี้

sshd ไม่ได้บันทึกการปฏิเสธ key ทุกครั้ง ที่ค่าเริ่มต้น LogLevel INFO การปฏิเสธ key สำหรับ account ที่มีอยู่จริงจะถูกเขียนลง log ก็ต่อเมื่อจำนวนครั้งที่การเชื่อมต่อล้มเหลวถึงครึ่งหนึ่งของ MaxAuthTries ซึ่งเป็นความหมายของข้อความในคู่มือที่ว่า “เมื่อจำนวนครั้งที่ล้มเหลวถึงครึ่งหนึ่งของค่านี้ ระบบจะบันทึกความล้มเหลวเพิ่มเติม” หากใช้ค่าเริ่มต้น 6 การส่ง key ที่ถูกปฏิเสธ 3 ครั้งแรกจะไม่ถูกเขียนลง log ส่วน 3 ครั้งสุดท้ายจะแสดงเป็นบรรทัดลักษณะนี้ และตามด้วยบรรทัด maximum authentication attempts exceeded:

Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...

บรรทัดเหล่านี้ดูเหมือนเป็นความล้มเหลวหลายครั้ง แต่ filter sshd ของ fail2ban ไม่ได้นับบรรทัดเหล่านี้ ค่าเริ่มต้นที่มากับระบบคือ publickey = nofail โดยจะอ่านบรรทัด Failed publickey สำหรับผู้ใช้ที่ถูกต้อง เพื่อดึง address และ user name เท่านั้น บรรทัดที่ใช้ในการนับคือ maximum authentication attempts exceeded ดังนั้นการเชื่อมต่อหนึ่งครั้งที่ถึงขีดจำกัดจะเพิ่มความล้มเหลว 1 ครั้ง ไม่ใช่หลายครั้ง jail จะแบน source address เมื่อมีความล้มเหลว maxretry ครั้งเกิดขึ้นภายในช่วงเวลา findtime และ jail.conf ของ fail2ban เองจะกำหนดค่าเหล่านี้เป็น 5 และ 10 minutes การเชื่อมต่อล้มเหลวประมาณ 5 ครั้งภายใน 10 minutes ก็เพียงพอให้ address ของคุณถูกแบน และ script หรือเครื่องมือที่ retry เป็น loop จะถึงขีดจำกัดนี้อย่างรวดเร็ว

จากนั้นอาการจะเปลี่ยนไป และนี่คือส่วนที่ทำให้เกิดความสับสน คุณจะไม่เห็นข้อความ “Too many authentication failures” อีกต่อไป แต่จะไม่เห็นอะไรเลย การเชื่อมต่อจะค้างและหมดเวลาในที่สุด เพราะ firewall กำลัง drop packet ของคุณแทนที่จะตอบกลับ timeout ในกรณีที่ก่อนหน้านี้เคยได้รับข้อความ error คือสัญญาณสำคัญ และความแตกต่างนี้อธิบายไว้ใน SSH connection refused เทียบกับ connection timed out

จาก console ของ provider หรือจาก address อื่น ให้ตรวจสอบ jail และยกเลิกการแบน:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10

ใส่ address ของคุณเองใน ignoreip ภายใน jail.local ระหว่างที่แก้ไขปัญหาของ client จากนั้นนำ address ดังกล่าวออกเมื่อดำเนินการเสร็จ jail นี้ตั้งค่าไว้ใน คู่มือ fail2ban สำหรับ Ubuntu 24.04

สิ่งที่ควรทำเพียงครั้งเดียวเพื่อป้องกันไม่ให้ปัญหานี้เกิดขึ้นอีก

กำหนดให้เซิร์ฟเวอร์แต่ละเครื่องมีบล็อก Host เป็นของตัวเองในไฟล์ ~/.ssh/config โดยระบุค่า HostName, User, IdentityFile และ IdentitiesOnly yes หลังจากนั้น การใช้คำสั่ง ssh vps จะพิมพ์ได้สั้นลง โดยจะระบุคีย์เพียงคีย์เดียวเท่านั้น และจะไม่ทำให้เกิดข้อผิดพลาด MaxAuthTries ไม่ว่า ssh -v ของคุณจะมีข้อมูลมากเพียงใดก็ตาม นอกจากนี้ยังช่วยให้ผลลัพธ์ของ ssh -v สั้นพอที่จะอ่านได้ง่ายในวันที่เกิดปัญหาอื่นขึ้น

FAQ

จะแก้ปัญหา "Too many authentication failures" ตอนนี้ได้อย่างไร

ระบุ key เพียงรายการเดียวแทนการส่งทั้งหมด หากต้องการเชื่อมต่อทันที ให้เรียกใช้ ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host หากต้องการแก้ไขถาวร ให้เพิ่ม block ใน ~/.ssh/config โดยใช้ HostName, User และ IdentityFile ให้ชี้ไปยัง key ดังกล่าว แล้วใช้ IdentitiesOnly yes จากนั้นเรียกใช้ chmod 600 ~/.ssh/config ตรวจสอบด้วย ssh -v โดยควรเห็นบรรทัด Offering public key: เพียง 1 บรรทัดสำหรับ host ดังกล่าว

เหตุใด ssh -i ยังคงส่ง key รายการอื่น

เนื่องจาก -i เพิ่ม identity เข้าไปในรายการ แต่ไม่ได้จำกัดรายการนั้น key ที่โหลดอยู่ใน ssh-agent ยังคงอยู่ในรายการและยังถูกส่งไป โดยมักถูกส่งก่อน key ของคุณ ดังนั้น server อาจพบ MaxAuthTries ก่อนที่จะมาถึง key ของคุณ -o IdentitiesOnly=yes เป็น option ที่จำกัด ssh ให้ใช้เฉพาะ identity ที่คุณระบุ ใช้ -i และ -o IdentitiesOnly=yes ร่วมกัน หรือใช้ -o IdentityAgent=none เพื่อไม่ใช้ agent สำหรับการเชื่อมต่อครั้งนั้นเลย

ควรเพิ่ม MaxAuthTries บน server เพื่อแก้ปัญหานี้หรือไม่

ไม่ควร ในเกือบทุกกรณี client กำลังส่ง key ที่ server นี้ไม่มีทางยอมรับ การเพิ่มขีดจำกัดทำให้ server ตรวจสอบข้อเสนอที่ถูกปฏิเสธมากขึ้นต่อการเชื่อมต่อหนึ่งครั้ง สำหรับ client ทุกเครื่องและทุกความพยายาม brute force ที่มาถึง server ปัญหานี้จะเกิดขึ้นอีกทันทีเมื่อมี key เพิ่มเข้ามาใน agent ของคุณ ตรวจสอบค่าที่มีผลจริงด้วย sudo sshd -T | grep -i maxauthtries หากต้องการดูรายละเอียด จากนั้นแก้ไขฝั่ง client ด้วย IdentitiesOnly

เหตุใดปัญหานี้จึงเริ่มเกิดกับ server ที่เมื่อเดือนที่แล้วยังทำงานปกติ

agent ของคุณมี key มากขึ้น AddKeysToAgent yes ใน ~/.ssh/config จะโหลด key ทุกตัวที่คุณใช้งานไว้ และ desktop keyring agent จะโหลด key เองเมื่อ login เมื่อจำนวน key ที่โหลดไว้มากกว่า MaxAuthTries ของ server server ใดก็ตามที่ key ของคุณอยู่ลำดับท้ายในลำดับการส่งจะเริ่มเชื่อมต่อไม่สำเร็จ เรียกใช้ ssh-add -l แล้วเปรียบเทียบจำนวนกับขีดจำกัดบน server

ปัญหานี้ทำให้ fail2ban แบน IP address ของฉันได้หรือไม่

ได้ แม้จะเกิดช้ากว่าที่ server log แสดงให้เห็น filter sshd เริ่มต้นของ fail2ban จะไม่นับบรรทัด Failed publickey สำหรับ user ที่ถูกต้อง แต่จะนับบรรทัด maximum authentication attempts exceeded ดังนั้นการเชื่อมต่อแต่ละครั้งที่ถึงขีดจำกัดจะนับเป็น 1 failure เมื่อใช้ค่าเริ่มต้นที่มากับระบบคือ maxretry = 5 และ findtime = 10m การเชื่อมต่อในลักษณะนี้ประมาณ 5 ครั้งภายใน 10 นาทีจะทำให้ address ของคุณถูกแบน สัญญาณที่สังเกตได้คือ error จะเปลี่ยนเป็นการค้าง แล้วตามด้วย timeout เนื่องจาก packet ถูกทิ้งแทนที่จะได้รับการตอบกลับ ล้างการแบนจาก console ด้วย sudo fail2ban-client set sshd unbanip <your address> และแก้ไข client ก่อนเชื่อมต่ออีกครั้ง

#ssh#ssh-agent#openssh#ssh-config#troubleshooting