VPN Technologies and Implementation

1. VPN Fundamentals

1.1 ความหมายและวัตถุประสงค์ของ VPN

VPN (Virtual Private Network) คือเทคโนโลยีที่สร้างการเชื่อมต่อแบบ "อุโมงค์เสมือน" (Virtual Tunnel) ผ่านเครือข่ายสาธารณะ (เช่น Internet) เพื่อให้ข้อมูลที่รับ-ส่งมีความปลอดภัย เสมือนกับอยู่บนเครือข่ายส่วนตัว

วัตถุประสงค์หลักของ VPN:

ประวัติความเป็นมาของ VPN

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945', 'background': '#1d2021', 'mainBkg': '#282828', 'nodeBorder': '#d79921', 'clusterBkg': '#3c3836', 'titleColor': '#ebdbb2', 'edgeLabelBackground': '#3c3836', 'attributeBackgroundColorEven': '#282828', 'attributeBackgroundColorOdd': '#3c3836'}}}%%
flowchart TD
    subgraph ERA1["🕐 ยุคที่ 1: การเชื่อมต่อแบบ Leased Line (1970s-1990s)"]
        A["ARPANET - 1969"]:::gruvbox_yellow --> B["Leased Lines - เชื่อมสำนักงาน - 1970s"]:::gruvbox_orange
        B --> C["Frame Relay / ATM - WAN เบื้องต้น - 1980s-1990s"]:::gruvbox_orange
    end

    subgraph ERA2["🕑 ยุคที่ 2: โปรโตคอล VPN แรก (1993-2000)"]
        D["PPTP - Microsoft - 1993"]:::gruvbox_blue --> E["L2TP - RFC 2661 - 1999"]:::gruvbox_blue
        E --> F["IPSec - RFC 2401 - 1998"]:::gruvbox_blue
    end

    subgraph ERA3["🕒 ยุคที่ 3: SSL/TLS VPN (2001-2010)"]
        G["OpenVPN - OpenSSL-based - 2001"]:::gruvbox_green --> H["SSL VPN Appliances - Cisco, Juniper - 2004"]:::gruvbox_green
        H --> I["Cloud VPN - Services - 2010"]:::gruvbox_green
    end

    subgraph ERA4["🕓 ยุคที่ 4: VPN สมัยใหม่ (2015-ปัจจุบัน)"]
        J["WireGuard - Linux Kernel - 2015"]:::gruvbox_aqua --> K["Zero-Trust VPN - SDP Model - 2018"]:::gruvbox_aqua
        K --> L["Mesh VPN - Tailscale, Headscale - 2020+"]:::gruvbox_aqua
    end

    ERA1 --> ERA2 --> ERA3 --> ERA4

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2

1.2 ประเภทของ VPN

VPN แบ่งออกเป็น 3 ประเภทหลักตามลักษณะการใช้งาน:

1.2.1 Site-to-Site VPN

Site-to-Site VPN คือการเชื่อมต่อเครือข่ายองค์กรสองแห่ง (หรือมากกว่า) เข้าหากันผ่าน Internet โดยอุปกรณ์ Gateway (Router/Firewall) ทำหน้าที่สร้างและจัดการ Tunnel

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836', 'tertiaryColor': '#504945'}}}%%
flowchart LR
    subgraph SITE_A["🏢 สำนักงานกรุงเทพ - 192.168.1.0/24"]
        PC_A1["💻 PC-A1 - 192.168.1.10"]:::gruvbox_green
        PC_A2["💻 PC-A2 - 192.168.1.11"]:::gruvbox_green
        GW_A["🔒 VPN Gateway - 203.0.113.1"]:::gruvbox_yellow
        PC_A1 --> GW_A
        PC_A2 --> GW_A
    end

    subgraph INTERNET["🌐 Internet (สาธารณะ)"]
        NET["~~~ Encrypted Tunnel ~~~ - IPSec / WireGuard"]:::gruvbox_orange
    end

    subgraph SITE_B["🏢 สำนักงานเชียงใหม่ - 10.0.0.0/24"]
        GW_B["🔒 VPN Gateway - 198.51.100.1"]:::gruvbox_yellow
        SRV_B1["🖥️ Server-B1 - 10.0.0.20"]:::gruvbox_blue
        SRV_B2["🖥️ Server-B2 - 10.0.0.21"]:::gruvbox_blue
        GW_B --> SRV_B1
        GW_B --> SRV_B2
    end

    GW_A <-->|"🔐 Encrypted"| NET
    NET <-->|"🔐 Encrypted"| GW_B

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_orange fill:#504945,stroke:#d65d0e,color:#fe8019
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2

กรณีใช้งาน Site-to-Site VPN:

1.2.2 Remote Access VPN

Remote Access VPN ให้ผู้ใช้รายบุคคลเชื่อมต่อเข้าสู่เครือข่ายองค์กรจากที่บ้านหรือที่สาธารณะ

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart TD
    subgraph USERS["👥 ผู้ใช้ระยะไกล"]
        U1["🏠 พนักงาน Work From Home - 203.0.113.50"]:::gruvbox_green
        U2["☕ Cafe / โรงแรม - 198.51.100.80"]:::gruvbox_green
        U3["📱 มือถือ 4G/5G - 10.20.30.40"]:::gruvbox_green
    end

    subgraph VPNSERVER["🔒 VPN Server - (องค์กร)"]
        VS["VPN Concentrator - 203.0.113.1:51820"]:::gruvbox_yellow
    end

    subgraph CORP["🏢 เครือข่ายองค์กร - 172.16.0.0/16"]
        DB["🗄️ Database Server - 172.16.1.10"]:::gruvbox_blue
        FILE["📁 File Server - 172.16.1.20"]:::gruvbox_blue
        INTRA["🌐 Intranet - 172.16.2.0/24"]:::gruvbox_aqua
    end

    U1 -->|"🔐 Encrypted Tunnel"| VS
    U2 -->|"🔐 Encrypted Tunnel"| VS
    U3 -->|"🔐 Encrypted Tunnel"| VS
    VS --> DB
    VS --> FILE
    VS --> INTRA

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2

1.2.3 Client-to-Site vs Site-to-Site — สรุปเปรียบเทียบ

คุณลักษณะ Remote Access VPN Site-to-Site VPN
ผู้ใช้งาน ผู้ใช้รายบุคคล Gateway อุปกรณ์
ต้องติดตั้ง Client ✅ ใช่ ❌ ไม่ใช่
จำนวน Endpoint Dynamic Fixed
ตัวอย่าง Protocol WireGuard, OpenVPN IPSec IKEv2
ความซับซ้อนในการตั้งค่า ปานกลาง สูง
เหมาะสำหรับ Work From Home สาขาองค์กร

1.3 วิธีการทำงานของ Tunneling

Tunneling คือกระบวนการห่อหุ้ม (Encapsulate) แพ็กเก็ตต้นฉบับด้วย Header ใหม่ เพื่อให้สามารถส่งผ่านเครือข่ายสาธารณะได้อย่างปลอดภัย

1.3.1 กระบวนการ Encapsulation

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart LR
    subgraph ORIGINAL["📦 แพ็กเก็ตต้นฉบับ"]
        O1["IP Header - Src: 192.168.1.10 - Dst: 10.0.0.20"]:::gruvbox_blue
        O2["TCP Header - Port 443"]:::gruvbox_green
        O3["Data - (Payload)"]:::gruvbox_aqua
    end

    subgraph ENCRYPTED["🔒 เข้ารหัส Payload"]
        E1["IP Header - (เดิม)"]:::gruvbox_blue
        E2["TCP Header - (เดิม)"]:::gruvbox_green
        E3["🔐 Encrypted Data"]:::gruvbox_orange
    end

    subgraph TUNNEL["🌐 ห่อหุ้มด้วย Tunnel Header"]
        T1["Outer IP Header - Src: 203.0.113.1 - Dst: 198.51.100.1"]:::gruvbox_yellow
        T2["VPN Header - (WireGuard/IPSec)"]:::gruvbox_orange
        T3["🔒 Inner Encrypted Packet"]:::gruvbox_red
    end

    ORIGINAL -->|"1️⃣ Encrypt"| ENCRYPTED
    ENCRYPTED -->|"2️⃣ Encapsulate"| TUNNEL

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2
    classDef gruvbox_red fill:#282828,stroke:#cc241d,color:#ebdbb2

