บทนำ: SSH คือประตูหน้าของเซิร์ฟเวอร์ — ถ้าล็อกไม่ดี ก็จบเกม
SSH (Secure Shell) เป็นเครื่องมือที่ sysadmin ทุกคนใช้ทุกวัน จริงๆ แล้วมันคือ "ประตูหน้า" ของเซิร์ฟเวอร์ Linux ที่เราเข้าไปจัดการทุกอย่าง ปัญหาก็คือ ประตูบานนี้มันถูกเปิดรับทุกคนบนอินเทอร์เน็ต เลยกลายเป็นเป้าโจมตีอันดับหนึ่งของ automated bots และผู้โจมตีจริงๆ ไปโดยปริยาย
จากสถิติในปี 2026 เซิร์ฟเวอร์ที่เปิด port 22 ไว้จะโดนพยายาม brute-force เฉลี่ย หลายพันครั้งต่อวัน เลยนะครับ ผู้โจมตียังเริ่มใช้วิธีซับซ้อนขึ้นด้วย เช่น proxy chains เพื่อซ่อนตัว หรือการติดตั้ง TinyProxy กับ Sing-box บนเซิร์ฟเวอร์ที่ยึดได้เพื่อใช้เป็น proxy node
ข่าวดีก็คือ OpenSSH เวอร์ชันล่าสุด (10.3 ณ เดือนเมษายน 2026) มาพร้อมฟีเจอร์ความปลอดภัยที่ดีมากๆ ไม่ว่าจะเป็น Post-Quantum Key Exchange เป็นค่า default, รองรับ FIDO2 hardware key และ SSH Certificate Authority แต่พูดตรงๆ นะ ฟีเจอร์เหล่านี้ไม่มีประโยชน์เลยถ้าเราไม่รู้จักตั้งค่ามัน
บทความนี้จะพาคุณผ่านทุกขั้นตอนของการ hardening SSH บน Linux ตั้งแต่พื้นฐานไปจนถึง advanced — FIDO2 key, SSH certificates, post-quantum crypto, การตรวจสอบด้วย ssh-audit — ทั้งหมดพร้อมคอนฟิกที่ใช้ได้จริงใน production ครับ
OpenSSH 10.x ในปี 2026: อะไรเปลี่ยนไปบ้าง
Post-Quantum Key Exchange เป็นค่า Default
ฟีเจอร์เด่นสุดของ OpenSSH 10.0 คือการเปลี่ยน default key exchange algorithm เป็น mlkem768x25519-sha256 ซึ่งเป็น hybrid post-quantum/classical algorithm ที่รวม ML-KEM (Module-Lattice Key Encapsulation Mechanism) ตามมาตรฐาน FIPS 203 เข้ากับ X25519 ECDH แบบดั้งเดิม
ทำไมเรื่องนี้ถึงสำคัญ? เพราะ quantum computer ที่ใหญ่พอจะทำลายการเข้ารหัสแบบ classical ได้นั้น คาดว่าจะเกิดขึ้นภายใน 5-20 ปี (ราวกลางทศวรรษ 2030) ผู้โจมตีอาจใช้กลยุทธ์ "harvest now, decrypt later" คือบันทึก traffic ที่เข้ารหัสไว้ก่อน แล้วค่อยถอดรหัสเมื่อ quantum computer พร้อม
การใช้ hybrid key exchange ป้องกันเรื่องนี้ได้ตั้งแต่วันนี้เลย
ตั้งแต่ OpenSSH 10.1 เป็นต้นมา ถ้า connection ไม่ได้ใช้ post-quantum key exchange จะมี warning message โผล่ขึ้นมาด้วย (ปิดได้ด้วย WarnWeakCrypto ถ้ารำคาญ)
ตรวจสอบเวอร์ชันและ algorithm ที่รองรับ
# ตรวจสอบเวอร์ชัน OpenSSH
ssh -V
# ดู key exchange algorithms ที่รองรับ
ssh -Q kex
# ดู ciphers ที่รองรับ
ssh -Q cipher
# ดู MAC algorithms ที่รองรับ
ssh -Q mac
ถ้าเวอร์ชันของคุณต่ำกว่า 10.0 แนะนำให้อัปเดตโดยเร็วเลย เพราะ mlkem768x25519-sha256 จะยังไม่ถูกใช้เป็น default:
# Ubuntu/Debian
sudo apt update && sudo apt upgrade openssh-server openssh-client
# RHEL/Rocky/Alma
sudo dnf update openssh-server openssh-clients
# ตรวจสอบหลังอัปเดต
ssh -V
ปิด Password Authentication: ก้าวแรกที่สำคัญที่สุด
พูดเลยนะครับว่าการปิด password authentication แล้วเปลี่ยนมาใช้ key-based authentication เป็น สิ่งที่สำคัญที่สุด ในการ hardening SSH เลย มันตัด attack vector หลักอย่าง brute-force password guessing ออกไปทั้งหมด
สร้าง SSH Key ด้วย Ed25519
Ed25519 เป็น key type ที่แนะนำในปี 2026 เพราะ key ขนาดเล็ก (256-bit) แต่แข็งแกร่ง สร้างและยืนยันเร็วกว่า RSA มาก แถมมีช่องทาง side-channel attack น้อยกว่าด้วย:
# สร้าง Ed25519 key (แนะนำ)
ssh-keygen -t ed25519 -C "[email protected]"
# ถ้าต้องการ RSA (สำหรับ compatibility กับระบบเก่า)
# ใช้ขนาดอย่างน้อย 4096-bit
ssh-keygen -t rsa -b 4096 -C "[email protected]"
# คัดลอก public key ไปยังเซิร์ฟเวอร์
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
ตั้งค่า sshd_config เพื่อปิด Password
สร้างไฟล์ drop-in configuration จะได้จัดการง่ายและไม่กระทบ config หลัก:
# /etc/ssh/sshd_config.d/01-auth-hardening.conf
# ปิด password authentication ทั้งหมด
PasswordAuthentication no
KbdInteractiveAuthentication no
# เปิด public key authentication
PubkeyAuthentication yes
# ปิดการใช้ empty passwords
PermitEmptyPasswords no
# ปิด root login โดยตรง
PermitRootLogin no
# จำกัดเฉพาะ user/group ที่อนุญาต
AllowGroups ssh-users
# จำกัดจำนวนครั้งที่พยายาม authenticate ต่อ connection
MaxAuthTries 3
# จำกัดจำนวน session พร้อมกัน
MaxSessions 3
คำเตือนสำคัญมาก: ก่อนปิด password authentication ต้องแน่ใจว่า SSH key ของคุณทำงานได้แล้ว และมี console access สำรองไว้เสมอ (เช่น IPMI, KVM, หรือ cloud console) ไม่งั้นอาจ lock ตัวเองออกจากเซิร์ฟเวอร์ — เคยเห็นคนทำพลาดเรื่องนี้มาหลายรายแล้วครับ
# ทดสอบ config ก่อน restart
sudo sshd -t
# ถ้าไม่มี error ให้ restart sshd
sudo systemctl restart sshd
# ทดสอบ login ด้วย key ใน terminal ใหม่ (อย่าปิด session เดิม!)
ssh -i ~/.ssh/id_ed25519 user@server
FIDO2 Hardware Key: Private Key ไม่มีวันหลุดออกจากอุปกรณ์
ทำไมต้อง FIDO2
แม้ SSH key จะปลอดภัยกว่า password มากแล้ว แต่ถ้า private key ยังเก็บเป็นไฟล์บนเครื่อง ก็ยังมีความเสี่ยงที่จะถูกขโมยได้อยู่ดี (เช่น จาก malware หรือ disk ที่ถูก compromise) FIDO2 hardware key อย่าง YubiKey แก้ปัญหาตรงนี้ได้หมดเลย เพราะ:
- Private key ไม่เคยออกจากอุปกรณ์ — การ sign ทั้งหมดเกิดขึ้นภายในตัว hardware key เอง
- ต้องมี physical presence — ต้องแตะอุปกรณ์เพื่อยืนยันทุกครั้ง
- รองรับ PIN verification — เพิ่มอีกชั้นความปลอดภัย (something you know + something you have)
ข้อกำหนดเบื้องต้น
ต้องใช้ OpenSSH 8.2 ขึ้นไป (แนะนำ 8.3+ สำหรับ verify-required) ซึ่งเซิร์ฟเวอร์ Linux ในปี 2026 แทบทุกดิสโทรจะมาพร้อมเวอร์ชันที่รองรับอยู่แล้ว ไม่ต้องห่วงเรื่องนี้
# ตรวจสอบว่า OpenSSH รองรับ FIDO2
ssh -Q key | grep sk
# ควรเห็น: [email protected], [email protected]
สร้าง FIDO2-Backed SSH Key
# สร้าง Ed25519-SK key (แนะนำ)
# -O resident: เก็บ credential บน hardware key (ใช้ข้ามเครื่องได้)
# -O verify-required: ต้องใส่ PIN ทุกครั้งที่ใช้
ssh-keygen -t ed25519-sk -O resident -O verify-required -C "admin@workstation (FIDO2)"
# ถ้า hardware key ไม่รองรับ Ed25519 ให้ใช้ ECDSA
ssh-keygen -t ecdsa-sk -O resident -O verify-required -C "admin@workstation (FIDO2)"
ระบบจะถาม PIN ของ FIDO2 key และให้แตะอุปกรณ์เพื่อยืนยัน จากนั้นจะได้ไฟล์ 2 ไฟล์:
~/.ssh/id_ed25519_sk— key handle (ไม่ใช่ private key จริงๆ นะ ใช้งานไม่ได้โดยไม่มี hardware key)~/.ssh/id_ed25519_sk.pub— public key (คัดลอกไปวางใน authorized_keys ของเซิร์ฟเวอร์)
ใช้ FIDO2 Key ข้ามเครื่อง (Resident Key)
ถ้าสร้าง key ด้วย -O resident สามารถดึง key handle จาก hardware key มาใช้บนเครื่องใหม่ได้เลย สะดวกมาก:
# ดึง resident key จาก FIDO2 device
ssh-keygen -K
# จะสร้างไฟล์ id_ed25519_sk_rk และ id_ed25519_sk_rk.pub ในไดเรกทอรีปัจจุบัน
# ย้ายไปที่ ~/.ssh/
mv id_ed25519_sk_rk* ~/.ssh/
chmod 600 ~/.ssh/id_ed25519_sk_rk
ตั้งค่า Server ให้รับเฉพาะ FIDO2 Key
# /etc/ssh/sshd_config.d/01-auth-hardening.conf (เพิ่มเติม)
# บังคับให้ใช้ key types ที่มี hardware backing เท่านั้น
PubkeyAcceptedAlgorithms [email protected],[email protected],[email protected]
# หรือถ้าต้องการรองรับทั้ง FIDO2 และ Ed25519 ปกติ
# PubkeyAcceptedAlgorithms [email protected],ssh-ed25519,[email protected]
SSH Certificate Authority: บอกลา authorized_keys แบบกระจาย
ปัญหาของ authorized_keys แบบดั้งเดิม
ในองค์กรที่มีเซิร์ฟเวอร์หลายสิบหรือหลายร้อยเครื่อง การจัดการ authorized_keys กลายเป็นฝันร้ายเลยครับ ต้องคัดลอก public key ไปยังทุกเซิร์ฟเวอร์ เมื่อพนักงานลาออกก็ต้องลบ key จากทุกเซิร์ฟเวอร์ แถมไม่มีทางรู้ด้วยว่า key ไหนหมดอายุแล้วหรือยังใช้อยู่
SSH Certificate Authority (CA) แก้ปัญหาเหล่านี้ได้ทั้งหมด
หลักการทำงาน
หลักการง่ายๆ คือ แทนที่จะกระจาย public key ไปทุกเซิร์ฟเวอร์ คุณสร้าง CA key pair หนึ่งชุด แล้วใช้มัน sign user key ให้กลายเป็น certificate เซิร์ฟเวอร์แค่ trust CA public key ตัวเดียว ก็จะยอมรับทุก certificate ที่ CA sign ให้ โดย certificate สามารถกำหนด:
- Validity period — หมดอายุอัตโนมัติ เช่น 8 ชั่วโมง (สั้นมากแต่ปลอดภัยสุด)
- Principals — user ที่ได้รับอนุญาตให้ login เป็น
- Extensions — สิทธิ์เพิ่มเติม เช่น permit-pty, permit-port-forwarding
ตั้งค่า User CA
# สร้าง User CA key pair (ทำครั้งเดียว เก็บรักษาให้ดี!)
ssh-keygen -t ed25519 -f /etc/ssh/user_ca -C "User CA for MyOrg"
# sign user key เป็น certificate
# -s: CA private key
# -I: identity (สำหรับ logging)
# -n: principals (user ที่อนุญาตให้ login เป็น)
# -V: validity period
ssh-keygen -s /etc/ssh/user_ca \
-I "somchai@myorg" \
-n somchai,deploy \
-V +8h \
/home/somchai/.ssh/id_ed25519.pub
# ผลลัพธ์: /home/somchai/.ssh/id_ed25519-cert.pub
ตั้งค่า Server ให้ Trust CA
# คัดลอก CA public key ไปยังเซิร์ฟเวอร์
sudo cp user_ca.pub /etc/ssh/user_ca.pub
# เพิ่มใน sshd_config
# /etc/ssh/sshd_config.d/02-certificate-auth.conf
# Trust User CA
TrustedUserCAKeys /etc/ssh/user_ca.pub
# กำหนด principals ที่อนุญาตต่อ user
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
# สร้างไฟล์ principals สำหรับแต่ละ user
sudo mkdir -p /etc/ssh/auth_principals
# user somchai สามารถ login ได้ด้วย principal "somchai" หรือ "deploy"
echo -e "somchai\ndeploy" | sudo tee /etc/ssh/auth_principals/somchai
# restart sshd
sudo sshd -t && sudo systemctl restart sshd
ตั้งค่า Host CA (กำจัด TOFU Warning)
Host certificate ช่วยให้ client ยืนยันตัวตนของเซิร์ฟเวอร์ได้โดยไม่ต้อง trust-on-first-use (TOFU) ซึ่งแปลว่าจะไม่มี "Are you sure you want to continue connecting?" น่ารำคาญอีกต่อไป:
# สร้าง Host CA key pair
ssh-keygen -t ed25519 -f /etc/ssh/host_ca -C "Host CA for MyOrg"
# sign host key ของเซิร์ฟเวอร์
ssh-keygen -s /etc/ssh/host_ca \
-I "web-server-01.myorg.com" \
-h \
-n "web-server-01.myorg.com,10.0.1.50" \
-V +52w \
/etc/ssh/ssh_host_ed25519_key.pub
# เพิ่มใน sshd_config ของเซิร์ฟเวอร์
# HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
# ฝั่ง client: เพิ่ม Host CA ใน known_hosts
# ~/.ssh/known_hosts (หรือ /etc/ssh/ssh_known_hosts สำหรับ system-wide)
@cert-authority *.myorg.com ssh-ed25519 AAAA...host_ca_public_key...
Hardening Cipher Suite: ใช้เฉพาะ Algorithm ที่แข็งแกร่ง
คอนฟิกที่แนะนำสำหรับปี 2026
เรื่องการเลือก cipher, key exchange และ MAC algorithm ถูกต้องเป็นเรื่องสำคัญมากนะครับ Algorithm ที่อ่อนแอหรือมีช่องโหว่ที่ทราบแล้วควรถูกปิดทั้งหมด ไม่มีเหตุผลให้เปิดค้างไว้:
# /etc/ssh/sshd_config.d/03-crypto-hardening.conf
# === Key Exchange Algorithms ===
# Post-quantum hybrid + strong classical algorithms
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512,curve25519-sha256,[email protected],diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
# === Ciphers ===
# ChaCha20-Poly1305 เป็นตัวเลือกแรก (เร็วบน CPU ที่ไม่มี AES-NI)
# AES-256-GCM สำหรับ CPU ที่มี AES-NI
Ciphers [email protected],[email protected],[email protected]
# === MAC Algorithms ===
# ใช้เฉพาะ Encrypt-then-MAC (-etm) เท่านั้น
MACs [email protected],[email protected],[email protected]
# === Host Key Algorithms ===
HostKeyAlgorithms ssh-ed25519,[email protected],[email protected],[email protected],rsa-sha2-512,rsa-sha2-256
# === บังคับ RSA key ขนาดขั้นต่ำ ===
RequiredRSASize 3072
Harden DH Moduli
ถ้าเซิร์ฟเวอร์ใช้ Diffie-Hellman key exchange ควรลบ moduli ที่มีขนาดเล็กกว่า 3072-bit ออกด้วย ขั้นตอนไม่ยาก:
# สำรอง moduli เดิม
sudo cp /etc/ssh/moduli /etc/ssh/moduli.backup
# เก็บเฉพาะ moduli ที่มีขนาด >= 3072-bit
sudo awk '$5 >= 3071' /etc/ssh/moduli > /tmp/moduli.safe
sudo mv /tmp/moduli.safe /etc/ssh/moduli
sudo chmod 644 /etc/ssh/moduli
สร้าง Host Key ใหม่ที่แข็งแกร่ง
# ลบ host key เก่า
sudo rm /etc/ssh/ssh_host_*
# สร้าง Ed25519 host key (แนะนำเป็นตัวหลัก)
sudo ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
# สร้าง RSA host key ขนาด 4096-bit (สำหรับ compatibility)
sudo ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
# restart sshd
sudo systemctl restart sshd
ป้องกัน Brute-Force ด้วย Fail2Ban และ Rate Limiting
ติดตั้งและตั้งค่า Fail2Ban
แม้จะปิด password authentication แล้ว Fail2Ban ก็ยังมีประโยชน์อยู่นะครับ เพราะช่วยลด log noise และ ban IP ที่พยายามเชื่อมต่อซ้ำๆ ซึ่งกิน resource เซิร์ฟเวอร์โดยไม่จำเป็น ส่วนตัวผมติดตั้งมันบนทุกเซิร์ฟเวอร์ที่ดูแลครับ:
# ติดตั้ง Fail2Ban
sudo apt install fail2ban # Debian/Ubuntu
sudo dnf install fail2ban # RHEL/Rocky/Alma
# สร้าง local config (ไม่แก้ไฟล์หลักเพื่อป้องกันการถูก overwrite ตอน update)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# /etc/fail2ban/jail.d/sshd.conf
[sshd]
enabled = true
port = ssh
backend = systemd
filter = sshd[mode=aggressive]
# Ban 1 ชั่วโมงหลังจากพยายามผิด 3 ครั้ง
maxretry = 3
bantime = 3600
# ดูย้อนหลัง 10 นาที
findtime = 600
# Ban ซ้ำจะเพิ่มเวลาเป็น 2 เท่า
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 86400
# ใช้ nftables แทน iptables (สำหรับระบบที่ใช้ nftables)
banaction = nftables-multiport
banaction_allports = nftables-allports
# เปิดใช้งานและเริ่ม Fail2Ban
sudo systemctl enable --now fail2ban
# ตรวจสอบสถานะ
sudo fail2ban-client status sshd
Rate Limiting ด้วย nftables
เพิ่มอีกชั้นป้องกันด้วย connection rate limiting ที่ระดับ firewall ครับ อันนี้ช่วยป้องกัน DHEat denial-of-service attack ได้ด้วย:
# เพิ่มใน nftables ruleset
# อนุญาตไม่เกิน 10 connections ต่อ 10 วินาทีจาก IP เดียวกัน
nft add rule inet filter input tcp dport 22 ct state new limit rate 10/minute burst 5 packets accept
nft add rule inet filter input tcp dport 22 ct state new drop
การตั้งค่าเสริมเพื่อเพิ่มความปลอดภัย
เปลี่ยน Port และจำกัด Listen Address
ต้องบอกตรงๆ ว่าการเปลี่ยน SSH port ไม่ใช่มาตรการรักษาความปลอดภัยที่แท้จริง มันเป็นแค่ "security through obscurity" เท่านั้น แต่มันช่วยลด automated scanning noise ได้เยอะมากจริงๆ ถ้าใช้ร่วมกับมาตรการอื่นก็คุ้มค่าที่จะทำ:
# /etc/ssh/sshd_config.d/04-network-hardening.conf
# เปลี่ยน port (เลือก port ที่ไม่ซ้ำกับ service อื่น)
Port 2222
# จำกัดให้ listen เฉพาะ IP ที่ต้องการ
ListenAddress 10.0.1.50
ListenAddress 192.168.1.100
# ตั้ง idle timeout
ClientAliveInterval 300
ClientAliveCountMax 2
# ปิด features ที่ไม่จำเป็น
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
# แสดง banner ก่อน login
Banner /etc/ssh/banner.txt
# ใช้ ProxyJump แทน agent forwarding
# (ตั้งค่าฝั่ง client ใน ~/.ssh/config)
# Host production
# HostName 10.0.1.50
# ProxyJump bastion.myorg.com
# User somchai
ตั้งค่า 2FA ด้วย TOTP (สำหรับ High-Security Environment)
สำหรับสภาพแวดล้อมที่ต้องการความปลอดภัยสูงสุด สามารถเพิ่ม TOTP (Time-based One-Time Password) เป็นชั้นที่สามได้ อันนี้อาจจะ overkill สำหรับ homelab แต่สำหรับ production server ที่จัดการข้อมูลสำคัญ ถือว่าคุ้มครับ:
# ติดตั้ง Google Authenticator PAM module
sudo apt install libpam-google-authenticator # Debian/Ubuntu
sudo dnf install google-authenticator # RHEL/Rocky/Alma
# ตั้งค่าสำหรับ user
google-authenticator -t -d -f -r 3 -R 30 -w 3
# /etc/pam.d/sshd — เพิ่มบรรทัดนี้
auth required pam_google_authenticator.so
# /etc/ssh/sshd_config.d/05-2fa.conf
# บังคับให้ใช้ทั้ง key และ TOTP
AuthenticationMethods publickey,keyboard-interactive
KbdInteractiveAuthentication yes
ตรวจสอบอัตโนมัติด้วย ssh-audit
ติดตั้งและใช้งาน ssh-audit
ssh-audit เป็นเครื่องมือที่ดีที่สุดสำหรับตรวจสอบว่า SSH server ตั้งค่าได้ปลอดภัยหรือยัง มันวิเคราะห์ algorithm ทั้งหมดที่เซิร์ฟเวอร์ offer แล้วจัดระดับเป็น pass, warn หรือ fail ให้เลย ใช้งานง่ายมาก:
# ติดตั้ง ssh-audit
pip install ssh-audit
# หรือใช้ Docker
docker run --rm -it ghcr.io/jtesta/ssh-audit:latest target-server:22
# สแกนเซิร์ฟเวอร์
ssh-audit target-server
# สแกนด้วย policy เฉพาะ (เช่น Ubuntu 24.04 LTS)
ssh-audit --policy "Hardened Ubuntu Server 24.04 LTS (version 1)" target-server
สร้าง Script ตรวจสอบอัตโนมัติ
แนะนำให้สร้าง script สำหรับตรวจสอบ SSH configuration เป็นประจำ จะได้ไม่ต้องนั่งรันมือทุกที:
#!/bin/bash
# /usr/local/bin/ssh-security-check.sh
# ตรวจสอบความปลอดภัย SSH อัตโนมัติ
set -euo pipefail
LOG_FILE="/var/log/ssh-security-audit.log"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "=== SSH Security Audit: $TIMESTAMP ===" | tee -a "$LOG_FILE"
# 1. ตรวจสอบเวอร์ชัน OpenSSH
echo "[CHECK] OpenSSH Version:" | tee -a "$LOG_FILE"
ssh -V 2>&1 | tee -a "$LOG_FILE"
# 2. ตรวจสอบ effective config
echo "[CHECK] Password Authentication:" | tee -a "$LOG_FILE"
sshd -T 2>/dev/null | grep -i passwordauthentication | tee -a "$LOG_FILE"
echo "[CHECK] Root Login:" | tee -a "$LOG_FILE"
sshd -T 2>/dev/null | grep -i permitrootlogin | tee -a "$LOG_FILE"
echo "[CHECK] Key Exchange Algorithms:" | tee -a "$LOG_FILE"
sshd -T 2>/dev/null | grep -i kexalgorithms | tee -a "$LOG_FILE"
# 3. ตรวจสอบ permissions
echo "[CHECK] SSH config file permissions:" | tee -a "$LOG_FILE"
stat -c "%a %U:%G %n" /etc/ssh/sshd_config | tee -a "$LOG_FILE"
echo "[CHECK] Host key permissions:" | tee -a "$LOG_FILE"
stat -c "%a %U:%G %n" /etc/ssh/ssh_host_*_key 2>/dev/null | tee -a "$LOG_FILE"
# 4. ตรวจสอบ Fail2Ban status
echo "[CHECK] Fail2Ban SSHD jail:" | tee -a "$LOG_FILE"
fail2ban-client status sshd 2>/dev/null | tee -a "$LOG_FILE" || echo "Fail2Ban not active" | tee -a "$LOG_FILE"
# 5. รัน ssh-audit (ถ้าติดตั้งแล้ว)
if command -v ssh-audit &>/dev/null; then
echo "[CHECK] ssh-audit scan:" | tee -a "$LOG_FILE"
ssh-audit localhost 2>&1 | tail -20 | tee -a "$LOG_FILE"
fi
echo "=== Audit Complete ===" | tee -a "$LOG_FILE"
# ให้สิทธิ์ execute และตั้ง cron
sudo chmod +x /usr/local/bin/ssh-security-check.sh
# ตรวจสอบทุกสัปดาห์ วันจันทร์ 06:00
echo "0 6 * * 1 root /usr/local/bin/ssh-security-check.sh" | sudo tee /etc/cron.d/ssh-security-audit
สรุป: Checklist การ Hardening SSH ฉบับสมบูรณ์
มาถึงจุดสำคัญแล้วครับ นี่คือ checklist ที่คุณสามารถใช้ตรวจสอบว่า SSH server ได้รับการ hardening อย่างครบถ้วนหรือยัง:
| รายการ | ระดับความสำคัญ | สถานะ |
|---|---|---|
| อัปเดต OpenSSH เป็นเวอร์ชันล่าสุด (10.x) | วิกฤต | ☐ |
| ปิด Password Authentication | วิกฤต | ☐ |
| ใช้ Ed25519 key หรือ FIDO2 key | วิกฤต | ☐ |
| ปิด Root Login | วิกฤต | ☐ |
| ตั้งค่า cipher suite ที่แข็งแกร่ง | สูง | ☐ |
| ลบ DH moduli ขนาดเล็ก | สูง | ☐ |
| ติดตั้ง Fail2Ban | สูง | ☐ |
| ตั้ง AllowGroups/AllowUsers | สูง | ☐ |
| ตั้งค่า SSH Certificate Authority | ปานกลาง | ☐ |
| เปิดใช้ FIDO2 hardware key | ปานกลาง | ☐ |
| เปลี่ยน SSH port | ปานกลาง | ☐ |
| ตั้ง idle timeout | ปานกลาง | ☐ |
| ปิด X11/Agent/TCP forwarding | ปานกลาง | ☐ |
| เพิ่ม 2FA (TOTP) | ปานกลาง | ☐ |
| ตรวจสอบด้วย ssh-audit เป็นประจำ | ต่อเนื่อง | ☐ |
สิ่งที่อยากเน้นย้ำคือ การ hardening SSH ไม่ใช่สิ่งที่ทำครั้งเดียวแล้วลืมไปได้ ควร audit เป็นประจำอย่างน้อยทุกสัปดาห์ และอัปเดต OpenSSH ทันทีเมื่อมี security patch ใหม่ออกมา
สำหรับองค์กรที่ต้องการ automate ทั้งหมดนี้ ลองดู Ansible, Puppet หรือ Chef สำหรับจัดการ SSH config ข้าม fleet ได้ครับ มันจะช่วยให้ทุกเซิร์ฟเวอร์มี config ที่ consistent และอัปเดตง่ายขึ้นมากเลย
คำถามที่พบบ่อย (FAQ)
ถ้าปิด Password Authentication แล้วทำ SSH Key หาย จะ lock ตัวเองออกไหม?
ใช่ เป็นไปได้ครับ ดังนั้นก่อนปิด password authentication ต้องแน่ใจว่ามี console access สำรองไว้เสมอ เช่น IPMI, KVM, หรือ cloud provider console นอกจากนี้ควรเก็บ backup key ไว้ในที่ปลอดภัย (เช่น password manager หรือ hardware security key ตัวที่สอง) จะได้ไม่ต้องตื่นตระหนกตอนตี 3
Post-Quantum Key Exchange ทำให้ SSH ช้าลงไหม?
แทบไม่รู้สึกเลยครับ key exchange เกิดขึ้นแค่ตอนเริ่มต้น connection เท่านั้น ไม่ได้กระทบ throughput ของ data transfer หลังจากนั้น จากการทดสอบ mlkem768x25519-sha256 เพิ่มเวลา handshake เพียงไม่กี่ millisecond ผู้ใช้ทั่วไปจะไม่รู้สึกแตกต่างเลย
FIDO2 Key กับ SSH Key ปกติต่างกันอย่างไร?
SSH key ปกติเก็บ private key เป็นไฟล์บนดิสก์ ถ้าเครื่องถูก compromise ผู้โจมตีอาจขโมยไฟล์นี้ได้ ส่วน FIDO2 key จะทำการ sign ภายในตัว hardware เอง private key ไม่เคยออกจากอุปกรณ์ และต้องมีการแตะ (physical presence) ทุกครั้งที่ใช้งาน แม้เครื่องจะถูก compromise ก็ไม่สามารถใช้ key ได้โดยไม่มีอุปกรณ์จริงอยู่ในมือ
ยังจำเป็นต้องติดตั้ง Fail2Ban ไหม ถ้าปิด Password Authentication แล้ว?
แนะนำอย่างยิ่งว่าควรติดตั้งครับ แม้จะปิด password แล้ว Fail2Ban ยังช่วยลด log noise, บล็อก IP ที่พยายามเชื่อมต่อซ้ำๆ ซึ่งสิ้นเปลือง resource และป้องกันกรณีที่ configuration ถูกเปลี่ยนกลับโดยไม่ตั้งใจ (เรื่องนี้เกิดบ่อยกว่าที่คิดนะ) นอกจากนี้ยังช่วยป้องกัน DoS จากการพยายาม key exchange จำนวนมากอีกด้วย
SSH Certificate มีข้อเสียอะไรบ้าง?
ข้อเสียหลักคือความซับซ้อนในการจัดการ CA key ที่ต้องรักษาความปลอดภัยอย่างสูงสุด ถ้า CA private key ถูกขโมย ผู้โจมตีสามารถ sign certificate ปลอมได้เลย นอกจากนี้ OpenSSH ยังไม่มี built-in revocation mechanism ที่ดีนัก (ต้องใช้ KRL — Key Revocation List) และต้องมีกระบวนการ renew certificate ก่อนหมดอายุด้วย สำหรับทีมเล็กๆ ที่มีเซิร์ฟเวอร์ไม่กี่เครื่อง authorized_keys อาจจะง่ายกว่าและเพียงพอแล้วครับ