ตั้ง Two-Factor Authentication (2FA) สำหรับ SSH

ตั้ง Two-Factor Authentication (2FA) สำหรับ SSH

มิถุนายน 2026 · อ่าน 7 นาที

Password เพียงอย่างเดียวไม่เพียงพอสำหรับการป้องกัน SSH ถ้า password หลุดหรือถูก brute force ได้ VPS จะตกเป็นของผู้ไม่หวังดีทันที การเพิ่ม 2FA (Two-Factor Authentication) ด้วย TOTP (Time-based One-Time Password) ทำให้แม้ password หลุดก็เข้าไม่ได้หากไม่มี device

สำคัญ: เปิด SSH session ไว้อีกอันเสมอตลอดการตั้งค่า ถ้า config ผิดพลาดจะได้แก้ไขได้โดยไม่ถูก lock out

ติดตั้ง Google Authenticator PAM

sudo apt update
sudo apt install libpam-google-authenticator -y

# ตั้งค่า TOTP สำหรับ user ปัจจุบัน
google-authenticator

ตอบคำถามที่ถาม:

จด QR code (scan ด้วย Google Authenticator app) และ backup codes ทั้ง 5 โค้ดเก็บไว้ในที่ปลอดภัย

ตั้งค่า PAM สำหรับ SSH

sudo nano /etc/pam.d/sshd
# เพิ่มบรรทัดนี้หลัง @include common-auth
auth required pam_google_authenticator.so
sudo nano /etc/ssh/sshd_config
# แก้หรือเพิ่มบรรทัดเหล่านี้
ChallengeResponseAuthentication yes
# หรือใน SSH เวอร์ชันใหม่:
KbdInteractiveAuthentication yes

UsePAM yes

# ถ้าต้องการทั้ง SSH key และ 2FA:
AuthenticationMethods publickey,keyboard-interactive
# Restart SSH daemon
sudo systemctl restart ssh

# ทดสอบใน terminal ใหม่ (อย่าปิด session เดิม)
ssh user@YOUR_VPS_IP

ให้ SSH Key ข้ามขั้นตอน 2FA (Optional)

ถ้าต้องการให้ SSH key bypass 2FA ได้ (สะดวกกว่า แต่ security น้อยกว่า):

sudo nano /etc/pam.d/sshd

# แก้บรรทัดที่เพิ่มเป็น:
auth required pam_google_authenticator.so nullok
sudo nano /etc/ssh/sshd_config

# ตั้ง AuthenticationMethods ให้รองรับทั้งสอง mode
AuthenticationMethods publickey publickey,keyboard-interactive
Tip: ถ้าใช้ automation scripts หรือ CI/CD ที่ต้องการ SSH key โดยไม่มี 2FA ให้สร้าง user แยกสำหรับ automation และตั้ง Match User deploybot block ใน sshd_config เพื่อข้าม 2FA เฉพาะ user นั้น

ตรวจสอบว่า 2FA ทำงานถูกต้อง

# ตรวจ sshd config syntax
sudo sshd -t

# ตรวจสถานะ SSH service
systemctl status ssh

# ทดสอบ login ใหม่ (ต้องถามทั้ง password และ OTP code)
ssh -v user@YOUR_VPS_IP

# ตรวจว่า PAM module โหลด
grep google-authenticator /var/log/auth.log | tail -10
Tip: ถ้า login สำเร็จโดยไม่ถาม OTP แสดงว่า config ยังไม่ถูกต้อง ตรวจ /etc/pam.d/sshd และ /etc/ssh/sshd_config อีกรอบ

แก้ปัญหาที่พบบ่อย

SSH ไม่ถาม Verification Code เลย

ChallengeResponseAuthentication ยังเป็น no หรือ PAM ไม่ได้ include google-authenticator:

# ตรวจ sshd_config
grep -i "ChallengeResponse\|KbdInteractive\|UsePAM" /etc/ssh/sshd_config

# ตรวจ PAM
grep -n "google-authenticator" /etc/pam.d/sshd

# อ่าน journal หลัง login
sudo journalctl -u ssh -n 30

ถูก Lock Out ทั้งที่รู้ code ถูกต้อง

เวลาของ VPS กับ phone ต่างกันเกิน 30 วินาที ต้อง sync NTP ก่อน:

# ตรวจเวลา server
date
timedatectl

# Sync NTP
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncd

google-authenticator file หาย หรือ reinstall phone

ไฟล์ ~/.google_authenticator เก็บ secret key ถ้าหายต้องสร้างใหม่:

# สร้างใหม่ (ต้อง scan QR code ใน app อีกรอบ)
google-authenticator

# ถ้า lock out ทั้งหมด ต้องเข้าผ่าน VPS console (KVM)
# แล้วปิด 2FA ชั่วคราวเพื่อ recovery

Backup codes ทั้งหมดถูกใช้หมดแล้ว

สร้าง backup codes ใหม่โดย regenerate google-authenticator แต่ต้อง scan QR ใน app ใหม่ด้วย:

# เปิด file แก้ backup codes โดยตรง (บรรทัดที่ขึ้นต้นด้วย 8 ตัวเลข)
nano ~/.google_authenticator
# หรือ regenerate ทั้งหมด
google-authenticator -f -t -d -r 3 -R 30 -w 3

คำถามที่พบบ่อย

2FA กับ SSH key ต่างกันอย่างไร ควรใช้อันไหน?

SSH key ป้องกัน brute force ได้ดีมากเพราะ key ยาวมาก แต่ถ้า private key หลุดออกไปก็เข้าได้เลย 2FA เพิ่มชั้นป้องกันที่ต้องมี device ด้วย ในอุดมคติควรใช้ทั้งสองอย่างพร้อมกัน: SSH key + 2FA

TOTP กับ HOTP ต่างกันอย่างไร?

TOTP (Time-based OTP) สร้าง code ใหม่ทุก 30 วินาที ใช้เวลาเป็น input HOTP (HMAC-based OTP) ใช้ counter แทน เพิ่มทีละ 1 ทุกครั้งที่ใช้ TOTP นิยมกว่าเพราะ code หมดอายุเองอัตโนมัติ

ถ้าโทรศัพท์หายจะ lock out ไหม?

ใช่ ถ้าไม่มี backup codes จะ lock out หากโทรศัพท์หาย ทางออกคือ: 1) เก็บ backup codes ไว้นอกเครื่อง 2) เปิด 2FA บน device 2 เครื่อง 3) เก็บ secret key (.google_authenticator) ไว้ใน password manager