1.3.2 การคำนวณ MTU สำหรับ VPN

MTU (Maximum Transmission Unit) ของ VPN จะน้อยกว่า Physical MTU เนื่องจากมี Header เพิ่มเข้ามา

MTUVPN = MTUPhysical - OverheadVPN Header

ตัวแปร:

ตัวอย่างการคำนวณ WireGuard MTU:

ส่วนประกอบ ขนาด (bytes)
Ethernet MTU ปกติ 1500
Outer IP Header (IPv4) 20
UDP Header 8
WireGuard Header 32
MTU ที่เหลือสำหรับ Inner Packet 1440
MTUWireGuard = 1500 - 20 - 8 - 32 = 1440 bytes

หมายเหตุ: ถ้าใช้ IPv6 เป็น Outer Header ให้เปลี่ยน 20 เป็น 40 bytes ดังนั้น MTU WireGuard over IPv6 = 1500 - 40 - 8 - 32 = 1420 bytes


2. VPN Protocols

2.1 IPSec (Internet Protocol Security)

IPSec เป็นชุดโปรโตคอลระดับ Network Layer ที่ให้ความปลอดภัยแก่การสื่อสาร IP โดยรองรับทั้ง Authentication และ Encryption

2.1.1 องค์ประกอบของ IPSec

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart TD
    IPSEC["🛡️ IPSec Suite"]:::gruvbox_yellow

    subgraph PROTOCOLS["โปรโตคอลหลัก"]
        AH["AH - Authentication Header - IP Protocol 51 - Authentication เท่านั้น - ไม่ Encrypt"]:::gruvbox_blue
        ESP["ESP - Encapsulating Security Payload - IP Protocol 50 - Authentication + Encryption - แนะนำให้ใช้"]:::gruvbox_green
    end

    subgraph MODES["โหมดการทำงาน"]
        TRANSPORT["Transport Mode - เข้ารหัสเฉพาะ Payload - ใช้ Host-to-Host"]:::gruvbox_orange
        TUNNEL["Tunnel Mode - เข้ารหัสทั้ง Packet - ใช้ Gateway-to-Gateway"]:::gruvbox_orange
    end

    subgraph IKE["IKE - Internet Key Exchange"]
        IKEv1["IKEv1 - เก่า ซับซ้อน"]:::gruvbox_red
        IKEv2["IKEv2 (แนะนำ) - เร็วกว่า ง่ายกว่า - รองรับ MOBIKE"]:::gruvbox_aqua
    end

    IPSEC --> AH
    IPSEC --> ESP
    IPSEC --> TRANSPORT
    IPSEC --> TUNNEL
    IPSEC --> IKEv1
    IPSEC --> IKEv2

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2
    classDef gruvbox_red fill:#282828,stroke:#cc241d,color:#ebdbb2

2.1.2 IKE Phase และกระบวนการ Handshake

IKEv2 Handshake แบ่งเป็น 2 Phase:

  1. IKE_SA_INIT — แลกเปลี่ยน Cryptographic Parameters, Nonce, Diffie-Hellman Public Values
  2. IKE_AUTH — ยืนยันตัวตน และสร้าง Child SA (IPSec SA)

การคำนวณ Diffie-Hellman Key Exchange:

g^a mod p = A (Alice ส่งให้ Bob) g^b mod p = B (Bob ส่งให้ Alice) Kshared = Ba mod p = Ab mod p = gab mod p

ตัวแปร:

ตัวอย่างการคำนวณ (ค่าเล็กเพื่อการเรียนรู้):

g = 5, p = 23

Alice เลือก a = 6:   A = 5^6 mod 23 = 15625 mod 23 = 8
Bob เลือก b = 15:    B = 5^15 mod 23 = 30517578125 mod 23 = 19

K_shared (Alice) = B^a mod p = 19^6 mod 23 = 47045881 mod 23 = 2
K_shared (Bob)   = A^b mod p = 8^15 mod 23 = 35184372088832 mod 23 = 2

✅ ทั้งสองฝ่ายได้ K_shared = 2 เหมือนกัน
   โดยที่ไม่เคยส่งค่า a=6 หรือ b=15 ผ่านเครือข่าย

2.2 SSL/TLS VPN

SSL/TLS VPN ใช้โปรโตคอล TLS (Transport Layer Security) ที่ทำงานระดับ Application Layer ข้อดีคือผ่าน Firewall ได้ง่ายเพราะใช้ Port 443 (HTTPS)

2.2.1 ประเภทของ SSL VPN

2.2.2 TLS Handshake ใน VPN

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
sequenceDiagram
    participant C as 💻 Client
    participant S as 🔒 VPN Server

    C->>S: ClientHello (TLS Version, Cipher Suites, Random_C)
    S->>C: ServerHello (เลือก Cipher Suite, Random_S)
    S->>C: Certificate (X.509 Public Key)
    S->>C: ServerHelloDone
    C->>C: ✅ ตรวจสอบ Certificate
    C->>S: ClientKeyExchange (Encrypted Pre-Master Secret)
    C->>S: ChangeCipherSpec
    C->>S: Finished (Encrypted)
    S->>C: ChangeCipherSpec
    S->>C: Finished (Encrypted)
    Note over C,S: 🔐 Session Established — ข้อมูลถูกเข้ารหัสแล้ว
    C->>S: VPN Data (Encrypted with Session Key)
    S->>C: VPN Data (Encrypted with Session Key)

การสร้าง Session Key จาก Pre-Master Secret:

MasterSecret = PRF ( PreMasterSecret , RandomC + RandomS )

ตัวแปร:


2.3 WireGuard

WireGuard คือโปรโตคอล VPN รุ่นใหม่ล่าสุด ออกแบบให้เรียบง่าย เร็ว และปลอดภัย รองรับใน Linux Kernel ตั้งแต่เวอร์ชัน 5.6 (มีนาคม 2020)

2.3.1 หลักการทำงานของ WireGuard

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart LR
    subgraph WG_CRYPTO["🔐 Cryptographic Primitives"]
        C1["Curve25519 - Key Exchange (ECDH)"]:::gruvbox_yellow
        C2["ChaCha20-Poly1305 - Authenticated Encryption"]:::gruvbox_green
        C3["BLAKE2s - Hashing"]:::gruvbox_blue
        C4["SipHash24 - Hashtable Keys"]:::gruvbox_aqua
        C5["HKDF - Key Derivation"]:::gruvbox_orange
    end

    subgraph WG_SESSION["📡 Session Management"]
        S1["Noise Protocol Framework - Handshake"]:::gruvbox_purple
        S2["Static Keys - (Long-term Identity)"]:::gruvbox_yellow
        S3["Ephemeral Keys - (Per-session)"]:::gruvbox_green
        S4["Session Keys - (สำหรับ Data)"]:::gruvbox_blue
    end

    C1 --> S1
    C2 --> S4
    C3 --> S1
    S1 --> S2
    S1 --> S3
    S3 --> S4

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2
    classDef gruvbox_purple fill:#282828,stroke:#b16286,color:#ebdbb2

2.3.2 WireGuard Handshake (Noise IKpsk2)

WireGuard ใช้ Noise Protocol Framework ที่มีเพียง 1 Round-Trip (เทียบกับ IKEv2 ที่ต้องใช้ 2 Round-Trip)

สมการการสร้าง Session Key:

Ci , k = HKDF ( Ci-1 , DH ( privi , pubj ) )

ตัวแปร:


3. Modern VPN Solutions

3.1 WireGuard — การติดตั้งและตั้งค่า

3.1.1 การติดตั้ง WireGuard บน Linux

