/static/codemoomoo2.png

บทที่ 3. Application Layer Protocols: File Transfer and Remote Access (โปรโตคอลชั้นแอปพลิเคชัน: การถ่ายโอนไฟล์และการเข้าถึงระยะไกล)

แนวคิด: เปรียบเทียบโปรโตคอลที่ไม่ปลอดภัย vs. ปลอดภัย ใช้งานจริงได้ทันที — บทนี้พาสำรวจโปรโตคอลการถ่ายโอนไฟล์ตั้งแต่ FTP ดั้งเดิมที่ส่งข้อมูลแบบ Plaintext ไปจนถึง SFTP, FTPS, SCP และ SSH ที่มีการเข้ารหัส พร้อมตัวอย่างการใช้งานจริงบน Linux


3.1 FTP (File Transfer Protocol): หลักการทำงานและจุดอ่อน

3.1.1 ประวัติและวิวัฒนาการของ FTP

FTP (File Transfer Protocol) เป็นโปรโตคอลสำหรับการถ่ายโอนไฟล์ผ่านเครือข่าย TCP/IP ที่เก่าแก่ที่สุดโปรโตคอลหนึ่ง ถูกออกแบบในยุคที่ความปลอดภัยยังไม่ใช่ความกังวลหลัก ทำให้มีช่องโหว่ด้าน Security มากมาย

flowchart LR
  subgraph era1["ยุคเริ่มต้น Early Era (1971–1985)"]
    A["1971\nRFC 114\nFTP ต้นแบบ Original FTP"]
    B["1980\nRFC 765\nปรับปรุงครั้งแรก First Update"]
    C["1985\nRFC 959\nมาตรฐานปัจจุบัน Current Standard"]
    A --> B --> C
  end
  subgraph era2["ยุคอินเทอร์เน็ต Internet Era (1990–2000)"]
    D["1994\nFTP Passive Mode\nแก้ปัญหา Firewall/NAT"]
    E["1997\nRFC 2228\nFTP Security Extensions"]
    F["1999\nRFC 2640\nรองรับ Unicode Support"]
    D --> E --> F
  end
  subgraph era3["ยุคปลอดภัย Secure Era (1999–ปัจจุบัน)"]
    G["1999\nSSH-2 + SFTP\nทางเลือกปลอดภัย Secure Alternative"]
    H["2005\nFTPS RFC 4217\nFTP over TLS"]
    I["2014\nRFC 7151\nFTP HOST Command"]
    J["ปัจจุบัน Present\nFTP ถูกแทนที่\nด้วย SFTP/FTPS/SCP"]
    G --> H --> I --> J
  end
  era1 --> era2 --> era3

3.1.2 สถาปัตยกรรมและหลักการทำงาน

FTP ใช้โมเดล Client-Server โดยมีคุณสมบัติเฉพาะตัวที่แตกต่างจากโปรโตคอลอื่น คือการใช้ การเชื่อมต่อ 2 ช่องทาง (Dual-Channel Architecture):

sequenceDiagram
  participant C as FTP Client (ผู้ใช้งาน)
  participant S as FTP Server (เซิร์ฟเวอร์)

  Note over C,S: Control Connection (TCP Port 21) — ช่องทางควบคุม
  C->>S: TCP SYN (เชื่อมต่อ Port 21)
  S-->>C: 220 Service Ready (พร้อมให้บริการ)
  C->>S: USER student01
  S-->>C: 331 Password Required (ต้องการรหัสผ่าน)
  C->>S: PASS P@ssw0rd2024
  S-->>C: 230 Login Successful (เข้าสู่ระบบสำเร็จ)
  C->>S: PWD (ขอดู Directory ปัจจุบัน)
  S-->>C: 257 "/home/student01"
  C->>S: LIST (แสดงรายการไฟล์)
  Note over C,S: Data Connection (TCP Port 20) — ช่องทางข้อมูล
  S->>C: เปิด Data Connection Port 20
  S-->>C: 150 Opening Data Connection
  S-->>C: ส่งข้อมูล Directory Listing
  S-->>C: 226 Transfer Complete (ถ่ายโอนสำเร็จ)
  C->>S: QUIT (ออกจากระบบ)
  S-->>C: 221 Goodbye

3.1.3 FTP Modes: Active Mode และ Passive Mode

3.1.3.1 Active Mode (โหมดแอคทีฟ)

ใน Active Mode เซิร์ฟเวอร์เป็นฝ่ายเริ่มต้น Data Connection กลับมาหา Client:

  1. Client เชื่อมต่อ Control Channel ไปยัง Server Port 21
  2. Client ส่งคำสั่ง PORT พร้อมระบุ IP และ Port ที่ตัวเองรับฟัง
  3. Server เปิด Data Connection จาก Port 20 ไปยัง Client Port ที่ระบุ
  4. ถ่ายโอนข้อมูล

ปัญหาหลัก: Firewall ที่ Client มักบล็อก Incoming Connection จาก Server Port 20

sequenceDiagram
  participant C as Client (IP: 192.168.1.100)
  participant F as Client Firewall (ไฟร์วอลล์ผู้ใช้)
  participant S as FTP Server (IP: 203.0.113.10)

  C->>S: Control: PORT 192,168,1,100,200,50 (แจ้ง Port 51250 สำหรับรับข้อมูล)
  S-->>C: 200 PORT Command OK
  S->>F: Data: SYN จาก Port 20 → Port 51250
  F-->>S: BLOCKED! Firewall ปฏิเสธการเชื่อมต่อขาเข้า
  Note over C,S: Active Mode ล้มเหลวเมื่อมี Firewall/NAT

3.1.3.2 Passive Mode (โหมดพาสซีฟ)

ใน Passive Mode Client เป็นฝ่ายเริ่มต้น Data Connection แก้ปัญหา Firewall/NAT ได้:

  1. Client ส่งคำสั่ง PASV เพื่อขอให้ Server เปิด Port รอรับ
  2. Server เปิด Port แบบ Ephemeral (สุ่ม) และแจ้งกลับมา
  3. Client เชื่อมต่อ Data Connection ไปยัง Server Port ที่ระบุ
  4. ถ่ายโอนข้อมูล
sequenceDiagram
  participant C as Client (IP: 192.168.1.100)
  participant S as FTP Server (IP: 203.0.113.10)

  C->>S: Control: PASV (ขอโหมด Passive)
  S-->>C: 227 Entering Passive Mode (203,0,113,10,195,149) → Port 50069 พร้อมรับ
  C->>S: Data: SYN จาก Ephemeral Port → Port 50069
  S-->>C: Data: SYN-ACK (ตอบรับ)
  Note over C,S: Passive Mode ทำงานได้แม้มี NAT/Firewall
  S-->>C: 150 File Status Okay (กำลังส่งไฟล์)
  S-->>C: File Data (ข้อมูลไฟล์)
  S-->>C: 226 Transfer Complete

การคำนวณ Port จาก PASV Response:

เมื่อ Server ตอบ 227 Entering Passive Mode (203,0,113,10,195,149) ค่าสองตัวสุดท้ายคือ p₁ และ p₂ ใช้สูตร:

Port = (p1×256) + p2

ตัวอย่างการคำนวณ: จาก Response (203,0,113,10,195,149):

# ตรวจสอบด้วย Linux
echo $((195 * 256 + 149))
# ผลลัพธ์: 50069

3.1.4 FTP Commands และ Response Codes

คำสั่ง (Command) ความหมาย ตัวอย่าง
USER ส่งชื่อผู้ใช้ USER student01
PASS ส่งรหัสผ่าน (Plaintext!) PASS P@ssw0rd2024
LIST แสดงรายการไฟล์ละเอียด LIST /home
RETR ดาวน์โหลดไฟล์ RETR report.pdf
STOR อัปโหลดไฟล์ STOR data.csv
DELE ลบไฟล์ DELE old_file.txt
MKD สร้าง Directory MKD /backup
CWD เปลี่ยน Directory CWD /home/student01
PWD แสดง Directory ปัจจุบัน PWD
QUIT ออกจากระบบ QUIT
PASV เข้าสู่ Passive Mode PASV
PORT ระบุ Port สำหรับ Active Mode PORT 192,168,1,100,200,50
TYPE กำหนดโหมดการส่ง (A=ASCII, I=Binary) TYPE I
FTP Response Code ความหมาย
220 Service Ready — พร้อมให้บริการ
230 User Logged In — เข้าสู่ระบบสำเร็จ
331 Password Required — ต้องการรหัสผ่าน
530 Not Logged In — ไม่ได้เข้าสู่ระบบ
150 File Status Okay — เริ่มถ่ายโอน
226 Closing Data Connection — ถ่ายโอนเสร็จสิ้น
421 Service Not Available — ไม่พร้อมให้บริการ
550 File Unavailable — ไม่พบไฟล์หรือไม่มีสิทธิ์

