SFTP server setup บน VPS ด้วย OpenSSH

ตั้งค่า SFTP Server บน VPS ให้ปลอดภัย: OpenSSH + Chroot

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

SFTP (SSH File Transfer Protocol) คือ protocol สำหรับโอนไฟล์ที่ทำงานบน SSH ปลอดภัยกว่า FTP ทั่วไปมาก เพราะข้อมูลถูกเข้ารหัสทั้งหมด ไม่ต้องติดตั้ง daemon แยก ใช้ OpenSSH ที่มีอยู่แล้วบน VPS และตั้งค่า chroot jail เพื่อจำกัดผู้ใช้ให้เข้าถึงได้เฉพาะโฟลเดอร์ที่กำหนด

หลักการทำงานของ SFTP Chroot

เมื่อ user เชื่อมต่อ SFTP แบบ chroot user จะ "ถูกขัง" อยู่ใน directory ที่กำหนด ไม่สามารถ cd ออกไปข้างนอกได้เลย เหมาะสำหรับ:

สร้าง SFTP User พร้อม Chroot

# 1. สร้าง group สำหรับ SFTP users
groupadd sftpusers

# 2. สร้าง user ที่เข้าถึงได้เฉพาะ SFTP (ไม่มี shell login)
useradd -g sftpusers -d /sftp/webdeploy -s /sbin/nologin webdeploy

# 3. ตั้ง password (หรือใช้ SSH key แทน)
passwd webdeploy

# 4. สร้าง chroot directory (root ต้องเป็น root:root และ permission 755 เท่านั้น)
mkdir -p /sftp/webdeploy/www
chown root:root /sftp/webdeploy
chmod 755 /sftp/webdeploy

# โฟลเดอร์ที่ user เขียนได้
chown webdeploy:sftpusers /sftp/webdeploy/www
chmod 755 /sftp/webdeploy/www
Chroot directory ต้อง owned by root: ถ้า chroot dir เป็นของ user หรือ group ที่ไม่ใช่ root OpenSSH จะปฏิเสธ chroot และ user จะ login ไม่ได้ นี่คือข้อผิดพลาดที่พบบ่อยที่สุด

ตั้งค่า sshd_config

nano /etc/ssh/sshd_config
# ท้ายไฟล์ เพิ่ม block นี้
Match Group sftpusers
    ChrootDirectory /sftp/%u
    ForceCommand internal-sftp
    AllowTcpForwarding no
    X11Forwarding no
    PasswordAuthentication yes
# ตรวจสอบ syntax
sshd -t

# Reload (ไม่ต้อง restart ซึ่งจะ drop connection ที่มีอยู่)
systemctl reload sshd

ใช้ SSH Key แทน Password (แนะนำ)

# บน client machine สร้าง key pair
ssh-keygen -t ed25519 -f ~/.ssh/sftp_webdeploy -N ""

# วาง public key บน server
mkdir -p /sftp/webdeploy/.ssh
cat ~/.ssh/sftp_webdeploy.pub >> /sftp/webdeploy/.ssh/authorized_keys
chown -R webdeploy:sftpusers /sftp/webdeploy/.ssh
chmod 700 /sftp/webdeploy/.ssh
chmod 600 /sftp/webdeploy/.ssh/authorized_keys
authorized_keys ใน chroot: ต้องอยู่ใน /sftp/webdeploy/.ssh/ เพราะ OpenSSH มองจาก chroot root ไม่ใช่ /home/webdeploy/.ssh/ — ต้องตั้ง AuthorizedKeysFile .ssh/authorized_keys ใน sshd_config ด้วย
# เพิ่มใน sshd_config (ก่อน Match block)
AuthorizedKeysFile .ssh/authorized_keys %h/.ssh/authorized_keys

ทดสอบ SFTP Connection

# ทดสอบด้วย password
sftp webdeploy@YOUR_VPS_IP

# ทดสอบด้วย SSH key
sftp -i ~/.ssh/sftp_webdeploy webdeploy@YOUR_VPS_IP

# คำสั่งใน SFTP shell
sftp> ls
sftp> cd www
sftp> put localfile.html
sftp> get remotefile.html
sftp> bye
# ทดสอบว่า user ออกนอก chroot ไม่ได้
sftp> cd ..
sftp> pwd
# ควรแสดง / (root ของ chroot ไม่ใช่ root จริง)

เพิ่ม SFTP User สำหรับลูกค้าหลายคน

#!/bin/bash
# สร้าง SFTP user ใหม่แบบ batch
create_sftp_user() {
  local USERNAME="$1"
  local PASSWORD="$2"

  useradd -g sftpusers -d "/sftp/${USERNAME}" -s /sbin/nologin "$USERNAME"
  echo "${USERNAME}:${PASSWORD}" | chpasswd

  mkdir -p "/sftp/${USERNAME}/upload"
  chown root:root "/sftp/${USERNAME}"
  chmod 755 "/sftp/${USERNAME}"
  chown "${USERNAME}:sftpusers" "/sftp/${USERNAME}/upload"
  chmod 755 "/sftp/${USERNAME}/upload"

  echo "Created SFTP user: $USERNAME"
}

create_sftp_user "client_a" "SecurePass1!"
create_sftp_user "client_b" "SecurePass2!"

Monitor SFTP Activity

# ดู login ของ SFTP users
grep "subsystem request for sftp" /var/log/auth.log

# จำนวน connection ปัจจุบัน
ss -tnp | grep ':22'

# ไฟล์ที่ถูก upload ล่าสุด
find /sftp -newer /tmp/.lastcheck -type f -ls