# Ubuntu/Debian
sudo apt update && sudo apt install -y wireguard wireguard-tools

# Arch Linux / Void Linux
sudo pacman -S wireguard-tools
# หรือ
sudo xbps-install -S wireguard-tools

# ตรวจสอบการติดตั้ง
which wg
wg --version

3.1.2 สร้าง Key Pairs สำหรับ WireGuard

# สร้าง Private Key
wg genkey > server_private.key

# สร้าง Public Key จาก Private Key
wg pubkey < server_private.key > server_public.key

# หรือสร้างทั้งคู่พร้อมกัน
wg genkey | tee server_private.key | wg pubkey > server_public.key

# ดูค่า Keys
echo "Private Key: $(cat server_private.key)"
echo "Public Key:  $(cat server_public.key)"

# สร้าง Pre-shared Key (เพิ่มความปลอดภัยอีกชั้น)
wg genpsk > preshared.key

ตัวอย่าง Output:

Private Key: 0Fj3j+K2vMkqXmj/rFq8F5V5x9p5DxC8s4aT0R8P9W4=
Public Key:  mNzD4e7sF8vP2kQ1rT6xJ5bH0cM3pL9wY4nE7oA1gI0=

⚠️ คำเตือน: Private Key ต้องเก็บเป็นความลับ ห้ามเผยแพร่หรือ commit ลง Git

3.1.3 ตัวอย่างข้อมูลสำหรับการทดลอง Lab

สมมติมีสถานการณ์ดังนี้:

Role Hostname Public IP WireGuard IP Port
Server vpn.example.com 203.0.113.1 10.8.0.1/24 51820
Client-1 laptop-alice Dynamic 10.8.0.2/32 -
Client-2 laptop-bob Dynamic 10.8.0.3/32 -

Keys (ตัวอย่างสำหรับ Lab เท่านั้น — ห้ามใช้ Production):

Role Private Key Public Key
Server sPriv_AAAA... sPub_BBBB...
Alice aPriv_CCCC... aPub_DDDD...
Bob bPriv_EEEE... bPub_FFFF...

3.1.4 การตั้งค่า WireGuard Server

# /etc/wireguard/wg0.conf (Server Configuration)
# ไฟล์ตั้งค่า WireGuard สำหรับ Server

[Interface]
# Private Key ของ Server (ได้จาก wg genkey)
PrivateKey = sPriv_AAAA...
# IP Address ของ WireGuard Interface บน Server
Address = 10.8.0.1/24
# Port ที่ Server รับฟัง
ListenPort = 51820
# เปิด IP Forwarding เพื่อให้ Client เข้าถึง LAN ได้
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

# ===== Peer: Alice =====
[Peer]
# Public Key ของ Alice
PublicKey = aPub_DDDD...
# IP ที่อนุญาตให้ Alice ใช้
AllowedIPs = 10.8.0.2/32

# ===== Peer: Bob =====
[Peer]
PublicKey = bPub_FFFF...
AllowedIPs = 10.8.0.3/32

3.1.5 การตั้งค่า WireGuard Client (Alice)

# /etc/wireguard/wg0.conf (Client Configuration — Alice)

[Interface]
# Private Key ของ Alice
PrivateKey = aPriv_CCCC...
# IP Address ของ Alice ใน VPN Network
Address = 10.8.0.2/32
# DNS Server ที่ใช้เมื่อเชื่อม VPN
DNS = 8.8.8.8

[Peer]
# Public Key ของ Server
PublicKey = sPub_BBBB...
# IP:Port ของ Server
Endpoint = 203.0.113.1:51820
# 0.0.0.0/0 = ส่ง Traffic ทั้งหมดผ่าน VPN (Full Tunnel)
# 10.8.0.0/24 = ส่งเฉพาะ VPN Traffic (Split Tunnel)
AllowedIPs = 0.0.0.0/0
# ส่ง Keepalive ทุก 25 วินาที (สำหรับ NAT Traversal)
PersistentKeepalive = 25

3.1.6 การเปิดใช้งาน WireGuard

# เปิด WireGuard Interface
sudo wg-quick up wg0

# หยุด WireGuard
sudo wg-quick down wg0

# ตั้งค่าให้เริ่มอัตโนมัติเมื่อ Boot
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# ดูสถานะ
sudo wg show
sudo wg show wg0

# ตรวจสอบ Route
ip route show

ตัวอย่าง Output ของ wg show:

interface: wg0
  public key: sPub_BBBB...
  private key: (hidden)
  listening port: 51820

peer: aPub_DDDD...
  endpoint: 198.51.100.50:54321
  allowed ips: 10.8.0.2/32
  latest handshake: 2 minutes, 15 seconds ago
  transfer: 4.56 MiB received, 12.34 MiB sent

3.1.7 Code Python สำหรับตรวจสอบสถานะ WireGuard

#!/usr/bin/env python3
"""
โมดูลตรวจสอบสถานะ WireGuard VPN
วิชา Network Security — สัปดาห์ที่ 9
ผู้สอน: อรรถพล คงหวาน
"""

import subprocess
import re
from datetime import datetime
from dataclasses import dataclass, field
from typing import Optional


@dataclass
class WireGuardPeer:
    """ข้อมูล Peer ใน WireGuard"""
    public_key: str
    endpoint: Optional[str] = None
    allowed_ips: list = field(default_factory=list)
    latest_handshake: Optional[str] = None
    transfer_rx: str = "0 B"
    transfer_tx: str = "0 B"


@dataclass  
class WireGuardInterface:
    """ข้อมูล WireGuard Interface"""
    name: str
    public_key: str
    listen_port: Optional[int] = None
    peers: list = field(default_factory=list)


def get_wireguard_status(interface: str = "wg0") -> dict:
    """
    ดึงข้อมูลสถานะ WireGuard จากคำสั่ง wg show
    
    Args:
        interface: ชื่อ WireGuard interface (default: wg0)
    
    Returns:
        dict ที่มีข้อมูลสถานะของ WireGuard
    """
    try:
        # รัน wg show dump เพื่อได้ข้อมูลแบบ machine-readable
        result = subprocess.run(
            ["sudo", "wg", "show", interface, "dump"],
            capture_output=True, text=True, check=True
        )
        return parse_wg_dump(result.stdout)
    except subprocess.CalledProcessError as e:
        print(f"❌ ไม่สามารถดึงข้อมูล WireGuard: {e.stderr}")
        return {}
    except FileNotFoundError:
        print("❌ ไม่พบคำสั่ง wg — กรุณาติดตั้ง wireguard-tools")
        return {}


def parse_wg_dump(dump_output: str) -> dict:
    """
    แปลง Output จาก 'wg show dump' ให้เป็น dict
    
    Format ของ dump:
    บรรทัดแรก: interface_privkey pubkey listen_port fwmark
    บรรทัดถัดไป: peer_pubkey preshared endpoint allowed_ips handshake rx tx keepalive
    """
    lines = dump_output.strip().split(' - ')
    if not lines:
        return {}
    
    result = {"interface": {}, "peers": []}
    
    # บรรทัดแรกคือ Interface
    iface_parts = lines[0].split('\t')
    result["interface"] = {
        "private_key": "(hidden)",
        "public_key": iface_parts[1] if len(iface_parts) > 1 else "unknown",
        "listen_port": iface_parts[2] if len(iface_parts) > 2 else "unknown",
    }
    
    # บรรทัดถัดไปคือ Peers
    for line in lines[1:]:
        parts = line.split('\t')
        if len(parts) >= 7:
            # แปลง timestamp เป็นเวลาที่อ่านได้
            handshake_ts = int(parts[4]) if parts[4].isdigit() else 0
            if handshake_ts > 0:
                handshake_dt = datetime.fromtimestamp(handshake_ts)
                handshake_str = handshake_dt.strftime("%Y-%m-%d %H:%M:%S")
            else:
                handshake_str = "ยังไม่เคย Handshake"
            
            # แปลงขนาดข้อมูลให้อ่านง่าย
            rx_bytes = int(parts[5]) if parts[5].isdigit() else 0
            tx_bytes = int(parts[6]) if parts[6].isdigit() else 0
            
            peer = {
                "public_key": parts[0][:20] + "...",  # แสดงแค่ 20 ตัวแรก
                "endpoint": parts[2] if parts[2] != "(none)" else "ไม่ทราบ",
                "allowed_ips": parts[3],
                "latest_handshake": handshake_str,
                "transfer_rx": format_bytes(rx_bytes),
                "transfer_tx": format_bytes(tx_bytes),
            }
            result["peers"].append(peer)
    
    return result


