VPN (Virtual Private Network) คือเทคโนโลยีที่สร้างการเชื่อมต่อแบบ "อุโมงค์เสมือน" (Virtual Tunnel) ผ่านเครือข่ายสาธารณะ (เช่น Internet) เพื่อให้ข้อมูลที่รับ-ส่งมีความปลอดภัย เสมือนกับอยู่บนเครือข่ายส่วนตัว
วัตถุประสงค์หลักของ 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
VPN แบ่งออกเป็น 3 ประเภทหลักตามลักษณะการใช้งาน:
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:
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
| คุณลักษณะ | Remote Access VPN | Site-to-Site VPN |
|---|---|---|
| ผู้ใช้งาน | ผู้ใช้รายบุคคล | Gateway อุปกรณ์ |
| ต้องติดตั้ง Client | ✅ ใช่ | ❌ ไม่ใช่ |
| จำนวน Endpoint | Dynamic | Fixed |
| ตัวอย่าง Protocol | WireGuard, OpenVPN | IPSec IKEv2 |
| ความซับซ้อนในการตั้งค่า | ปานกลาง | สูง |
| เหมาะสำหรับ | Work From Home | สาขาองค์กร |
Tunneling คือกระบวนการห่อหุ้ม (Encapsulate) แพ็กเก็ตต้นฉบับด้วย Header ใหม่ เพื่อให้สามารถส่งผ่านเครือข่ายสาธารณะได้อย่างปลอดภัย
%%{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
MTU (Maximum Transmission Unit) ของ VPN จะน้อยกว่า Physical MTU เนื่องจากมี Header เพิ่มเข้ามา
ตัวแปร:
ตัวอย่างการคำนวณ WireGuard MTU:
| ส่วนประกอบ | ขนาด (bytes) |
|---|---|
| Ethernet MTU ปกติ | 1500 |
| Outer IP Header (IPv4) | 20 |
| UDP Header | 8 |
| WireGuard Header | 32 |
| MTU ที่เหลือสำหรับ Inner Packet | 1440 |
หมายเหตุ: ถ้าใช้ IPv6 เป็น Outer Header ให้เปลี่ยน 20 เป็น 40 bytes ดังนั้น MTU WireGuard over IPv6 = 1500 - 40 - 8 - 32 = 1420 bytes
IPSec เป็นชุดโปรโตคอลระดับ Network Layer ที่ให้ความปลอดภัยแก่การสื่อสาร IP โดยรองรับทั้ง Authentication และ Encryption
%%{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
IKEv2 Handshake แบ่งเป็น 2 Phase:
การคำนวณ Diffie-Hellman Key Exchange:
ตัวแปร:
ตัวอย่างการคำนวณ (ค่าเล็กเพื่อการเรียนรู้):
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 ผ่านเครือข่าย
SSL/TLS VPN ใช้โปรโตคอล TLS (Transport Layer Security) ที่ทำงานระดับ Application Layer ข้อดีคือผ่าน Firewall ได้ง่ายเพราะใช้ Port 443 (HTTPS)
%%{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:
ตัวแปร:
WireGuard คือโปรโตคอล VPN รุ่นใหม่ล่าสุด ออกแบบให้เรียบง่าย เร็ว และปลอดภัย รองรับใน Linux Kernel ตั้งแต่เวอร์ชัน 5.6 (มีนาคม 2020)
%%{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
WireGuard ใช้ Noise Protocol Framework ที่มีเพียง 1 Round-Trip (เทียบกับ IKEv2 ที่ต้องใช้ 2 Round-Trip)
สมการการสร้าง Session Key:
ตัวแปร:
# 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
# สร้าง 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
สมมติมีสถานการณ์ดังนี้:
| 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... |
# /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
# /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
# เปิด 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
#!/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
Sshuttle เป็นเครื่องมือที่สร้าง VPN แบบ Transparent ผ่าน SSH โดยไม่ต้องมี Root Access ฝั่ง Server และไม่ต้องตั้งค่า VPN Server ล่วงหน้า
%%{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
# Ubuntu/Debian
sudo apt install sshuttle
# pip (ทุก Platform)
pip install sshuttle
# Arch Linux
sudo pacman -S sshuttle
# ตรวจสอบการติดตั้ง
sshuttle --version
# ===== ตัวอย่างที่ 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
#!/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}")
%%{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"]
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 |
PFS (Perfect Forward Secrecy) คือคุณสมบัติที่ทำให้การถอดรหัสข้อมูลในอดีตเป็นไปไม่ได้ แม้จะได้ Private Key ในปัจจุบัน โดยใช้ Ephemeral Key (Key ชั่วคราว) สำหรับแต่ละ Session
ตัวแปร:
# ตรวจสอบ 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
| คุณลักษณะ | 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 ที่มี |
%%{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
#!/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
%%{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 ครอบคลุมตั้งแต่:
ข้อสรุปสำคัญ:
WireGuard Official Documentation — https://www.wireguard.com/papers/wireguard.pdf
Donenfeld, J. A. (2017). WireGuard: Next Generation Kernel Network Tunnel. NDSS Symposium
RFC 4301 — Kent, S., & Seo, K. (2005). Security Architecture for the Internet Protocol. IETF.
https://www.rfc-editor.org/rfc/rfc4301
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
RFC 5246 — Dierks, T., & Rescorla, E. (2008). The Transport Layer Security (TLS) Protocol Version 1.2. IETF.
Sshuttle Documentation — https://sshuttle.readthedocs.io/
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
The Noise Protocol Framework — Perrin, T. (2018).
https://noiseprotocol.org/noise.html
Stallings, W. (2017). Cryptography and Network Security: Principles and Practice (7th ed.). Pearson.
Kaufman, C., Perlman, R., & Speciner, M. (2002). Network Security: Private Communication in a Public World (2nd ed.). Prentice Hall.
Linux man pages — man wg, man wg-quick, man sshuttle