3.1.5 การทดลองใช้งาน FTP บน Linux

สถานการณ์จำลอง (Lab Scenario)

สมมติสภาพแวดล้อมดังนี้:

ขั้นตอนที่ 1: ติดตั้ง FTP Server (vsftpd)

# ติดตั้ง vsftpd บน Ubuntu/Debian
sudo apt update && sudo apt install vsftpd -y

# สร้างผู้ใช้ทดสอบ
sudo useradd -m -s /bin/bash student01
echo "student01:P@ssw0rd2024" | sudo chpasswd

# กำหนดค่าพื้นฐาน (ไม่ปลอดภัย — ใช้เพื่อสาธิตเท่านั้น!)
sudo tee /etc/vsftpd.conf << 'EOF'
listen=YES
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
EOF

sudo systemctl restart vsftpd
sudo systemctl status vsftpd

ขั้นตอนที่ 2: สร้างไฟล์ทดสอบ

# สร้างไฟล์ทดสอบขนาดประมาณ 1 MB
dd if=/dev/urandom bs=1024 count=1024 | base64 > /home/student01/network_lab.txt
ls -lh /home/student01/network_lab.txt
# -rw-r--r-- 1 student01 student01 1.4M Jun 10 10:00 network_lab.txt

ขั้นตอนที่ 3: เชื่อมต่อ FTP และใช้งาน

# ติดตั้ง ftp client
sudo apt install ftp -y

# เชื่อมต่อ FTP Server
ftp 192.168.1.10
# Connected to 192.168.1.10.
# 220 (vsFTPd 3.0.5)
# Name: student01
# 331 Please specify the password.
# Password: [พิมพ์ P@ssw0rd2024]
# 230 Login successful.

# คำสั่งพื้นฐานใน FTP prompt
ftp> pwd                    # ดู directory ปัจจุบัน
ftp> ls -la                 # แสดงไฟล์ทั้งหมด
ftp> get network_lab.txt    # ดาวน์โหลดไฟล์
# 1433600 bytes received in 0.23 secs (6238.52 kB/s)
ftp> put /tmp/upload.txt    # อัปโหลดไฟล์
ftp> bye                    # ออกจากระบบ

ขั้นตอนที่ 4: ดักจับ Packet ด้วย tcpdump (แสดงช่องโหว่)

# บน Machine ในเครือข่ายเดียวกัน — ดักจับ FTP Traffic
sudo tcpdump -i eth0 -A 'port 21' -w /tmp/ftp_capture.pcap &

# ทำการ Login FTP ใหม่จาก Client
ftp 192.168.1.10  # ใส่ student01 / P@ssw0rd2024

# หยุด tcpdump
sudo kill %1

# ตรวจสอบ — เห็น Credentials แบบ Plaintext!
sudo tcpdump -r /tmp/ftp_capture.pcap -A | grep -E 'USER|PASS'
# ผลลัพธ์ที่น่ากลัว:
# ..USER student01..
# ..PASS P@ssw0rd2024..   ← รหัสผ่านโชว์แจ้งๆ!

⚠️ คำเตือนสำคัญ: รหัสผ่านปรากฏใน Packet แบบ Cleartext นี่คือเหตุผลหลักที่ไม่ควรใช้ FTP บน Production

การคำนวณ Transfer Rate:

จากตัวอย่าง: ไฟล์ขนาด 1,433,600 bytes ถ่ายโอนใน 0.23 วินาที

R = S T = 1,433,600 bytes 0.23 s 6,233,043 B/s 5.94 MB/s

แปลงเป็น Megabits per second (Mbps):

RMbps = S×8 T×106 = 1,433,600×8 0.23×106 49.9 Mbps

ตัวแปร: R = Transfer Rate, S = File Size (bytes), T = Transfer Time (วินาที)

# คำนวณ Transfer Rate ด้วย Python3
python3 -c "
size_bytes = 1_433_600
time_sec = 0.23
rate_bps   = size_bytes / time_sec
rate_kbps  = rate_bps / 1024
rate_mbps  = rate_bps * 8 / 1_000_000
print(f'Transfer Rate: {rate_bps:,.0f} B/s')
print(f'Transfer Rate: {rate_kbps:,.2f} KB/s')
print(f'Transfer Rate: {rate_mbps:.2f} Mbps')
"
# Transfer Rate: 6,233,043 B/s
# Transfer Rate: 6,086.96 KB/s
# Transfer Rate: 49.86 Mbps

3.1.6 จุดอ่อนและช่องโหว่ของ FTP

mindmap
  root((FTP จุดอ่อน - Vulnerabilities))
    ไม่มีการเข้ารหัส - No Encryption
      Credentials เป็น Plaintext
      Data เป็น Plaintext
      Sniffing ได้ง่ายด้วย tcpdump
    การพิสูจน์ตัวตนอ่อนแอ - Weak Authentication
      รองรับ Anonymous Login
      ไม่มี Brute-force Protection
      ไม่รองรับ MFA
    ปัญหา Active Mode
      NAT Traversal ยาก
      Firewall ต้องเปิด Port เพิ่ม
      FTP Bounce Attack
    MITM Attack
      PORT Command IP Spoofing
      Man-in-the-Middle ได้ง่าย
      ไม่มี Server Authentication
    Anonymous FTP
      เข้าถึงไฟล์โดยไม่ต้อง Login
      เสี่ยงต่อ Data Leakage
      เสี่ยงต่อ Malware Distribution
ช่องโหว่ ความรุนแรง คำอธิบาย
Plaintext Credentials 🔴 วิกฤต Username/Password ส่งในรูปแบบที่อ่านได้ทุกคน
Plaintext Data 🔴 วิกฤต ข้อมูลไฟล์ไม่มีการเข้ารหัสใดๆ
FTP Bounce Attack 🟠 สูง ใช้ Server เป็น Proxy โจมตีเครื่องอื่น
Anonymous Login 🟠 สูง เข้าถึงไฟล์โดยไม่ต้อง Authenticate
No Integrity Check 🟡 กลาง ไม่ตรวจสอบว่าข้อมูลถูกแก้ไขระหว่างทางหรือไม่
PORT Command Spoofing 🟡 กลาง แอบอ้าง IP ในคำสั่ง PORT เพื่อ Redirect Data

3.2 SFTP (SSH File Transfer Protocol) และการกำหนดค่า

3.2.1 สถาปัตยกรรมของ SFTP

SFTP (SSH File Transfer Protocol) ไม่ใช่ FTP ที่เข้ารหัส แต่เป็นโปรโตคอลใหม่ที่ทำงานเป็น Subsystem ของ SSH ทั้งหมดผ่าน Port 22 เพียง Port เดียว

💡 ความต่างสำคัญ: SFTP ≠ FTPS — SFTP ทำงานบน SSH ทั้งหมด ส่วน FTPS คือ FTP ที่ใช้ TLS/SSL เพิ่มเข้าไป

graph TB
  subgraph client["SFTP Client (ฝั่งผู้ใช้งาน)"]
    App["Application\nไฟล์แมเนเจอร์ / CLI sftp / WinSCP"]
    SFTPLib["SFTP Library\nโปรโตคอล SFTP v3–v6"]
    SSHClient["SSH Transport Layer\nการเข้ารหัส + Authentication"]
  end
  subgraph network["Network (เครือข่าย)"]
    TCP["TCP Port 22\nช่องเดียว One Channel\n(เข้ารหัสทั้งหมด Fully Encrypted)"]
  end
  subgraph server["SSH Server (ฝั่งเซิร์ฟเวอร์)"]
    SSHDaemon["sshd Daemon\nตรวจสอบ Authentication"]
    Subsystem["SFTP Subsystem\n/usr/lib/openssh/sftp-server\nหรือ internal-sftp"]
    FS["Filesystem\nระบบไฟล์ (อาจมี Chroot)"]
  end
  App --> SFTPLib --> SSHClient --> TCP --> SSHDaemon --> Subsystem --> FS
  style client fill:#4A2518,color:#FFF5DC
  style network fill:#2C1A0E,color:#FFF5DC
  style server fill:#3D1F10,color:#FFF5DC

คุณสมบัติที่โดดเด่นของ SFTP:

3.2.2 การติดตั้งและกำหนดค่า OpenSSH SFTP Server

ข้อมูลสภาพแวดล้อมทดสอบ:

ขั้นตอนที่ 1: ตรวจสอบ SFTP Subsystem

# ตรวจสอบว่า SFTP Subsystem มีอยู่
grep -i sftp /etc/ssh/sshd_config
# Subsystem sftp /usr/lib/openssh/sftp-server