def format_bytes(num_bytes: int) -> str:
    """แปลงขนาด bytes ให้อ่านง่าย"""
    for unit in ['B', 'KiB', 'MiB', 'GiB', 'TiB']:
        if num_bytes < 1024.0:
            return f"{num_bytes:.2f} {unit}"
        num_bytes /= 1024.0
    return f"{num_bytes:.2f} PiB"


def calculate_vpn_mtu(
    physical_mtu: int = 1500,
    ipv6_outer: bool = False,
    protocol: str = "wireguard"
) -> int:
    """
    คำนวณ MTU ที่เหมาะสมสำหรับ VPN
    
    Args:
        physical_mtu: MTU ของ Physical Interface (default 1500)
        ipv6_outer: ใช้ IPv6 เป็น Outer Header หรือไม่
        protocol: โปรโตคอล VPN ที่ใช้
    
    Returns:
        MTU ที่แนะนำสำหรับ VPN Interface
    """
    # ขนาด Overhead ของแต่ละ Protocol
    overheads = {
        "wireguard": {
            "ipv4_outer_ip": 20,
            "ipv6_outer_ip": 40,
            "udp": 8,
            "wireguard_header": 32,
        },
        "openvpn_udp": {
            "ipv4_outer_ip": 20,
            "ipv6_outer_ip": 40,
            "udp": 8,
            "openvpn_header": 38,  # overhead ประมาณ
        },
        "ipsec_esp": {
            "ipv4_outer_ip": 20,
            "ipv6_outer_ip": 40,
            "esp_header": 8,
            "esp_trailer": 2,
            "esp_auth": 12,
            "iv": 16,
        }
    }
    
    if protocol not in overheads:
        raise ValueError(f"ไม่รองรับ Protocol: {protocol}")
    
    overhead = overheads[protocol]
    total_overhead = 0
    
    # คำนวณ Overhead รวม
    ip_header = "ipv6_outer_ip" if ipv6_outer else "ipv4_outer_ip"
    
    for key, value in overhead.items():
        if key == "ipv4_outer_ip" and ipv6_outer:
            continue  # ข้ามถ้าใช้ IPv6
        if key == "ipv6_outer_ip" and not ipv6_outer:
            continue  # ข้ามถ้าใช้ IPv4
        total_overhead += value
    
    vpn_mtu = physical_mtu - total_overhead
    
    print(f" - 📊 การคำนวณ MTU สำหรับ {protocol.upper()}")
    print(f"{'='*50}")
    print(f"  Physical MTU:           {physical_mtu:>6} bytes")
    print(f"  Outer IP Header ({'IPv6' if ipv6_outer else 'IPv4'}): -{overhead.get(ip_header, 0):>4} bytes")
    
    for key, value in overhead.items():
        if "outer_ip" not in key:
            label = key.replace("_", " ").title()
            print(f"  {label:<26} -{value:>4} bytes")
    
    print(f"{'─'*50}")
    print(f"  VPN MTU ที่แนะนำ:        {vpn_mtu:>6} bytes")
    
    return vpn_mtu


def display_status(status: dict):
    """แสดงสถานะ WireGuard ในรูปแบบที่อ่านง่าย"""
    if not status:
        return
    
    print(" - 🔒 WireGuard VPN Status")
    print("=" * 60)
    
    iface = status.get("interface", {})
    print(f"Interface Public Key : {iface.get('public_key', 'unknown')[:30]}...")
    print(f"Listening Port       : {iface.get('listen_port', 'unknown')}")
    
    peers = status.get("peers", [])
    print(f" - 📡 Connected Peers: {len(peers)}")
    print("-" * 60)
    
    for i, peer in enumerate(peers, 1):
        print(f" -   Peer #{i}:")
        print(f"    Public Key    : {peer.get('public_key', 'unknown')}")
        print(f"    Endpoint      : {peer.get('endpoint', 'ไม่ทราบ')}")
        print(f"    Allowed IPs   : {peer.get('allowed_ips', 'none')}")
        print(f"    Last Handshake: {peer.get('latest_handshake', 'ไม่ทราบ')}")
        print(f"    ↓ Received    : {peer.get('transfer_rx', '0 B')}")
        print(f"    ↑ Sent        : {peer.get('transfer_tx', '0 B')}")


# ===== ตัวอย่างการใช้งาน =====
if __name__ == "__main__":
    print("🚀 WireGuard VPN Monitor — Network Security Lab")
    print("=" * 60)
    
    # คำนวณ MTU สำหรับ VPN Protocols ต่าง ๆ
    wg_mtu_v4 = calculate_vpn_mtu(1500, ipv6_outer=False, protocol="wireguard")
    wg_mtu_v6 = calculate_vpn_mtu(1500, ipv6_outer=True, protocol="wireguard")
    ipsec_mtu = calculate_vpn_mtu(1500, ipv6_outer=False, protocol="ipsec_esp")
    
    print(f" - 📋 สรุปการเปรียบเทียบ MTU:")
    print(f"  WireGuard (IPv4): {wg_mtu_v4} bytes")
    print(f"  WireGuard (IPv6): {wg_mtu_v6} bytes")
    print(f"  IPSec ESP (IPv4): {ipsec_mtu} bytes")
    
    # ดึงสถานะ WireGuard จริง (ต้องรันในระบบที่มี WireGuard)
    print(" -  - 🔍 ดึงข้อมูลสถานะ WireGuard...")
    status = get_wireguard_status("wg0")
    
    if status:
        display_status(status)
    else:
        print("ℹ️  ไม่พบข้อมูล WireGuard (อาจยังไม่ได้เปิดใช้งาน)")
        print("   รัน: sudo wg-quick up wg0 เพื่อเริ่ม WireGuard")

ตัวอย่าง Output ของโปรแกรม:

🚀 WireGuard VPN Monitor — Network Security Lab
============================================================

📊 การคำนวณ MTU สำหรับ WIREGUARD
==================================================
  Physical MTU:             1500 bytes
  Outer IP Header (IPv4):    -20 bytes
  Udp                         -8 bytes
  Wireguard Header            -32 bytes
──────────────────────────────────────────────────
  VPN MTU ที่แนะนำ:           1440 bytes

📊 การคำนวณ MTU สำหรับ WIREGUARD
==================================================
  Physical MTU:             1500 bytes
  Outer IP Header (IPv6):    -40 bytes
  Udp                         -8 bytes
  Wireguard Header            -32 bytes
──────────────────────────────────────────────────
  VPN MTU ที่แนะนำ:           1420 bytes

3.2 Sshuttle — Transparent Proxy VPN

Sshuttle เป็นเครื่องมือที่สร้าง VPN แบบ Transparent ผ่าน SSH โดยไม่ต้องมี Root Access ฝั่ง Server และไม่ต้องตั้งค่า VPN Server ล่วงหน้า

