คำตอบสั้น ๆ: เปิด SSH 2FA บน Linux Server ให้ต้องใช้ทั้ง SSH Key และรหัส 6 หลักจากแอป Authenticator ด้วย libpam-google-authenticator พร้อมรหัสฉุกเฉินและวิธีไม่ล็อกตัวเองออก
คู่มือนี้อธิบาย SSH 2FA ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
SSH 2FA คือการให้ผู้ดูแลยืนยันตัวตนสองชั้นก่อนเข้าเซิร์ฟเวอร์ ชั้นแรกคือ SSH Key ชั้นที่สองคือรหัส 6 หลักที่เปลี่ยนทุก 30 วินาที (TOTP) จากแอปบนมือถือ เช่น Google Authenticator หรือ Microsoft Authenticator ถ้า Private Key หลุดจากโน้ตบุ๊กที่ถูกขโมยหรือติดมัลแวร์ ผู้ไม่หวังดีก็ยังเข้าเครื่องไม่ได้ เพราะไม่มีมือถือของคุณ
คู่มือนี้ใช้โมดูล PAM pam_google_authenticator ทำงานแบบออฟไลน์ทั้งหมด ไม่ส่งข้อมูลไปที่ Google เมื่อจบคุณจะมี SSH 2FA ที่ถาม Key ก่อนแล้วจึงถามรหัส มีรหัสฉุกเฉินเก็บไว้ ยกเว้นบัญชีอัตโนมัติได้ และมีทางเข้าสำรองถ้ามือถือหาย
สิ่งที่ต้องเตรียม
- Linux Server ที่ใช้ Ubuntu 22.04/24.04, Debian 12 หรือ AlmaLinux/Rocky Linux 9 ที่เข้าด้วย SSH Key ได้แล้ว (ดู ตั้งค่า SSH Key)
- แอป Authenticator ที่รองรับ TOTP บนมือถือ
- ช่องทางสำรองที่ทดสอบแล้วว่าใช้ได้ เช่น Console ผ่านหน้าเว็บของผู้ให้บริการ (ดู การ Remote เข้า Console ผ่าน Web UI) และรหัสผ่านของผู้ใช้ เพราะ Console ถามรหัสผ่าน ไม่ใช่ Key
- นาฬิกาเครื่องที่ซิงก์เวลาแล้ว คำสั่ง
timedatectlต้องแสดงSystem clock synchronized: yes
คำเตือน: ขั้นตอนนี้แก้วิธีล็อกอิน SSH ให้เปิด Session ที่เป็น root ค้างไว้หนึ่งหน้าต่างตลอดการตั้งค่า และทดสอบด้วยหน้าต่างใหม่เสมอ ห้ามปิดหน้าต่างเดิมจนกว่าจะล็อกอินแบบใหม่สำเร็จ
ขั้นตอนที่ 1: เตรียมทางสำรองก่อนเริ่ม
sudo -i # หน้าต่างนี้เปิดค้างไว้
passwd admin # ตั้งรหัสผ่านไว้ใช้กับ Console
timedatectl | grep synchronized
ก่อนเปิด SSH 2FA ให้ลองเข้า Console ผ่านหน้าเว็บด้วยรหัสผ่านนี้หนึ่งครั้ง ถ้ายังไม่ซิงก์เวลา ให้ตั้งตาม คู่มือซิงก์เวลา ก่อน เพราะ TOTP คำนวณจากเวลา ถ้านาฬิกาคลาดเกินหนึ่งนาที รหัสจะผิดตลอด
ขั้นตอนที่ 2: ติดตั้งโมดูล Google Authenticator สำหรับ PAM
# Ubuntu / Debian
sudo apt update && sudo apt install -y libpam-google-authenticator
# AlmaLinux / Rocky Linux 9
sudo dnf install -y epel-release
sudo dnf install -y google-authenticator qrencode
ขั้นตอนที่ 3: สร้าง Secret และรหัสฉุกเฉินให้ผู้ใช้
รันด้วยผู้ใช้ที่จะล็อกอิน ไม่ใช้ sudo ตัวเลือกด้านล่างคือ TOTP (-t) ห้ามใช้รหัสเดิมซ้ำ (-d) จำกัด 3 ครั้งต่อ 30 วินาที (-r 3 -R 30) และยอมให้เวลาคลาดได้หนึ่งช่วง (-w 3)
# Ubuntu / Debian
google-authenticator -t -d -f -r 3 -R 30 -w 3
# AlmaLinux / Rocky Linux 9: เก็บไว้ใน ~/.ssh เพื่อให้ SELinux อนุญาต
google-authenticator -t -d -f -r 3 -R 30 -w 3 -s ~/.ssh/google_authenticator
restorecon -Rv ~/.ssh
สแกน QR Code ด้วยแอป แล้วพิมพ์รหัส 6 หลักเพื่อยืนยัน โปรแกรมจะแสดงรหัสฉุกเฉิน (Emergency Scratch Code) 5 ชุด แต่ละชุดใช้ได้ครั้งเดียว ให้เก็บใน Password Manager หรือพิมพ์เก็บไว้ ห้ามเก็บไว้บนเซิร์ฟเวอร์เครื่องนี้ ทำซ้ำขั้นตอนนี้กับทุกผู้ใช้ที่ต้องเข้า SSH ก่อนเปิด SSH 2FA ในขั้นตอนถัดไป เพราะผู้ใช้ที่ไม่มีไฟล์ Secret จะเข้าไม่ได้เลย และควรปิด SSH ของ root (PermitRootLogin no) แล้วใช้ sudo แทน
ขั้นตอนที่ 4: ให้ PAM ของ sshd ถามรหัส TOTP
แก้ไฟล์ /etc/pam.d/sshd สิ่งสำคัญคือปิดบรรทัดที่ถามรหัสผ่าน Linux ไม่เช่นนั้นระบบจะถาม Key แล้วตามด้วยรหัสผ่านและรหัส TOTP รวมสามชั้น
# Ubuntu / Debian: ใส่ # หน้าบรรทัดนี้ แล้วเพิ่มบรรทัดใหม่ใต้บรรทัดนั้น
#@include common-auth
auth required pam_google_authenticator.so
# AlmaLinux / Rocky Linux 9: ใส่ # หน้าบรรทัด password-auth แล้วเพิ่ม
#auth substack password-auth
auth required pam_google_authenticator.so secret=/home/${USER}/.ssh/google_authenticator