# ตรวจสอบว่าไฟล์มีอยู่จริง
ls -la /usr/lib/openssh/sftp-server
# -rwxr-xr-x 1 root root 121616 ... /usr/lib/openssh/sftp-server

ขั้นตอนที่ 2: สร้างโครงสร้าง Directory สำหรับ SFTP

# สร้าง Directory โครงสร้าง
sudo mkdir -p /srv/sftp/sftpuser01/uploads
sudo mkdir -p /srv/sftp/sftpuser01/downloads

# สร้าง SFTP Group
sudo groupadd sftpusers

# สร้าง SFTP User (ไม่มี Shell Login)
sudo useradd -M -d /srv/sftp/sftpuser01 -G sftpusers -s /sbin/nologin sftpuser01
echo "sftpuser01:SftpP@ss2024!" | sudo chpasswd

# กำหนดความเป็นเจ้าของ — สำคัญมากสำหรับ Chroot!
# Chroot Directory ต้องเป็น owner โดย root เท่านั้น ห้ามให้ user เป็นเจ้าของ
sudo chown root:root /srv/sftp/sftpuser01
sudo chmod 755 /srv/sftp/sftpuser01

# Subdirectory ให้ user เป็นเจ้าของได้
sudo chown sftpuser01:sftpusers /srv/sftp/sftpuser01/uploads
sudo chown sftpuser01:sftpusers /srv/sftp/sftpuser01/downloads
sudo chmod 755 /srv/sftp/sftpuser01/uploads /srv/sftp/sftpuser01/downloads

# ตรวจสอบ
ls -la /srv/sftp/sftpuser01/
# drwxr-xr-x  4 root       root      4096 ...  .
# drwxr-xr-x  2 sftpuser01 sftpusers 4096 ...  downloads
# drwxr-xr-x  2 sftpuser01 sftpusers 4096 ...  uploads

ขั้นตอนที่ 3: กำหนดค่า sshd_config สำหรับ SFTP Chroot

# แก้ไข /etc/ssh/sshd_config
sudo nano /etc/ssh/sshd_config

เพิ่มการตั้งค่าต่อไปนี้ (ที่ส่วนท้ายของไฟล์):

# ปิด Subsystem เดิม
# Subsystem sftp /usr/lib/openssh/sftp-server

# ใช้ internal-sftp แทน (รองรับ Chroot ได้ดีกว่า)
Subsystem sftp internal-sftp -l INFO -f AUTH

# กำหนดค่าเฉพาะสำหรับ sftpusers group
Match Group sftpusers
    ForceCommand internal-sftp -l INFO
    ChrootDirectory /srv/sftp/%u
    AllowTcpForwarding no
    X11Forwarding no
    AllowAgentForwarding no
    PermitTunnel no
# ตรวจสอบ Config ก่อน Restart
sudo sshd -t && echo "Config OK"

# Restart SSH Service
sudo systemctl restart sshd

3.2.3 การใช้งาน SFTP Client

# เชื่อมต่อ SFTP Server
sftp sftpuser01@192.168.1.10
# Connected to 192.168.1.10.
# sftp>

# คำสั่งสำคัญใน SFTP
sftp> pwd                    # ดู Remote Directory ปัจจุบัน
sftp> lpwd                   # ดู Local Directory ปัจจุบัน
sftp> ls -la                 # แสดงไฟล์บน Remote
sftp> lls /tmp               # แสดงไฟล์บน Local
sftp> cd uploads             # เปลี่ยน Remote Directory
sftp> lcd /tmp               # เปลี่ยน Local Directory

# อัปโหลดไฟล์เดียว
sftp> put /tmp/report.pdf uploads/
# Uploading /tmp/report.pdf to /uploads/report.pdf
# report.pdf  100%  256KB  1.2MB/s  00:00

# ดาวน์โหลดไฟล์
sftp> get downloads/data.csv /tmp/