3.2.1 วิธีการทำงานของ Sshuttle

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart TD
    subgraph CLIENT["💻 Client (Local Machine)"]
        APP["🌐 แอปพลิเคชัน - (Browser, curl, etc.)"]:::gruvbox_blue
        IPTBL["iptables Rules - (สร้างโดย sshuttle)"]:::gruvbox_yellow
        SSHUTTLE["sshuttle Process - (Local Proxy)"]:::gruvbox_green
    end

    subgraph SSH_TUNNEL["🔐 SSH Tunnel (Encrypted)"]
        TUNNEL["SSH Encrypted Channel - Port 22"]:::gruvbox_orange
    end

    subgraph SERVER["🖥️ SSH Server (Remote)"]
        SSH_SRV["SSH Daemon"]:::gruvbox_aqua
        PYTHON_SRV["Python Helper - (auto-uploaded by sshuttle)"]:::gruvbox_green
        FORWARD["Forward to Destination"]:::gruvbox_blue
    end

    subgraph DEST["🌍 Destination"]
        WEB["Web Server - 10.0.0.20:80"]:::gruvbox_red
    end

    APP -->|"1️⃣ TCP Connection"| IPTBL
    IPTBL -->|"2️⃣ Redirect to sshuttle"| SSHUTTLE
    SSHUTTLE -->|"3️⃣ ส่งผ่าน SSH"| TUNNEL
    TUNNEL -->|"4️⃣ Receive"| SSH_SRV
    SSH_SRV --> PYTHON_SRV
    PYTHON_SRV -->|"5️⃣ Forward"| FORWARD
    FORWARD -->|"6️⃣ Connect"| WEB
    WEB -.->|"Response"| FORWARD
    FORWARD -.->|"Response"| PYTHON_SRV
    PYTHON_SRV -.->|"Response"| SSH_SRV
    SSH_SRV -.->|"Response"| TUNNEL
    TUNNEL -.->|"Response"| SSHUTTLE
    SSHUTTLE -.->|"Response"| APP

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2
    classDef gruvbox_red fill:#282828,stroke:#cc241d,color:#ebdbb2
    classDef gruvbox_purple fill:#282828,stroke:#b16286,color:#ebdbb2

3.2.2 การติดตั้ง Sshuttle

# Ubuntu/Debian
sudo apt install sshuttle

# pip (ทุก Platform)
pip install sshuttle

# Arch Linux
sudo pacman -S sshuttle

# ตรวจสอบการติดตั้ง
sshuttle --version

3.2.3 การใช้งาน Sshuttle — ตัวอย่างคำสั่ง

# ===== ตัวอย่างที่ 1: Route ทุก Traffic ผ่าน SSH =====
# ส่ง Traffic ทั้งหมด (0.0.0.0/0) ผ่าน SSH Server
sshuttle --dns -r user@ssh-server.example.com 0.0.0.0/0

# ===== ตัวอย่างที่ 2: Route เฉพาะ Subnet ที่ต้องการ =====
# ส่งเฉพาะ Traffic ที่ไปยัง 10.0.0.0/8 ผ่าน SSH
sshuttle -r user@203.0.113.1 10.0.0.0/8

# ===== ตัวอย่างที่ 3: ใช้ SSH Key และ Port ที่กำหนด =====
sshuttle -r user@203.0.113.1:2222 \
    --ssh-cmd "ssh -i ~/.ssh/my_key" \
    10.0.0.0/8 192.168.0.0/16

# ===== ตัวอย่างที่ 4: ยกเว้น Subnet บางส่วน =====
# Route ทุกอย่าง ยกเว้น 192.168.1.0/24 (LAN ของตัวเอง)
sshuttle -r user@203.0.113.1 0.0.0.0/0 \
    --exclude 192.168.1.0/24

# ===== ตัวอย่างที่ 5: เปิด VPN แบบ Daemon (Background) =====
sshuttle -r user@203.0.113.1 0.0.0.0/0 \
    --daemon --pidfile /tmp/sshuttle.pid

# หยุด Sshuttle Daemon
kill $(cat /tmp/sshuttle.pid)

# ===== ตัวอย่างที่ 6: Debug Mode =====
sshuttle -r user@203.0.113.1 10.0.0.0/8 -vvv

3.2.4 Script Python สำหรับจัดการ Sshuttle

#!/usr/bin/env python3
"""
ตัวจัดการ Sshuttle VPN — เครื่องมือช่วยสร้างและจัดการ VPN over SSH
วิชา Network Security — สัปดาห์ที่ 9
ผู้สอน: อรรถพล คงหวาน
"""

import subprocess
import os
import signal
import time
from pathlib import Path
from dataclasses import dataclass
from typing import Optional


@dataclass
class SshuttleConfig:
    """
    การตั้งค่าสำหรับ Sshuttle VPN
    """
    # ข้อมูล SSH Server
    ssh_host: str           # เช่น "203.0.113.1"
    ssh_user: str           # เช่น "admin"
    ssh_port: int = 22      # Port ของ SSH Server
    ssh_key: Optional[str] = None  # Path ของ SSH Private Key
    
    # การตั้งค่า Routing
    subnets: list = None    # Subnets ที่ต้องการ Route ผ่าน VPN
    exclude_subnets: list = None  # Subnets ที่ยกเว้น
    dns: bool = True        # ส่ง DNS ผ่าน VPN ด้วย
    
    # การตั้งค่า Process
    daemon: bool = False    # รันแบบ Background
    pid_file: str = "/tmp/sshuttle.pid"
    
    def __post_init__(self):
        if self.subnets is None:
            # Default: Route ทุก Traffic
            self.subnets = ["0.0.0.0/0"]
        if self.exclude_subnets is None:
            self.exclude_subnets = []


class SshuttleManager:
    """ตัวจัดการ Sshuttle VPN Session"""
    
    def __init__(self, config: SshuttleConfig):
        self.config = config
        self.process: Optional[subprocess.Popen] = None
    
    def build_command(self) -> list:
        """สร้างคำสั่ง sshuttle จากการตั้งค่า"""
        cmd = ["sshuttle"]
        
        # กำหนด Remote Host
        remote = f"{self.config.ssh_user}@{self.config.ssh_host}"
        if self.config.ssh_port != 22:
            remote += f":{self.config.ssh_port}"
        cmd.extend(["-r", remote])
        
        # เพิ่ม SSH Key ถ้ากำหนด
        if self.config.ssh_key:
            ssh_cmd = f"ssh -i {self.config.ssh_key}"
            cmd.extend(["--ssh-cmd", ssh_cmd])
        
        # เพิ่ม DNS forwarding
        if self.config.dns:
            cmd.append("--dns")
        
        # เพิ่ม Subnets ที่ต้องการ Route
        cmd.extend(self.config.subnets)
        
        # เพิ่ม Subnets ที่ยกเว้น
        for subnet in self.config.exclude_subnets:
            cmd.extend(["--exclude", subnet])
        
        # รันแบบ Daemon
        if self.config.daemon:
            cmd.extend(["--daemon", "--pidfile", self.config.pid_file])
        
        return cmd
    
    def start(self) -> bool:
        """
        เริ่ม Sshuttle VPN
        
        Returns:
            True ถ้าสำเร็จ, False ถ้าล้มเหลว
        """
        cmd = self.build_command()
        print(f"🚀 เริ่ม Sshuttle VPN...")
        print(f"   คำสั่ง: {' '.join(cmd)}")
        
        try:
            if self.config.daemon:
                # รันแบบ Daemon
                result = subprocess.run(
                    cmd, check=True,
                    capture_output=True, text=True
                )
                print(f"✅ Sshuttle Daemon เริ่มทำงานแล้ว (PID file: {self.config.pid_file})")
                return True
            else:
                # รันแบบ Foreground (Blocking)
                self.process = subprocess.Popen(
                    cmd,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    text=True
                )
                print(f"✅ Sshuttle VPN กำลังทำงาน (PID: {self.process.pid})")
                print("   กด Ctrl+C เพื่อหยุด")
                self.process.wait()
                return True
                
        except subprocess.CalledProcessError as e:
            print(f"❌ ไม่สามารถเริ่ม Sshuttle: {e.stderr}")
            return False
        except FileNotFoundError:
            print("❌ ไม่พบคำสั่ง sshuttle — กรุณาติดตั้งก่อน")
            print("   pip install sshuttle")
            return False
        except KeyboardInterrupt:
            print(" - ⚠️ หยุด Sshuttle VPN")
            return True
    
    def stop(self) -> bool:
        """หยุด Sshuttle VPN"""
        if self.config.daemon:
            pid_file = Path(self.config.pid_file)
            if pid_file.exists():
                pid = int(pid_file.read_text().strip())
                try:
                    os.kill(pid, signal.SIGTERM)
                    pid_file.unlink()
                    print(f"✅ หยุด Sshuttle Daemon (PID: {pid})")
                    return True
                except ProcessLookupError:
                    print(f"⚠️ ไม่พบ Process PID {pid}")
                    return False
        
        if self.process and self.process.poll() is None:
            self.process.terminate()
            self.process.wait(timeout=5)
            print("✅ หยุด Sshuttle VPN สำเร็จ")
            return True
        
        return False
    
    def test_connectivity(self, test_host: str = "8.8.8.8") -> bool:
        """ทดสอบการเชื่อมต่อผ่าน VPN"""
        print(f" - 🔍 ทดสอบการเชื่อมต่อไปยัง {test_host}...")
        try:
            result = subprocess.run(
                ["ping", "-c", "3", "-W", "2", test_host],
                capture_output=True, text=True
            )
            if result.returncode == 0:
                # แยกข้อมูล RTT
                lines = result.stdout.split(' - ')
                stats_line = [l for l in lines if 'avg' in l or 'rtt' in l]
                if stats_line:
                    print(f"✅ การเชื่อมต่อสำเร็จ")
                    print(f"   {stats_line[-1].strip()}")
                return True
            else:
                print(f"❌ ไม่สามารถเชื่อมต่อ: {result.stderr}")
                return False
        except Exception as e:
            print(f"❌ เกิดข้อผิดพลาด: {e}")
            return False


