การยืนยันตัวตนด้วยรหัสผ่านผ่าน SSH คือพื้นผิวที่เปิดกว้างที่สุดของเซิร์ฟเวอร์ธรรมดา ไม่มีทั้ง Fail2ban และเกณฑ์ใดที่ช่วยได้: หนึ่งพันที่อยู่ที่ลองชั่วโมงละครั้งจะไม่มีวันถึงขีดจำกัด และพวกมันจะเดาต่อไปตราบเท่าที่การเดายังเป็นไปได้ คีย์ขจัดความเป็นไปได้นั้นทิ้ง และในบรรดารายการ hardening ทั้งหมด นี่คือการตั้งค่าเดียวที่เปลี่ยนสถานการณ์ในเชิงคุณภาพ
มีเพียงเรื่องเดียวที่น่ากลัวเกี่ยวกับมัน: ปิดรหัสผ่านแล้วติดอยู่ข้างนอก ด้านล่างคือลำดับที่ทำให้สิ่งนั้นเกิดขึ้นไม่ได้
คีย์
สร้างบนเครื่องของคุณเอง ไม่ใช่บนเซิร์ฟเวอร์:
ssh-keygen -t ed25519 -C "work laptop"
ใช้ ed25519 ไม่ใช่ RSA: สั้นกว่า เร็วกว่า และไม่มีคำถามเรื่องความยาว RSA จำเป็นเฉพาะเมื่อต้องเข้าถึงของที่เก่ามาก จากนั้นใช้ -t rsa -b 4096
การตั้ง passphrase ให้คีย์นั้นคุ้มค่า: ไฟล์คีย์อาจถูกขโมยจากแล็ปท็อป และหากไม่มี passphrase มันก็ใช้งานได้ทันที คุณไม่ต้องพิมพ์ทุกครั้ง — ssh-agent จัดการให้ และบน macOS กับ Linux เดสก์ท็อปส่วนใหญ่มันทำงานอยู่แล้ว
การคัดลอกไปยังเซิร์ฟเวอร์ใช้คำสั่งเดียว ขณะที่รหัสผ่านยังใช้ได้:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@203.0.113.25
ถ้าไม่มี ssh-copy-id ให้เพิ่มเนื้อหาของไฟล์ .pub เป็นบรรทัดหนึ่งใน ~/.ssh/authorized_keys บนเซิร์ฟเวอร์ สิทธิ์สำคัญ: ไดเรกทอรี .ssh เป็น 700 ไฟล์เป็น 600 เจ้าของคือผู้ใช้นั้น ถ้าเป็นอย่างอื่น sshd จะปฏิเสธการอ่านไฟล์อย่างเงียบ ๆ และนั่นคือสาเหตุที่พบบ่อยที่สุดของ «คีย์ใช้ไม่ได้»
การตรวจสอบที่ตัดสินทุกอย่าง
ก่อนปิดอะไรก็ตาม ให้เปิดการเชื่อมต่อที่สองโดยไม่ปิดอันแรก:
ssh -o PasswordAuthentication=no user@203.0.113.25
ตัวเลือกนี้ห้ามไคลเอนต์ถอยกลับไปใช้รหัสผ่าน — ดังนั้นถ้าเข้าสู่ระบบได้ ก็แปลว่าเข้าได้ด้วยคีย์ อย่าไปต่อจนกว่าคำสั่งนี้จะใช้งานได้ และเปิดการเชื่อมต่อแรกทิ้งไว้จนถึงที่สุด: มันคือสิ่งที่จะแก้ทุกอย่างที่คุณอาจทำพัง
การปิดรหัสผ่านและกับดักที่มองไม่เห็น
การตั้งค่าไปอยู่ในไฟล์แยกเพื่อไม่ให้การอัปเดตแพ็กเกจเขียนทับ แต่ชื่อไฟล์สำคัญ:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LogLevel VERBOSE
EOF
ประเด็นคือ OpenSSH ใช้ค่าแรกที่พบสำหรับพารามิเตอร์หนึ่ง ไม่ใช่ค่าสุดท้ายอย่างที่เกือบทุกที่เป็น ไฟล์ใน sshd_config.d ถูกอ่านตามลำดับตัวอักษร และอิมเมจคลาวด์ของ Ubuntu วาง 50-cloud-init.conf ไว้ที่นั่น ซึ่งบ่อยครั้งมี PasswordAuthentication yes อยู่ ในสถานการณ์นั้นไฟล์หมายเลข 90 ของคุณจะไม่ทำอะไรเลย: การตั้งค่าดูเหมือนอยู่ในที่ของมันขณะที่รหัสผ่านยังใช้งานได้ต่อไป จึงเป็นที่มาของเลข 10 — มันถูกอ่านก่อน
ดูว่าผลลัพธ์จริงเป็นอย่างไรได้โดยไม่ต้องเดา:
sudo sshd -T | grep -Ei 'passwordauth|permitrootlogin|pubkeyauth'
คำสั่งนี้พิมพ์ไฟล์ตั้งค่าที่มีผลจริงหลังจากรวม include ทั้งหมด เชื่อมัน อย่าเชื่อเนื้อหาของไฟล์
จากนั้นตรวจไวยากรณ์และโหลดบริการใหม่อย่างนุ่มนวล:
sudo sshd -t && sudo systemctl reload ssh
sshd -t เป็นสิ่งบังคับ: การพิมพ์ผิดในไฟล์ตั้งค่าพร้อมกับ restart จะทิ้งบริการให้ดับและคุณอยู่ข้างนอก ส่วน reload ก็ไม่ตัดเซสชันที่เปิดอยู่ด้วย
Ubuntu 24.04: พอร์ตไม่ได้อยู่ตรงที่คุณคิด
กับดักแยกต่างหากบน Ubuntu รุ่นใหม่: ที่นั่น sshd เริ่มทำงานผ่านซ็อกเก็ตของ systemd ในโหมดนั้นบรรทัด Port ใน sshd_config ไม่ทำอะไรเลย — ตัวที่รับฟังคือซ็อกเก็ต ไม่ใช่เดมอน ถ้าคุณจะเปลี่ยนพอร์ต สิ่งที่ต้องแก้คือสิ่งนี้:
sudo systemctl edit ssh.socket
และ ListenStream= (ค่าว่างจะรีเซ็ตค่าเดิม) ต้องระบุพอร์ตใหม่ อาการที่บ่งบอก: แก้ไฟล์ตั้งค่าแล้ว รีสตาร์ตบริการแล้ว แต่เซิร์ฟเวอร์ยังตอบที่ 22
ในเมื่อพูดถึงการเปลี่ยนพอร์ตแล้ว: ในฐานะการป้องกันมันไม่ได้ผล — ตัวสแกนหาบริการบนพอร์ตใดก็ได้ภายในไม่กี่นาที ผลอย่างเดียวของมันคือล็อกที่เงียบขึ้น เพราะการเดารหัสผ่านหมู่จะไปที่ 22 เท่านั้น นั่นสะดวก แต่อย่าสับสนกับความปลอดภัย
ใครมีสิทธิ์เข้าสู่ระบบได้บ้าง
ส่วนเสริมที่มีประโยชน์คือรายชื่อที่ชัดเจน:
AllowUsers deploy admin
ทุกคนที่ไม่อยู่ในรายการจะถูกตัดก่อนที่คีย์จะถูกตรวจด้วยซ้ำ นั่นยังครอบคลุมกรณีที่แพ็กเกจบางตัวสร้างผู้ใช้ระบบพร้อมเชลล์และไดเรกทอรีบ้านด้วย
ทางเข้าสำรอง
คีย์เดียวบนแล็ปท็อปเครื่องเดียวคือจุดล้มเหลวจุดเดียว ดิสก์เสีย แล็ปท็อปหาย แล้วเซิร์ฟเวอร์ก็เข้าไม่ได้ตลอดกาล ขั้นต่ำที่สมเหตุสมผล:
- คีย์ที่สองจากอุปกรณ์อื่นใน
authorized_keys; - สำเนาคีย์ส่วนตัวในตัวจัดการรหัสผ่านหรือบนแฟลชไดรฟ์ที่เข้ารหัส;
- สิทธิ์เข้าถึงคอนโซลของผู้ให้บริการที่ผ่านการทดสอบแล้ว — VNC หรือ serial ผ่านการทดสอบหมายความว่าคุณเคยเข้าผ่านมันอย่างน้อยหนึ่งครั้ง ไม่ใช่ «มีปุ่มอยู่ที่ไหนสักแห่งในแผง»
ในโอกาสเดียวกัน ดูด้วยว่ามีอะไรอยู่ใน authorized_keys แล้วบ้าง — ทั้งของผู้ใช้คุณและของ root คีย์ของคนอื่นที่อยู่ตรงนั้นรอดพ้นการเปลี่ยนรหัสผ่านทุกครั้งและยังคงเป็นสิทธิ์เข้าถึงที่ใช้งานได้
หลังจากนั้น
การเดารหัสผ่านจะไม่หายไป มันเพียงกลายเป็นไร้ประโยชน์: ในล็อกจะยังมีบรรทัด Failed password นับพัน ซึ่งไม่มีบรรทัดใดจบลงด้วยความสำเร็จได้ สิ่งที่ควรเฝ้าดูตอนนี้คือการเข้าสู่ระบบที่สำเร็จ: จากที่อยู่ไหน ในนามผู้ใช้ใด เวลาใด การเข้าสู่ระบบด้วยคีย์สำเร็จจากที่อยู่แปลกหน้าคือเหตุการณ์ที่สำคัญกว่าความล้มเหลวนับล้านครั้งมาก และสังเกตได้ยากกว่ามากในกระแสทั่วไป นั่นคือภาพที่หน้าเดโมด้านล่างแสดง