# อัปโหลดหลายไฟล์ด้วย wildcard
sftp> mput /tmp/*.log uploads/

# ดาวน์โหลดทั้ง Directory (Recursive)
sftp> get -r downloads/ /tmp/backup/

ใช้ sftp แบบ Non-interactive สำหรับสคริปต์อัตโนมัติ:

# สร้างไฟล์ batch commands
cat > /tmp/sftp_batch.txt << 'EOF'
cd uploads
put /tmp/report_2024.pdf
put /tmp/data_export.csv
ls -la
bye
EOF

# รันแบบ batch (ไม่ต้องกด Enter)
sftp -b /tmp/sftp_batch.txt sftpuser01@192.168.1.10

3.2.4 การทดสอบ Chroot Jail

# ทดสอบว่า Chroot ทำงาน
sftp sftpuser01@192.168.1.10

sftp> cd /etc
# Permission denied.   ← Chroot ป้องกันแล้ว!

sftp> ls /
# downloads   uploads   ← เห็นแค่ directory ที่กำหนด

# ทดสอบว่าเข้า Shell ไม่ได้
ssh sftpuser01@192.168.1.10
# This service allows sftp connections only.
# Connection to 192.168.1.10 closed.   ← ForceCommand ทำงาน!

# ตรวจสอบ Log การเข้าถึง
sudo tail -f /var/log/auth.log | grep sftp
# Jun 10 10:15 server sshd[1234]: Accepted password for sftpuser01 from 192.168.1.100
# Jun 10 10:15 server sshd[1234]: subsystem request for sftp by user sftpuser01

3.3 FTPS (FTP over SSL/TLS)

3.3.1 ความแตกต่างระหว่าง Implicit และ Explicit FTPS

FTPS (FTP Secure) คือ FTP ที่เพิ่มชั้นการเข้ารหัส TLS/SSL ต่างจาก SFTP ตรงที่ยังใช้โครงสร้าง Dual-Channel และ FTP Command Set เดิม มี 2 แบบ:

คุณสมบัติ Implicit FTPS Explicit FTPS (FTPES)
Port 990 (Control), 989 (Data) 21 (ทั้ง Control และ Data)
การเข้ารหัส บังคับตั้งแต่เริ่มต้น Mandatory เริ่มจาก Plaintext แล้ว Upgrade ด้วย AUTH TLS
คำสั่ง Upgrade ไม่มี — เข้ารหัสทันที AUTH TLS หรือ AUTH SSL
Backward Compat ❌ ไม่รองรับ FTP ธรรมดา ✅ รองรับ (แต่ควรบังคับ TLS)
RFC ไม่มี RFC อย่างเป็นทางการ RFC 4217
การใช้งาน ลดลง Legacy แพร่หลายกว่า Preferred

3.3.2 กระบวนการ TLS Handshake ใน FTPS

sequenceDiagram
  participant C as FTPS Client
  participant S as FTPS Server

  Note over C,S: Explicit FTPS (FTPES) — เริ่มจาก Plaintext แล้ว Upgrade
  C->>S: TCP Connect Port 21
  S-->>C: 220 FTP Server Ready (Plaintext)
  C->>S: AUTH TLS (ขอ Upgrade เป็น TLS)
  S-->>C: 234 AUTH TLS OK (ยอมรับ Upgrade)
  Note over C,S: TLS Handshake เริ่มต้น
  C->>S: ClientHello (TLS Version + Supported Ciphers)
  S-->>C: ServerHello + Certificate (ใบรับรอง)
  C->>S: Certificate Verification (ตรวจสอบ CA)
  C->>S: Key Exchange (แลกเปลี่ยน Key)
  S-->>C: Finished (TLS Established)
  Note over C,S: ตั้งแต่นี้ทุกอย่างเข้ารหัส Encrypted from here
  C->>S: USER student01 ENCRYPTED
  S-->>C: 331 Password Required ENCRYPTED
  C->>S: PASS P@ssw0rd2024 ENCRYPTED
  S-->>C: 230 Login Successful ENCRYPTED

TLS Record Overhead Calculation:

เมื่อส่งข้อมูลผ่าน TLS จะมี Overhead เพิ่มขึ้นต่อ Record:

OTLS = Hheader + LIV + LMAC + Ppadding

ตัวอย่าง TLS 1.3 with AES-128-GCM: H=5, IV=0 (ฝังใน Nonce), MAC(GCM Auth Tag)=16, P=0:

OTLS 1.3 = 5+0+16+0 =21 bytes per record

เปอร์เซ็นต์ Overhead ต่อ TLS Record ขนาดสูงสุด 16,384 bytes:

Roverhead% = 2116,384 ×100 0.128%

Overhead ของ TLS น้อยมาก (< 0.2%) ไม่มีผลกระทบด้านประสิทธิภาพในการใช้งานจริง

python3 -c "
header, auth_tag = 5, 16
record_size = 16384
overhead = header + auth_tag
pct = (overhead / record_size) * 100
print(f'TLS Record Size:  {record_size:,} bytes')
print(f'TLS Overhead:     {overhead} bytes/record')
print(f'Overhead %:       {pct:.3f}%')
"
# TLS Record Size:  16,384 bytes
# TLS Overhead:     21 bytes/record
# Overhead %:       0.128%

3.3.3 การกำหนดค่า vsftpd สำหรับ FTPS

ขั้นตอนที่ 1: สร้าง Self-signed TLS Certificate

# สร้าง Certificate อายุ 365 วัน
sudo openssl req -x509 -nodes -days 365 \
  -newkey rsa:2048 \
  -keyout /etc/ssl/private/vsftpd.key \
  -out /etc/ssl/certs/vsftpd.crt \
  -subj "/C=TH/ST=Songkhla/L=Hat_Yai/O=RMUTSV/OU=NetworkSec/CN=192.168.1.10"

# กำหนด Permission ที่ปลอดภัย
sudo chmod 600 /etc/ssl/private/vsftpd.key

# ตรวจสอบ Certificate
sudo openssl x509 -in /etc/ssl/certs/vsftpd.crt -text -noout | grep -E "Subject:|Not After"
# Subject: C=TH, ST=Songkhla, O=RMUTSV, CN=192.168.1.10
# Not After : Jun 10 10:00:00 2025 GMT

ขั้นตอนที่ 2: กำหนดค่า vsftpd.conf สำหรับ FTPS

sudo tee /etc/vsftpd.conf << 'EOF'
# vsftpd — Explicit FTPS Configuration
listen=YES
listen_ipv6=NO
local_enable=YES
anonymous_enable=NO
write_enable=YES
local_umask=022
chroot_local_user=YES
allow_writeable_chroot=NO

# TLS Configuration
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1_2=YES
ssl_sslv2=NO
ssl_sslv3=NO
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key

# Passive Mode
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=50000

# Logging
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log
log_ftp_protocol=YES
EOF

sudo systemctl restart vsftpd

ขั้นตอนที่ 3: ทดสอบ FTPS ด้วย lftp

# ติดตั้ง lftp
sudo apt install lftp -y

# เชื่อมต่อ FTPS
lftp << 'EOF'
set ftp:ssl-force true
set ftp:ssl-protect-data true
set ssl:verify-certificate no
open -u student01,P@ssw0rd2024 ftp://192.168.1.10
ls
bye
EOF

# ตรวจสอบว่า Credentials ไม่โชว์ใน Packet
sudo tcpdump -i eth0 -A 'port 21' -w /tmp/ftps.pcap &
lftp -u student01,P@ssw0rd2024 ftps://192.168.1.10 -e "ls; bye"
sudo kill %1
sudo tcpdump -r /tmp/ftps.pcap -A | grep -i "pass\|user"
# ไม่ควรเห็น Credentials — เข้ารหัสแล้ว!

3.4 SCP (Secure Copy Protocol) และ SSHFS (SSH Filesystem)

3.4.1 SCP: หลักการทำงานและการใช้งาน

SCP (Secure Copy Protocol) คือโปรโตคอลสำหรับคัดลอกไฟล์ระหว่างเครื่องอย่างปลอดภัยผ่าน SSH ทำงานโดยส่ง SSH Command พิเศษไปยัง Remote Host ใช้ Port 22 เพียง Port เดียว

⚠️ หมายเหตุสำคัญ: OpenSSH 9.0+ ได้ Deprecate SCP Protocol เดิม และใช้ SFTP Protocol ทำงานหลังเบื้องหลังแทน คำสั่ง scp ยังคงใช้ได้ตามปกติ

sequenceDiagram
  participant L as Local Machine (เครื่องต้นทาง)
  participant R as Remote Server (192.168.1.10)

  Note over L,R: SCP ทำงานบน SSH Channel — Port 22 เท่านั้น
  L->>R: SSH Connection + Authentication (Key หรือ Password)
  R-->>L: SSH Session Established (ช่องทางเข้ารหัส)
  L->>R: SSH Command: scp -t /destination/ (โหมด Receive)
  R-->>L: Ready to receive (0x00 = OK)
  L->>R: File Metadata Header (ชื่อ, ขนาด, Permissions)
  L->>R: File Data Stream (ข้อมูลไฟล์ — เข้ารหัสทั้งหมด)
  R-->>L: Acknowledgment 0x00
  Note over L,R: ทำซ้ำสำหรับไฟล์ถัดไปถ้ามี

SCP Command Syntax และตัวอย่าง:

# รูปแบบพื้นฐาน
scp [OPTIONS] SOURCE DESTINATION

# ตัวอย่างที่ 1: คัดลอกไฟล์จาก Local ไป Remote
scp /tmp/report.pdf student01@192.168.1.10:/home/student01/

# ตัวอย่างที่ 2: คัดลอกไฟล์จาก Remote มา Local
scp student01@192.168.1.10:/home/student01/data.csv /tmp/

# ตัวอย่างที่ 3: คัดลอก Directory ทั้งหมด (Recursive)
scp -r /tmp/project/ student01@192.168.1.10:/home/student01/

# ตัวอย่างที่ 4: ระบุ SSH Key
scp -i ~/.ssh/id_ed25519 /tmp/report.pdf student01@192.168.1.10:/home/student01/

# ตัวอย่างที่ 5: ระบุ Port ที่ไม่ใช่ 22
scp -P 2222 /tmp/file.txt student01@192.168.1.10:/home/student01/

# ตัวอย่างที่ 6: จำกัด Bandwidth ที่ 1024 KB/s
scp -l 1024 /tmp/large_file.tar.gz student01@192.168.1.10:/home/student01/

# ตัวอย่างที่ 7: คัดลอกระหว่าง 2 Remote Hosts
scp student01@192.168.1.10:/data/file.txt student02@192.168.1.20:/backup/

การทดลองและตรวจสอบ Integrity:

# สร้างไฟล์ทดสอบ 10MB
dd if=/dev/urandom bs=1M count=10 of=/tmp/test_10mb.bin
ls -lh /tmp/test_10mb.bin

# คัดลอกและจับเวลา
time scp /tmp/test_10mb.bin student01@192.168.1.10:/home/student01/
# test_10mb.bin  100%   10MB  45.2MB/s   00:00
# real  0m0.234s

# ตรวจสอบ Integrity ด้วย MD5 Checksum
LOCAL_MD5=$(md5sum /tmp/test_10mb.bin | cut -d' ' -f1)
REMOTE_MD5=$(ssh student01@192.168.1.10 "md5sum /home/student01/test_10mb.bin" | cut -d' ' -f1)
echo "Local:  $LOCAL_MD5"
echo "Remote: $REMOTE_MD5"
[ "$LOCAL_MD5" = "$REMOTE_MD5" ] && echo "✅ Files Match!" || echo "❌ Files Differ!"

3.4.2 SSHFS: การเมานต์ระบบไฟล์ผ่าน SSH

SSHFS (SSH Filesystem) ทำให้ Mount Remote Directory ผ่าน SSH เป็นเหมือน Local Drive โดยใช้ FUSE (Filesystem in Userspace)

graph TB
  subgraph local["Local Machine (เครื่องผู้ใช้)"]
    App["Application\nอ่าน/เขียนไฟล์ปกติ"]
    Mount["Mount Point\n/mnt/remote_server\n(เสมือน Local Drive)"]
    FUSE["FUSE Driver\nส่งต่อ File Operations ผ่าน Kernel"]
    SSHFS_C["SSHFS Client\nแปลง VFS Calls เป็น SFTP Commands"]
  end
  subgraph tunnel["SSH Encrypted Tunnel (Port 22)"]
    SSH_T["AES-256 / ChaCha20\nทุก Byte เข้ารหัส"]
  end
  subgraph remote["Remote Server (192.168.1.10)"]
    SSHD2["sshd + internal-sftp"]
    FS2["Remote Filesystem\n/home/student01/"]
  end
  App --> Mount --> FUSE --> SSHFS_C --> SSH_T --> SSHD2 --> FS2
  style local fill:#4A2518,color:#FFF5DC
  style tunnel fill:#2C1A0E,color:#FFF5DC
  style remote fill:#3D1F10,color:#FFF5DC

การติดตั้งและใช้งาน SSHFS:

# ติดตั้ง SSHFS
sudo apt install sshfs -y

# สร้าง Mount Point
mkdir -p /mnt/server_home

# Mount Remote Directory
sshfs student01@192.168.1.10:/home/student01/ /mnt/server_home \
  -o reconnect \
  -o ServerAliveInterval=15 \
  -o ServerAliveCountMax=3 \
  -o IdentityFile=~/.ssh/id_ed25519

# ตรวจสอบว่า Mount สำเร็จ
df -h /mnt/server_home
# student01@192.168.1.10:/home/student01  50G  5G  45G  10%  /mnt/server_home

# ใช้งานเหมือน Local Drive!
ls -la /mnt/server_home/
cp /tmp/new_file.txt /mnt/server_home/
cat /mnt/server_home/readme.txt

# Unmount เมื่อเสร็จ
fusermount -u /mnt/server_home

Auto-mount ผ่าน /etc/fstab:

# เพิ่มใน /etc/fstab
echo "student01@192.168.1.10:/home/student01 /mnt/server_home fuse.sshfs \
  defaults,_netdev,reconnect,IdentityFile=/home/localuser/.ssh/id_ed25519,\
  ServerAliveInterval=15,uid=1000,gid=1000 0 0" | sudo tee -a /etc/fstab

sudo mount -a   # ทดสอบ fstab

3.4.3 การเปรียบเทียบ SCP vs rsync vs SSHFS

คุณสมบัติ SCP rsync over SSH SSHFS
วัตถุประสงค์ Copy ไฟล์ครั้งเดียว Sync/Backup Mount เป็น Drive
Incremental Transfer ❌ ส่งทั้งหมดทุกครั้ง ✅ ส่งเฉพาะส่วนที่เปลี่ยน ✅ On-demand
Resume ต่อได้
ใช้งานเหมือน Local
Compression -C flag -z flag ✅ รองรับ
Bandwidth Efficient ต่ำ สูงมาก กลาง
ความง่ายใช้งาน ง่ายมาก ปานกลาง ปานกลาง
Use Case Copy ไฟล์เดี่ยว Backup/Sync Edit Remote Files
# rsync over SSH — Incremental Backup
rsync -avz --progress \
  -e "ssh -i ~/.ssh/id_ed25519" \
  /local/project/ \
  student01@192.168.1.10:/home/student01/project/
# -a = archive (รักษา permissions, timestamps, symlinks)
# -v = verbose
# -z = compress ระหว่างส่ง
# --progress = แสดงความคืบหน้า

# Dry Run ดูก่อนว่าจะ sync อะไรบ้าง
rsync -avz --dry-run -e "ssh -i ~/.ssh/id_ed25519" \
  /local/project/ student01@192.168.1.10:/home/student01/project/

3.5 SSH (Secure Shell): Key-based Authentication, Configuration Hardening

3.5.1 สถาปัตยกรรมและโปรโตคอล SSH

SSH (Secure Shell) เป็นโปรโตคอลสำหรับการสื่อสารที่ปลอดภัยผ่านเครือข่ายที่ไม่น่าเชื่อถือ พัฒนาโดย Tatu Ylönen ในปี 1995 เพื่อแทน Telnet และ rsh ที่ส่งข้อมูลแบบ Plaintext

graph TB
  subgraph layers["SSH Protocol Layers ชั้นโปรโตคอล (RFC 4251-4254)"]
    L4["SSH Connection Protocol (RFC 4254)\nจัดการ Channels: Shell, SFTP, Port Forward, X11"]
    L3["SSH Authentication Protocol (RFC 4252)\nPassword, Public Key, GSSAPI, Host-based"]
    L2["SSH Transport Layer Protocol (RFC 4253)\nKey Exchange ECDH/DH, Encryption AES/ChaCha20, Integrity HMAC"]
    L1["TCP/IP Network Layer\nPort 22 — ช่องทางเครือข่าย"]
    L4 --> L3 --> L2 --> L1
  end
  style L4 fill:#6B3A2A,color:#FFF5DC
  style L3 fill:#5A2E1A,color:#FFF5DC
  style L2 fill:#4A2518,color:#FFF5DC
  style L1 fill:#3D1F10,color:#FFF5DC
sequenceDiagram
  participant C as SSH Client
  participant S as SSH Server (sshd)

  Note over C,S: Phase 1: TCP Connection & Version Exchange
  C->>S: TCP SYN Port 22
  S-->>C: TCP SYN-ACK
  C->>S: SSH-2.0-OpenSSH_9.0
  S-->>C: SSH-2.0-OpenSSH_9.0p1 Ubuntu-3

  Note over C,S: Phase 2: Key Exchange — ECDH Curve25519
  C->>S: SSH_MSG_KEXINIT (รายการ Algorithm ที่รองรับ)
  S-->>C: SSH_MSG_KEXINIT (เลือก Algorithm ที่ดีที่สุด)
  C->>S: SSH_MSG_KEX_ECDH_INIT (Client Ephemeral Public Key)
  S-->>C: SSH_MSG_KEX_ECDH_REPLY (Server Public Key + Signature)
  Note over C,S: ทั้งสองฝ่ายคำนวณ Shared Secret ⟶ Session Keys (ไม่ผ่านเครือข่าย)

  Note over C,S: Phase 3: User Authentication
  C->>S: SSH_MSG_USERAUTH_REQUEST (username + auth method)
  alt Public Key Authentication (แนะนำ)
    C->>S: ส่ง Public Key + Signature (ลายเซ็นด้วย Private Key)
    S->>S: ตรวจสอบ Public Key ใน ~/.ssh/authorized_keys
    S-->>C: SSH_MSG_USERAUTH_SUCCESS
  else Password Authentication
    S-->>C: ขอ Password
    C->>S: Password (Encrypted ด้วย Session Key)
    S-->>C: SSH_MSG_USERAUTH_SUCCESS
  end

  Note over C,S: Phase 4: Encrypted Session
  C->>S: Open Channel (shell / sftp / port-forward)
  S-->>C: Channel Confirmed — สื่อสาร Encrypted ทั้งหมด

3.5.2 การสร้างและจัดการ SSH Keys

ประเภท SSH Key Algorithm:

Algorithm Key Size Security Level ความเร็ว แนะนำ
RSA 2048 / 4096 บิต 112 / 140 บิต equiv ช้า ✅ ถ้า Legacy จำเป็น
DSA 1024 บิต (fixed) 80 บิต equiv ปานกลาง ❌ เลิกใช้แล้ว
ECDSA 256 / 384 / 521 บิต 128 / 192 / 260 บิต equiv เร็ว
Ed25519 255 บิต (fixed) ~128 บิต equiv เร็วมาก ✅✅ แนะนำสูงสุด

การคำนวณ Security Level ของ RSA Key:

SRSA 1.923 × (log2n) 1/3 × (log2log2n) 2/3 - 4.69

ตัวแปร: S = Security bits equivalent, n = จำนวนบิตของ RSA Key

# คำนวณ Security Level ของ RSA Keys
python3 -c "
import math

def rsa_security_bits(n_bits):
    log2_n = n_bits
    log2_log2_n = math.log2(n_bits)
    return 1.923 * (log2_n ** (1/3)) * (log2_log2_n ** (2/3)) - 4.69

for bits in [1024, 2048, 3072, 4096]:
    sec = rsa_security_bits(bits)
    status = 'INSECURE' if sec < 100 else 'OK' if sec < 128 else 'GOOD'
    print(f'RSA-{bits}: ~{sec:.1f}-bit security [{status}]')
"
# RSA-1024: ~80.0-bit security  [INSECURE] — Deprecated!
# RSA-2048: ~111.5-bit security [OK]       — Acceptable until 2030
# RSA-3072: ~128.6-bit security [GOOD]     — Recommended
# RSA-4096: ~140.0-bit security [GOOD]     — Strong

การสร้าง SSH Key Pair:

# ========================================
# สร้าง Ed25519 Key (แนะนำที่สุด)
# ========================================
ssh-keygen -t ed25519 \
  -C "student01@rmutsv.ac.th" \
  -f ~/.ssh/id_ed25519
# กด Enter สองครั้ง (ไม่ใส่ Passphrase สำหรับ Lab)
# หรือใส่ Passphrase เพื่อความปลอดภัยสูงสุด

# ตรวจสอบไฟล์ที่สร้าง
ls -la ~/.ssh/
# -rw-------  1 user user  411 ... id_ed25519       ← Private Key (เก็บลับ!)
# -rw-r--r--  1 user user   97 ... id_ed25519.pub   ← Public Key (แชร์ได้)

# ดูเนื้อหา Public Key
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... student01@rmutsv.ac.th

# ตรวจสอบ Key Fingerprint
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# 256 SHA256:xxxxxxxxxxxxxxxxxxxx student01@rmutsv.ac.th (ED25519)

# ========================================
# สร้าง RSA-4096 Key (สำหรับ Legacy System)
# ========================================
ssh-keygen -t rsa -b 4096 -C "student01@rmutsv.ac.th" -f ~/.ssh/id_rsa_4096

3.5.3 Key-based Authentication: กระบวนการทำงาน

sequenceDiagram
  participant C as SSH Client (มี Private Key)
  participant S as SSH Server (มี authorized_keys)

  Note over C,S: ขั้นตอนเตรียมการ — ทำเพียงครั้งเดียว
  C->>S: ssh-copy-id — ส่ง Public Key ไปเก็บใน ~/.ssh/authorized_keys

  Note over C,S: การ Login ด้วย Key — ทุกครั้งที่เชื่อมต่อ
  C->>S: SSH Connection + ระบุ Public Key ที่ต้องการใช้
  S->>S: ตรวจสอบ Public Key อยู่ใน authorized_keys?
  S-->>C: Challenge: Random Data เข้ารหัสด้วย Public Key
  C->>C: ถอดรหัส Challenge ด้วย Private Key (บน Local เท่านั้น)
  C->>S: ส่ง Response = Hash(Decrypted Challenge + Session ID)
  S->>S: ตรวจสอบ Response ถูกต้องไหม?
  S-->>C: Authentication Successful
  Note over C,S: Private Key ไม่เคยออกจากเครื่อง Client เลย!

ขั้นตอนการตั้งค่า Key-based Authentication:

# ========================================
# คัดลอก Public Key ไป Server
# ========================================
# วิธีที่ 1: ใช้ ssh-copy-id (ง่ายที่สุด)
ssh-copy-id -i ~/.ssh/id_ed25519.pub student01@192.168.1.10
# Number of key(s) added: 1
# Now try logging into the machine, with: "ssh 'student01@192.168.1.10'"

# วิธีที่ 2: Manual (ถ้า ssh-copy-id ไม่มี)
cat ~/.ssh/id_ed25519.pub | ssh student01@192.168.1.10 \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# ทดสอบ — Login โดยไม่ถาม Password
ssh student01@192.168.1.10
# student01@server:~$   ← เข้าได้ทันที!

# ========================================
# SSH Agent — จัดการ Key และ Passphrase
# ========================================
eval $(ssh-agent -s)             # Start Agent
ssh-add ~/.ssh/id_ed25519        # เพิ่ม Key
ssh-add -l                       # ดู Key ที่อยู่ใน Agent
ssh student01@192.168.1.10      # Login โดยไม่ถาม Passphrase

3.5.4 SSH Configuration Hardening (sshd_config)

# สำรองไฟล์ Config ก่อนแก้ไข
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

กำหนดค่า /etc/ssh/sshd_config แบบ Hardened:

# ==========================================
# /etc/ssh/sshd_config — Hardened Configuration
# RMUTSV Network Security Lab
# ==========================================

# --- Port & Binding ---
Port 2222
AddressFamily inet
ListenAddress 0.0.0.0

# --- Cryptographic Settings ---
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group14-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256

# --- Authentication ---
PasswordAuthentication no          # บังคับใช้ Key เท่านั้น
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitRootLogin no                 # ห้าม Login ด้วย Root
PermitEmptyPasswords no
ChallengeResponseAuthentication no
MaxAuthTries 3                     # ล้มเหลวได้สูงสุด 3 ครั้ง
MaxSessions 5

# --- Access Control ---
AllowUsers student01 admin backup_user    # อนุญาตเฉพาะ User เหล่านี้
# AllowGroups sshusers                    # หรือระบุเป็น Group

# --- Timeout ---
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2

# --- Feature Restrictions ---
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PermitTunnel no
PrintMotd no
Banner /etc/ssh/banner.txt

# --- Logging ---
LogLevel VERBOSE
SyslogFacility AUTH

# --- SFTP Subsystem ---
Subsystem sftp internal-sftp -l INFO

# --- SFTP Chroot สำหรับ sftpusers ---
Match Group sftpusers
    ForceCommand internal-sftp -l INFO
    ChrootDirectory /srv/sftp/%u
    AllowTcpForwarding no
    X11Forwarding no
    AllowAgentForwarding no
# สร้าง Banner เตือนผู้ใช้
sudo tee /etc/ssh/banner.txt << 'EOF'
*******************************************************************************
*   WARNING: Authorized Access Only — ห้ามเข้าถึงโดยไม่ได้รับอนุญาต         *
*   All connections are logged — ทุกการเชื่อมต่อถูกบันทึกและตรวจสอบ         *
*   RMUTSV Network Security Lab — ห้องปฏิบัติการความมั่นคงเครือข่าย          *
*******************************************************************************
EOF

# ตรวจสอบและ Apply
sudo sshd -t && echo "Config OK"
sudo systemctl reload sshd

# ทดสอบด้วย Port ใหม่
ssh -p 2222 student01@192.168.1.10

3.5.5 การเสริมความปลอดภัยด้วย fail2ban

fail2ban Monitor Log และ Ban IP ที่พยายาม Login ผิดพลาดหลายครั้ง:

# ติดตั้ง fail2ban
sudo apt install fail2ban -y

# กำหนดค่า
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime  = 3600     # Ban 1 ชั่วโมง (วินาที)
findtime = 600      # ดูย้อนหลัง 10 นาที
maxretry = 5        # Ban เมื่อผิดเกิน 5 ครั้ง

[sshd]
enabled  = true
port     = 2222
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 3
bantime  = 7200     # Ban SSH เป็นพิเศษ 2 ชั่วโมง
EOF

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

# ตรวจสอบสถานะ
sudo fail2ban-client status sshd
# |- Filter: Currently failed: 0, Total failed: 0
# `- Actions: Currently banned: 0, Total banned: 0

# Unban IP ที่ถูก Ban โดยไม่ตั้งใจ
sudo fail2ban-client set sshd unbanip 192.168.1.100

การคำนวณ Entropy ของ SSH Passphrase:

H = L × log2 (N)

ตัวอย่าง: Passphrase MyS3cur3P@ss! ยาว 13 ตัวอักษร จาก 95 ตัวอักษร ASCII Printable:

H = 13 × log2 (95) = 13 × 6.570 85.4 bits

ตัวแปร: H = Entropy (บิต), L = ความยาว Passphrase, N = จำนวนตัวอักษรที่เป็นไปได้

python3 -c "
import math
tests = [
    ('MyS3cur3P@ss!',  13, 95),   # ASCII Printable
    ('correcthorsebatterystaple', 25, 26),  # Lowercase only
    ('Ab1!Cd2@Ef3#', 12, 94),     # Mixed complex
]
for phrase, L, N in tests:
    H = L * math.log2(N)
    level = 'WEAK' if H < 60 else 'OK' if H < 80 else 'STRONG'
    print(f'Passphrase: {phrase!r:<30} L={L}, N={N}, H={H:.1f} bits [{level}]')
"
# Passphrase: 'MyS3cur3P@ss!'          L=13, N=95, H=85.4 bits [STRONG]
# Passphrase: 'correcthorsebatterystaple' L=25, N=26, H=117.7 bits [STRONG]
# Passphrase: 'Ab1!Cd2@Ef3#'           L=12, N=94, H=78.8 bits [OK]

3.6 เปรียบเทียบ: FTP vs. SFTP vs. FTPS vs. SCP — เลือกใช้เมื่อไหร่?

3.6.1 ตารางเปรียบเทียบคุณสมบัติ

คุณสมบัติ FTP SFTP FTPS (Explicit) SCP
Port หลัก 21+20 (Dual) 22 (Single) 21+Data Port 22 (Single)
การเข้ารหัส ❌ ไม่มี ✅ SSH (AES-256, ChaCha20) ✅ TLS 1.2/1.3 ✅ SSH
Credential Encryption ❌ Plaintext ✅ เข้ารหัส ✅ เข้ารหัส ✅ เข้ารหัส
SSH Key Support ❌ (ใช้ Certificate)
Firewall Friendly 🟡 ปัญหา NAT ✅ ดีมาก 🟡 ต้องเปิด Data Port ✅ ดีมาก
Resume Transfer 🟡 บางไคลเอนต์
Full File Ops ❌ (แค่ Copy)
Anonymous Access ✅ รองรับ
Chroot Jail 🟡 ซับซ้อน ✅ Built-in 🟡 vsftpd N/A
RFC Standard RFC 959 IETF Draft RFC 4217 ไม่มี RFC
สถานะ 🔴 Legacy/Insecure ✅ แนะนำ ✅ ยอมรับได้ ✅ ใช้ได้

3.6.2 แผนภาพการเลือกใช้โปรโตคอล

flowchart TD
  Start["เริ่มต้น: ต้องการถ่ายโอนไฟล์\nStart: Need to Transfer Files"]

  Start --> Q1{"ต้องการ Security?\nSecurity Required?"}
  Q1 -->|"ไม่ (Lab เท่านั้น)"| FTP["FTP\n⚠️ Lab Only — ไม่ใช้ Production"]
  Q1 -->|"ใช่ (เสมอใน Production)"| Q2

  Q2{"ใช้ SSH อยู่แล้วไหม?\nAlready using SSH?"}
  Q2 -->|"ใช่ — มี SSH"| Q3
  Q2 -->|"ไม่ — มีแค่ FTP Server"| Q4

  Q3{"ต้องการทำอะไร?"}
  Q3 -->|"Copy ไฟล์เดี่ยว/ไม่กี่ไฟล์"| SCP["SCP\n✅ ง่าย รวดเร็ว คำสั่งเดียว"]
  Q3 -->|"จัดการไฟล์ Interactive"| SFTP["SFTP\n✅ แนะนำ — Full File Operations"]
  Q3 -->|"Backup / Sync อัตโนมัติ"| RSYNC["rsync over SSH\n✅ Incremental — ประหยัด Bandwidth"]
  Q3 -->|"ทำงานกับไฟล์บ่อยๆ"| SSHFS["SSHFS\n✅ Mount เป็น Local Drive"]

  Q4{"Client รองรับ FTPS?"}
  Q4 -->|"ใช่ — Legacy Client"| FTPS["FTPS Explicit\n✅ FTP + TLS (RFC 4217)"]
  Q4 -->|"ไม่ — ย้ายได้เลย"| SFTP

  style FTP fill:#8B0000,color:#FFF
  style SCP fill:#1A4A1A,color:#FFF
  style SFTP fill:#1A3A4A,color:#FFF
  style RSYNC fill:#2A1A4A,color:#FFF
  style SSHFS fill:#1A2A4A,color:#FFF
  style FTPS fill:#3A2E10,color:#FFF

3.6.3 Use Cases และสถานการณ์จริง

สถานการณ์ โปรโตคอลที่เหมาะสม เหตุผล
ส่ง Report ไปยัง Server SCP ง่าย รวดเร็ว คำสั่งเดียวจบ
อัปโหลดเว็บไซต์ SFTP (GUI) จัดการ Permission ได้ รองรับ Resume
Backup ประจำวัน rsync over SSH Incremental ลดเวลาและ Bandwidth
Windows User SFTP (WinSCP) GUI ใช้งานง่าย ลาก-วางได้
Legacy FTP Server FTPS Upgrade Security โดยไม่เปลี่ยน Protocol
ทำงาน Edit ไฟล์บน Server SSHFS เหมือน Local Drive ทำงานกับ IDE ได้
Public Download Server HTTPS ดีกว่า FTP ทุกด้าน
IoT / Embedded System SCP หรือ SFTP Lightweight ใช้ทรัพยากรน้อย
CI/CD Pipeline SCP หรือ rsync Scriptable ทำงานอัตโนมัติได้

3.7 การกำหนดค่าเซิร์ฟเวอร์ถ่ายโอนไฟล์อย่างปลอดภัย

3.7.1 แนวทาง Security Hardening สำหรับ File Transfer Server

mindmap
  root((File Transfer - Server Security))
    การพิสูจน์ตัวตน - Authentication
      SSH Key เท่านั้น No Password
      MFA สำหรับ Admin Accounts
      ล็อค Account หลัง Login ผิด
      Passphrase บน Private Key
    การควบคุมการเข้าถึง - Access Control
      Chroot Jail — จำกัด Directory
      Principle of Least Privilege
      Per-User Permission Rules
      IP Whitelisting ถ้าเป็นไปได้
    การเข้ารหัส - Encryption
      TLS 1.2 ขึ้นไปสำหรับ FTPS
      AES-256-GCM / ChaCha20 สำหรับ SSH
      Perfect Forward Secrecy PFS
      Certificate Validation
    การ Monitor - Monitoring
      Log ทุก Connection
      Log ทุก File Transfer Operation
      Real-time Alert เมื่อผิดปกติ
      ตรวจสอบ Log เป็นประจำ
    Network Security
      Firewall Rules เฉพาะเจาะจง
      Rate Limiting ต่อ Connection
      fail2ban Block Brute-force
      IDS Integration Snort/Suricata

3.7.2 การตั้งค่า vsftpd แบบ Secure (FTPS + Chroot)

# ขั้นตอนที่ 1: โครงสร้าง Directory
sudo mkdir -p /srv/ftps/{uploads,downloads,shared}
sudo groupadd ftpsusers

# สร้าง User สำหรับ FTPS (ไม่มี Shell)
sudo useradd -M -d /srv/ftps -G ftpsusers -s /sbin/nologin ftpsuser01
echo "ftpsuser01:FtpsS3cur3!" | sudo chpasswd

# กำหนด Permission (สำคัญ!)
sudo chown root:root /srv/ftps
sudo chmod 755 /srv/ftps
sudo chown ftpsuser01:ftpsusers /srv/ftps/uploads /srv/ftps/downloads
sudo chmod 750 /srv/ftps/uploads /srv/ftps/downloads
sudo chown root:ftpsusers /srv/ftps/shared
sudo chmod 750 /srv/ftps/shared

# ขั้นตอนที่ 2: Config ที่ปลอดภัยสมบูรณ์
sudo tee /etc/vsftpd.conf << 'EOF'
# vsftpd — Secure FTPS + Chroot Configuration

listen=YES
listen_ipv6=NO
local_enable=YES
anonymous_enable=NO
write_enable=YES
local_umask=022

# Chroot
chroot_local_user=YES
allow_writeable_chroot=NO
secure_chroot_dir=/var/run/vsftpd/empty

# TLS/SSL (Explicit FTPS)
ssl_enable=YES
require_ssl_reuse=NO
ssl_ciphers=HIGH:!aNULL:!MD5:!RC4:!SSLv2:!SSLv3
force_local_data_ssl=YES
force_local_logins_ssl=YES
allow_anon_ssl=NO
ssl_tlsv1_2=YES
ssl_sslv2=NO
ssl_sslv3=NO
rsa_cert_file=/etc/ssl/certs/vsftpd.crt
rsa_private_key_file=/etc/ssl/private/vsftpd.key

# Passive Mode
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=50000
pasv_address=192.168.1.10

# Limits
local_max_rate=1048576    # 1 MB/s per connection
max_clients=20
max_per_ip=3
idle_session_timeout=300
data_connection_timeout=120

# Logging
xferlog_enable=YES
xferlog_file=/var/log/vsftpd.log
log_ftp_protocol=YES

ftpd_banner=Authorized Access Only — RMUTSV
EOF

sudo systemctl restart vsftpd && sudo systemctl status vsftpd

3.7.3 Script ตรวจสอบความปลอดภัยของ SSH Server

#!/bin/bash
# ssh_security_check.sh — ตรวจสอบความปลอดภัย SSH Server

echo "=== SSH Security Check — $(date) ==="
echo ""

# ตรวจสอบ SSH Version
echo "SSH Version: $(ssh -V 2>&1)"

# ตรวจสอบ Port
SSH_PORT=$(grep "^Port" /etc/ssh/sshd_config | awk '{print $2}')
echo "SSH Port: ${SSH_PORT:-22}"

# ฟังก์ชันตรวจสอบ
check_config() {
    local key="$1" expected="$2" desc="$3"
    val=$(grep "^${key}" /etc/ssh/sshd_config | awk '{print $2}')
    if [ "$val" = "$expected" ]; then
        echo "  ✅ $desc: $val"
    else
        echo "  ❌ $desc: ${val:-not set} (ควรเป็น: $expected)"
    fi
}

echo ""
echo "--- Authentication Settings ---"
check_config "PasswordAuthentication" "no"    "Password Auth Disabled"
check_config "PermitRootLogin"         "no"   "Root Login Disabled"
check_config "PermitEmptyPasswords"    "no"   "Empty Password Disabled"
check_config "PubkeyAuthentication"    "yes"  "PubKey Auth Enabled"

echo ""
echo "--- Feature Restrictions ---"
check_config "X11Forwarding"           "no"   "X11 Forwarding Disabled"
check_config "AllowTcpForwarding"      "no"   "TCP Forwarding Disabled"
check_config "AllowAgentForwarding"    "no"   "Agent Forwarding Disabled"

echo ""
echo "--- fail2ban Status ---"
if systemctl is-active fail2ban &>/dev/null; then
    echo "  ✅ fail2ban: active"
    sudo fail2ban-client status sshd 2>/dev/null | grep -E "failed|banned"
else
    echo "  ❌ fail2ban: not running"
fi

echo ""
echo "--- Recent Failed Login Attempts (last 10) ---"
sudo grep "Failed password\|Invalid user" /var/log/auth.log 2>/dev/null | tail -10

echo ""
echo "--- Active SSH Sessions ---"
who | grep pts || echo "  (no active sessions)"

3.7.4 การ Monitor และ Log การถ่ายโอนไฟล์

# Monitor SFTP Activity แบบ Real-time
sudo tail -f /var/log/auth.log | grep -E "sftp|Accepted|Failed"

# วิเคราะห์ vsftpd Transfer Log
# Format: Date Duration ClientIP Size FilePath Mode Compress Direction AuthType User ...
# ตัวอย่าง:
# Mon Jun 10 11:00:00 2024 1 192.168.1.100 1048576 /srv/ftps/uploads/data.csv b _ i r ftpsuser01 ftp 0 * c

# คำนวณ Total Transfer ต่อ User
awk '{
    direction=$12; size=$8; user=$14
    if(direction=="i") upload[user] += size
    else if(direction=="o") download[user] += size
    count[user]++
}
END {
    printf "%-20s %12s %12s %8s\n", "User", "Upload(B)", "Download(B)", "Files"
    for(u in count)
        printf "%-20s %12d %12d %8d\n", u, upload[u], download[u], count[u]
}' /var/log/vsftpd.log | sort -k2 -rn

3.7.5 Checklist ความปลอดภัยของ File Transfer Server

#!/bin/bash
# file_transfer_security_checklist.sh

PASS=0; FAIL=0; WARN=0

chk() {
    local desc="$1" result="$2"
    case "$result" in
        PASS) echo "  ✅ PASS: $desc"; ((PASS++)) ;;
        FAIL) echo "  ❌ FAIL: $desc"; ((FAIL++)) ;;
        *)    echo "  ⚠️  WARN: $desc"; ((WARN++)) ;;
    esac
}

echo "=== File Transfer Server Security Checklist ==="
echo "Date: $(date)"
echo ""

echo "--- SSH Server ---"
PASS_AUTH=$(grep "^PasswordAuthentication" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}')
chk "Password Authentication Disabled" "$([ "$PASS_AUTH" = "no" ] && echo PASS || echo FAIL)"

ROOT=$(grep "^PermitRootLogin" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}')
chk "Root Login Disabled" "$([ "$ROOT" = "no" ] && echo PASS || echo FAIL)"

PORT=$(grep "^Port" /etc/ssh/sshd_config 2>/dev/null | awk '{print $2}')
chk "Non-default SSH Port (${PORT:-22})" "$([ "${PORT:-22}" != "22" ] && echo PASS || echo WARN)"

chk "fail2ban Running" "$(systemctl is-active fail2ban &>/dev/null && echo PASS || echo FAIL)"

echo ""
echo "--- vsftpd (FTPS) ---"
if [ -f /etc/vsftpd.conf ]; then
    ANON=$(grep "^anonymous_enable" /etc/vsftpd.conf | cut -d= -f2)
    chk "Anonymous Login Disabled" "$([ "$ANON" = "NO" ] && echo PASS || echo FAIL)"

    SSL=$(grep "^ssl_enable" /etc/vsftpd.conf | cut -d= -f2)
    chk "TLS/SSL Enabled" "$([ "$SSL" = "YES" ] && echo PASS || echo FAIL)"

    CHROOT=$(grep "^chroot_local_user" /etc/vsftpd.conf | cut -d= -f2)
    chk "Chroot Jail Enabled" "$([ "$CHROOT" = "YES" ] && echo PASS || echo FAIL)"
else
    chk "vsftpd Config Found" "WARN"
fi

echo ""
echo "=== Summary ==="
TOTAL=$((PASS + FAIL + WARN))
SCORE=$(( TOTAL > 0 ? PASS * 100 / TOTAL : 0 ))
echo "  PASS: $PASS | FAIL: $FAIL | WARN: $WARN"
echo "  Security Score: $SCORE%"
[ $SCORE -ge 80 ] && echo "  Status: ACCEPTABLE" || echo "  Status: NEEDS IMPROVEMENT"

สรุป (Summary)

บทที่ 3 นำเสนอโปรโตคอลการถ่ายโอนไฟล์และการเข้าถึงระยะไกลตั้งแต่ต้นกำเนิดจนถึงปัจจุบัน โดยแบ่งเป็น 2 กลุ่มหลัก:

โปรโตคอล Legacy ที่ไม่ปลอดภัย:

โปรโตคอลที่ปลอดภัย (Secure Alternatives):

หลักการสำคัญที่ต้องจำ:

  1. ห้ามใช้ FTP บน Production ใช้ SFTP หรือ FTPS แทนเสมอ
  2. ใช้ SSH Key Authentication แทน Password ทุกครั้งที่ทำได้ ใช้ Ed25519 สำหรับ Key ใหม่
  3. ตั้งค่า Chroot Jail เพื่อจำกัดผู้ใช้ให้เข้าถึงได้เฉพาะ Directory ที่กำหนด
  4. Monitor และ Log ทุก File Transfer ด้วย xferlog และ auth.log
  5. ใช้ fail2ban ป้องกัน Brute-force Attack
  6. ทดสอบ TLS/SSH Configuration สม่ำเสมอด้วย ssh-audit หรือ ssl-labs
graph LR
  subgraph unsafe["ไม่ปลอดภัย — อย่าใช้ใน Production"]
    FTP["FTP\nPort 21/20\nPlaintext Everything"]
    TELNET["Telnet\nPort 23\nPlaintext Shell"]
  end
  subgraph secure["ปลอดภัย — ใช้แทน Secure Alternatives"]
    SFTP2["SFTP\nPort 22\nSSH Subsystem — แนะนำสูงสุด"]
    FTPS2["FTPS\nPort 21+TLS\nRFC 4217"]
    SCP2["SCP\nPort 22\nSSH-based Copy"]
    SSH3["SSH\nPort 22\nEncrypted Shell"]
    RSYNC2["rsync/SSH\nPort 22\nIncremental Sync"]
  end
  FTP -->|"แทนที่ด้วย"| SFTP2
  FTP -->|"หรือ"| FTPS2
  FTP -->|"สำหรับ Copy"| SCP2
  TELNET -->|"แทนที่ด้วย"| SSH3
  style unsafe fill:#6B0000,color:#FFF
  style secure fill:#0D3B0D,color:#FFF

เอกสารอ้างอิง (References)

  1. RFC 959 — Postel, J., & Reynolds, J. (1985). File Transfer Protocol (FTP). IETF. https://datatracker.ietf.org/doc/html/rfc959

  2. RFC 4217 — Ford-Hutchinson, P. (2005). Securing FTP with TLS. IETF. https://datatracker.ietf.org/doc/html/rfc4217

  3. RFC 4251 — Ylonen, T., & Lonvick, C. (2006). The Secure Shell (SSH) Protocol Architecture. IETF. https://datatracker.ietf.org/doc/html/rfc4251

  4. RFC 4252 — Ylonen, T., & Lonvick, C. (2006). The Secure Shell (SSH) Authentication Protocol. IETF. https://datatracker.ietf.org/doc/html/rfc4252

  5. RFC 4253 — Ylonen, T., & Lonvick, C. (2006). The Secure Shell (SSH) Transport Layer Protocol. IETF. https://datatracker.ietf.org/doc/html/rfc4253

  6. RFC 4254 — Ylonen, T., & Lonvick, C. (2006). The Secure Shell (SSH) Connection Protocol. IETF. https://datatracker.ietf.org/doc/html/rfc4254

  7. OpenSSH Project — OpenBSD Foundation. (2024). OpenSSH Manual Pages. https://www.openssh.com/manual.html

  8. NIST SP 800-52 Rev. 2 — McKay, K., & Cooper, D. (2019). Guidelines for the Selection, Configuration, and Use of TLS Implementations. NIST. https://csrc.nist.gov/publications/detail/sp/800-52/rev-2/final

  9. NIST SP 800-57 Part 1 Rev. 5 — Barker, E. (2020). Recommendation for Key Management. NIST. https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final

  10. vsftpd Documentation — Gilbert, C. (2023). vsftpd — Very Secure FTP Daemon. https://security.appspot.com/vsftpd.html

  11. SSHFS / libfuse — Szeredi, M. (2023). SSHFS — SSH Filesystem. https://github.com/libfuse/sshfs

  12. fail2ban — Fail2ban Project. (2024). Ban hosts that cause multiple authentication errors. https://www.fail2ban.org/

  13. Barrett, D. J., Silverman, R. E., & Byrnes, R. G. (2005). SSH, The Secure Shell: The Definitive Guide (2nd ed.). O'Reilly Media.

  14. CIS Benchmark for Ubuntu Linux — Center for Internet Security. (2024). CIS Ubuntu Linux 22.04 LTS Benchmark v1.0.0. https://www.cisecurity.org/benchmark/ubuntu_linux

  15. OWASP — OWASP Foundation. (2023). Transport Layer Security Cheat Sheet. https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html

  16. Ylönen, T. (1996). SSH — Secure Login Connections over the Internet. Proceedings of the 6th USENIX Security Symposium, San Jose, CA.