# ===== ตัวอย่างการใช้งาน =====
if __name__ == "__main__":
    print("🔐 Sshuttle VPN Manager — Network Security Lab")
    print("=" * 60)
    
    # สร้าง Config สำหรับ Lab
    config = SshuttleConfig(
        ssh_host="203.0.113.1",       # IP ของ SSH Server (ตัวอย่าง)
        ssh_user="student",
        ssh_port=22,
        ssh_key="~/.ssh/lab_key",     # SSH Key สำหรับ Lab
        subnets=["10.0.0.0/8"],       # Route เฉพาะ Internal Network
        exclude_subnets=[],
        dns=True,
        daemon=False,
    )
    
    print(f" - 📋 การตั้งค่า VPN:")
    print(f"  SSH Server : {config.ssh_user}@{config.ssh_host}:{config.ssh_port}")
    print(f"  Route      : {', '.join(config.subnets)}")
    print(f"  DNS        : {'ส่งผ่าน VPN' if config.dns else 'ใช้ Local DNS'}")
    
    manager = SshuttleManager(config)
    
    # แสดงคำสั่งที่จะใช้
    cmd = manager.build_command()
    print(f" - 📟 คำสั่งที่จะรัน:")
    print(f"  {' '.join(cmd)}")
    
    print(" - 💡 ตัวอย่างคำสั่ง sshuttle อื่น ๆ:")
    examples = [
        ("Route ทุก Traffic", "sshuttle -r user@server 0.0.0.0/0 --dns"),
        ("Route Internal Only", "sshuttle -r user@server 10.0.0.0/8 192.168.0.0/16"),
        ("Background Mode", "sshuttle -r user@server 0.0.0.0/0 --daemon"),
        ("Debug Mode", "sshuttle -r user@server 0.0.0.0/0 -vvv"),
    ]
    for desc, cmd_str in examples:
        print(f"  • {desc}:")
        print(f"    {cmd_str}")

4. VPN Security Best Practices

4.1 หลักการความปลอดภัย VPN

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
mindmap
  root(("🔒 VPN Security - Best Practices"))
    ("🔑 Key Management")
      ["ใช้ Key ขนาดใหญ่พอ - (RSA ≥ 2048, EC ≥ 256)"]
      ["หมุนเวียน Key - สม่ำเสมอ"]
      ["เก็บ Private Key - อย่างปลอดภัย"]
    ("🔐 Encryption")
      ["ใช้ Algorithm ที่ทันสมัย - (ChaCha20, AES-256-GCM)"]
      ["หลีกเลี่ยง - DES, 3DES, RC4"]
      ["Perfect Forward Secrecy - (PFS)"]
    ("🛡️ Authentication")
      ["Multi-Factor Auth - (MFA)"]
      ["Certificate-based - Authentication"]
      ["ห้ามใช้ Password - อ่อนแอ"]
    ("📡 Network")
      ["จำกัด Access - ด้วย Firewall"]
      ["Network Segmentation - หลัง VPN"]
      ["Monitor VPN Logs - สม่ำเสมอ"]
    ("🔄 Operations")
      ["อัปเดต VPN Software - สม่ำเสมอ"]
      ["Audit Log - ทุก Connection"]
      ["แผน Incident Response"]

4.2 การเลือก Cipher Suite

Cipher Suite ที่แนะนำสำหรับ VPN ในปัจจุบัน (2024):

ระดับความปลอดภัย Key Exchange Authentication Encryption MAC
⭐⭐⭐ สูงสุด X25519 (Curve25519) Ed25519 ChaCha20-Poly1305 BLAKE2s
⭐⭐⭐ สูงสุด ECDH P-384 ECDSA P-384 AES-256-GCM SHA-384
⭐⭐ ดี ECDH P-256 ECDSA P-256 AES-128-GCM SHA-256
❌ หลีกเลี่ยง RSA-1024 RSA-1024 3DES MD5
❌ ไม่ปลอดภัย DH-768 - DES SHA-1

4.3 Perfect Forward Secrecy (PFS)

PFS (Perfect Forward Secrecy) คือคุณสมบัติที่ทำให้การถอดรหัสข้อมูลในอดีตเป็นไปไม่ได้ แม้จะได้ Private Key ในปัจจุบัน โดยใช้ Ephemeral Key (Key ชั่วคราว) สำหรับแต่ละ Session

Ksession = KDF ( DHephemeral ( privA,temp , pubB,temp ) , nonce )

ตัวแปร:

4.4 การตรวจสอบและ Monitoring

# ตรวจสอบ WireGuard Connection
sudo wg show all

# ดู Log ของ WireGuard
sudo journalctl -u wg-quick@wg0 -f

# ตรวจสอบ Traffic ผ่าน WireGuard Interface
sudo tcpdump -i wg0 -n

# ดู Routing Table หลังเชื่อม VPN
ip route show

# ทดสอบว่า IP ภายนอกเปลี่ยนแล้ว
curl ifconfig.me
curl ipinfo.io/ip

# ตรวจสอบ DNS Leak
curl https://api.ipify.org
nslookup whoami.akamai.net

5. เปรียบเทียบ VPN Solutions

5.1 ตารางเปรียบเทียบ VPN Protocols

คุณลักษณะ WireGuard IPSec IKEv2 OpenVPN Sshuttle
ปีเปิดตัว 2015 1998 2001 2012
Layer L3 L3 L3 L4 (TCP)
Protocol UDP UDP UDP/TCP TCP (SSH)
Port เริ่มต้น 51820/UDP 500, 4500/UDP 1194/UDP 22/TCP
Encryption ChaCha20-Poly1305 AES-256-GCM AES-256-GCM AES-256-GCM (SSH)
Key Exchange Curve25519 DH/ECDH DH/ECDH DH (SSH)
ขนาดโค้ด ~4,000 บรรทัด ซับซ้อนมาก ~70,000 บรรทัด เล็กน้อย
ความเร็ว ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
ง่ายต่อการตั้งค่า ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐
รองรับ NAT ✅ ดีมาก ⚠️ ต้องการ NAT-T ✅ ดี ✅ ดีมาก
ต้องการ Root บน Server
Stealth/ผ่าน Firewall ⚠️ ⚠️ ✅ (TCP 443) ✅ (Port 22)
ใช้งานดีกับ ทุกกรณี Enterprise ทั่วไป ใช้ SSH Server ที่มี