ตั้ง Fail2ban สำหรับ SFTP

# สร้าง jail สำหรับ sftp (ใช้ rule เดิมกับ sshd)
nano /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
systemctl reload fail2ban

SFTP ที่ตั้งค่าถูกต้องด้วย chroot + SSH key เป็นวิธี deploy ไฟล์ที่ปลอดภัยและใช้งานได้จริงในระดับ production — ไม่ต้องพึ่ง FTP ที่ส่งข้อมูลแบบ plain text หรือ password authentication ที่เสี่ยง brute force

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

# ทดสอบ SFTP connection (จาก client)
sftp -i ~/.ssh/sftp_webdeploy webdeploy@YOUR_VPS_IP

# ทดสอบว่า chroot ทำงาน — ไม่ควรออกนอกไดเรกทอรีได้
sftp> pwd
sftp> cd ..
sftp> pwd
# ทั้งสองคำสั่งควรแสดง / (root ของ chroot ไม่ใช่ root จริง)

# ดู log การเชื่อมต่อ
grep "sftp" /var/log/auth.log | tail -20

# ตรวจสอบ sshd_config syntax
sshd -t && echo "Config OK"
Tip: ทดสอบด้วย sftp -v (verbose) เพื่อดู debug log ระหว่าง connection — จะแสดงทุก step รวมถึงเหตุผลที่ authentication ล้มเหลว

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

Error: "subsystem request for sftp failed on channel 0"

เกิดจาก chroot directory ไม่ได้ owned by root:root หรือ permission ไม่ใช่ 755 ซึ่งเป็น requirement ของ OpenSSH:

# ตรวจสอบ ownership ของ chroot dir
ls -la /sftp/
# ต้องเป็น: drwxr-xr-x root root /sftp/webdeploy

# แก้ไข
chown root:root /sftp/webdeploy
chmod 755 /sftp/webdeploy
systemctl reload sshd

Error: "Permission denied (publickey,password)" ทั้งที่ใส่ key ถูก

ใน chroot environment authorized_keys ต้องอยู่ที่ตำแหน่งพิเศษ ไม่ใช่ /home/user/.ssh/:

# ตรวจสอบตำแหน่ง authorized_keys
ls -la /sftp/webdeploy/.ssh/authorized_keys
# ต้องมีไฟล์นี้อยู่

# ตรวจสอบ permission
stat /sftp/webdeploy/.ssh/authorized_keys
# ต้องเป็น: 600 (rw-------)

# ตรวจสอบ AuthorizedKeysFile ใน sshd_config
grep AuthorizedKeysFile /etc/ssh/sshd_config

Error: SFTP login ได้แต่ไม่สามารถ upload ไฟล์ ("Permission denied")

โฟลเดอร์ที่ต้องการ upload ต้องเป็น owned by user ที่ใช้ login ไม่ใช่ root:

# ตรวจสอบ ownership ของโฟลเดอร์ upload
ls -la /sftp/webdeploy/
# www/ ต้องเป็นของ webdeploy:sftpusers

# แก้ไข
chown webdeploy:sftpusers /sftp/webdeploy/www
chmod 755 /sftp/webdeploy/www

Error: "Bad owner or modes for /sftp/webdeploy/.ssh"

OpenSSH ต้องการให้ .ssh directory เป็น owned by user และ permission 700 เท่านั้น:

chown webdeploy:sftpusers /sftp/webdeploy/.ssh
chmod 700 /sftp/webdeploy/.ssh
chmod 600 /sftp/webdeploy/.ssh/authorized_keys
systemctl reload sshd

Error: user สามารถ SSH login แบบ shell ได้ ทั้งที่ตั้ง nologin

ต้องตรวจสอบว่า ForceCommand internal-sftp อยู่ใน Match block ของ sshd_config และ Match block ครอบ user กลุ่มนี้ถูกต้อง:

grep -A6 "Match Group sftpusers" /etc/ssh/sshd_config
# ต้องมี: ForceCommand internal-sftp

# ทดสอบ
ssh webdeploy@YOUR_VPS_IP
# ควรได้รับ: "This service allows sftp connections only." แล้ว disconnect ทันที

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

SFTP ต่างจาก FTP และ FTPS อย่างไร?

FTP คือ protocol เก่าที่ส่งข้อมูลและ password แบบ plain text ไม่ปลอดภัย, FTPS คือ FTP ที่เพิ่ม SSL/TLS ต้องจัดการ certificate แยก, SFTP (SSH File Transfer Protocol) ทำงานบน SSH ที่มีอยู่แล้ว เข้ารหัสทุกอย่างโดยอัตโนมัติ ใช้ port 22 เดียวกับ SSH และตั้งค่าง่ายกว่ามาก

ใช้ FileZilla หรือ WinSCP เชื่อมต่อ SFTP server นี้ได้ไหม?

ได้เลย ทั้ง FileZilla และ WinSCP รองรับ SFTP protocol ตั้ง Protocol เป็น "SFTP – SSH File Transfer Protocol" ใส่ host, port 22, username และ private key ไฟล์ (PPK สำหรับ WinSCP หรือ OpenSSH format สำหรับ FileZilla) ก็เชื่อมต่อได้ทันที

จะ monitor ว่ามีใคร upload ไฟล์อะไรได้อย่างไร?

ดูได้จาก auth.log: grep "Accepted\|sftp" /var/log/auth.log จะแสดง login timestamp และ IP ส่วนไฟล์ที่ upload ไม่มี log โดยตรง ต้องใช้ inotifywait หรือตั้ง auditd เพื่อ monitor filesystem event ใน /sftp/ directory