5.2 แผนภาพการเลือก VPN ที่เหมาะสม

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart TD
    START["🤔 ต้องการใช้ VPN - ประเภทไหน?"]:::gruvbox_yellow

    Q1{"มี SSH Server - ที่เข้าถึงได้?"}:::gruvbox_blue
    Q2{"ต้องการ - ประสิทธิภาพสูง?"}:::gruvbox_blue
    Q3{"มี Root Access - บน Server?"}:::gruvbox_blue
    Q4{"ต้องการผ่าน - Firewall เข้มงวด?"}:::gruvbox_blue
    Q5{"ต้องการ - Enterprise Features?"}:::gruvbox_blue

    SSHUTTLE["✅ Sshuttle - VPN over SSH - ง่าย ไม่ต้องตั้งค่า Server"]:::gruvbox_green
    WIREGUARD["✅ WireGuard - เร็วที่สุด ทันสมัย - ตั้งค่าง่าย"]:::gruvbox_green
    OPENVPN_TCP["✅ OpenVPN (TCP 443) - ผ่าน Firewall ได้ - ปลอดภัยสูง"]:::gruvbox_aqua
    IPSEC["✅ IPSec IKEv2 - Mobile-friendly - Enterprise Standard"]:::gruvbox_orange
    OPENVPN["✅ OpenVPN - ยืดหยุ่น รองรับดี - ทุก Platform"]:::gruvbox_aqua

    START --> Q1
    Q1 -->|"ใช่"| SSHUTTLE
    Q1 -->|"ไม่ใช่"| Q3
    Q3 -->|"ไม่มี Root"| Q4
    Q3 -->|"มี Root"| Q2
    Q2 -->|"ใช่"| WIREGUARD
    Q2 -->|"ปานกลาง"| Q5
    Q4 -->|"ใช่ เข้มงวดมาก"| OPENVPN_TCP
    Q4 -->|"ไม่ (ปกติ)"| WIREGUARD
    Q5 -->|"ใช่"| IPSEC
    Q5 -->|"ไม่"| OPENVPN

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2

5.3 การทดสอบประสิทธิภาพ VPN — ตัวอย่างการวัด Throughput

#!/usr/bin/env python3
"""
เครื่องมือวัดประสิทธิภาพ VPN — Throughput Calculator
วิชา Network Security — สัปดาห์ที่ 9
ผู้สอน: อรรถพล คงหวาน
"""

import subprocess
import time
import statistics
from dataclasses import dataclass
from typing import Optional


@dataclass
class SpeedTestResult:
    """ผลการทดสอบความเร็ว"""
    protocol: str           # ชื่อ VPN Protocol
    avg_latency_ms: float   # ค่าเฉลี่ย Latency (ms)
    jitter_ms: float        # Jitter (ms) — ความผันผวน
    throughput_mbps: float  # ความเร็วส่งข้อมูล (Mbps)
    packet_loss_pct: float  # เปอร์เซ็นต์ Packet Loss


def measure_latency(host: str, count: int = 10) -> dict:
    """
    วัด Latency โดยใช้ ping
    
    Args:
        host: Host ที่ต้องการวัด
        count: จำนวนครั้งที่ ping
    
    Returns:
        dict ที่มีค่า min, avg, max, jitter
    """
    try:
        result = subprocess.run(
            ["ping", "-c", str(count), "-q", host],
            capture_output=True, text=True, timeout=30
        )
        
        # แยกข้อมูลจาก ping output
        lines = result.stdout.split(' - ')
        
        # ดึงบรรทัด statistics
        stat_line = [l for l in lines if 'rtt' in l.lower() or 'round-trip' in l.lower()]
        loss_line = [l for l in lines if 'packet loss' in l.lower()]
        
        latency_values = {"min": 0, "avg": 0, "max": 0, "jitter": 0, "loss": 0}
        
        if stat_line:
            # format: rtt min/avg/max/mdev = X/X/X/X ms
            parts = stat_line[0].split('=')[1].strip().split('/')
            if len(parts) >= 4:
                latency_values["min"] = float(parts[0])
                latency_values["avg"] = float(parts[1])
                latency_values["max"] = float(parts[2])
                latency_values["jitter"] = float(parts[3].split()[0])
        
        if loss_line:
            # format: X packets transmitted, Y received, Z% packet loss
            for part in loss_line[0].split(','):
                if 'loss' in part.lower():
                    loss_str = part.strip().split('%')[0].strip().split()[-1]
                    latency_values["loss"] = float(loss_str)
        
        return latency_values
    
    except (subprocess.TimeoutExpired, Exception) as e:
        print(f"❌ ไม่สามารถวัด Latency: {e}")
        return {"min": 0, "avg": 0, "max": 0, "jitter": 0, "loss": 100}


def calculate_vpn_overhead_impact(
    base_throughput_mbps: float,
    overhead_bytes: int,
    mtu: int = 1500
) -> dict:
    """
    คำนวณผลกระทบของ VPN Overhead ต่อ Throughput
    
    Args:
        base_throughput_mbps: ความเร็วพื้นฐาน (Mbps)
        overhead_bytes: ขนาด Overhead ของ VPN (bytes)
        mtu: MTU ของ Physical Interface
    
    Returns:
        dict ที่มีผลการคำนวณ
    """
    # สัดส่วน Overhead
    overhead_ratio = overhead_bytes / mtu
    
    # ความเร็วหลังหักค่า Overhead (ประมาณการ)
    effective_throughput = base_throughput_mbps * (1 - overhead_ratio)
    
    # คำนวณ Payload ที่ได้จริงต่อ Packet
    payload_per_packet = mtu - overhead_bytes
    
    # จำนวน Packets ต่อวินาที
    # 1 Mbps = 1,000,000 bits/s = 125,000 bytes/s
    bytes_per_sec = base_throughput_mbps * 125_000
    packets_per_sec = bytes_per_sec / mtu
    
    return {
        "base_throughput_mbps": base_throughput_mbps,
        "overhead_bytes": overhead_bytes,
        "overhead_ratio_pct": overhead_ratio * 100,
        "effective_throughput_mbps": round(effective_throughput, 2),
        "payload_per_packet": payload_per_packet,
        "estimated_packets_per_sec": round(packets_per_sec),
        "throughput_loss_mbps": round(base_throughput_mbps - effective_throughput, 2)
    }


def compare_vpn_protocols(base_throughput_mbps: float = 100.0):
    """แสดงการเปรียบเทียบผลกระทบ Overhead ของแต่ละ VPN Protocol"""
    
    protocols = {
        "WireGuard (IPv4)": {"overhead": 60},   # 20 + 8 + 32
        "WireGuard (IPv6)": {"overhead": 80},   # 40 + 8 + 32
        "OpenVPN (UDP)":    {"overhead": 66},   # 20 + 8 + 38
        "IPSec ESP (IPv4)": {"overhead": 58},   # 20 + 8 + 2 + 12 + 16
    }
    
    print(f" - 📊 เปรียบเทียบ VPN Overhead (Base: {base_throughput_mbps} Mbps)")
    print("=" * 70)
    print(f"{'Protocol':<22} {'Overhead':>8} {'Loss %':>8} {'Effective':>12} {'Packets/s':>12}")
    print("-" * 70)
    
    results = {}
    for proto, info in protocols.items():
        r = calculate_vpn_overhead_impact(
            base_throughput_mbps,
            info["overhead"]
        )
        results[proto] = r
        print(
            f"{proto:<22} "
            f"{info['overhead']:>6} B  "
            f"{r['overhead_ratio_pct']:>6.1f}%  "
            f"{r['effective_throughput_mbps']:>8.1f} Mbps  "
            f"{r['estimated_packets_per_sec']:>8,}"
        )
    
    print("-" * 70)
    
    # หา Protocol ที่ดีที่สุด
    best_proto = max(results, key=lambda k: results[k]["effective_throughput_mbps"])
    print(f" - ✅ Protocol ที่แนะนำ (Overhead น้อยสุด): {best_proto}")
    print(f"   Effective Throughput: {results[best_proto]['effective_throughput_mbps']} Mbps")
    
    return results


# ===== ตัวอย่างการใช้งาน =====
if __name__ == "__main__":
    print("⚡ VPN Performance Analyzer — Network Security Lab")
    print("=" * 70)
    
    # เปรียบเทียบ VPN Protocols
    compare_vpn_protocols(base_throughput_mbps=1000.0)
    
    # ตัวอย่างการวัด Latency (ต้องมีการเชื่อมต่อ)
    print(" -  - 🔍 ตัวอย่างการวัด Latency:")
    print("  (ในการใช้งานจริง จะวัดก่อนและหลังเชื่อม VPN)")
    
    test_scenarios = [
        {"label": "ก่อนเชื่อม VPN (Direct)", "avg_ms": 15.2, "jitter": 2.1},
        {"label": "WireGuard VPN", "avg_ms": 17.8, "jitter": 2.4},
        {"label": "OpenVPN (UDP)", "avg_ms": 22.5, "jitter": 4.2},
        {"label": "Sshuttle", "avg_ms": 28.3, "jitter": 6.1},
    ]
    
    print(f" - {'Scenario':<30} {'Avg Latency':>12} {'Jitter':>8} {'Overhead':>10}")
    print("-" * 65)
    base_latency = test_scenarios[0]["avg_ms"]
    for s in test_scenarios:
        overhead = s["avg_ms"] - base_latency
        overhead_str = f"+{overhead:.1f} ms" if overhead > 0 else "baseline"
        print(
            f"{s['label']:<30} "
            f"{s['avg_ms']:>8.1f} ms  "
            f"{s['jitter']:>5.1f} ms  "
            f"{overhead_str:>10}"
        )

ตัวอย่าง Output:

📊 เปรียบเทียบ VPN Overhead (Base: 1000.0 Mbps)
======================================================================
Protocol               Overhead     Loss %    Effective    Packets/s
----------------------------------------------------------------------
WireGuard (IPv4)         60 B       4.0%    960.0 Mbps       66,667
WireGuard (IPv6)         80 B       5.3%    946.7 Mbps       66,667
OpenVPN (UDP)            66 B       4.4%    956.0 Mbps       66,667
IPSec ESP (IPv4)         58 B       3.9%    961.3 Mbps       66,667
----------------------------------------------------------------------

✅ Protocol ที่แนะนำ (Overhead น้อยสุด): IPSec ESP (IPv4)
   Effective Throughput: 961.33 Mbps

Scenario                       Avg Latency   Jitter    Overhead
-----------------------------------------------------------------
ก่อนเชื่อม VPN (Direct)          15.2 ms    2.1 ms    baseline
WireGuard VPN                    17.8 ms    2.4 ms    +2.6 ms
OpenVPN (UDP)                    22.5 ms    4.2 ms    +7.3 ms
Sshuttle                         28.3 ms    6.1 ms   +13.1 ms

6. สรุปโดยรวม

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#282828', 'primaryTextColor': '#ebdbb2', 'primaryBorderColor': '#d79921', 'lineColor': '#83a598', 'secondaryColor': '#3c3836'}}}%%
flowchart TD
    subgraph CONCEPTS["📚 แนวคิดหลักที่เรียนในสัปดาห์นี้"]
        C1["🌐 VPN คืออะไร? - Tunnel เสมือนบน Internet"]:::gruvbox_yellow
        C2["📡 ประเภท VPN - Site-to-Site / Remote Access"]:::gruvbox_yellow
        C3["🔐 Tunneling - Encapsulation กระบวนการ"]:::gruvbox_yellow
    end

    subgraph PROTOCOLS_LEARNED["🛡️ Protocols ที่ศึกษา"]
        P1["IPSec - IKEv2 + ESP - Enterprise Standard"]:::gruvbox_blue
        P2["SSL/TLS VPN - Port 443 - Clientless Access"]:::gruvbox_blue
        P3["WireGuard - ทันสมัย เร็ว ง่าย - Kernel-level"]:::gruvbox_green
    end

    subgraph TOOLS_USED["🔧 เครื่องมือที่ใช้"]
        T1["wg / wg-quick - จัดการ WireGuard"]:::gruvbox_orange
        T2["sshuttle - VPN over SSH - ไม่ต้อง Root Server"]:::gruvbox_orange
        T3["Python Scripts - ตรวจสอบ & วิเคราะห์"]:::gruvbox_orange
    end

    subgraph SECURITY["🔒 Security Best Practices"]
        S1["Perfect Forward Secrecy - Ephemeral Keys"]:::gruvbox_aqua
        S2["Strong Cipher Suite - ChaCha20 / AES-256-GCM"]:::gruvbox_aqua
        S3["Multi-Factor Auth - Monitoring & Logging"]:::gruvbox_aqua
    end

    CONCEPTS --> PROTOCOLS_LEARNED
    PROTOCOLS_LEARNED --> TOOLS_USED
    TOOLS_USED --> SECURITY

    classDef gruvbox_yellow fill:#282828,stroke:#d79921,color:#ebdbb2
    classDef gruvbox_blue fill:#282828,stroke:#458588,color:#ebdbb2
    classDef gruvbox_green fill:#282828,stroke:#98971a,color:#ebdbb2
    classDef gruvbox_orange fill:#282828,stroke:#d65d0e,color:#ebdbb2
    classDef gruvbox_aqua fill:#282828,stroke:#689d6a,color:#ebdbb2

ในสัปดาห์นี้เราได้เรียนรู้เกี่ยวกับ VPN Technologies and Implementation ครอบคลุมตั้งแต่:

  1. พื้นฐาน VPN — ความหมาย วัตถุประสงค์ และประเภท (Site-to-Site, Remote Access)
  2. กระบวนการ Tunneling — การ Encapsulate แพ็กเก็ตและการคำนวณ MTU
  3. โปรโตคอล VPN — IPSec (AH/ESP, IKEv2), SSL/TLS VPN, และ WireGuard
  4. WireGuard — โปรโตคอล VPN สมัยใหม่ที่ใช้ Curve25519, ChaCha20-Poly1305, และ Noise Protocol
  5. Sshuttle — VPN Transparent Proxy ที่ทำงานบน SSH ไม่ต้องการ Root บน Server
  6. Security Best Practices — PFS, Cipher Suite ที่แนะนำ, และการ Monitoring
  7. การเปรียบเทียบ — ช่วยเลือก VPN Solution ที่เหมาะสมกับแต่ละสถานการณ์

ข้อสรุปสำคัญ:


7. เอกสารอ้างอิง

  1. WireGuard Official Documentationhttps://www.wireguard.com/papers/wireguard.pdf
    Donenfeld, J. A. (2017). WireGuard: Next Generation Kernel Network Tunnel. NDSS Symposium

  2. RFC 4301 — Kent, S., & Seo, K. (2005). Security Architecture for the Internet Protocol. IETF.
    https://www.rfc-editor.org/rfc/rfc4301

  3. RFC 7296 — Kaufman, C., Hoffman, P., Nir, Y., Eronen, P., & Kivinen, T. (2014).
    Internet Key Exchange Protocol Version 2 (IKEv2). IETF.
    https://www.rfc-editor.org/rfc/rfc7296

  4. RFC 5246 — Dierks, T., & Rescorla, E. (2008). The Transport Layer Security (TLS) Protocol Version 1.2. IETF.

  5. Sshuttle Documentationhttps://sshuttle.readthedocs.io/

  6. NIST SP 800-77 Rev. 1 — Barker, E., et al. (2020). Guide to IPsec VPNs. NIST.
    https://doi.org/10.6028/NIST.SP.800-77r1

  7. The Noise Protocol Framework — Perrin, T. (2018).
    https://noiseprotocol.org/noise.html

  8. Stallings, W. (2017). Cryptography and Network Security: Principles and Practice (7th ed.). Pearson.

  9. Kaufman, C., Perlman, R., & Speciner, M. (2002). Network Security: Private Communication in a Public World (2nd ed.). Prentice Hall.

  10. Linux man pagesman wg, man wg-quick, man sshuttle